|
|
// 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 ( "errors" "net" "unsafe" )
// 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 (o *Option) Get(c *Conn, b []byte) (int, error) { if o.Name < 1 || o.Len < 1 { return 0, errors.New("invalid option") } if len(b) < o.Len { return 0, errors.New("short buffer") } return o.get(c, b) }
// GetInt returns an integer value for the option.
//
// The Len field of Option must be either 1 or 4.
func (o *Option) GetInt(c *Conn) (int, error) { if o.Len != 1 && o.Len != 4 { return 0, errors.New("invalid option") } var b []byte var bb [4]byte if o.Len == 1 { b = bb[:1] } else { b = bb[:4] } n, err := o.get(c, b) if err != nil { return 0, err } if n != o.Len { return 0, errors.New("invalid option length") } if o.Len == 1 { return int(b[0]), nil } return int(NativeEndian.Uint32(b[:4])), nil }
// Set writes the option and value to the kernel.
func (o *Option) Set(c *Conn, b []byte) error { if o.Name < 1 || o.Len < 1 { return errors.New("invalid option") } if len(b) < o.Len { return errors.New("short buffer") } return o.set(c, b) }
// SetInt writes the option and value to the kernel.
//
// The Len field of Option must be either 1 or 4.
func (o *Option) SetInt(c *Conn, v int) error { if o.Len != 1 && o.Len != 4 { return errors.New("invalid option") } var b []byte if o.Len == 1 { b = []byte{byte(v)} } else { var bb [4]byte NativeEndian.PutUint32(bb[:o.Len], uint32(v)) b = bb[:4] } return o.set(c, b) }
func controlHeaderLen() int { return roundup(sizeofCmsghdr) }
func controlMessageLen(dataLen int) int { return roundup(sizeofCmsghdr) + dataLen }
// ControlMessageSpace returns the whole length of control message.
func ControlMessageSpace(dataLen int) int { return roundup(sizeofCmsghdr) + roundup(dataLen) }
// 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 (m ControlMessage) Data(dataLen int) []byte { l := controlHeaderLen() if len(m) < l || len(m) < l+dataLen { return nil } return m[l : l+dataLen] }
// Next returns the control message at the next on m.
//
// Next works only for standard control messages.
func (m ControlMessage) Next(dataLen int) ControlMessage { l := ControlMessageSpace(dataLen) if len(m) < l { return nil } return m[l:] }
// MarshalHeader marshals the header fields of the control message at
// the head on m.
func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error { if len(m) < controlHeaderLen() { return errors.New("short message") } h := (*cmsghdr)(unsafe.Pointer(&m[0])) h.set(controlMessageLen(dataLen), lvl, typ) return nil }
// ParseHeader parses and returns the header fields of the control
// message at the head on m.
func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) { l := controlHeaderLen() if len(m) < l { return 0, 0, 0, errors.New("short message") } h := (*cmsghdr)(unsafe.Pointer(&m[0])) return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil }
// Marshal marshals the control message at the head on m, and returns
// the next control message.
func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) { l := len(data) if len(m) < ControlMessageSpace(l) { return nil, errors.New("short message") } h := (*cmsghdr)(unsafe.Pointer(&m[0])) h.set(controlMessageLen(l), lvl, typ) if l > 0 { copy(m.Data(l), data) } return m.Next(l), nil }
// Parse parses m as a single or multiple control messages.
//
// Parse works for both standard and compatible messages.
func (m ControlMessage) Parse() ([]ControlMessage, error) { var ms []ControlMessage for len(m) >= controlHeaderLen() { h := (*cmsghdr)(unsafe.Pointer(&m[0])) l := h.len() if l <= 0 { return nil, errors.New("invalid header length") } if uint64(l) < uint64(controlHeaderLen()) { return nil, errors.New("invalid message length") } if uint64(l) > uint64(len(m)) { 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 |
// +-----+---------------+------+----------+
ms = append(ms, ControlMessage(m[:l])) ll := l - controlHeaderLen() if len(m) >= ControlMessageSpace(ll) { m = m[ControlMessageSpace(ll):] } else { m = m[controlMessageLen(ll):] } } return ms, nil }
// NewControlMessage returns a new stream of control messages.
func NewControlMessage(dataLen []int) ControlMessage { var l int for i := range dataLen { l += ControlMessageSpace(dataLen[i]) } return make([]byte, l) }
// 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 (c *Conn) RecvMsg(m *Message, flags int) error { return c.recvMsg(m, flags) }
// SendMsg wraps sendmsg system call.
//
// The provided flags is a set of platform-dependent flags, such as
// syscall.MSG_DONTROUTE.
func (c *Conn) SendMsg(m *Message, flags int) error { return c.sendMsg(m, flags) }
// 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 (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) { return c.recvMsgs(ms, flags) }
// 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 (c *Conn) SendMsgs(ms []Message, flags int) (int, error) { return c.sendMsgs(ms, flags) }
|