[Python-checkins] cpython (merge default -> default): Merge heads

serhiy.storchaka python-checkins at python.org
Sun Nov 10 20:06:14 CET 2013


http://hg.python.org/cpython/rev/80aa6a1e38e7
changeset:   87039:80aa6a1e38e7
parent:      87038:d2cc6254d399
parent:      87037:466549b1cad8
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Sun Nov 10 21:05:38 2013 +0200
summary:
  Merge heads

files:
  Doc/library/socket.rst  |    4 +-
  Lib/test/test_socket.py |   16 ++++
  Modules/socketmodule.c  |  112 +++++++++++++++++++++++++++-
  3 files changed, 128 insertions(+), 4 deletions(-)


diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -594,7 +594,7 @@
    both the value of *address_family* and the underlying implementation of
    :c:func:`inet_pton`.
 
-   Availability: Unix (maybe not all platforms).
+   Availability: Unix (maybe not all platforms), Windows.
 
 
 .. function:: inet_ntop(address_family, packed_ip)
@@ -610,7 +610,7 @@
    specified address family, :exc:`ValueError` will be raised.  A
    :exc:`OSError` is raised for errors from the call to :func:`inet_ntop`.
 
-   Availability: Unix (maybe not all platforms).
+   Availability: Unix (maybe not all platforms), Windows.
 
 
 ..
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -980,6 +980,14 @@
                 return
         except ImportError:
             return
+
+        if sys.platform == "win32":
+            try:
+                inet_pton(AF_INET6, '::')
+            except OSError as e:
+                if e.winerror == 10022:
+                    return # IPv6 might not be installed on this PC
+
         f = lambda a: inet_pton(AF_INET6, a)
         assertInvalid = lambda a: self.assertRaises(
             (OSError, ValueError), f, a
@@ -1058,6 +1066,14 @@
                 return
         except ImportError:
             return
+
+        if sys.platform == "win32":
+            try:
+                inet_ntop(AF_INET6, b'\x00' * 16)
+            except OSError as e:
+                if e.winerror == 10022:
+                    return # IPv6 might not be installed on this PC
+
         f = lambda a: inet_ntop(AF_INET6, a)
         assertInvalid = lambda a: self.assertRaises(
             (OSError, ValueError), f, a
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -5023,7 +5023,7 @@
     return PyUnicode_FromString(inet_ntoa(packed_addr));
 }
 
-#ifdef HAVE_INET_PTON
+#if defined(HAVE_INET_PTON) || defined(MS_WINDOWS)
 
 PyDoc_STRVAR(inet_pton_doc,
 "inet_pton(af, ip) -> packed IP address string\n\
@@ -5031,6 +5031,10 @@
 Convert an IP address from string format to a packed string suitable\n\
 for use with low-level network functions.");
 
+#endif
+
+#ifdef HAVE_INET_PTON
+
 static PyObject *
 socket_inet_pton(PyObject *self, PyObject *args)
 {
@@ -5075,12 +5079,52 @@
         return NULL;
     }
 }
+#elif defined(MS_WINDOWS)
+
+static PyObject *
+socket_inet_pton(PyObject *self, PyObject *args)
+{
+    int af;
+    char* ip;
+    struct sockaddr_in6 addr;
+    INT ret, size;
+
+    if (!PyArg_ParseTuple(args, "is:inet_pton", &af, &ip)) {
+        return NULL;
+    }
+
+    size = sizeof(addr); 
+    ret = WSAStringToAddressA(ip, af, NULL, (LPSOCKADDR)&addr, &size);
+
+    if (ret) {
+        PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
+        return NULL;
+    } else if(af == AF_INET) {
+        struct sockaddr_in *addr4 = (struct sockaddr_in*)&addr;
+        return PyBytes_FromStringAndSize((const char *)&(addr4->sin_addr), 
+                                         sizeof(addr4->sin_addr));
+    } else if (af == AF_INET6) {
+        return PyBytes_FromStringAndSize((const char *)&(addr.sin6_addr), 
+                                          sizeof(addr.sin6_addr));
+    } else {
+        PyErr_SetString(PyExc_OSError, "unknown address family");
+        return NULL;
+    }
+}
+
+#endif
+
+#if defined(HAVE_INET_PTON) || defined(MS_WINDOWS)
 
 PyDoc_STRVAR(inet_ntop_doc,
 "inet_ntop(af, packed_ip) -> string formatted IP address\n\
 \n\
 Convert a packed IP address of the given family to string format.");
 
+#endif
+
+
+#ifdef HAVE_INET_PTON
 static PyObject *
 socket_inet_ntop(PyObject *self, PyObject *args)
 {
@@ -5134,6 +5178,70 @@
     return NULL;
 }
 
+#elif defined(MS_WINDOWS)
+
+static PyObject *
+socket_inet_ntop(PyObject *self, PyObject *args)
+{
+    int af;
+    char* packed;
+    int len;
+    struct sockaddr_in6 addr;
+    DWORD addrlen, ret, retlen;
+#ifdef ENABLE_IPV6
+    char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1];
+#else
+    char ip[INET_ADDRSTRLEN + 1];
+#endif
+
+    /* Guarantee NUL-termination for PyUnicode_FromString() below */
+    memset((void *) &ip[0], '\0', sizeof(ip));
+
+    if (!PyArg_ParseTuple(args, "iy#:inet_ntop", &af, &packed, &len)) {
+        return NULL;
+    }
+
+    if (af == AF_INET) {
+        struct sockaddr_in * addr4 = (struct sockaddr_in *)&addr;
+
+        if (len != sizeof(struct in_addr)) {
+            PyErr_SetString(PyExc_ValueError,
+                "invalid length of packed IP address string");
+            return NULL;
+        }
+        memset(addr4, 0, sizeof(struct sockaddr_in));
+        addr4->sin_family = AF_INET;
+        memcpy(&(addr4->sin_addr), packed, sizeof(addr4->sin_addr));
+        addrlen = sizeof(struct sockaddr_in);
+    } else if (af == AF_INET6) {
+        if (len != sizeof(struct in6_addr)) {
+            PyErr_SetString(PyExc_ValueError,
+                "invalid length of packed IP address string");
+            return NULL;
+        }
+
+        memset(&addr, 0, sizeof(addr));
+        addr.sin6_family = AF_INET6;
+        memcpy(&(addr.sin6_addr), packed, sizeof(addr.sin6_addr));
+        addrlen = sizeof(addr);
+    } else {
+        PyErr_Format(PyExc_ValueError,
+            "unknown address family %d", af);
+        return NULL;
+    }
+
+    retlen = sizeof(ip);
+    ret = WSAAddressToStringA((struct sockaddr*)&addr, addrlen, NULL, 
+                              ip, &retlen);
+
+    if (ret) {
+        PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
+        return NULL;
+    } else {
+        return PyUnicode_FromString(ip);
+    }
+}
+
 #endif /* HAVE_INET_PTON */
 
 /* Python interface to getaddrinfo(host, port). */
@@ -5600,7 +5708,7 @@
      METH_VARARGS, inet_aton_doc},
     {"inet_ntoa",               socket_inet_ntoa,
      METH_VARARGS, inet_ntoa_doc},
-#ifdef HAVE_INET_PTON
+#if defined(HAVE_INET_PTON) || defined(MS_WINDOWS)
     {"inet_pton",               socket_inet_pton,
      METH_VARARGS, inet_pton_doc},
     {"inet_ntop",               socket_inet_ntop,

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list