OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / internal / socket / socket.go
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         "unsafe"
13 )
14
15 // An Option represents a sticky socket option.
16 type Option struct {
17         Level int // level
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
20 }
21
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")
27         }
28         if len(b) < o.Len {
29                 return 0, errors.New("short buffer")
30         }
31         return o.get(c, b)
32 }
33
34 // GetInt returns an integer value for the option.
35 //
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")
40         }
41         var b []byte
42         var bb [4]byte
43         if o.Len == 1 {
44                 b = bb[:1]
45         } else {
46                 b = bb[:4]
47         }
48         n, err := o.get(c, b)
49         if err != nil {
50                 return 0, err
51         }
52         if n != o.Len {
53                 return 0, errors.New("invalid option length")
54         }
55         if o.Len == 1 {
56                 return int(b[0]), nil
57         }
58         return int(NativeEndian.Uint32(b[:4])), nil
59 }
60
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")
65         }
66         if len(b) < o.Len {
67                 return errors.New("short buffer")
68         }
69         return o.set(c, b)
70 }
71
72 // SetInt writes the option and value to the kernel.
73 //
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")
78         }
79         var b []byte
80         if o.Len == 1 {
81                 b = []byte{byte(v)}
82         } else {
83                 var bb [4]byte
84                 NativeEndian.PutUint32(bb[:o.Len], uint32(v))
85                 b = bb[:4]
86         }
87         return o.set(c, b)
88 }
89
90 func controlHeaderLen() int {
91         return roundup(sizeofCmsghdr)
92 }
93
94 func controlMessageLen(dataLen int) int {
95         return roundup(sizeofCmsghdr) + dataLen
96 }
97
98 // ControlMessageSpace returns the whole length of control message.
99 func ControlMessageSpace(dataLen int) int {
100         return roundup(sizeofCmsghdr) + roundup(dataLen)
101 }
102
103 // A ControlMessage represents the head message in a stream of control
104 // messages.
105 //
106 // A control message comprises of a header, data and a few padding
107 // fields to conform to the interface to the kernel.
108 //
109 // See RFC 3542 for further information.
110 type ControlMessage []byte
111
112 // Data returns the data field of the control message at the head on
113 // w.
114 func (m ControlMessage) Data(dataLen int) []byte {
115         l := controlHeaderLen()
116         if len(m) < l || len(m) < l+dataLen {
117                 return nil
118         }
119         return m[l : l+dataLen]
120 }
121
122 // Next returns the control message at the next on w.
123 //
124 // Next works only for standard control messages.
125 func (m ControlMessage) Next(dataLen int) ControlMessage {
126         l := ControlMessageSpace(dataLen)
127         if len(m) < l {
128                 return nil
129         }
130         return m[l:]
131 }
132
133 // MarshalHeader marshals the header fields of the control message at
134 // the head on w.
135 func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
136         if len(m) < controlHeaderLen() {
137                 return errors.New("short message")
138         }
139         h := (*cmsghdr)(unsafe.Pointer(&m[0]))
140         h.set(controlMessageLen(dataLen), lvl, typ)
141         return nil
142 }
143
144 // ParseHeader parses and returns the header fields of the control
145 // message at the head on w.
146 func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
147         l := controlHeaderLen()
148         if len(m) < l {
149                 return 0, 0, 0, errors.New("short message")
150         }
151         h := (*cmsghdr)(unsafe.Pointer(&m[0]))
152         return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
153 }
154
155 // Marshal marshals the control message at the head on w, and returns
156 // the next control message.
157 func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
158         l := len(data)
159         if len(m) < ControlMessageSpace(l) {
160                 return nil, errors.New("short message")
161         }
162         h := (*cmsghdr)(unsafe.Pointer(&m[0]))
163         h.set(controlMessageLen(l), lvl, typ)
164         if l > 0 {
165                 copy(m.Data(l), data)
166         }
167         return m.Next(l), nil
168 }
169
170 // Parse parses w as a single or multiple control messages.
171 //
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]))
177                 l := h.len()
178                 if l <= 0 {
179                         return nil, errors.New("invalid header length")
180                 }
181                 if uint64(l) < uint64(controlHeaderLen()) {
182                         return nil, errors.New("invalid message length")
183                 }
184                 if uint64(l) > uint64(len(m)) {
185                         return nil, errors.New("short buffer")
186                 }
187                 // On message reception:
188                 //
189                 // |<- ControlMessageSpace --------------->|
190                 // |<- controlMessageLen ---------->|      |
191                 // |<- controlHeaderLen ->|         |      |
192                 // +---------------+------+---------+------+
193                 // |    Header     | PadH |  Data   | PadD |
194                 // +---------------+------+---------+------+
195                 //
196                 // On compatible message reception:
197                 //
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):]
207                 } else {
208                         m = m[controlMessageLen(ll):]
209                 }
210         }
211         return ms, nil
212 }
213
214 // NewControlMessage returns a new stream of control messages.
215 func NewControlMessage(dataLen []int) ControlMessage {
216         var l int
217         for i := range dataLen {
218                 l += ControlMessageSpace(dataLen[i])
219         }
220         return make([]byte, l)
221 }
222
223 // A Message represents an IO message.
224 type Message struct {
225         // When writing, the Buffers field must contain at least one
226         // byte to write.
227         // When reading, the Buffers field will always contain a byte
228         // to read.
229         Buffers [][]byte
230
231         // OOB contains protocol-specific control or miscellaneous
232         // ancillary data known as out-of-band data.
233         OOB []byte
234
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.
240         Addr net.Addr
241
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
245 }
246
247 // RecvMsg wraps recvmsg system call.
248 //
249 // The provided flags is a set of platform-dependent flags, such as
250 // syscall.MSG_PEEK.
251 func (c *Conn) RecvMsg(m *Message, flags int) error {
252         return c.recvMsg(m, flags)
253 }
254
255 // SendMsg wraps sendmsg system call.
256 //
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)
261 }
262
263 // RecvMsgs wraps recvmmsg system call.
264 //
265 // It returns the number of processed messages.
266 //
267 // The provided flags is a set of platform-dependent flags, such as
268 // syscall.MSG_PEEK.
269 //
270 // Only Linux supports this.
271 func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) {
272         return c.recvMsgs(ms, flags)
273 }
274
275 // SendMsgs wraps sendmmsg system call.
276 //
277 // It returns the number of processed messages.
278 //
279 // The provided flags is a set of platform-dependent flags, such as
280 // syscall.MSG_DONTROUTE.
281 //
282 // Only Linux supports this.
283 func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
284         return c.sendMsgs(ms, flags)
285 }