Index: Lib/socket.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/socket.py,v retrieving revision 1.45 diff -u -r1.45 socket.py --- Lib/socket.py 9 Aug 2004 04:51:40 -0000 1.45 +++ Lib/socket.py 16 Jan 2005 03:43:43 -0000 @@ -148,8 +148,8 @@ __doc__ = _realsocket.__doc__ - __slots__ = ["_sock", "send", "recv", "sendto", "recvfrom", - "__weakref__"] + __slots__ = ["_sock", "send", "recv", "sendto", "recvfrom", + "recvall", "__weakref__"] def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None): if _sock is None: @@ -159,6 +159,7 @@ self.recv = self._sock.recv self.sendto = self._sock.sendto self.recvfrom = self._sock.recvfrom + self.recvall = self._sock.recvall def close(self): self._sock = _closedsocket() Index: Modules/socketmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/socketmodule.c,v retrieving revision 1.311 diff -u -r1.311 socketmodule.c --- Modules/socketmodule.c 7 Nov 2004 14:24:25 -0000 1.311 +++ Modules/socketmodule.c 16 Jan 2005 03:43:45 -0000 @@ -2178,6 +2178,96 @@ \n\ Like recv(buffersize, flags) but also return the sender's address info."); +/* s.recvall(nbytes [,flags]) method */ + +static PyObject* +sock_recvall(PySocketSockObject *s, PyObject *args) +{ + int total_size; /* #bytes to receive in total (=arg2) */ + int flags=0; /* optional flags for recv() */ +#ifndef MSG_WAITALL + PyObject* Buffer_PyString; /* result buffer (allocated here) */ + char* Buffer; /* pointer to start of raw buffer area inside Buffer_PyString */ + char* p_Buffer; /* cursor pointing into raw buffer area */ + int bytes_get; /* # bytes still to get */ + int bytes_got; /* # bytes already got */ + int n, timeout=0; +#else + PyObject* recv_newargs; /* to pass new args to sock_recv() */ + PyObject* recv_result; /* the result of sock_recv() */ +#endif + + if (!PyArg_ParseTuple(args, "i|i:recvall", &total_size, &flags)) + return NULL; + + if (total_size < 0) { + PyErr_SetString(PyExc_ValueError, "negative buffersize in recvall"); + return NULL; + } + +#ifdef MSG_WAITALL + /* just use recv() with the MSG_WAITALL flag added. */ + flags |= MSG_WAITALL; + recv_newargs=Py_BuildValue("ii",total_size,flags); + recv_result= sock_recv(s, recv_newargs); + Py_DECREF(recv_newargs); + return recv_result; +#else + /* no support for MSG_WAITALL, so simulate it by doing a loop ourselves. */ + + Buffer_PyString = PyString_FromStringAndSize(NULL,total_size); /* allocate uninitialized string of given length */ + if (Buffer_PyString == NULL) + return NULL; + + Buffer = PyString_AS_STRING(Buffer_PyString); + + bytes_got = 0; + n = 1; /* for while() below */ + p_Buffer = Buffer; + + Py_BEGIN_ALLOW_THREADS /* no other thread can possibly have a reference to our string buffer object so we can safely release the GIL */ + + while ( (bytes_got 0) ) + { + bytes_get = total_size - bytes_got; + timeout = internal_select(s, 0); + if(timeout) + break; + n = recv(s->sock_fd, p_Buffer, bytes_get, flags); /* XXX use SEGMENT_SIZE here??? */ + p_Buffer += n; + bytes_got += n; + } + + Py_END_ALLOW_THREADS + + if (timeout==-1 && errno) { + Py_DECREF(Buffer_PyString); + return PyErr_SetFromErrno(socket_error); + } + if (timeout) { + Py_DECREF(Buffer_PyString); + PyErr_SetString(socket_timeout, "timed out"); + return NULL; + } + + if (n < 0) { /* this happens when the connection breaks amidst a transfer */ + Py_DECREF(Buffer_PyString); + return s->errorhandler(); + } + + return(Buffer_PyString); +#endif /* MSG_WAITALL */ +} + +PyDoc_STRVAR(recvall_doc, +"recvall(buffersize[, flags]) -> data\n\ +\n\ +Receive a well-known buffersize bytes from the socket in one go.\n\ +When the system supports the MSG_WAITALL socket flag, it will use that.\n\ +Otherwise, it will use an internal loop to simulate the effect.\n\ +Also see recv()."); + + /* s.send(data [,flags]) method */ static PyObject * @@ -2397,6 +2487,8 @@ recv_doc}, {"recvfrom", (PyCFunction)sock_recvfrom, METH_VARARGS, recvfrom_doc}, + {"recvall", (PyCFunction)sock_recvall, METH_VARARGS, + recvall_doc }, {"send", (PyCFunction)sock_send, METH_VARARGS, send_doc}, {"sendall", (PyCFunction)sock_sendall, METH_VARARGS,