More rational support for Windows (tested on Roj's NT 3.5 machine only).

Use PyArg_ParseTuple() where it makes sense.
This commit is contained in:
Guido van Rossum 1996-06-20 16:25:29 +00:00
parent 920b13d529
commit be32c8921c
1 changed files with 117 additions and 141 deletions

View File

@ -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))
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))
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))
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))
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))
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 */