mirror of
https://github.com/python/cpython.git
synced 2025-10-25 15:58:57 +00:00
Made SocketType and socket the same thing: a subclassable type whose
constructor acts just like socket() before. All three arguments have a sensible default now; socket() is equivalent to socket(AF_INET, SOCK_STREAM). One minor issue: the socket() function and the SocketType had different doc strings; socket.__doc__ gave the signature, SocketType.__doc__ gave the methods. I've merged these for now, but maybe the list of methods is no longer necessary since it can easily be recovered through socket.__dict__.keys(). The problem with keeping it is that the total doc string is a bit long (34 lines -- it scrolls of a standard tty screen). Another general issue with the socket module is that it's a big mess. There's pages and pages of random platform #ifdefs, and the naming conventions are totally wrong: it uses Py prefixes and CapWords for static functions. That's a cleanup for another day... (Also I think the big starting comment that summarizes the API can go -- it's a repeat of the docstring.)
This commit is contained in:
parent
bd67d6f32c
commit
384ca9c6dd
1 changed files with 167 additions and 119 deletions
|
|
@ -9,8 +9,8 @@ Limitations:
|
||||||
|
|
||||||
- only AF_INET, AF_INET6 and AF_UNIX address families are supported in a
|
- only AF_INET, AF_INET6 and AF_UNIX address families are supported in a
|
||||||
portable manner, though AF_PACKET is supported under Linux.
|
portable manner, though AF_PACKET is supported under Linux.
|
||||||
- no read/write operations (use send/recv or makefile instead)
|
- no read/write operations (use sendall/recv or makefile instead)
|
||||||
- additional restrictions apply on Windows
|
- additional restrictions apply on Windows (compensated for by socket.py)
|
||||||
|
|
||||||
Module interface:
|
Module interface:
|
||||||
|
|
||||||
|
|
@ -77,6 +77,9 @@ Socket methods:
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
|
/* XXX This is a terrible mess of of platform-dependent preprocessor hacks.
|
||||||
|
I hope some day someone can clean this up please... */
|
||||||
|
|
||||||
/* Hacks for gethostbyname_r(). On some non-Linux platforms, the configure
|
/* Hacks for gethostbyname_r(). On some non-Linux platforms, the configure
|
||||||
script doesn't get this right, so we hardcode some platform checks below.
|
script doesn't get this right, so we hardcode some platform checks below.
|
||||||
On the other hand, not all Linux versions agree, so there the settings
|
On the other hand, not all Linux versions agree, so there the settings
|
||||||
|
|
@ -267,6 +270,10 @@ typedef int SOCKET_T;
|
||||||
#define SOCKETCLOSE close
|
#define SOCKETCLOSE close
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* XXX There's a problem here: *static* functions are not supposed to have
|
||||||
|
a Py prefix (or use CapitalizedWords). Later... */
|
||||||
|
|
||||||
/* Global variable holding the exception type for errors detected
|
/* Global variable holding the exception type for errors detected
|
||||||
by this module (but not argument type or memory errors, etc.). */
|
by this module (but not argument type or memory errors, etc.). */
|
||||||
|
|
||||||
|
|
@ -511,21 +518,15 @@ staticforward PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args);
|
||||||
staticforward PyTypeObject PySocketSock_Type;
|
staticforward PyTypeObject PySocketSock_Type;
|
||||||
|
|
||||||
|
|
||||||
/* Create a new socket object.
|
/* Initialize a new socket object. */
|
||||||
This just creates the object and initializes it.
|
|
||||||
If the creation fails, return NULL and set an exception (implicit
|
|
||||||
in NEWOBJ()). */
|
|
||||||
|
|
||||||
static PySocketSockObject *
|
static void
|
||||||
PySocketSock_New(SOCKET_T fd, int family, int type, int proto)
|
init_sockobject(PySocketSockObject *s,
|
||||||
|
SOCKET_T fd, int family, int type, int proto)
|
||||||
{
|
{
|
||||||
#ifdef RISCOS
|
#ifdef RISCOS
|
||||||
int block = 1;
|
int block = 1;
|
||||||
#endif
|
#endif
|
||||||
PySocketSockObject *s;
|
|
||||||
PySocketSock_Type.ob_type = &PyType_Type;
|
|
||||||
s = PyObject_New(PySocketSockObject, &PySocketSock_Type);
|
|
||||||
if (s != NULL) {
|
|
||||||
s->sock_fd = fd;
|
s->sock_fd = fd;
|
||||||
s->sock_family = family;
|
s->sock_family = family;
|
||||||
s->sock_type = type;
|
s->sock_type = type;
|
||||||
|
|
@ -535,7 +536,22 @@ PySocketSock_New(SOCKET_T fd, int family, int type, int proto)
|
||||||
socketioctl(s->sock_fd, 0x80046679, (u_long*)&block);
|
socketioctl(s->sock_fd, 0x80046679, (u_long*)&block);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a new socket object.
|
||||||
|
This just creates the object and initializes it.
|
||||||
|
If the creation fails, return NULL and set an exception (implicit
|
||||||
|
in NEWOBJ()). */
|
||||||
|
|
||||||
|
static PySocketSockObject *
|
||||||
|
PySocketSock_New(SOCKET_T fd, int family, int type, int proto)
|
||||||
|
{
|
||||||
|
PySocketSockObject *s;
|
||||||
|
s = (PySocketSockObject *)
|
||||||
|
PyType_GenericNew(&PySocketSock_Type, NULL, NULL);
|
||||||
|
if (s != NULL)
|
||||||
|
init_sockobject(s, fd, family, type, proto);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1720,16 +1736,7 @@ PySocketSock_dealloc(PySocketSockObject *s)
|
||||||
{
|
{
|
||||||
if (s->sock_fd != -1)
|
if (s->sock_fd != -1)
|
||||||
(void) SOCKETCLOSE(s->sock_fd);
|
(void) SOCKETCLOSE(s->sock_fd);
|
||||||
PyObject_Del(s);
|
s->ob_type->tp_free((PyObject *)s);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Return a socket object's named attribute. */
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
PySocketSock_getattr(PySocketSockObject *s, char *name)
|
|
||||||
{
|
|
||||||
return Py_FindMethod(PySocketSock_methods, (PyObject *) s, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1754,23 +1761,136 @@ PySocketSock_repr(PySocketSockObject *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a new, uninitialized socket object. */
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
PySocketSock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
PyObject *new;
|
||||||
|
|
||||||
|
new = type->tp_alloc(type, 0);
|
||||||
|
if (new != NULL)
|
||||||
|
((PySocketSockObject *)new)->sock_fd = -1;
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize a new socket object. */
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
static int
|
||||||
|
PySocketSock_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
PySocketSockObject *s = (PySocketSockObject *)self;
|
||||||
|
SOCKET_T fd;
|
||||||
|
int family = AF_INET, type = SOCK_STREAM, proto = 0;
|
||||||
|
static char *keywords[] = {"family", "type", "proto", 0};
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
||||||
|
"|iii:socket", keywords,
|
||||||
|
&family, &type, &proto))
|
||||||
|
return -1;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
fd = socket(family, type, proto);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
if (fd == INVALID_SOCKET)
|
||||||
|
#else
|
||||||
|
if (fd < 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
PySocket_Err();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
init_sockobject(s, fd, family, type, proto);
|
||||||
|
/* From now on, ignore SIGPIPE and let the error checking
|
||||||
|
do the work. */
|
||||||
|
#ifdef SIGPIPE
|
||||||
|
(void) signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Type object for socket objects. */
|
/* Type object for socket objects. */
|
||||||
|
|
||||||
|
static char socket_doc[] =
|
||||||
|
"socket([family[, type[, proto]]]) -> socket object\n\
|
||||||
|
\n\
|
||||||
|
Open a socket of the given type. The family argument specifies the\n\
|
||||||
|
address family; it defaults to AF_INET. The type argument specifies\n\
|
||||||
|
whether this is a stream (SOCK_STREAM, this is the default)\n\
|
||||||
|
or datagram (SOCK_DGRAM) socket. The protocol argument defaults to 0,\n\
|
||||||
|
specifying the default protocol.\n\
|
||||||
|
\n\
|
||||||
|
A socket represents one endpoint of a network connection.\n\
|
||||||
|
\n\
|
||||||
|
Methods:\n\
|
||||||
|
\n\
|
||||||
|
accept() -- accept a connection, returning new socket and client address\n\
|
||||||
|
bind() -- bind the socket to a local address\n\
|
||||||
|
close() -- close the socket\n\
|
||||||
|
connect() -- connect the socket to a remote address\n\
|
||||||
|
connect_ex() -- connect, return an error code instead of an exception \n\
|
||||||
|
dup() -- return a new socket object identical to the current one (*)\n\
|
||||||
|
fileno() -- return underlying file descriptor\n\
|
||||||
|
getpeername() -- return remote address (*)\n\
|
||||||
|
getsockname() -- return local address\n\
|
||||||
|
getsockopt() -- get socket options\n\
|
||||||
|
listen() -- start listening for incoming connections\n\
|
||||||
|
makefile() -- return a file object corresponding tot the socket (*)\n\
|
||||||
|
recv() -- receive data\n\
|
||||||
|
recvfrom() -- receive data and sender's address\n\
|
||||||
|
send() -- send data, may not send all of it\n\
|
||||||
|
sendall() -- send all data\n\
|
||||||
|
sendto() -- send data to a given address\n\
|
||||||
|
setblocking() -- set or clear the blocking I/O flag\n\
|
||||||
|
setsockopt() -- set socket options\n\
|
||||||
|
shutdown() -- shut down traffic in one or both directions\n\
|
||||||
|
\n\
|
||||||
|
(*) not available on all platforms!)";
|
||||||
|
|
||||||
static PyTypeObject PySocketSock_Type = {
|
static PyTypeObject PySocketSock_Type = {
|
||||||
PyObject_HEAD_INIT(0) /* Must fill in type value later */
|
PyObject_HEAD_INIT(0) /* Must fill in type value later */
|
||||||
0,
|
0, /* ob_size */
|
||||||
"socket",
|
"socket.socket", /* tp_name */
|
||||||
sizeof(PySocketSockObject),
|
sizeof(PySocketSockObject), /* tp_basicsize */
|
||||||
0,
|
0, /* tp_itemsize */
|
||||||
(destructor)PySocketSock_dealloc, /*tp_dealloc*/
|
(destructor)PySocketSock_dealloc, /* tp_dealloc */
|
||||||
0, /*tp_print*/
|
0, /* tp_print */
|
||||||
(getattrfunc)PySocketSock_getattr, /*tp_getattr*/
|
0, /* tp_getattr */
|
||||||
0, /*tp_setattr*/
|
0, /* tp_setattr */
|
||||||
0, /*tp_compare*/
|
0, /* tp_compare */
|
||||||
(reprfunc)PySocketSock_repr, /*tp_repr*/
|
(reprfunc)PySocketSock_repr, /* tp_repr */
|
||||||
0, /*tp_as_number*/
|
0, /* tp_as_number */
|
||||||
0, /*tp_as_sequence*/
|
0, /* tp_as_sequence */
|
||||||
0, /*tp_as_mapping*/
|
0, /* tp_as_mapping */
|
||||||
|
0, /* tp_hash */
|
||||||
|
0, /* tp_call */
|
||||||
|
0, /* tp_str */
|
||||||
|
PyObject_GenericGetAttr, /* tp_getattro */
|
||||||
|
0, /* tp_setattro */
|
||||||
|
0, /* tp_as_buffer */
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||||
|
socket_doc, /* tp_doc */
|
||||||
|
0, /* tp_traverse */
|
||||||
|
0, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
0, /* tp_iter */
|
||||||
|
0, /* tp_iternext */
|
||||||
|
PySocketSock_methods, /* tp_methods */
|
||||||
|
0, /* tp_members */
|
||||||
|
0, /* tp_getset */
|
||||||
|
0, /* tp_base */
|
||||||
|
0, /* tp_dict */
|
||||||
|
0, /* tp_descr_get */
|
||||||
|
0, /* tp_descr_set */
|
||||||
|
0, /* tp_dictoffset */
|
||||||
|
PySocketSock_init, /* tp_init */
|
||||||
|
PyType_GenericAlloc, /* tp_alloc */
|
||||||
|
PySocketSock_new, /* tp_new */
|
||||||
|
_PyObject_Del, /* tp_free */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2149,51 +2269,6 @@ static char getprotobyname_doc[] =
|
||||||
Return the protocol number for the named protocol. (Rarely used.)";
|
Return the protocol number for the named protocol. (Rarely used.)";
|
||||||
|
|
||||||
|
|
||||||
/* Python interface to socket(family, type, proto).
|
|
||||||
The third (protocol) argument is optional.
|
|
||||||
Return a new socket object. */
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
|
||||||
static PyObject *
|
|
||||||
PySocket_socket(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
PySocketSockObject *s;
|
|
||||||
SOCKET_T fd;
|
|
||||||
int family, type, proto = 0;
|
|
||||||
if (!PyArg_ParseTuple(args, "ii|i:socket", &family, &type, &proto))
|
|
||||||
return NULL;
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
|
||||||
fd = socket(family, type, proto);
|
|
||||||
Py_END_ALLOW_THREADS
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
if (fd == INVALID_SOCKET)
|
|
||||||
#else
|
|
||||||
if (fd < 0)
|
|
||||||
#endif
|
|
||||||
return PySocket_Err();
|
|
||||||
s = PySocketSock_New(fd, family, type, proto);
|
|
||||||
/* If the object can't be created, don't forget to close the
|
|
||||||
file descriptor again! */
|
|
||||||
if (s == NULL)
|
|
||||||
(void) SOCKETCLOSE(fd);
|
|
||||||
/* From now on, ignore SIGPIPE and let the error checking
|
|
||||||
do the work. */
|
|
||||||
#ifdef SIGPIPE
|
|
||||||
(void) signal(SIGPIPE, SIG_IGN);
|
|
||||||
#endif
|
|
||||||
return (PyObject *) s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char socket_doc[] =
|
|
||||||
"socket(family, type[, proto]) -> socket object\n\
|
|
||||||
\n\
|
|
||||||
Open a socket of the given type. The family argument specifies the\n\
|
|
||||||
address family; it is normally AF_INET, sometimes AF_UNIX.\n\
|
|
||||||
The type argument specifies whether this is a stream (SOCK_STREAM)\n\
|
|
||||||
or datagram (SOCK_DGRAM) socket. The protocol argument defaults to 0,\n\
|
|
||||||
specifying the default protocol.";
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_DUP
|
#ifndef NO_DUP
|
||||||
/* Create a socket object from a numeric file description.
|
/* Create a socket object from a numeric file description.
|
||||||
Useful e.g. if stdin is a socket.
|
Useful e.g. if stdin is a socket.
|
||||||
|
|
@ -2886,8 +2961,6 @@ static PyMethodDef PySocket_methods[] = {
|
||||||
METH_VARARGS, getservbyname_doc},
|
METH_VARARGS, getservbyname_doc},
|
||||||
{"getprotobyname", PySocket_getprotobyname,
|
{"getprotobyname", PySocket_getprotobyname,
|
||||||
METH_VARARGS,getprotobyname_doc},
|
METH_VARARGS,getprotobyname_doc},
|
||||||
{"socket", PySocket_socket,
|
|
||||||
METH_VARARGS, socket_doc},
|
|
||||||
#ifndef NO_DUP
|
#ifndef NO_DUP
|
||||||
{"fromfd", PySocket_fromfd,
|
{"fromfd", PySocket_fromfd,
|
||||||
METH_VARARGS, fromfd_doc},
|
METH_VARARGS, fromfd_doc},
|
||||||
|
|
@ -3029,33 +3102,6 @@ static char module_doc[] =
|
||||||
"Implementation module for socket operations. See the socket module\n\
|
"Implementation module for socket operations. See the socket module\n\
|
||||||
for documentation.";
|
for documentation.";
|
||||||
|
|
||||||
static char sockettype_doc[] =
|
|
||||||
"A socket represents one endpoint of a network connection.\n\
|
|
||||||
\n\
|
|
||||||
Methods:\n\
|
|
||||||
\n\
|
|
||||||
accept() -- accept a connection, returning new socket and client address\n\
|
|
||||||
bind() -- bind the socket to a local address\n\
|
|
||||||
close() -- close the socket\n\
|
|
||||||
connect() -- connect the socket to a remote address\n\
|
|
||||||
connect_ex() -- connect, return an error code instead of an exception \n\
|
|
||||||
dup() -- return a new socket object identical to the current one (*)\n\
|
|
||||||
fileno() -- return underlying file descriptor\n\
|
|
||||||
getpeername() -- return remote address (*)\n\
|
|
||||||
getsockname() -- return local address\n\
|
|
||||||
getsockopt() -- get socket options\n\
|
|
||||||
listen() -- start listening for incoming connections\n\
|
|
||||||
makefile() -- return a file object corresponding tot the socket (*)\n\
|
|
||||||
recv() -- receive data\n\
|
|
||||||
recvfrom() -- receive data and sender's address\n\
|
|
||||||
send() -- send data\n\
|
|
||||||
sendto() -- send data to a given address\n\
|
|
||||||
setblocking() -- set or clear the blocking I/O flag\n\
|
|
||||||
setsockopt() -- set socket options\n\
|
|
||||||
shutdown() -- shut down traffic in one or both directions\n\
|
|
||||||
\n\
|
|
||||||
(*) not available on all platforms!)";
|
|
||||||
|
|
||||||
DL_EXPORT(void)
|
DL_EXPORT(void)
|
||||||
init_socket(void)
|
init_socket(void)
|
||||||
{
|
{
|
||||||
|
|
@ -3076,6 +3122,7 @@ init_socket(void)
|
||||||
#endif /* __TOS_OS2__ */
|
#endif /* __TOS_OS2__ */
|
||||||
#endif /* MS_WINDOWS */
|
#endif /* MS_WINDOWS */
|
||||||
#endif /* RISCOS */
|
#endif /* RISCOS */
|
||||||
|
PySocketSock_Type.ob_type = &PyType_Type;
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
PySSL_Type.ob_type = &PyType_Type;
|
PySSL_Type.ob_type = &PyType_Type;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -3117,11 +3164,12 @@ init_socket(void)
|
||||||
PyModule_AddIntConstant(m, "SSL_ERROR_SSL",
|
PyModule_AddIntConstant(m, "SSL_ERROR_SSL",
|
||||||
SSL_ERROR_SSL);
|
SSL_ERROR_SSL);
|
||||||
#endif /* USE_SSL */
|
#endif /* USE_SSL */
|
||||||
PySocketSock_Type.ob_type = &PyType_Type;
|
|
||||||
PySocketSock_Type.tp_doc = sockettype_doc;
|
|
||||||
if (PyDict_SetItemString(d, "SocketType",
|
if (PyDict_SetItemString(d, "SocketType",
|
||||||
(PyObject *)&PySocketSock_Type) != 0)
|
(PyObject *)&PySocketSock_Type) != 0)
|
||||||
return;
|
return;
|
||||||
|
if (PyDict_SetItemString(d, "socket",
|
||||||
|
(PyObject *)&PySocketSock_Type) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Address families (we only support AF_INET and AF_UNIX) */
|
/* Address families (we only support AF_INET and AF_UNIX) */
|
||||||
#ifdef AF_UNSPEC
|
#ifdef AF_UNSPEC
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue