Adds wrappers for recvmsg()
and sendmsg()
to ext/sockets.
The module ext/sockets, a wrapper around the sockets API, does not include support to recvmsg()
and sendmsg()
. This RFC addresses this shortcoming.
The sendmsg()
and recvmsg()
functions are the most general I/O functions. Their signatures:
ssize_t recvmsg(int socket, struct msghdr *message, int flags); ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); struct msghdr { void *msg_name; /* optional address */ socklen_t msg_namelen; /* size of address */ struct iovec *msg_iov; /* scatter/gather array */ size_t msg_iovlen; /* # elements in msg_iov */ void *msg_control; /* ancillary data, see below */ size_t msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ }; struct iovec { /* Scatter/gather array items */ void *iov_base; /* Starting address */ size_t iov_len; /* Number of bytes to transfer */ }; struct cmsghdr { socklen_t cmsg_len; /* data byte count, including header */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type */ /* followed by unsigned char cmsg_data[]; */ };
A thorough discussion is not appropriate here. For PHP purposes, what matters is that these functions allow attaching and retrieving some sort of metadata when sending or receiving data, respectively. The type of the metadata units is specified by the pair cmsg_level/cmsg_type.
Some functionality is only available by using these functions. It can also save us from polluting socket_sendto()
and socket_recvfrom()
with even more address family specific options. It was already an error to add the $port
parameter to what should be a socket/address type agnostic interface. See pull request #220.
Three new functions are added:
int socket_recvmsg(resource $socket, /* in/out */ array &$msghdr, int $flags); int socket_sendmsg(resource $socket, array $msghdr, int $flags); int socket_cmsg_space(int $level, int $type);
The last function is analogous to the CMSG_SPACE
macro. It's used to calculate the size of the buffer that should be allocated for receiving the ancillary data. See below.
The arrays match the native structures closely, except prefixes are dropped (for instance, if the native field is named msg_flags
, the PHP array will include an entry with key 'flags'). Fields that indicate array or string length are dropped, as they are unnecessary in PHP. The version of msghdr passed to socket_recvmsg
also differs in that 1) it has no control
element, only a controllen
(hopefully calculated with socket_cmsg_space
), as the control
buffer is allocated by PHP and 2) it has a buffer_size
element instead of a iov
array. PHP allocates a single struct iovec
to receive the data.
The following message types are supported:
The functions socket_set_option()
and socket_get_option()
were also changed to allow sticking the IPv6 options. For more information on this see RFC 3542.
See the tests. The branch includes these:
This includes these tests:
The branch is available on Github. It should not work on Windows yet.