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.
5 // Package socket provides a portable interface for socket system
7 package socket // import "golang.org/x/net/internal/socket"
15 // An Option represents a sticky socket option.
18 Name int // name; must be equal or greater than 1
19 Len int // length of value in bytes; must be equal or greater than 1
22 // Get reads a value for the option from the kernel.
23 // It returns the number of bytes written into b.
24 func (o *Option) Get(c *Conn, b []byte) (int, error) {
25 if o.Name < 1 || o.Len < 1 {
26 return 0, errors.New("invalid option")
29 return 0, errors.New("short buffer")
34 // GetInt returns an integer value for the option.
36 // The Len field of Option must be either 1 or 4.
37 func (o *Option) GetInt(c *Conn) (int, error) {
38 if o.Len != 1 && o.Len != 4 {
39 return 0, errors.New("invalid option")
53 return 0, errors.New("invalid option length")
58 return int(NativeEndian.Uint32(b[:4])), nil
61 // Set writes the option and value to the kernel.
62 func (o *Option) Set(c *Conn, b []byte) error {
63 if o.Name < 1 || o.Len < 1 {
64 return errors.New("invalid option")
67 return errors.New("short buffer")
72 // SetInt writes the option and value to the kernel.
74 // The Len field of Option must be either 1 or 4.
75 func (o *Option) SetInt(c *Conn, v int) error {
76 if o.Len != 1 && o.Len != 4 {
77 return errors.New("invalid option")
84 NativeEndian.PutUint32(bb[:o.Len], uint32(v))
90 func controlHeaderLen() int {
91 return roundup(sizeofCmsghdr)
94 func controlMessageLen(dataLen int) int {
95 return roundup(sizeofCmsghdr) + dataLen
98 // ControlMessageSpace returns the whole length of control message.
99 func ControlMessageSpace(dataLen int) int {
100 return roundup(sizeofCmsghdr) + roundup(dataLen)
103 // A ControlMessage represents the head message in a stream of control
106 // A control message comprises of a header, data and a few padding
107 // fields to conform to the interface to the kernel.
109 // See RFC 3542 for further information.
110 type ControlMessage []byte
112 // Data returns the data field of the control message at the head on
114 func (m ControlMessage) Data(dataLen int) []byte {
115 l := controlHeaderLen()
116 if len(m) < l || len(m) < l+dataLen {
119 return m[l : l+dataLen]
122 // Next returns the control message at the next on m.
124 // Next works only for standard control messages.
125 func (m ControlMessage) Next(dataLen int) ControlMessage {
126 l := ControlMessageSpace(dataLen)
133 // MarshalHeader marshals the header fields of the control message at
135 func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
136 if len(m) < controlHeaderLen() {
137 return errors.New("short message")
139 h := (*cmsghdr)(unsafe.Pointer(&m[0]))
140 h.set(controlMessageLen(dataLen), lvl, typ)
144 // ParseHeader parses and returns the header fields of the control
145 // message at the head on m.
146 func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
147 l := controlHeaderLen()
149 return 0, 0, 0, errors.New("short message")
151 h := (*cmsghdr)(unsafe.Pointer(&m[0]))
152 return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
155 // Marshal marshals the control message at the head on m, and returns
156 // the next control message.
157 func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
159 if len(m) < ControlMessageSpace(l) {
160 return nil, errors.New("short message")
162 h := (*cmsghdr)(unsafe.Pointer(&m[0]))
163 h.set(controlMessageLen(l), lvl, typ)
165 copy(m.Data(l), data)
167 return m.Next(l), nil
170 // Parse parses m as a single or multiple control messages.
172 // Parse works for both standard and compatible messages.
173 func (m ControlMessage) Parse() ([]ControlMessage, error) {
174 var ms []ControlMessage
175 for len(m) >= controlHeaderLen() {
176 h := (*cmsghdr)(unsafe.Pointer(&m[0]))
179 return nil, errors.New("invalid header length")
181 if uint64(l) < uint64(controlHeaderLen()) {
182 return nil, errors.New("invalid message length")
184 if uint64(l) > uint64(len(m)) {
185 return nil, errors.New("short buffer")
187 // On message reception:
189 // |<- ControlMessageSpace --------------->|
190 // |<- controlMessageLen ---------->| |
191 // |<- controlHeaderLen ->| | |
192 // +---------------+------+---------+------+
193 // | Header | PadH | Data | PadD |
194 // +---------------+------+---------+------+
196 // On compatible message reception:
198 // | ... |<- controlMessageLen ----------->|
199 // | ... |<- controlHeaderLen ->| |
200 // +-----+---------------+------+----------+
201 // | ... | Header | PadH | Data |
202 // +-----+---------------+------+----------+
203 ms = append(ms, ControlMessage(m[:l]))
204 ll := l - controlHeaderLen()
205 if len(m) >= ControlMessageSpace(ll) {
206 m = m[ControlMessageSpace(ll):]
208 m = m[controlMessageLen(ll):]
214 // NewControlMessage returns a new stream of control messages.
215 func NewControlMessage(dataLen []int) ControlMessage {
217 for i := range dataLen {
218 l += ControlMessageSpace(dataLen[i])
220 return make([]byte, l)
223 // A Message represents an IO message.
224 type Message struct {
225 // When writing, the Buffers field must contain at least one
227 // When reading, the Buffers field will always contain a byte
231 // OOB contains protocol-specific control or miscellaneous
232 // ancillary data known as out-of-band data.
235 // Addr specifies a destination address when writing.
236 // It can be nil when the underlying protocol of the raw
237 // connection uses connection-oriented communication.
238 // After a successful read, it may contain the source address
239 // on the received packet.
242 N int // # of bytes read or written from/to Buffers
243 NN int // # of bytes read or written from/to OOB
244 Flags int // protocol-specific information on the received message
247 // RecvMsg wraps recvmsg system call.
249 // The provided flags is a set of platform-dependent flags, such as
251 func (c *Conn) RecvMsg(m *Message, flags int) error {
252 return c.recvMsg(m, flags)
255 // SendMsg wraps sendmsg system call.
257 // The provided flags is a set of platform-dependent flags, such as
258 // syscall.MSG_DONTROUTE.
259 func (c *Conn) SendMsg(m *Message, flags int) error {
260 return c.sendMsg(m, flags)
263 // RecvMsgs wraps recvmmsg system call.
265 // It returns the number of processed messages.
267 // The provided flags is a set of platform-dependent flags, such as
270 // Only Linux supports this.
271 func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) {
272 return c.recvMsgs(ms, flags)
275 // SendMsgs wraps sendmmsg system call.
277 // It returns the number of processed messages.
279 // The provided flags is a set of platform-dependent flags, such as
280 // syscall.MSG_DONTROUTE.
282 // Only Linux supports this.
283 func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
284 return c.sendMsgs(ms, flags)