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  }