Added socket.getservbyport(), and make its second argument and that of

getservbyname() optional.  Update the tests and the docs.
This commit is contained in:
Barry Warsaw 2004-06-28 00:50:43 +00:00
parent 1ed5705154
commit 11b91a0ea3
4 changed files with 73 additions and 18 deletions

View File

@ -272,10 +272,16 @@ modes, the correct protocol is chosen automatically if the protocol is
omitted or zero. omitted or zero.
\end{funcdesc} \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 Translate an Internet service name and protocol name to a port number
for that service. The protocol name should be \code{'tcp'} or for that service. The optional protocol name, if given, should be
\code{'udp'}. \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} \end{funcdesc}
\begin{funcdesc}{socket}{\optional{family\optional{, \begin{funcdesc}{socket}{\optional{family\optional{,

View File

@ -284,22 +284,34 @@ class GeneralModuleTests(unittest.TestCase):
self.assertEqual(swapped & mask, mask) self.assertEqual(swapped & mask, mask)
self.assertRaises(OverflowError, func, 1L<<34) self.assertRaises(OverflowError, func, 1L<<34)
def testGetServByName(self): def testGetServBy(self):
# Testing getservbyname() eq = self.assertEqual
# try a few protocols - not everyone has telnet enabled # Find one service that exists, then check all the related interfaces.
for proto in ("telnet", "ssh", "www", "ftp"): # 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: try:
socket.getservbyname(proto, 'tcp') port = socket.getservbyname(service, 'tcp')
break
except socket.error:
pass
try:
socket.getservbyname(proto, 'udp')
break break
except socket.error: except socket.error:
pass pass
else: else:
raise socket.error 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): def testDefaultTimeout(self):
# Testing default timeout # Testing default timeout

View File

@ -231,6 +231,9 @@ Core and builtins
Extension modules 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 - time module code that deals with input POSIX timestamps will now raise
ValueError if more than a second is lost in precision when the 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 timestamp is cast to the platform C time_t type. There's no chance

View File

@ -25,7 +25,8 @@ Module interface:
- socket.gethostbyaddr(IP address) --> (hostname, [alias, ...], [IP addr, ...]) - socket.gethostbyaddr(IP address) --> (hostname, [alias, ...], [IP addr, ...])
- socket.gethostname() --> host name (string: 'spam' or 'spam.domain.com') - socket.gethostname() --> host name (string: 'spam' or 'spam.domain.com')
- socket.getprotobyname(protocolname) --> protocol number - 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.socket([family[, type [, proto]]]) --> new socket object
- socket.ntohs(16 bit value) --> new int object - socket.ntohs(16 bit value) --> new int object
- socket.ntohl(32 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 * static PyObject *
socket_getservbyname(PyObject *self, PyObject *args) socket_getservbyname(PyObject *self, PyObject *args)
{ {
char *name, *proto; char *name, *proto=NULL;
struct servent *sp; struct servent *sp;
if (!PyArg_ParseTuple(args, "ss:getservbyname", &name, &proto)) if (!PyArg_ParseTuple(args, "s|s:getservbyname", &name, &proto))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
sp = getservbyname(name, proto); sp = getservbyname(name, proto);
@ -2899,12 +2900,43 @@ socket_getservbyname(PyObject *self, PyObject *args)
} }
PyDoc_STRVAR(getservbyname_doc, PyDoc_STRVAR(getservbyname_doc,
"getservbyname(servicename, protocolname) -> integer\n\ "getservbyname(servicename[, protocolname]) -> integer\n\
\n\ \n\
Return a port number from a service name and protocol name.\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). /* Python interface to getprotobyname(name).
This only returns the protocol number, since the other info is This only returns the protocol number, since the other info is
already known or not useful (like the list of aliases). */ already known or not useful (like the list of aliases). */
@ -3530,6 +3562,8 @@ static PyMethodDef socket_methods[] = {
METH_VARARGS, gethostname_doc}, METH_VARARGS, gethostname_doc},
{"getservbyname", socket_getservbyname, {"getservbyname", socket_getservbyname,
METH_VARARGS, getservbyname_doc}, METH_VARARGS, getservbyname_doc},
{"getservbyport", socket_getservbyport,
METH_VARARGS, getservbyport_doc},
{"getprotobyname", socket_getprotobyname, {"getprotobyname", socket_getprotobyname,
METH_VARARGS,getprotobyname_doc}, METH_VARARGS,getprotobyname_doc},
#ifndef NO_DUP #ifndef NO_DUP