summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/lib/libsocket.tex12
-rw-r--r--Lib/test/test_socket.py32
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/socketmodule.c44
4 files changed, 73 insertions, 18 deletions
diff --git a/Doc/lib/libsocket.tex b/Doc/lib/libsocket.tex
index 9ff5f01..f78ad2f 100644
--- a/Doc/lib/libsocket.tex
+++ b/Doc/lib/libsocket.tex
@@ -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{,
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 6e2f80c..2831454 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -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
diff --git a/Misc/NEWS b/Misc/NEWS
index 41a79c8..138afe2 100644
--- 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
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 255e4df..46015f1 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -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