github.com/Andyfoo/golang/x/net@v0.0.0-20190901054642-57c1bf301704/internal/socket/socket.go (about) 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 "github.com/Andyfoo/golang/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 func controlHeaderLen() int { 94 return roundup(sizeofCmsghdr) 95 } 96 97 func controlMessageLen(dataLen int) int { 98 return roundup(sizeofCmsghdr) + dataLen 99 } 100 101 // ControlMessageSpace returns the whole length of control message. 102 func ControlMessageSpace(dataLen int) int { 103 return roundup(sizeofCmsghdr) + roundup(dataLen) 104 } 105 106 // A ControlMessage represents the head message in a stream of control 107 // messages. 108 // 109 // A control message comprises of a header, data and a few padding 110 // fields to conform to the interface to the kernel. 111 // 112 // See RFC 3542 for further information. 113 type ControlMessage []byte 114 115 // Data returns the data field of the control message at the head on 116 // m. 117 func (m ControlMessage) Data(dataLen int) []byte { 118 l := controlHeaderLen() 119 if len(m) < l || len(m) < l+dataLen { 120 return nil 121 } 122 return m[l : l+dataLen] 123 } 124 125 // Next returns the control message at the next on m. 126 // 127 // Next works only for standard control messages. 128 func (m ControlMessage) Next(dataLen int) ControlMessage { 129 l := ControlMessageSpace(dataLen) 130 if len(m) < l { 131 return nil 132 } 133 return m[l:] 134 } 135 136 // MarshalHeader marshals the header fields of the control message at 137 // the head on m. 138 func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error { 139 if len(m) < controlHeaderLen() { 140 return errors.New("short message") 141 } 142 h := (*cmsghdr)(unsafe.Pointer(&m[0])) 143 h.set(controlMessageLen(dataLen), lvl, typ) 144 return nil 145 } 146 147 // ParseHeader parses and returns the header fields of the control 148 // message at the head on m. 149 func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) { 150 l := controlHeaderLen() 151 if len(m) < l { 152 return 0, 0, 0, errors.New("short message") 153 } 154 h := (*cmsghdr)(unsafe.Pointer(&m[0])) 155 return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil 156 } 157 158 // Marshal marshals the control message at the head on m, and returns 159 // the next control message. 160 func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) { 161 l := len(data) 162 if len(m) < ControlMessageSpace(l) { 163 return nil, errors.New("short message") 164 } 165 h := (*cmsghdr)(unsafe.Pointer(&m[0])) 166 h.set(controlMessageLen(l), lvl, typ) 167 if l > 0 { 168 copy(m.Data(l), data) 169 } 170 return m.Next(l), nil 171 } 172 173 // Parse parses m as a single or multiple control messages. 174 // 175 // Parse works for both standard and compatible messages. 176 func (m ControlMessage) Parse() ([]ControlMessage, error) { 177 var ms []ControlMessage 178 for len(m) >= controlHeaderLen() { 179 h := (*cmsghdr)(unsafe.Pointer(&m[0])) 180 l := h.len() 181 if l <= 0 { 182 return nil, errors.New("invalid header length") 183 } 184 if uint64(l) < uint64(controlHeaderLen()) { 185 return nil, errors.New("invalid message length") 186 } 187 if uint64(l) > uint64(len(m)) { 188 return nil, errors.New("short buffer") 189 } 190 // On message reception: 191 // 192 // |<- ControlMessageSpace --------------->| 193 // |<- controlMessageLen ---------->| | 194 // |<- controlHeaderLen ->| | | 195 // +---------------+------+---------+------+ 196 // | Header | PadH | Data | PadD | 197 // +---------------+------+---------+------+ 198 // 199 // On compatible message reception: 200 // 201 // | ... |<- controlMessageLen ----------->| 202 // | ... |<- controlHeaderLen ->| | 203 // +-----+---------------+------+----------+ 204 // | ... | Header | PadH | Data | 205 // +-----+---------------+------+----------+ 206 ms = append(ms, ControlMessage(m[:l])) 207 ll := l - controlHeaderLen() 208 if len(m) >= ControlMessageSpace(ll) { 209 m = m[ControlMessageSpace(ll):] 210 } else { 211 m = m[controlMessageLen(ll):] 212 } 213 } 214 return ms, nil 215 } 216 217 // NewControlMessage returns a new stream of control messages. 218 func NewControlMessage(dataLen []int) ControlMessage { 219 var l int 220 for i := range dataLen { 221 l += ControlMessageSpace(dataLen[i]) 222 } 223 return make([]byte, l) 224 } 225 226 // A Message represents an IO message. 227 type Message struct { 228 // When writing, the Buffers field must contain at least one 229 // byte to write. 230 // When reading, the Buffers field will always contain a byte 231 // to read. 232 Buffers [][]byte 233 234 // OOB contains protocol-specific control or miscellaneous 235 // ancillary data known as out-of-band data. 236 OOB []byte 237 238 // Addr specifies a destination address when writing. 239 // It can be nil when the underlying protocol of the raw 240 // connection uses connection-oriented communication. 241 // After a successful read, it may contain the source address 242 // on the received packet. 243 Addr net.Addr 244 245 N int // # of bytes read or written from/to Buffers 246 NN int // # of bytes read or written from/to OOB 247 Flags int // protocol-specific information on the received message 248 } 249 250 // RecvMsg wraps recvmsg system call. 251 // 252 // The provided flags is a set of platform-dependent flags, such as 253 // syscall.MSG_PEEK. 254 func (c *Conn) RecvMsg(m *Message, flags int) error { 255 return c.recvMsg(m, flags) 256 } 257 258 // SendMsg wraps sendmsg system call. 259 // 260 // The provided flags is a set of platform-dependent flags, such as 261 // syscall.MSG_DONTROUTE. 262 func (c *Conn) SendMsg(m *Message, flags int) error { 263 return c.sendMsg(m, flags) 264 } 265 266 // RecvMsgs wraps recvmmsg system call. 267 // 268 // It returns the number of processed messages. 269 // 270 // The provided flags is a set of platform-dependent flags, such as 271 // syscall.MSG_PEEK. 272 // 273 // Only Linux supports this. 274 func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) { 275 return c.recvMsgs(ms, flags) 276 } 277 278 // SendMsgs wraps sendmmsg system call. 279 // 280 // It returns the number of processed messages. 281 // 282 // The provided flags is a set of platform-dependent flags, such as 283 // syscall.MSG_DONTROUTE. 284 // 285 // Only Linux supports this. 286 func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) { 287 return c.sendMsgs(ms, flags) 288 }