]> granicus.if.org Git - python/commitdiff
Added socket.getservbyport(), and make its second argument and that of
authorBarry Warsaw <barry@python.org>
Mon, 28 Jun 2004 00:50:43 +0000 (00:50 +0000)
committerBarry Warsaw <barry@python.org>
Mon, 28 Jun 2004 00:50:43 +0000 (00:50 +0000)
getservbyname() optional.  Update the tests and the docs.

Doc/lib/libsocket.tex
Lib/test/test_socket.py
Misc/NEWS
Modules/socketmodule.c

index 9ff5f0118f09346c7f9c58858a7c104ab490c276..f78ad2fc2101959c2e81b55511431b64c8a5d119 100644 (file)
@@ -272,10 +272,16 @@ modes, the correct protocol is chosen automatically if the protocol is
 omitted or zero.
 \end{funcdesc}
 
-\begin{funcdesc}{getservbyname}{servicename, protocolname}
+\begin{funcdesc}{getservbyname}{servicename\optional{, protocolname}}
 Translate an Internet service name and protocol name to a port number
-for that service.  The protocol name should be \code{'tcp'} or
-\code{'udp'}.
+for that service.  The optional protocol name, if given, should be
+\code{'tcp'} or \code{'udp'}, otherwise any protocol will match.
+\end{funcdesc}
+
+\begin{funcdesc}{getservbyport}{port\optional{, protocolname}}
+Translate an Internet port number and protocol name to a service name
+for that service.  The optional protocol name, if given, should be
+\code{'tcp'} or \code{'udp'}, otherwise any protocol will match.
 \end{funcdesc}
 
 \begin{funcdesc}{socket}{\optional{family\optional{,
index 6e2f80c407bd7395d96ad0a3639d82b24326143a..283145489514264a1d0d9b415e28708a3ffb8b31 100644 (file)
@@ -284,22 +284,34 @@ class GeneralModuleTests(unittest.TestCase):
             self.assertEqual(swapped & mask, mask)
             self.assertRaises(OverflowError, func, 1L<<34)
 
-    def testGetServByName(self):
-        # Testing getservbyname()
-        # try a few protocols - not everyone has telnet enabled
-        for proto in ("telnet", "ssh", "www", "ftp"):
+    def testGetServBy(self):
+        eq = self.assertEqual
+        # Find one service that exists, then check all the related interfaces.
+        # I've ordered this by protocols that have both a tcp and udp
+        # protocol, at least for modern Linuxes.
+        for service in ('ssh', 'www', 'echo', 'imap2'):
             try:
-                socket.getservbyname(proto, 'tcp')
-                break
-            except socket.error:
-                pass
-            try:
-                socket.getservbyname(proto, 'udp')
+                port = socket.getservbyname(service, 'tcp')
                 break
             except socket.error:
                 pass
         else:
             raise socket.error
+        # Try same call with optional protocol omitted
+        port2 = socket.getservbyname(service)
+        eq(port, port2)
+        # Try udp, but don't barf it it doesn't exist
+        try:
+            udpport = socket.getservbyname(service, 'udp')
+        except socket.error:
+            udpport = None
+        else:
+            eq(udpport, port)
+        # Now make sure the lookup by port returns the same service name
+        eq(socket.getservbyport(port2), service)
+        eq(socket.getservbyport(port, 'tcp'), service)
+        if udpport is not None:
+            eq(socket.getservbyport(udpport, 'udp'), service)
 
     def testDefaultTimeout(self):
         # Testing default timeout
index 41a79c87511a6aa9780db35187c7e8430c5e4460..138afe279324919b265fa5149619f2012e92eea4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -231,6 +231,9 @@ Core and builtins
 Extension modules
 -----------------
 
+- Added socket.getservbyport(), and make the second argument in
+  getservbyname() and getservbyport() optional.
+
 - time module code that deals with input POSIX timestamps will now raise
   ValueError if more than a second is lost in precision when the
   timestamp is cast to the platform C time_t type.  There's no chance
index 255e4dfc4d5f9155621f7f39c22eb3aee53ec108..46015f16cd47bb8a671ace7cbb05a7e965621fd8 100644 (file)
@@ -25,7 +25,8 @@ Module interface:
 - socket.gethostbyaddr(IP address) --> (hostname, [alias, ...], [IP addr, ...])
 - socket.gethostname() --> host name (string: 'spam' or 'spam.domain.com')
 - socket.getprotobyname(protocolname) --> protocol number
-- socket.getservbyname(servicename, protocolname) --> port number
+- socket.getservbyname(servicename[, protocolname]) --> port number
+- socket.getservbyport(portnumber[, protocolname]) --> service name
 - socket.socket([family[, type [, proto]]]) --> new socket object
 - socket.ntohs(16 bit value) --> new int object
 - socket.ntohl(32 bit value) --> new int object
@@ -2884,9 +2885,9 @@ for a host.  The host argument is a string giving a host name or IP number.");
 static PyObject *
 socket_getservbyname(PyObject *self, PyObject *args)
 {
-       char *name, *proto;
+       char *name, *proto=NULL;
        struct servent *sp;
-       if (!PyArg_ParseTuple(args, "ss:getservbyname", &name, &proto))
+       if (!PyArg_ParseTuple(args, "s|s:getservbyname", &name, &proto))
                return NULL;
        Py_BEGIN_ALLOW_THREADS
        sp = getservbyname(name, proto);
@@ -2899,12 +2900,43 @@ socket_getservbyname(PyObject *self, PyObject *args)
 }
 
 PyDoc_STRVAR(getservbyname_doc,
-"getservbyname(servicename, protocolname) -> integer\n\
+"getservbyname(servicename[, protocolname]) -> integer\n\
 \n\
 Return a port number from a service name and protocol name.\n\
-The protocol name should be 'tcp' or 'udp'.");
+The optional protocol name, if given, should be 'tcp' or 'udp',\n\
+otherwise any protocol will match.");
 
 
+/* Python interface to getservbyport(port).
+   This only returns the service name, since the other info is already
+   known or not useful (like the list of aliases). */
+
+/*ARGSUSED*/
+static PyObject *
+socket_getservbyport(PyObject *self, PyObject *args)
+{
+       int port;
+       char *proto=NULL;
+       struct servent *sp;
+       if (!PyArg_ParseTuple(args, "i|s:getservbyport", &port, &proto))
+               return NULL;
+       Py_BEGIN_ALLOW_THREADS
+       sp = getservbyport(htons(port), proto);
+       Py_END_ALLOW_THREADS
+       if (sp == NULL) {
+               PyErr_SetString(socket_error, "port/proto not found");
+               return NULL;
+       }
+       return PyString_FromString(sp->s_name);
+}
+
+PyDoc_STRVAR(getservbyport_doc,
+"getservbyport(port[, protocolname]) -> string\n\
+\n\
+Return the service name from a port number and protocol name.\n\
+The optional protocol name, if given, should be 'tcp' or 'udp',\n\
+otherwise any protocol will match.");
+
 /* Python interface to getprotobyname(name).
    This only returns the protocol number, since the other info is
    already known or not useful (like the list of aliases). */
@@ -3530,6 +3562,8 @@ static PyMethodDef socket_methods[] = {
         METH_VARARGS, gethostname_doc},
        {"getservbyname",       socket_getservbyname,
         METH_VARARGS, getservbyname_doc},
+       {"getservbyport",       socket_getservbyport,
+        METH_VARARGS, getservbyport_doc},
        {"getprotobyname",      socket_getprotobyname,
         METH_VARARGS,getprotobyname_doc},
 #ifndef NO_DUP