--- Python-3.5.0a3/Doc/library/socket.rst 2015/04/06 16:05:48 1.1 +++ Python-3.5.0a3/Doc/library/socket.rst 2015/04/06 16:08:50 @@ -109,10 +109,24 @@ - Certain other address families (:const:`AF_BLUETOOTH`, :const:`AF_PACKET`, :const:`AF_CAN`) support specific representations. .. XXX document them! +.. versionadded:: 3.5 + Linux-only support for IUCV is also available using the :const:`AF_IUCV` + address family on s390x. IUCV is a non-IP based network protocol designed + for virtual-machine to virtual-machine communication. Addresses are represented + by a tuple. The form of the tuple is + ``(node, userid, name)``, where: + + - *node* is the name of the z/VM system upon which the partner is running. Currenty, + this is ignored and only intra-z/VM communication is supported by the kernel. + - *userid* is the name of the virtual machine to communicate with. If left as blanks, + then it defaults to the virtual machine in which the program is running. + - *name* is the name of the application end point running within the virtual machine. + Multiple applications may be running and using `AF_IUCV`. + For IPv4 addresses, two special forms are accepted instead of a host address: the empty string represents :const:`INADDR_ANY`, and the string ``''`` represents :const:`INADDR_BROADCAST`. This behavior is not compatible with IPv6, therefore, you may want to avoid these if you intend to support IPv6 with your Python programs. --- Python-3.5.0a3/Modules/socketmodule.c 2015/04/06 16:05:48 1.1 +++ Python-3.5.0a3/Modules/socketmodule.c 2015/04/06 16:51:04 @@ -5,12 +5,12 @@ 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_TIPC, and AF_IUCV 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). Module interface: @@ -72,10 +72,15 @@ if addr_type is TIPC_ADDR_ID: v1 is the node v2 is the ref v3 is ignored +- an AF_IUCV address is expressed as + (node, user, name) + - node: Name of z/VM system (default NULL) [1-8 char] + - user: User ID to connect to on that node [1-8 char] + - name: : Name of application end point running within user [1-8 char] Local naming conventions: - names starting with sock_ are socket object methods - names starting with socket_ are module-level functions @@ -262,10 +267,14 @@ /* Generic socket object definitions and includes */ #define PySocket_BUILDING_SOCKET #include "socketmodule.h" +#ifdef AF_IUCV +#include +#endif + /* Addressing includes */ #ifndef MS_WINDOWS /* Non-MS WINDOWS includes */ @@ -988,10 +997,21 @@ bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); return PyUnicode_FromString(buf); } #endif +#ifdef AF_IUCV +/* Support routine to strip trailing blanks for a string */ +static __inline__ void +strip(char *var, size_t lVar) +{ + int i; + + for (i = lVar - 2; (isspace(var[i]) && (i >= 0)); i--); + var[++i] = 0; +} +#endif /* Create an object representing the given socket address, suitable for passing it back to bind(), connect() etc. The family field of the sockaddr structure is inspected to determine what kind of address it really is. */ @@ -1214,10 +1234,29 @@ "Invalid address type"); return 0; } #endif + +#ifdef AF_IUCV + case AF_IUCV : + { + struct sockaddr_iucv *a = (struct sockaddr_iucv *) addr; + char node[9], user[9], name[9]; + + node[8] = user[8] = name[8] = 0; + memcpy(node, a->siucv_nodeid, sizeof(a->siucv_nodeid)); + memcpy(user, a->siucv_user_id, sizeof(a->siucv_user_id)); + memcpy(name, a->siucv_name, sizeof(a->siucv_name)); + strip(node, sizeof(node)); + strip(user, sizeof(user)); + strip(name, sizeof(name)); + + return Py_BuildValue("sss", &node, &user, &name); + } +#endif + /* More cases here... */ default: /* If we don't know the address family, don't raise an exception -- return it as an (int, bytes) tuple. */ @@ -1777,17 +1816,72 @@ *len_ret = sizeof(*addr); return 1; } #endif + default: PyErr_SetString(PyExc_OSError, "getsockaddrarg: unsupported PF_SYSTEM protocol"); return 0; } #endif +#ifdef AF_IUCV + case AF_IUCV: + { + char *node, *user, *name; +#ifdef PY_SSIZE_T_CLEAN + Py_ssize_t lNode, lUser, lName; +#else + int lNode, lUser, lName; +#endif + struct sockaddr_iucv *addr; + + if (!PyTuple_Check(args)) { + PyErr_Format( + PyExc_TypeError, + "getsockaddrarg: " + "AF_IUCV address must be tuple, not %.500s", + Py_TYPE(args)->tp_name); + return 0; + } + + if (!PyArg_ParseTuple(args, "s#s#s#", + &node, &lNode, + &user, &lUser, + &name, &lName)) + return 0; + + addr = (struct sockaddr_iucv *) addr_ret; + memset(addr, 0, sizeof(struct sockaddr_iucv)); + lNode = MIN(lNode, sizeof(addr->siucv_nodeid)); + lUser = MIN(lUser, sizeof(addr->siucv_user_id)); + lName = MIN(lName, sizeof(addr->siucv_name)); + + addr->siucv_family = AF_IUCV; + memset(addr->siucv_nodeid, ' ', sizeof(addr->siucv_nodeid)); + memset(addr->siucv_user_id, ' ', sizeof(addr->siucv_user_id)); + memset(addr->siucv_name, ' ', sizeof(addr->siucv_name)); + memcpy(addr->siucv_nodeid, node, lNode); + memcpy(addr->siucv_user_id, user, lUser); + memcpy(addr->siucv_name, name, lName); + if (addr->siucv_user_id[0] == ' ') { + PyErr_SetString(PyExc_ValueError, "Missing z/VM user name"); + return 0; + } + if (addr->siucv_name[0] == ' ') { + PyErr_SetString(PyExc_ValueError, "Missing application name"); + return 0; + } + + *len_ret = sizeof(*addr); + + return 1; + } +#endif + /* More cases here... */ default: PyErr_SetString(PyExc_OSError, "getsockaddrarg: bad family"); return 0; @@ -1905,10 +1999,18 @@ "unknown PF_SYSTEM protocol"); return 0; } #endif +#ifdef AF_IUCV + case AF_IUCV: + { + *len_ret = sizeof (struct sockaddr_iucv); + return 1; + } +#endif + /* More cases here... */ default: PyErr_SetString(PyExc_OSError, "getsockaddrlen: bad family"); return 0; @@ -6263,10 +6365,14 @@ PyModule_AddIntMacro(m, TIPC_SUBSCR_TIMEOUT); PyModule_AddIntMacro(m, TIPC_CFG_SRV); PyModule_AddIntMacro(m, TIPC_TOP_SRV); #endif +#ifdef AF_IUCV + PyModule_AddIntConstant(m, "AF_IUCV", AF_IUCV); +#endif + /* Socket types */ PyModule_AddIntMacro(m, SOCK_STREAM); PyModule_AddIntMacro(m, SOCK_DGRAM); /* We have incomplete socket support. */ PyModule_AddIntMacro(m, SOCK_RAW); --- Python-3.5.0a3/Lib/test/test_socket.py 2015/04/06 16:05:48 1.1 +++ Python-3.5.0a3/Lib/test/test_socket.py 2015/04/06 17:10:45 @@ -5278,10 +5278,75 @@ Test the sendfile() implementation of socket.sendfile(). """ def meth_from_sock(self, sock): return getattr(sock, "_sendfile_use_sendfile") +def isIUCVAvailable(): + """Check if this platform supports IUCV + + """ + if not hasattr(socket, "AF_IUCV"): + return False + if not os.path.isfile("/proc/modules"): + return False + with open("/proc/modules") as f: + for line in f: + if line.startswith("af_iucv "): + return True + return False + +def getIUCVTarget(): + """Extract my z/VM user id from /proc/sysinfo + + """ + with open("/proc/sysinfo") as f: + for line in f: + if line.startswith("VM00 Name:"): + return line[22:].strip() + +@unittest.skipUnless(isIUCVAvailable(), + "Platform does not support AF_IUCV - ignoring") +class IUCVThreadableTest(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_IUCV, socket.SOCK_STREAM) + print(self.srv) + self.srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + userid = getIUCVTarget() + srvaddr = ("", userid, "SELF") + self.srv.bind(srvaddr) + self.srv.listen(5) + self.serverExplicitReady() + self.conn, self.connaddr = self.srv.accept() + self.addCleanup(self.conn.close) + self.addCleanup(self.srv.close) + + 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_IUCV, socket.SOCK_STREAM) + print(self.cli) + userid = getIUCVTarget() + addr = ("", userid, "SELF") + 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, BasicUDPTest, UDPTimeoutTest ] @@ -5333,10 +5398,11 @@ InterruptedSendTimeoutTest, TestSocketSharing, SendfileUsingSendTest, SendfileUsingSendfileTest, ]) + tests.extend([IUCVThreadableTest]) thread_info = support.threading_setup() support.run_unittest(*tests) support.threading_cleanup(*thread_info) --- Python-3.5.0a3/Lib/plat-linux/IN.py 2015/04/06 16:05:48 1.1 +++ Python-3.5.0a3/Lib/plat-linux/IN.py 2015/04/06 16:25:09 @@ -383,11 +383,12 @@ PF_SNA = 22 PF_IRDA = 23 PF_PPPOX = 24 PF_WANPIPE = 25 PF_BLUETOOTH = 31 -PF_MAX = 32 +PF_IUCV = 32 +PF_MAX = 33 AF_UNSPEC = PF_UNSPEC AF_LOCAL = PF_LOCAL AF_UNIX = PF_UNIX AF_FILE = PF_FILE AF_INET = PF_INET @@ -413,10 +414,11 @@ AF_SNA = PF_SNA AF_IRDA = PF_IRDA AF_PPPOX = PF_PPPOX AF_WANPIPE = PF_WANPIPE AF_BLUETOOTH = PF_BLUETOOTH +AF_IUCV = PF_IUCV AF_MAX = PF_MAX SOL_RAW = 255 SOL_DECNET = 261 SOL_X25 = 262 SOL_PACKET = 263