// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package socket provides a portable interface for socket system // calls.
package socket // import "golang.org/x/net/internal/socket" import ( ) var errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH) // An Option represents a sticky socket option. type Option struct { Level int // level Name int // name; must be equal or greater than 1 Len int // length of value in bytes; must be equal or greater than 1 } // Get reads a value for the option from the kernel. // It returns the number of bytes written into b. func ( *Option) ( *Conn, []byte) (int, error) { if .Name < 1 || .Len < 1 { return 0, errors.New("invalid option") } if len() < .Len { return 0, errors.New("short buffer") } return .get(, ) } // GetInt returns an integer value for the option. // // The Len field of Option must be either 1 or 4. func ( *Option) ( *Conn) (int, error) { if .Len != 1 && .Len != 4 { return 0, errors.New("invalid option") } var []byte var [4]byte if .Len == 1 { = [:1] } else { = [:4] } , := .get(, ) if != nil { return 0, } if != .Len { return 0, errors.New("invalid option length") } if .Len == 1 { return int([0]), nil } return int(NativeEndian.Uint32([:4])), nil } // Set writes the option and value to the kernel. func ( *Option) ( *Conn, []byte) error { if .Name < 1 || .Len < 1 { return errors.New("invalid option") } if len() < .Len { return errors.New("short buffer") } return .set(, ) } // SetInt writes the option and value to the kernel. // // The Len field of Option must be either 1 or 4. func ( *Option) ( *Conn, int) error { if .Len != 1 && .Len != 4 { return errors.New("invalid option") } var []byte if .Len == 1 { = []byte{byte()} } else { var [4]byte NativeEndian.PutUint32([:.Len], uint32()) = [:4] } return .set(, ) } // ControlMessageSpace returns the whole length of control message. func ( int) int { return controlMessageSpace() } // A ControlMessage represents the head message in a stream of control // messages. // // A control message comprises of a header, data and a few padding // fields to conform to the interface to the kernel. // // See RFC 3542 for further information. type ControlMessage []byte // Data returns the data field of the control message at the head on // m. func ( ControlMessage) ( int) []byte { := controlHeaderLen() if len() < || len() < + { return nil } return [ : +] } // Next returns the control message at the next on m. // // Next works only for standard control messages. func ( ControlMessage) ( int) ControlMessage { := ControlMessageSpace() if len() < { return nil } return [:] } // MarshalHeader marshals the header fields of the control message at // the head on m. func ( ControlMessage) (, , int) error { if len() < controlHeaderLen() { return errors.New("short message") } := (*cmsghdr)(unsafe.Pointer(&[0])) .set(controlMessageLen(), , ) return nil } // ParseHeader parses and returns the header fields of the control // message at the head on m. func ( ControlMessage) () (, , int, error) { := controlHeaderLen() if len() < { return 0, 0, 0, errors.New("short message") } := (*cmsghdr)(unsafe.Pointer(&[0])) return .lvl(), .typ(), int(uint64(.len()) - uint64()), nil } // Marshal marshals the control message at the head on m, and returns // the next control message. func ( ControlMessage) (, int, []byte) (ControlMessage, error) { := len() if len() < ControlMessageSpace() { return nil, errors.New("short message") } := (*cmsghdr)(unsafe.Pointer(&[0])) .set(controlMessageLen(), , ) if > 0 { copy(.Data(), ) } return .Next(), nil } // Parse parses m as a single or multiple control messages. // // Parse works for both standard and compatible messages. func ( ControlMessage) () ([]ControlMessage, error) { var []ControlMessage for len() >= controlHeaderLen() { := (*cmsghdr)(unsafe.Pointer(&[0])) := .len() if <= 0 { return nil, errors.New("invalid header length") } if uint64() < uint64(controlHeaderLen()) { return nil, errors.New("invalid message length") } if uint64() > uint64(len()) { return nil, errors.New("short buffer") } // On message reception: // // |<- ControlMessageSpace --------------->| // |<- controlMessageLen ---------->| | // |<- controlHeaderLen ->| | | // +---------------+------+---------+------+ // | Header | PadH | Data | PadD | // +---------------+------+---------+------+ // // On compatible message reception: // // | ... |<- controlMessageLen ----------->| // | ... |<- controlHeaderLen ->| | // +-----+---------------+------+----------+ // | ... | Header | PadH | Data | // +-----+---------------+------+----------+ = append(, ControlMessage([:])) := - controlHeaderLen() if len() >= ControlMessageSpace() { = [ControlMessageSpace():] } else { = [controlMessageLen():] } } return , nil } // NewControlMessage returns a new stream of control messages. func ( []int) ControlMessage { var int for := range { += ControlMessageSpace([]) } return make([]byte, ) } // A Message represents an IO message. type Message struct { // When writing, the Buffers field must contain at least one // byte to write. // When reading, the Buffers field will always contain a byte // to read. Buffers [][]byte // OOB contains protocol-specific control or miscellaneous // ancillary data known as out-of-band data. OOB []byte // Addr specifies a destination address when writing. // It can be nil when the underlying protocol of the raw // connection uses connection-oriented communication. // After a successful read, it may contain the source address // on the received packet. Addr net.Addr N int // # of bytes read or written from/to Buffers NN int // # of bytes read or written from/to OOB Flags int // protocol-specific information on the received message } // RecvMsg wraps recvmsg system call. // // The provided flags is a set of platform-dependent flags, such as // syscall.MSG_PEEK. func ( *Conn) ( *Message, int) error { return .recvMsg(, ) } // SendMsg wraps sendmsg system call. // // The provided flags is a set of platform-dependent flags, such as // syscall.MSG_DONTROUTE. func ( *Conn) ( *Message, int) error { return .sendMsg(, ) } // RecvMsgs wraps recvmmsg system call. // // It returns the number of processed messages. // // The provided flags is a set of platform-dependent flags, such as // syscall.MSG_PEEK. // // Only Linux supports this. func ( *Conn) ( []Message, int) (int, error) { return .recvMsgs(, ) } // SendMsgs wraps sendmmsg system call. // // It returns the number of processed messages. // // The provided flags is a set of platform-dependent flags, such as // syscall.MSG_DONTROUTE. // // Only Linux supports this. func ( *Conn) ( []Message, int) (int, error) { return .sendMsgs(, ) }