Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Doc/library/socket.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,13 @@ created. Socket addresses are represented as follows:
- *addr* - Optional bytes-like object specifying the hardware physical
address, whose interpretation depends on the device.

- :const:`AF_QIPCRTR` is a Linux-only socket based interface for communicating
Comment thread
serhiy-storchaka marked this conversation as resolved.
with services running on co-processors in Qualcomm platforms. The address
family is represented as a ``(node, port)`` tuple where the *node* and *port*
are non-negative integers.

.. versionadded:: 3.7

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be 3.8, not 3.7.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!


If you use a hostname in the *host* portion of IPv4/v6 socket address, the
program may show a nondeterministic behavior, as Python uses the first address
returned from the DNS resolution. The socket address will be resolved
Expand Down Expand Up @@ -481,6 +488,13 @@ Constants
:const:`HCI_DATA_DIR` are not available for FreeBSD, NetBSD, or
DragonFlyBSD.

.. data:: AF_QIPCRTR

Constant for Qualcomm's IPC router protocol, used to communicate with
service providing remote processors.

Availability: Linux >= 4.7.

Functions
^^^^^^^^^

Expand Down
41 changes: 41 additions & 0 deletions Lib/test/test_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ def _have_socket_alg():
s.close()
return True

def _have_socket_qipcrtr():
"""Check whether AF_QIPCRTR sockets are supported on this host."""
try:
s = socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM, 0)
except (AttributeError, OSError):
return False
else:
s.close()
return True

def _have_socket_vsock():
"""Check whether AF_VSOCK sockets are supported on this host."""
ret = get_cid() is not None
Expand All @@ -113,6 +123,8 @@ def _is_fd_in_blocking_mode(sock):

HAVE_SOCKET_ALG = _have_socket_alg()

HAVE_SOCKET_QIPCRTR = _have_socket_qipcrtr()

HAVE_SOCKET_VSOCK = _have_socket_vsock()

# Size in bytes of the int type
Expand Down Expand Up @@ -2054,6 +2066,34 @@ def _testSelect(self):
self.data = b'select'
self.cli.sendto(self.data, 0, (HOST, self.port))

@unittest.skipUnless(HAVE_SOCKET_QIPCRTR,
'QIPCRTR sockets required for this test.')
class BasicQIPCRTRTest(unittest.TestCase):

def testCrucialConstants(self):
socket.AF_QIPCRTR

def testCreateSocket(self):
with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
pass

def testUnbound(self):
with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
self.assertEqual(s.getsockname()[1], 0)

def testBindSock(self):
with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
support.bind_port(s, host=s.getsockname()[0])
self.assertNotEqual(s.getsockname()[1], 0)

def testInvalidBindSock(self):
with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
self.assertRaises(OSError, support.bind_port, s, host=-2)

def testAutoBindSock(self):
with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
s.connect((123, 123))
self.assertNotEqual(s.getsockname()[1], 0)

@unittest.skipIf(fcntl is None, "need fcntl")
@unittest.skipUnless(HAVE_SOCKET_VSOCK,
Expand Down Expand Up @@ -5978,6 +6018,7 @@ def test_main():
tests.extend([BasicCANTest, CANTest])
tests.extend([BasicRDSTest, RDSTest])
tests.append(LinuxKernelCryptoAPI)
tests.append(BasicQIPCRTRTest)
tests.extend([
BasicVSOCKTest,
ThreadedVSOCKSocketStreamTest,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Add support for sockets of the AF_QIPCRTR address family, supported by the
Linux kernel. This is used to communicate with services, such as GPS or
radio, running on Qualcomm devices.
51 changes: 49 additions & 2 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ This module provides an interface to Berkeley socket IPC.
Limitations:

- Only AF_INET, AF_INET6 and AF_UNIX address families are supported in a
portable manner, though AF_PACKET, AF_NETLINK and AF_TIPC are supported
under Linux.
portable manner, though AF_PACKET, AF_NETLINK, AF_QIPCRTR and AF_TIPC are
Comment thread
serhiy-storchaka marked this conversation as resolved.
supported under Linux.
- No read/write operations (use sendall/recv or makefile instead).
- Additional restrictions apply on some non-Unix platforms (compensated
for by socket.py).
Expand Down Expand Up @@ -55,6 +55,8 @@ Module interface:
the Ethernet protocol number to be received. For example:
("eth0",0x1234). Optional 3rd,4th,5th elements in the tuple
specify packet-type and ha-type/addr.
- an AF_QIPCRTR socket address is a (node, port) tuple where the
node and port are non-negative integers.
- an AF_TIPC socket address is expressed as
(addr_type, v1, v2, v3 [, scope]); where addr_type can be one of:
TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, and TIPC_ADDR_ID;
Expand Down Expand Up @@ -1293,6 +1295,14 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
}
#endif /* AF_NETLINK */

#if defined(AF_QIPCRTR)
case AF_QIPCRTR:
{
struct sockaddr_qrtr *a = (struct sockaddr_qrtr *) addr;
return Py_BuildValue("II", a->sq_node, a->sq_port);
}
#endif /* AF_QIPCRTR */

#if defined(AF_VSOCK)
case AF_VSOCK:
{
Expand Down Expand Up @@ -1668,6 +1678,30 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
}
#endif /* AF_NETLINK */

#if defined(AF_QIPCRTR)
case AF_QIPCRTR:
{
struct sockaddr_qrtr* addr;
unsigned int node, port;
addr = (struct sockaddr_qrtr *)addr_ret;
if (!PyTuple_Check(args)) {
PyErr_Format(
PyExc_TypeError,
"getsockaddrarg: "
"AF_QIPCRTR address must be tuple, not %.500s",
Py_TYPE(args)->tp_name);
return 0;
}
if (!PyArg_ParseTuple(args, "II:getsockaddrarg", &node, &port))
return 0;
addr->sq_family = AF_QIPCRTR;
addr->sq_node = node;
addr->sq_port = port;
*len_ret = sizeof(*addr);
return 1;
}
#endif /* AF_QIPCRTR */

#if defined(AF_VSOCK)
case AF_VSOCK:
{
Expand Down Expand Up @@ -2263,6 +2297,14 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
}
#endif /* AF_NETLINK */

#if defined(AF_QIPCRTR)
case AF_QIPCRTR:
{
*len_ret = sizeof (struct sockaddr_qrtr);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the extra space after sizeof

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, I'm ignoring this to follow the coding style in this function.

return 1;
}
#endif /* AF_QIPCRTR */

#if defined(AF_VSOCK)
case AF_VSOCK:
{
Expand Down Expand Up @@ -6983,6 +7025,11 @@ PyInit__socket(void)
#endif
#endif /* AF_NETLINK */

#ifdef AF_QIPCRTR
/* Qualcomm IPCROUTER */
PyModule_AddIntMacro(m, AF_QIPCRTR);
#endif

#ifdef AF_VSOCK
PyModule_AddIntConstant(m, "AF_VSOCK", AF_VSOCK);
PyModule_AddIntConstant(m, "SO_VM_SOCKETS_BUFFER_SIZE", 0);
Expand Down
12 changes: 12 additions & 0 deletions Modules/socketmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ typedef int socklen_t;
# undef AF_NETLINK
#endif

#ifdef HAVE_LINUX_QRTR_H
# ifdef HAVE_ASM_TYPES_H
# include <asm/types.h>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You must add the new addr type to the large sock_addr_t union.

# endif
# include <linux/qrtr.h>
#else
# undef AF_QIPCRTR
#endif

#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
Expand Down Expand Up @@ -203,6 +212,9 @@ typedef union sock_addr {
#ifdef HAVE_SOCKADDR_ALG
struct sockaddr_alg alg;
#endif
#ifdef AF_QIPCRTR
struct sockaddr_qrtr sq;
#endif
#ifdef AF_VSOCK
struct sockaddr_vm vm;
#endif
Expand Down
22 changes: 22 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -8023,6 +8023,28 @@ fi
done


# On Linux, qrtr.h requires asm/types.h
for ac_header in linux/qrtr.h
do :
ac_fn_c_check_header_compile "$LINENO" "linux/qrtr.h" "ac_cv_header_linux_qrtr_h" "
#ifdef HAVE_ASM_TYPES_H
#include <asm/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

"
if test "x$ac_cv_header_linux_qrtr_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LINUX_QRTR_H 1
_ACEOF

fi

done


for ac_header in linux/vm_sockets.h
do :
ac_fn_c_check_header_compile "$LINENO" "linux/vm_sockets.h" "ac_cv_header_linux_vm_sockets_h" "
Expand Down
10 changes: 10 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2112,6 +2112,16 @@ AC_CHECK_HEADERS(linux/netlink.h,,,[
#endif
])

# On Linux, qrtr.h requires asm/types.h
AC_CHECK_HEADERS(linux/qrtr.h,,,[
#ifdef HAVE_ASM_TYPES_H
#include <asm/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
])

AC_CHECK_HEADERS(linux/vm_sockets.h,,,[
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
Expand Down
3 changes: 3 additions & 0 deletions pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,9 @@
/* Define to 1 if you have the <linux/netlink.h> header file. */
#undef HAVE_LINUX_NETLINK_H

/* Define to 1 if you have the <linux/qrtr.h> header file. */
#undef HAVE_LINUX_QRTR_H

/* Define to 1 if you have the <linux/random.h> header file. */
#undef HAVE_LINUX_RANDOM_H

Expand Down