gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

socket.go (7661B)


      1 // Copyright 2017 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Package socket provides a portable interface for socket system
      6 // calls.
      7 package socket // import "golang.org/x/net/internal/socket"
      8 
      9 import (
     10 	"errors"
     11 	"net"
     12 	"runtime"
     13 	"unsafe"
     14 )
     15 
     16 var errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
     17 
     18 // An Option represents a sticky socket option.
     19 type Option struct {
     20 	Level int // level
     21 	Name  int // name; must be equal or greater than 1
     22 	Len   int // length of value in bytes; must be equal or greater than 1
     23 }
     24 
     25 // Get reads a value for the option from the kernel.
     26 // It returns the number of bytes written into b.
     27 func (o *Option) Get(c *Conn, b []byte) (int, error) {
     28 	if o.Name < 1 || o.Len < 1 {
     29 		return 0, errors.New("invalid option")
     30 	}
     31 	if len(b) < o.Len {
     32 		return 0, errors.New("short buffer")
     33 	}
     34 	return o.get(c, b)
     35 }
     36 
     37 // GetInt returns an integer value for the option.
     38 //
     39 // The Len field of Option must be either 1 or 4.
     40 func (o *Option) GetInt(c *Conn) (int, error) {
     41 	if o.Len != 1 && o.Len != 4 {
     42 		return 0, errors.New("invalid option")
     43 	}
     44 	var b []byte
     45 	var bb [4]byte
     46 	if o.Len == 1 {
     47 		b = bb[:1]
     48 	} else {
     49 		b = bb[:4]
     50 	}
     51 	n, err := o.get(c, b)
     52 	if err != nil {
     53 		return 0, err
     54 	}
     55 	if n != o.Len {
     56 		return 0, errors.New("invalid option length")
     57 	}
     58 	if o.Len == 1 {
     59 		return int(b[0]), nil
     60 	}
     61 	return int(NativeEndian.Uint32(b[:4])), nil
     62 }
     63 
     64 // Set writes the option and value to the kernel.
     65 func (o *Option) Set(c *Conn, b []byte) error {
     66 	if o.Name < 1 || o.Len < 1 {
     67 		return errors.New("invalid option")
     68 	}
     69 	if len(b) < o.Len {
     70 		return errors.New("short buffer")
     71 	}
     72 	return o.set(c, b)
     73 }
     74 
     75 // SetInt writes the option and value to the kernel.
     76 //
     77 // The Len field of Option must be either 1 or 4.
     78 func (o *Option) SetInt(c *Conn, v int) error {
     79 	if o.Len != 1 && o.Len != 4 {
     80 		return errors.New("invalid option")
     81 	}
     82 	var b []byte
     83 	if o.Len == 1 {
     84 		b = []byte{byte(v)}
     85 	} else {
     86 		var bb [4]byte
     87 		NativeEndian.PutUint32(bb[:o.Len], uint32(v))
     88 		b = bb[:4]
     89 	}
     90 	return o.set(c, b)
     91 }
     92 
     93 // ControlMessageSpace returns the whole length of control message.
     94 func ControlMessageSpace(dataLen int) int {
     95 	return controlMessageSpace(dataLen)
     96 }
     97 
     98 // A ControlMessage represents the head message in a stream of control
     99 // messages.
    100 //
    101 // A control message comprises of a header, data and a few padding
    102 // fields to conform to the interface to the kernel.
    103 //
    104 // See RFC 3542 for further information.
    105 type ControlMessage []byte
    106 
    107 // Data returns the data field of the control message at the head on
    108 // m.
    109 func (m ControlMessage) Data(dataLen int) []byte {
    110 	l := controlHeaderLen()
    111 	if len(m) < l || len(m) < l+dataLen {
    112 		return nil
    113 	}
    114 	return m[l : l+dataLen]
    115 }
    116 
    117 // Next returns the control message at the next on m.
    118 //
    119 // Next works only for standard control messages.
    120 func (m ControlMessage) Next(dataLen int) ControlMessage {
    121 	l := ControlMessageSpace(dataLen)
    122 	if len(m) < l {
    123 		return nil
    124 	}
    125 	return m[l:]
    126 }
    127 
    128 // MarshalHeader marshals the header fields of the control message at
    129 // the head on m.
    130 func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
    131 	if len(m) < controlHeaderLen() {
    132 		return errors.New("short message")
    133 	}
    134 	h := (*cmsghdr)(unsafe.Pointer(&m[0]))
    135 	h.set(controlMessageLen(dataLen), lvl, typ)
    136 	return nil
    137 }
    138 
    139 // ParseHeader parses and returns the header fields of the control
    140 // message at the head on m.
    141 func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
    142 	l := controlHeaderLen()
    143 	if len(m) < l {
    144 		return 0, 0, 0, errors.New("short message")
    145 	}
    146 	h := (*cmsghdr)(unsafe.Pointer(&m[0]))
    147 	return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
    148 }
    149 
    150 // Marshal marshals the control message at the head on m, and returns
    151 // the next control message.
    152 func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
    153 	l := len(data)
    154 	if len(m) < ControlMessageSpace(l) {
    155 		return nil, errors.New("short message")
    156 	}
    157 	h := (*cmsghdr)(unsafe.Pointer(&m[0]))
    158 	h.set(controlMessageLen(l), lvl, typ)
    159 	if l > 0 {
    160 		copy(m.Data(l), data)
    161 	}
    162 	return m.Next(l), nil
    163 }
    164 
    165 // Parse parses m as a single or multiple control messages.
    166 //
    167 // Parse works for both standard and compatible messages.
    168 func (m ControlMessage) Parse() ([]ControlMessage, error) {
    169 	var ms []ControlMessage
    170 	for len(m) >= controlHeaderLen() {
    171 		h := (*cmsghdr)(unsafe.Pointer(&m[0]))
    172 		l := h.len()
    173 		if l <= 0 {
    174 			return nil, errors.New("invalid header length")
    175 		}
    176 		if uint64(l) < uint64(controlHeaderLen()) {
    177 			return nil, errors.New("invalid message length")
    178 		}
    179 		if uint64(l) > uint64(len(m)) {
    180 			return nil, errors.New("short buffer")
    181 		}
    182 		// On message reception:
    183 		//
    184 		// |<- ControlMessageSpace --------------->|
    185 		// |<- controlMessageLen ---------->|      |
    186 		// |<- controlHeaderLen ->|         |      |
    187 		// +---------------+------+---------+------+
    188 		// |    Header     | PadH |  Data   | PadD |
    189 		// +---------------+------+---------+------+
    190 		//
    191 		// On compatible message reception:
    192 		//
    193 		// | ... |<- controlMessageLen ----------->|
    194 		// | ... |<- controlHeaderLen ->|          |
    195 		// +-----+---------------+------+----------+
    196 		// | ... |    Header     | PadH |   Data   |
    197 		// +-----+---------------+------+----------+
    198 		ms = append(ms, ControlMessage(m[:l]))
    199 		ll := l - controlHeaderLen()
    200 		if len(m) >= ControlMessageSpace(ll) {
    201 			m = m[ControlMessageSpace(ll):]
    202 		} else {
    203 			m = m[controlMessageLen(ll):]
    204 		}
    205 	}
    206 	return ms, nil
    207 }
    208 
    209 // NewControlMessage returns a new stream of control messages.
    210 func NewControlMessage(dataLen []int) ControlMessage {
    211 	var l int
    212 	for i := range dataLen {
    213 		l += ControlMessageSpace(dataLen[i])
    214 	}
    215 	return make([]byte, l)
    216 }
    217 
    218 // A Message represents an IO message.
    219 type Message struct {
    220 	// When writing, the Buffers field must contain at least one
    221 	// byte to write.
    222 	// When reading, the Buffers field will always contain a byte
    223 	// to read.
    224 	Buffers [][]byte
    225 
    226 	// OOB contains protocol-specific control or miscellaneous
    227 	// ancillary data known as out-of-band data.
    228 	OOB []byte
    229 
    230 	// Addr specifies a destination address when writing.
    231 	// It can be nil when the underlying protocol of the raw
    232 	// connection uses connection-oriented communication.
    233 	// After a successful read, it may contain the source address
    234 	// on the received packet.
    235 	Addr net.Addr
    236 
    237 	N     int // # of bytes read or written from/to Buffers
    238 	NN    int // # of bytes read or written from/to OOB
    239 	Flags int // protocol-specific information on the received message
    240 }
    241 
    242 // RecvMsg wraps recvmsg system call.
    243 //
    244 // The provided flags is a set of platform-dependent flags, such as
    245 // syscall.MSG_PEEK.
    246 func (c *Conn) RecvMsg(m *Message, flags int) error {
    247 	return c.recvMsg(m, flags)
    248 }
    249 
    250 // SendMsg wraps sendmsg system call.
    251 //
    252 // The provided flags is a set of platform-dependent flags, such as
    253 // syscall.MSG_DONTROUTE.
    254 func (c *Conn) SendMsg(m *Message, flags int) error {
    255 	return c.sendMsg(m, flags)
    256 }
    257 
    258 // RecvMsgs wraps recvmmsg system call.
    259 //
    260 // It returns the number of processed messages.
    261 //
    262 // The provided flags is a set of platform-dependent flags, such as
    263 // syscall.MSG_PEEK.
    264 //
    265 // Only Linux supports this.
    266 func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) {
    267 	return c.recvMsgs(ms, flags)
    268 }
    269 
    270 // SendMsgs wraps sendmmsg system call.
    271 //
    272 // It returns the number of processed messages.
    273 //
    274 // The provided flags is a set of platform-dependent flags, such as
    275 // syscall.MSG_DONTROUTE.
    276 //
    277 // Only Linux supports this.
    278 func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
    279 	return c.sendMsgs(ms, flags)
    280 }