diff options
-rw-r--r-- | Modules/socketmodule.c | 258 |
1 files changed, 117 insertions, 141 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index ebdda89..5fd12f3 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -31,6 +31,7 @@ Limitations: - only AF_INET and AF_UNIX address families are supported - no read/write operations (use send/recv or makefile instead) +- additional restrictions apply on Windows Module interface: @@ -58,6 +59,7 @@ Socket methods: - s.close() --> None - s.connect(sockaddr) --> None - s.fileno() --> file descriptor +- s.dup() --> same as socket.fromfd(os.dup(s.fileno(), ...) - s.getpeername() --> sockaddr - s.getsockname() --> sockaddr - s.getsockopt(level, optname[, buflen]) --> int or string @@ -113,7 +115,7 @@ Socket methods: #ifdef NT /* seem to be a few differences in the API */ #define close closesocket -#define NO_DUP /* Define for NT 3.1, Win3.1 and Win95, Undefine for NT3.5 */ +#define NO_DUP /* Actually it exists on NT 3.5, but what the heck... */ #define FORCE_ANSI_FUNC_DEFS #endif @@ -547,9 +549,12 @@ BUILD_FUNC_DEF_2(PySocketSock_getsockopt,PySocketSockObject *,s, PyObject *,args int optname; int res; PyObject *buf; - int buflen; + int buflen = 0; - if (PyArg_Parse(args, "(ii)", &level, &optname)) { + if (!PyArg_ParseTuple(args, "ii|i", &level, &optname, &buflen)) + return NULL; + + if (buflen == 0) { int flag = 0; int flagsize = sizeof flag; res = getsockopt(s->sock_fd, level, optname, @@ -558,9 +563,6 @@ BUILD_FUNC_DEF_2(PySocketSock_getsockopt,PySocketSockObject *,s, PyObject *,args return PySocket_Err(); return PyInt_FromLong(flag); } - PyErr_Clear(); - if (!PyArg_Parse(args, "(iii)", &level, &optname, &buflen)) - return NULL; if (buflen <= 0 || buflen > 1024) { PyErr_SetString(PySocket_Error, "getsockopt buflen out of range"); return NULL; @@ -648,6 +650,30 @@ BUILD_FUNC_DEF_2(PySocketSock_fileno,PySocketSockObject *,s, PyObject *,args) } +#ifndef NO_DUP +/* s.dup() method */ + +static PyObject * +BUILD_FUNC_DEF_2(PySocketSock_dup,PySocketSockObject *,s, PyObject *,args) +{ + int newfd; + PyObject *sock; + if (!PyArg_NoArgs(args)) + return NULL; + newfd = dup(s->sock_fd); + if (newfd < 0) + return PySocket_Err(); + sock = (PyObject *) PySocketSock_New(newfd, + s->sock_family, + s->sock_type, + s->sock_proto); + if (sock == NULL) + close(newfd); + return sock; +} +#endif + + /* s.getsockname() method */ static PyObject * @@ -754,14 +780,10 @@ BUILD_FUNC_DEF_2(PySocketSock_makefile,PySocketSockObject *,s, PyObject *,args) static PyObject * BUILD_FUNC_DEF_2(PySocketSock_recv,PySocketSockObject *,s, PyObject *,args) { - int len, n, flags; + int len, n, flags = 0; PyObject *buf; - flags = 0; - if (!PyArg_Parse(args, "i", &len)) { - PyErr_Clear(); - if (!PyArg_Parse(args, "(ii)", &len, &flags)) - return NULL; - } + if (!PyArg_ParseTuple(args, "i|i", &len, &flags)) + return NULL; buf = PyString_FromStringAndSize((char *) 0, len); if (buf == NULL) return NULL; @@ -785,13 +807,9 @@ BUILD_FUNC_DEF_2(PySocketSock_recvfrom,PySocketSockObject *,s, PyObject *,args) { char addrbuf[256]; PyObject *buf, *addr, *ret; - int addrlen, len, n, flags; - flags = 0; - if (!PyArg_Parse(args, "i", &len)) { - PyErr_Clear(); - if (!PyArg_Parse(args, "(ii)", &len, &flags)) - return NULL; - } + int addrlen, len, n, flags = 0; + if (!PyArg_ParseTuple(args, "i|i", &len, &flags)) + return NULL; if (!getsockaddrlen(s, &addrlen)) return NULL; buf = PyString_FromStringAndSize((char *) 0, len); @@ -825,13 +843,9 @@ static PyObject * BUILD_FUNC_DEF_2(PySocketSock_send,PySocketSockObject *,s, PyObject *,args) { char *buf; - int len, n, flags; - flags = 0; - if (!PyArg_Parse(args, "s#", &buf, &len)) { - PyErr_Clear(); - if (!PyArg_Parse(args, "(s#i)", &buf, &len, &flags)) - return NULL; - } + int len, n, flags = 0; + if (!PyArg_ParseTuple(args, "s#|i", &buf, &len, &flags)) + return NULL; Py_BEGIN_ALLOW_THREADS n = send(s->sock_fd, buf, len, flags); Py_END_ALLOW_THREADS @@ -890,16 +904,16 @@ BUILD_FUNC_DEF_2(PySocketSock_shutdown,PySocketSockObject *,s, PyObject *,args) static PyMethodDef PySocketSock_methods[] = { {"accept", (PyCFunction)PySocketSock_accept}, -#if 0 - {"allowbroadcast", (PyCFunction)PySocketSock_allowbroadcast}, -#endif {"setblocking", (PyCFunction)PySocketSock_setblocking}, {"setsockopt", (PyCFunction)PySocketSock_setsockopt}, - {"getsockopt", (PyCFunction)PySocketSock_getsockopt}, + {"getsockopt", (PyCFunction)PySocketSock_getsockopt, 1}, {"bind", (PyCFunction)PySocketSock_bind}, {"close", (PyCFunction)PySocketSock_close}, {"connect", (PyCFunction)PySocketSock_connect}, {"fileno", (PyCFunction)PySocketSock_fileno}, +#ifndef NO_DUP + {"dup", (PyCFunction)PySocketSock_dup}, +#endif {"getsockname", (PyCFunction)PySocketSock_getsockname}, #ifdef HAVE_GETPEERNAME {"getpeername", (PyCFunction)PySocketSock_getpeername}, @@ -908,9 +922,9 @@ static PyMethodDef PySocketSock_methods[] = { #ifndef NO_DUP {"makefile", (PyCFunction)PySocketSock_makefile, 1}, #endif - {"recv", (PyCFunction)PySocketSock_recv}, - {"recvfrom", (PyCFunction)PySocketSock_recvfrom}, - {"send", (PyCFunction)PySocketSock_send}, + {"recv", (PyCFunction)PySocketSock_recv, 1}, + {"recvfrom", (PyCFunction)PySocketSock_recvfrom, 1}, + {"send", (PyCFunction)PySocketSock_send, 1}, {"sendto", (PyCFunction)PySocketSock_sendto}, {"shutdown", (PyCFunction)PySocketSock_shutdown}, {NULL, NULL} /* sentinel */ @@ -1099,13 +1113,9 @@ BUILD_FUNC_DEF_2(PySocket_socket,PyObject *,self, PyObject *,args) #else int fd; #endif - int family, type, proto; - proto = 0; - if (!PyArg_Parse(args, "(ii)", &family, &type)) { - PyErr_Clear(); - if (!PyArg_Parse(args, "(iii)", &family, &type, &proto)) - return NULL; - } + int family, type, proto = 0; + if (!PyArg_ParseTuple(args, "ii|i", &family, &type, &proto)) + return NULL; Py_BEGIN_ALLOW_THREADS fd = socket(family, type, proto); Py_END_ALLOW_THREADS @@ -1138,13 +1148,9 @@ static PyObject * BUILD_FUNC_DEF_2(PySocket_fromfd,PyObject *,self, PyObject *,args) { PySocketSockObject *s; - int fd, family, type, proto; - proto = 0; - if (!PyArg_Parse(args, "(iii)", &fd, &family, &type)) { - PyErr_Clear(); - if (!PyArg_Parse(args, "(iiii)", &fd, &family, &type, &proto)) - return NULL; - } + int fd, family, type, proto = 0; + if (!PyArg_ParseTuple(args, "iii|i", &fd, &family, &type, &proto)) + return NULL; /* Dup the fd so it and the socket can be closed independently */ fd = dup(fd); if (fd < 0) @@ -1159,50 +1165,6 @@ BUILD_FUNC_DEF_2(PySocket_fromfd,PyObject *,self, PyObject *,args) } #endif /* NO_DUP */ -static PyObject * PySocket_WSAStartup(self, args) - PyObject *self, *args; -{ -#ifdef _MSC_VER - WSADATA WSAData; - int ret; - - if (!PyArg_NoArgs(args)) - return NULL; - ret = WSAStartup(0x0101, &WSAData); /* request version 1.1 */ - switch(ret){ - case WSASYSNOTREADY: - PyErr_SetString(PySocket_Error, - "WSAStartup failed: Network not ready\n"); - break; - case WSAVERNOTSUPPORTED: - case WSAEINVAL: - PyErr_SetString(PySocket_Error, - "WSAStartup failed: Requested version not supported"); - break; - case 0: /* no error */ - break; - default: - PyErr_SetString(PySocket_Error, - "WSAStartup failed"); - break; - } -#endif - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * PySocket_WSACleanup(self, args) - PyObject *self, *args; -{ - if (!PyArg_NoArgs(args)) - return NULL; -#ifdef _MSC_VER - WSACleanup(); -#endif - Py_INCREF(Py_None); - return Py_None; -} - static PyObject * BUILD_FUNC_DEF_2(PySocket_ntohs, PyObject *, self, PyObject *, args) { @@ -1258,11 +1220,9 @@ static PyMethodDef PySocket_methods[] = { {"gethostbyaddr", PySocket_gethostbyaddr}, {"gethostname", PySocket_gethostname}, {"getservbyname", PySocket_getservbyname}, - {"socket", PySocket_socket}, - {"WSAStartup", PySocket_WSAStartup}, - {"WSACleanup", PySocket_WSACleanup}, + {"socket", PySocket_socket, 1}, #ifndef NO_DUP - {"fromfd", PySocket_fromfd}, + {"fromfd", PySocket_fromfd, 1}, #endif {"ntohs", PySocket_ntohs}, {"ntohl", PySocket_ntohl}, @@ -1290,16 +1250,76 @@ BUILD_FUNC_DEF_3(insint,PyObject *,d, char *,name, int,value) } +#ifdef NT + +/* Additional initialization and cleanup for NT/Windows */ + +static void +NTcleanup() +{ + WSACleanup(); + fprintf(stderr, "WSACleanup called\n"); +} + +static int +NTinit() +{ + WSADATA WSAData; + int ret; + char buf[100]; + ret = WSAStartup(0x0101, &WSAData); + switch (ret) { + case 0: /* no error */ + atexit(NTcleanup); + return 1; + case WSASYSNOTREADY: + PyErr_SetString(PyExc_ImportError, + "WSAStartup failed: network not ready"); + break; + case WSAVERNOTSUPPORTED: + case WSAEINVAL: + PyErr_SetString(PyExc_ImportError, + "WSAStartup failed: requested version not supported"); + break; + default: + sprintf(buf, "WSAStartup failed: error code %d", ret); + PyErr_SetString(PyExc_ImportError, buf); + break; + } + return 0; +} + +#endif /* NT */ + + /* Initialize this module. This is called when the first 'import socket' is done, via a table in config.c, if config.c is compiled with USE_SOCKET - defined. */ + defined. + + For NT (which actually means any Windows variant (?)), this module + is actually called "_socket", and there's a wrapper "socket.py" + which implements some missing functionality (such as makefile(), + dup() and fromfd()). The import of "_socket" may fail with an + ImportError exception if initialization of WINSOCK fails. When + WINSOCK is initialized succesfully, a call to WSACleanup() is + scheduled to be made at exit time. */ void +#ifdef NT +init_socket() +#else initsocket() +#endif { PyObject *m, *d; +#ifdef NT + if (!NTinit()) + return; + m = Py_InitModule("_socket", PySocket_methods); +#else m = Py_InitModule("socket", PySocket_methods); +#endif d = PyModule_GetDict(m); PySocket_Error = PyString_FromString("socket.error"); if (PySocket_Error == NULL || @@ -1553,48 +1573,4 @@ initsocket() #ifdef IP_DROP_MEMBERSHIP insint(d, "IP_DROP_MEMBERSHIP", IP_DROP_MEMBERSHIP); #endif - -#ifdef MS_WIN16 -/* All windows sockets require a successful WSAStartup() before use */ - Py_XDECREF(PySocket_WSAStartup(NULL, NULL)); -#endif } - -#ifdef NT -BOOL WINAPI DllMain (HANDLE hInst, - ULONG ul_reason_for_call, - LPVOID lpReserved) -{ - const int opt = SO_SYNCHRONOUS_NONALERT; - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: { - WSADATA WSAData; - BOOL ok = TRUE; - char buf[100] = "Python can't initialize Windows Sockets Module!\n\r"; - if (WSAStartup(MAKEWORD(1,1), &WSAData)) { - wsprintf(buf+strlen(buf), "WSAStartup failed (%d)",WSAGetLastError()); - ok = FALSE; - } - /* - ** Setup sockets in non-overlapped mode by default - */ -// if (ok && setsockopt(INVALID_SOCKET,SOL_SOCKET,SO_OPENTYPE,(const char *)&opt,sizeof(opt)) != 0) { -// wsprintf(buf+strlen(buf),"setsockopt failed (%d)",WSAGetLastError()); -// ok = FALSE; -// } - if (!ok) { - MessageBox(NULL,buf,"WinSock Error",MB_OK|MB_SETFOREGROUND); - return FALSE; - } - break; - } - - case DLL_PROCESS_DETACH: - WSACleanup(); - break; - - } - return TRUE; -} -#endif /* NT */ |