.. versionadded:: 2.5
AF_NETLINK sockets are represented as pairs ``pid, groups``.
+.. versionadded:: 2.6
+ Linux-only support for TIPC is also available using the :const:`AF_TIPC`
+ address family. TIPC is an open, non-IP based networked protocol designed
+ for use in clustered computer environments. Addresses are represented by a
+ tuple, and the fields depend on the address type. The general tuple form is
+ ``(addr_type, v1, v2, v3 [, scope])``, where:
+
+ - *addr_type* is one of TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, or
+ TIPC_ADDR_ID.
+ - *scope* is one of TIPC_ZONE_SCOPE, TIPC_CLUSTER_SCOPE, and
+ TIPC_NODE_SCOPE.
+ - If *addr_type* is TIPC_ADDR_NAME, then *v1* is the server type, *v2* is
+ the port identifier, and *v3* should be 0.
+
+ If *addr_type* is TIPC_ADDR_NAMESEQ, then *v1* is the server type, *v2*
+ is the lower port number, and *v3* is the upper port number.
+
+ If *addr_type* is TIPC_ADDR_ID, then *v1* is the node, *v2* is the
+ reference, and *v3* should be set to 0.
+
+
All errors raise exceptions. The normal exceptions for invalid argument types
and out-of-memory conditions can be raised; errors related to socket or address
semantics raise the error :exc:`socket.error`.
.. versionadded:: 2.6
+.. data:: TIPC_*
+
+ TIPC related constants, matching the ones exported by the C socket API. See
+ the TIPC documentation for more information.
+
+ .. versionadded:: 2.6
.. data:: has_ipv6
buf = buffer(MSG)
self.serv_conn.send(buf)
+
+TIPC_STYPE = 2000
+TIPC_LOWER = 200
+TIPC_UPPER = 210
+
+def isTipcAvailable():
+ """Check if the TIPC module is loaded
+
+ The TIPC module is not loaded automatically on Ubuntu and probably
+ other Linux distros.
+ """
+ if not hasattr(socket, "AF_TIPC"):
+ return False
+ if not os.path.isfile("/proc/modules"):
+ return False
+ with open("/proc/modules") as f:
+ for line in f:
+ if line.startswith("tipc "):
+ return True
+ if test_support.debug:
+ print "TIPC module is not loaded, please 'sudo modprobe tipc'"
+ return False
+
+class TIPCTest (unittest.TestCase):
+ def testRDM(self):
+ srv = socket.socket(socket.AF_TIPC, socket.SOCK_RDM)
+ cli = socket.socket(socket.AF_TIPC, socket.SOCK_RDM)
+
+ srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ srvaddr = (socket.TIPC_ADDR_NAMESEQ, TIPC_STYPE,
+ TIPC_LOWER, TIPC_UPPER)
+ srv.bind(srvaddr)
+
+ sendaddr = (socket.TIPC_ADDR_NAME, TIPC_STYPE,
+ TIPC_LOWER + (TIPC_UPPER - TIPC_LOWER) / 2, 0)
+ cli.sendto(MSG, sendaddr)
+
+ msg, recvaddr = srv.recvfrom(1024)
+
+ self.assertEqual(cli.getsockname(), recvaddr)
+ self.assertEqual(msg, MSG)
+
+
+class TIPCThreadableTest (unittest.TestCase, ThreadableTest):
+ def __init__(self, methodName = 'runTest'):
+ unittest.TestCase.__init__(self, methodName = methodName)
+ ThreadableTest.__init__(self)
+
+ def setUp(self):
+ self.srv = socket.socket(socket.AF_TIPC, socket.SOCK_STREAM)
+ self.srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ srvaddr = (socket.TIPC_ADDR_NAMESEQ, TIPC_STYPE,
+ TIPC_LOWER, TIPC_UPPER)
+ self.srv.bind(srvaddr)
+ self.srv.listen(5)
+ self.serverExplicitReady()
+ self.conn, self.connaddr = self.srv.accept()
+
+ def clientSetUp(self):
+ # The is a hittable race between serverExplicitReady() and the
+ # accept() call; sleep a little while to avoid it, otherwise
+ # we could get an exception
+ time.sleep(0.1)
+ self.cli = socket.socket(socket.AF_TIPC, socket.SOCK_STREAM)
+ addr = (socket.TIPC_ADDR_NAME, TIPC_STYPE,
+ TIPC_LOWER + (TIPC_UPPER - TIPC_LOWER) / 2, 0)
+ self.cli.connect(addr)
+ self.cliaddr = self.cli.getsockname()
+
+ def testStream(self):
+ msg = self.conn.recv(1024)
+ self.assertEqual(msg, MSG)
+ self.assertEqual(self.cliaddr, self.connaddr)
+
+ def _testStream(self):
+ self.cli.send(MSG)
+ self.cli.close()
+
+
def test_main():
tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest,
TestExceptions, BufferIOTest, BasicTCPTest2]
tests.append(BasicSocketPairTest)
if sys.platform == 'linux2':
tests.append(TestLinuxAbstractNamespace)
+ if isTipcAvailable():
+ tests.append(TIPCTest)
+ tests.append(TIPCThreadableTest)
thread_info = test_support.threading_setup()
test_support.run_unittest(*tests)
Limitations:
- Only AF_INET, AF_INET6 and AF_UNIX address families are supported in a
- portable manner, though AF_PACKET and AF_NETLINK are supported under Linux.
+ portable manner, though AF_PACKET, AF_NETLINK and AF_TIPC are 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).
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_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;
+ and scope can be one of:
+ TIPC_ZONE_SCOPE, TIPC_CLUSTER_SCOPE, and TIPC_NODE_SCOPE.
+ The meaning of v1, v2 and v3 depends on the value of addr_type:
+ if addr_type is TIPC_ADDR_NAME:
+ v1 is the server type
+ v2 is the port identifier
+ v3 is ignored
+ if addr_type is TIPC_ADDR_NAMESEQ:
+ v1 is the server type
+ v2 is the lower port number
+ v3 is the upper port number
+ if addr_type is TIPC_ADDR_ID:
+ v1 is the node
+ v2 is the ref
+ v3 is ignored
+
Local naming conventions:
}
#endif
+#ifdef HAVE_LINUX_TIPC_H
+ case AF_TIPC:
+ {
+ struct sockaddr_tipc *a = (struct sockaddr_tipc *) addr;
+ if (a->addrtype == TIPC_ADDR_NAMESEQ) {
+ return Py_BuildValue("IIIII",
+ a->addrtype,
+ a->addr.nameseq.type,
+ a->addr.nameseq.lower,
+ a->addr.nameseq.upper,
+ a->scope);
+ } else if (a->addrtype == TIPC_ADDR_NAME) {
+ return Py_BuildValue("IIIII",
+ a->addrtype,
+ a->addr.name.name.type,
+ a->addr.name.name.instance,
+ a->addr.name.name.instance,
+ a->scope);
+ } else if (a->addrtype == TIPC_ADDR_ID) {
+ return Py_BuildValue("IIIII",
+ a->addrtype,
+ a->addr.id.node,
+ a->addr.id.ref,
+ 0,
+ a->scope);
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "Invalid address type");
+ return NULL;
+ }
+ }
+#endif
+
/* More cases here... */
default:
}
#endif
+#ifdef HAVE_LINUX_TIPC_H
+ case AF_TIPC:
+ {
+ unsigned int atype, v1, v2, v3;
+ unsigned int scope = TIPC_CLUSTER_SCOPE;
+ struct sockaddr_tipc *addr;
+
+ if (!PyTuple_Check(args)) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "getsockaddrarg: "
+ "AF_TIPC address must be tuple, not %.500s",
+ Py_TYPE(args)->tp_name);
+ return 0;
+ }
+
+ if (!PyArg_ParseTuple(args,
+ "IIII|I;Invalid TIPC address format",
+ &atype, &v1, &v2, &v3, &scope))
+ return 0;
+
+ addr = (struct sockaddr_tipc *) addr_ret;
+ memset(addr, 0, sizeof(struct sockaddr_tipc));
+
+ addr->family = AF_TIPC;
+ addr->scope = scope;
+ addr->addrtype = atype;
+
+ if (atype == TIPC_ADDR_NAMESEQ) {
+ addr->addr.nameseq.type = v1;
+ addr->addr.nameseq.lower = v2;
+ addr->addr.nameseq.upper = v3;
+ } else if (atype == TIPC_ADDR_NAME) {
+ addr->addr.name.name.type = v1;
+ addr->addr.name.name.instance = v2;
+ } else if (atype == TIPC_ADDR_ID) {
+ addr->addr.id.node = v1;
+ addr->addr.id.ref = v2;
+ } else {
+ /* Shouldn't happen */
+ PyErr_SetString(PyExc_TypeError, "Invalid address type");
+ return 0;
+ }
+
+ *len_ret = sizeof(*addr);
+
+ return 1;
+ }
+#endif
+
/* More cases here... */
default:
}
#endif
+#ifdef HAVE_LINUX_TIPC_H
+ case AF_TIPC:
+ {
+ *len_ret = sizeof (struct sockaddr_tipc);
+ return 1;
+ }
+#endif
+
/* More cases here... */
default:
PyModule_AddIntConstant(m, "PACKET_FASTROUTE", PACKET_FASTROUTE);
#endif
+#ifdef HAVE_LINUX_TIPC_H
+ PyModule_AddIntConstant(m, "AF_TIPC", AF_TIPC);
+
+ /* for addresses */
+ PyModule_AddIntConstant(m, "TIPC_ADDR_NAMESEQ", TIPC_ADDR_NAMESEQ);
+ PyModule_AddIntConstant(m, "TIPC_ADDR_NAME", TIPC_ADDR_NAME);
+ PyModule_AddIntConstant(m, "TIPC_ADDR_ID", TIPC_ADDR_ID);
+
+ PyModule_AddIntConstant(m, "TIPC_ZONE_SCOPE", TIPC_ZONE_SCOPE);
+ PyModule_AddIntConstant(m, "TIPC_CLUSTER_SCOPE", TIPC_CLUSTER_SCOPE);
+ PyModule_AddIntConstant(m, "TIPC_NODE_SCOPE", TIPC_NODE_SCOPE);
+
+ /* for setsockopt() */
+ PyModule_AddIntConstant(m, "SOL_TIPC", SOL_TIPC);
+ PyModule_AddIntConstant(m, "TIPC_IMPORTANCE", TIPC_IMPORTANCE);
+ PyModule_AddIntConstant(m, "TIPC_SRC_DROPPABLE", TIPC_SRC_DROPPABLE);
+ PyModule_AddIntConstant(m, "TIPC_DEST_DROPPABLE",
+ TIPC_DEST_DROPPABLE);
+ PyModule_AddIntConstant(m, "TIPC_CONN_TIMEOUT", TIPC_CONN_TIMEOUT);
+
+ PyModule_AddIntConstant(m, "TIPC_LOW_IMPORTANCE",
+ TIPC_LOW_IMPORTANCE);
+ PyModule_AddIntConstant(m, "TIPC_MEDIUM_IMPORTANCE",
+ TIPC_MEDIUM_IMPORTANCE);
+ PyModule_AddIntConstant(m, "TIPC_HIGH_IMPORTANCE",
+ TIPC_HIGH_IMPORTANCE);
+ PyModule_AddIntConstant(m, "TIPC_CRITICAL_IMPORTANCE",
+ TIPC_CRITICAL_IMPORTANCE);
+
+ /* for subscriptions */
+ PyModule_AddIntConstant(m, "TIPC_SUB_PORTS", TIPC_SUB_PORTS);
+ PyModule_AddIntConstant(m, "TIPC_SUB_SERVICE", TIPC_SUB_SERVICE);
+ PyModule_AddIntConstant(m, "TIPC_SUB_CANCEL", TIPC_SUB_CANCEL);
+ PyModule_AddIntConstant(m, "TIPC_WAIT_FOREVER", TIPC_WAIT_FOREVER);
+ PyModule_AddIntConstant(m, "TIPC_PUBLISHED", TIPC_PUBLISHED);
+ PyModule_AddIntConstant(m, "TIPC_WITHDRAWN", TIPC_WITHDRAWN);
+ PyModule_AddIntConstant(m, "TIPC_SUBSCR_TIMEOUT", TIPC_SUBSCR_TIMEOUT);
+ PyModule_AddIntConstant(m, "TIPC_CFG_SRV", TIPC_CFG_SRV);
+ PyModule_AddIntConstant(m, "TIPC_TOP_SRV", TIPC_TOP_SRV);
+#endif
+
/* Socket types */
PyModule_AddIntConstant(m, "SOCK_STREAM", SOCK_STREAM);
PyModule_AddIntConstant(m, "SOCK_DGRAM", SOCK_DGRAM);