Skip to content

Commit 96fe56a

Browse files
committed
Add support for the send/recvmsg API to the socket module. Patch by David Watson and Heiko Wundram. (Closes #6560)
1 parent 8983729 commit 96fe56a

File tree

7 files changed

+3167
-0
lines changed

7 files changed

+3167
-0
lines changed

Doc/library/socket.rst

+182
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ The module :mod:`socket` exports the following constants and functions:
198198
SOMAXCONN
199199
MSG_*
200200
SOL_*
201+
SCM_*
201202
IPPROTO_*
202203
IPPORT_*
203204
INADDR_*
@@ -511,6 +512,49 @@ The module :mod:`socket` exports the following constants and functions:
511512
Availability: Unix (maybe not all platforms).
512513

513514

515+
..
516+
XXX: Are sendmsg(), recvmsg() and CMSG_*() available on any
517+
non-Unix platforms? The old (obsolete?) 4.2BSD form of the
518+
interface, in which struct msghdr has no msg_control or
519+
msg_controllen members, is not currently supported.
520+
521+
.. function:: CMSG_LEN(length)
522+
523+
Return the total length, without trailing padding, of an ancillary
524+
data item with associated data of the given *length*. This value
525+
can often be used as the buffer size for :meth:`~socket.recvmsg` to
526+
receive a single item of ancillary data, but :rfc:`3542` requires
527+
portable applications to use :func:`CMSG_SPACE` and thus include
528+
space for padding, even when the item will be the last in the
529+
buffer. Raises :exc:`OverflowError` if *length* is outside the
530+
permissible range of values.
531+
532+
Availability: most Unix platforms, possibly others.
533+
534+
.. versionadded:: 3.3
535+
536+
537+
.. function:: CMSG_SPACE(length)
538+
539+
Return the buffer size needed for :meth:`~socket.recvmsg` to
540+
receive an ancillary data item with associated data of the given
541+
*length*, along with any trailing padding. The buffer space needed
542+
to receive multiple items is the sum of the :func:`CMSG_SPACE`
543+
values for their associated data lengths. Raises
544+
:exc:`OverflowError` if *length* is outside the permissible range
545+
of values.
546+
547+
Note that some systems might support ancillary data without
548+
providing this function. Also note that setting the buffer size
549+
using the results of this function may not precisely limit the
550+
amount of ancillary data that can be received, since additional
551+
data may be able to fit into the padding area.
552+
553+
Availability: most Unix platforms, possibly others.
554+
555+
.. versionadded:: 3.3
556+
557+
514558
.. function:: getdefaulttimeout()
515559

516560
Return the default timeout in seconds (float) for new socket objects. A value
@@ -742,6 +786,109 @@ correspond to Unix system calls applicable to sockets.
742786
to zero. (The format of *address* depends on the address family --- see above.)
743787

744788

789+
.. method:: socket.recvmsg(bufsize[, ancbufsize[, flags]])
790+
791+
Receive normal data (up to *bufsize* bytes) and ancillary data from
792+
the socket. The *ancbufsize* argument sets the size in bytes of
793+
the internal buffer used to receive the ancillary data; it defaults
794+
to 0, meaning that no ancillary data will be received. Appropriate
795+
buffer sizes for ancillary data can be calculated using
796+
:func:`CMSG_SPACE` or :func:`CMSG_LEN`, and items which do not fit
797+
into the buffer might be truncated or discarded. The *flags*
798+
argument defaults to 0 and has the same meaning as for
799+
:meth:`recv`.
800+
801+
The return value is a 4-tuple: ``(data, ancdata, msg_flags,
802+
address)``. The *data* item is a :class:`bytes` object holding the
803+
non-ancillary data received. The *ancdata* item is a list of zero
804+
or more tuples ``(cmsg_level, cmsg_type, cmsg_data)`` representing
805+
the ancillary data (control messages) received: *cmsg_level* and
806+
*cmsg_type* are integers specifying the protocol level and
807+
protocol-specific type respectively, and *cmsg_data* is a
808+
:class:`bytes` object holding the associated data. The *msg_flags*
809+
item is the bitwise OR of various flags indicating conditions on
810+
the received message; see your system documentation for details.
811+
If the receiving socket is unconnected, *address* is the address of
812+
the sending socket, if available; otherwise, its value is
813+
unspecified.
814+
815+
On some systems, :meth:`sendmsg` and :meth:`recvmsg` can be used to
816+
pass file descriptors between processes over an :const:`AF_UNIX`
817+
socket. When this facility is used (it is often restricted to
818+
:const:`SOCK_STREAM` sockets), :meth:`recvmsg` will return, in its
819+
ancillary data, items of the form ``(socket.SOL_SOCKET,
820+
socket.SCM_RIGHTS, fds)``, where *fds* is a :class:`bytes` object
821+
representing the new file descriptors as a binary array of the
822+
native C :c:type:`int` type. If :meth:`recvmsg` raises an
823+
exception after the system call returns, it will first attempt to
824+
close any file descriptors received via this mechanism.
825+
826+
Some systems do not indicate the truncated length of ancillary data
827+
items which have been only partially received. If an item appears
828+
to extend beyond the end of the buffer, :meth:`recvmsg` will issue
829+
a :exc:`RuntimeWarning`, and will return the part of it which is
830+
inside the buffer provided it has not been truncated before the
831+
start of its associated data.
832+
833+
On systems which support the :const:`SCM_RIGHTS` mechanism, the
834+
following function will receive up to *maxfds* file descriptors,
835+
returning the message data and a list containing the descriptors
836+
(while ignoring unexpected conditions such as unrelated control
837+
messages being received). See also :meth:`sendmsg`. ::
838+
839+
import socket, array
840+
841+
def recv_fds(sock, msglen, maxfds):
842+
fds = array.array("i") # Array of ints
843+
msg, ancdata, flags, addr = sock.recvmsg(msglen, socket.CMSG_LEN(maxfds * fds.itemsize))
844+
for cmsg_level, cmsg_type, cmsg_data in ancdata:
845+
if (cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS):
846+
# Append data, ignoring any truncated integers at the end.
847+
fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
848+
return msg, list(fds)
849+
850+
Availability: most Unix platforms, possibly others.
851+
852+
.. versionadded:: 3.3
853+
854+
855+
.. method:: socket.recvmsg_into(buffers[, ancbufsize[, flags]])
856+
857+
Receive normal data and ancillary data from the socket, behaving as
858+
:meth:`recvmsg` would, but scatter the non-ancillary data into a
859+
series of buffers instead of returning a new bytes object. The
860+
*buffers* argument must be an iterable of objects that export
861+
writable buffers (e.g. :class:`bytearray` objects); these will be
862+
filled with successive chunks of the non-ancillary data until it
863+
has all been written or there are no more buffers. The operating
864+
system may set a limit (:func:`~os.sysconf` value ``SC_IOV_MAX``)
865+
on the number of buffers that can be used. The *ancbufsize* and
866+
*flags* arguments have the same meaning as for :meth:`recvmsg`.
867+
868+
The return value is a 4-tuple: ``(nbytes, ancdata, msg_flags,
869+
address)``, where *nbytes* is the total number of bytes of
870+
non-ancillary data written into the buffers, and *ancdata*,
871+
*msg_flags* and *address* are the same as for :meth:`recvmsg`.
872+
873+
Example::
874+
875+
>>> import socket
876+
>>> s1, s2 = socket.socketpair()
877+
>>> b1 = bytearray(b'----')
878+
>>> b2 = bytearray(b'0123456789')
879+
>>> b3 = bytearray(b'--------------')
880+
>>> s1.send(b'Mary had a little lamb')
881+
22
882+
>>> s2.recvmsg_into([b1, memoryview(b2)[2:9], b3])
883+
(22, [], 0, None)
884+
>>> [b1, b2, b3]
885+
[bytearray(b'Mary'), bytearray(b'01 had a 9'), bytearray(b'little lamb---')]
886+
887+
Availability: most Unix platforms, possibly others.
888+
889+
.. versionadded:: 3.3
890+
891+
745892
.. method:: socket.recvfrom_into(buffer[, nbytes[, flags]])
746893

747894
Receive data from the socket, writing it into *buffer* instead of creating a
@@ -789,6 +936,41 @@ correspond to Unix system calls applicable to sockets.
789936
above.)
790937

791938

939+
.. method:: socket.sendmsg(buffers[, ancdata[, flags[, address]]])
940+
941+
Send normal and ancillary data to the socket, gathering the
942+
non-ancillary data from a series of buffers and concatenating it
943+
into a single message. The *buffers* argument specifies the
944+
non-ancillary data as an iterable of buffer-compatible objects
945+
(e.g. :class:`bytes` objects); the operating system may set a limit
946+
(:func:`~os.sysconf` value ``SC_IOV_MAX``) on the number of buffers
947+
that can be used. The *ancdata* argument specifies the ancillary
948+
data (control messages) as an iterable of zero or more tuples
949+
``(cmsg_level, cmsg_type, cmsg_data)``, where *cmsg_level* and
950+
*cmsg_type* are integers specifying the protocol level and
951+
protocol-specific type respectively, and *cmsg_data* is a
952+
buffer-compatible object holding the associated data. Note that
953+
some systems (in particular, systems without :func:`CMSG_SPACE`)
954+
might support sending only one control message per call. The
955+
*flags* argument defaults to 0 and has the same meaning as for
956+
:meth:`send`. If *address* is supplied and not ``None``, it sets a
957+
destination address for the message. The return value is the
958+
number of bytes of non-ancillary data sent.
959+
960+
The following function sends the list of file descriptors *fds*
961+
over an :const:`AF_UNIX` socket, on systems which support the
962+
:const:`SCM_RIGHTS` mechanism. See also :meth:`recvmsg`. ::
963+
964+
import socket, array
965+
966+
def send_fds(sock, msg, fds):
967+
return sock.sendmsg([msg], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", fds))])
968+
969+
Availability: most Unix platforms, possibly others.
970+
971+
.. versionadded:: 3.3
972+
973+
792974
.. method:: socket.setblocking(flag)
793975

794976
Set blocking or non-blocking mode of the socket: if *flag* is false, the

Doc/whatsnew/3.3.rst

+12
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,18 @@ signal
212212
* :func:`signal.signal` and :func:`signal.siginterrupt` raise an OSError,
213213
instead of a RuntimeError: OSError has an errno attribute.
214214

215+
socket
216+
------
217+
218+
The :class:`~socket.socket` class now exposes addititonal methods to
219+
process ancillary data when supported by the underlying platform:
220+
221+
* :func:`~socket.socket.sendmsg`
222+
* :func:`~socket.socket.recvmsg`
223+
* :func:`~socket.socket.recvmsg_into`
224+
225+
(Contributed by David Watson in :issue:`6560`, based on an earlier patch
226+
by Heiko Wundram)
215227

216228
ssl
217229
---

Lib/ssl.py

+24
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,14 @@ def sendto(self, data, flags_or_addr, addr=None):
355355
else:
356356
return socket.sendto(self, data, flags_or_addr, addr)
357357

358+
def sendmsg(self, *args, **kwargs):
359+
self._checkClosed()
360+
if self._sslobj:
361+
raise ValueError("sendmsg not allowed on instances of %s" %
362+
self.__class__)
363+
else:
364+
return socket.sendmsg(self, *args, **kwargs)
365+
358366
def sendall(self, data, flags=0):
359367
self._checkClosed()
360368
if self._sslobj:
@@ -413,6 +421,22 @@ def recvfrom_into(self, buffer, nbytes=None, flags=0):
413421
else:
414422
return socket.recvfrom_into(self, buffer, nbytes, flags)
415423

424+
def recvmsg(self, *args, **kwargs):
425+
self._checkClosed()
426+
if self._sslobj:
427+
raise ValueError("recvmsg not allowed on instances of %s" %
428+
self.__class__)
429+
else:
430+
return socket.recvmsg(self, *args, **kwargs)
431+
432+
def recvmsg_into(self, *args, **kwargs):
433+
self._checkClosed()
434+
if self._sslobj:
435+
raise ValueError("recvmsg_into not allowed on instances of %s" %
436+
self.__class__)
437+
else:
438+
return socket.recvmsg_into(self, *args, **kwargs)
439+
416440
def pending(self):
417441
self._checkClosed()
418442
if self._sslobj:

0 commit comments

Comments
 (0)