mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-02 23:27:31 -04:00
unix: improve Sendmsg and Recvmsg documentation
This clarifies these functions' behavior when the non-control data is empty but there is a control data present. It also makes clear the difference between Sendmsg, SendmsgN, and SendmsgBuffers, and between Recvmsg and RecvmsgBuffers. Fixes golang/go#56911 Change-Id: I1e35659e66e493c192af7f5a426a316f6052475c Reviewed-on: https://go-review.googlesource.com/c/sys/+/456816 Run-TryBot: Ian Lance Taylor <iant@google.com> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Ian Lance Taylor <iant@google.com>
This commit is contained in:
+45
-10
@@ -331,6 +331,19 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recvmsg receives a message from a socket using the recvmsg system call. The
|
||||||
|
// received non-control data will be written to p, and any "out of band"
|
||||||
|
// control data will be written to oob. The flags are passed to recvmsg.
|
||||||
|
//
|
||||||
|
// The results are:
|
||||||
|
// - n is the number of non-control data bytes read into p
|
||||||
|
// - oobn is the number of control data bytes read into oob; this may be interpreted using [ParseSocketControlMessage]
|
||||||
|
// - recvflags is flags returned by recvmsg
|
||||||
|
// - from is the address of the sender
|
||||||
|
//
|
||||||
|
// If the underlying socket type is not SOCK_DGRAM, a received message
|
||||||
|
// containing oob data and a single '\0' of non-control data is treated as if
|
||||||
|
// the message contained only control data, i.e. n will be zero on return.
|
||||||
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
|
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
|
||||||
var iov [1]Iovec
|
var iov [1]Iovec
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
@@ -346,13 +359,9 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecvmsgBuffers receives a message from a socket using the recvmsg
|
// RecvmsgBuffers receives a message from a socket using the recvmsg system
|
||||||
// system call. The flags are passed to recvmsg. Any non-control data
|
// call. This function is equivalent to Recvmsg, but non-control data read is
|
||||||
// read is scattered into the buffers slices. The results are:
|
// scattered into the buffers slices.
|
||||||
// - n is the number of non-control data read into bufs
|
|
||||||
// - oobn is the number of control data read into oob; this may be interpreted using [ParseSocketControlMessage]
|
|
||||||
// - recvflags is flags returned by recvmsg
|
|
||||||
// - from is the address of the sender
|
|
||||||
func RecvmsgBuffers(fd int, buffers [][]byte, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
|
func RecvmsgBuffers(fd int, buffers [][]byte, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
|
||||||
iov := make([]Iovec, len(buffers))
|
iov := make([]Iovec, len(buffers))
|
||||||
for i := range buffers {
|
for i := range buffers {
|
||||||
@@ -371,11 +380,38 @@ func RecvmsgBuffers(fd int, buffers [][]byte, oob []byte, flags int) (n, oobn in
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sendmsg sends a message on a socket to an address using the sendmsg system
|
||||||
|
// call. This function is equivalent to SendmsgN, but does not return the
|
||||||
|
// number of bytes actually sent.
|
||||||
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
|
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
|
||||||
_, err = SendmsgN(fd, p, oob, to, flags)
|
_, err = SendmsgN(fd, p, oob, to, flags)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendmsgN sends a message on a socket to an address using the sendmsg system
|
||||||
|
// call. p contains the non-control data to send, and oob contains the "out of
|
||||||
|
// band" control data. The flags are passed to sendmsg. The number of
|
||||||
|
// non-control bytes actually written to the socket is returned.
|
||||||
|
//
|
||||||
|
// Some socket types do not support sending control data without accompanying
|
||||||
|
// non-control data. If p is empty, and oob contains control data, and the
|
||||||
|
// underlying socket type is not SOCK_DGRAM, p will be treated as containing a
|
||||||
|
// single '\0' and the return value will indicate zero bytes sent.
|
||||||
|
//
|
||||||
|
// The Go function Recvmsg, if called with an empty p and a non-empty oob,
|
||||||
|
// will read and ignore this additional '\0'. If the message is received by
|
||||||
|
// code that does not use Recvmsg, or that does not use Go at all, that code
|
||||||
|
// will need to be written to expect and ignore the additional '\0'.
|
||||||
|
//
|
||||||
|
// If you need to send non-empty oob with p actually empty, and if the
|
||||||
|
// underlying socket type supports it, you can do so via a raw system call as
|
||||||
|
// follows:
|
||||||
|
//
|
||||||
|
// msg := &unix.Msghdr{
|
||||||
|
// Control: &oob[0],
|
||||||
|
// }
|
||||||
|
// msg.SetControllen(len(oob))
|
||||||
|
// n, _, errno := unix.Syscall(unix.SYS_SENDMSG, uintptr(fd), uintptr(unsafe.Pointer(msg)), flags)
|
||||||
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
|
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
|
||||||
var iov [1]Iovec
|
var iov [1]Iovec
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
@@ -394,9 +430,8 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SendmsgBuffers sends a message on a socket to an address using the sendmsg
|
// SendmsgBuffers sends a message on a socket to an address using the sendmsg
|
||||||
// system call. The flags are passed to sendmsg. Any non-control data written
|
// system call. This function is equivalent to SendmsgN, but the non-control
|
||||||
// is gathered from buffers. The function returns the number of bytes written
|
// data is gathered from buffers.
|
||||||
// to the socket.
|
|
||||||
func SendmsgBuffers(fd int, buffers [][]byte, oob []byte, to Sockaddr, flags int) (n int, err error) {
|
func SendmsgBuffers(fd int, buffers [][]byte, oob []byte, to Sockaddr, flags int) (n int, err error) {
|
||||||
iov := make([]Iovec, len(buffers))
|
iov := make([]Iovec, len(buffers))
|
||||||
for i := range buffers {
|
for i := range buffers {
|
||||||
|
|||||||
Reference in New Issue
Block a user