]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
partial backport of guido's 1.188.
authorAnthony Baxter <anthonybaxter@gmail.com>
Thu, 1 Nov 2001 14:14:26 +0000 (14:14 +0000)
committerAnthony Baxter <anthonybaxter@gmail.com>
Thu, 1 Nov 2001 14:14:26 +0000 (14:14 +0000)
  Add sendall() method, which loops until all data is written or an
  error occurs, and doesn't return a count.  (This is my second patch
  from SF patch #474307, with small change to the docstring for send().)

the 'partial' is because 1.188 also added a couple of Py_*_ALLOW_THREADS
wrappers around SSL_read and SSL_write, and I want to check those separately.

This is adding a new method to the socket object, which would normally
be a bad thing to do in a bugfix release - however, in this case, it
allows fixes for a nasty problem that would otherwise have a filthy
filthy fix to Get It Right. Still to-do is to patch the std library
modules to use sendall() where appropriate, rather than send().

Modules/socketmodule.c

index 9356b657c853209fbeaaacc414da5e48ee1b8a2f..37a167444a53f7fac733a8a8d214532d95f5692c 100644 (file)
@@ -59,6 +59,7 @@ Socket methods:
 - s.recv(buflen [,flags]) --> string
 - s.recvfrom(buflen [,flags]) --> string, sockaddr
 - s.send(string [,flags]) --> nbytes
+- s.sendall(string [,flags]) # tries to send everything in a loop
 - s.sendto(string, [flags,] sockaddr) --> nbytes
 - s.setblocking(0 | 1) --> None
 - s.setsockopt(level, optname, value) --> None
@@ -1421,10 +1422,45 @@ PySocketSock_send(PySocketSockObject *s, PyObject *args)
 }
 
 static char send_doc[] =
-"send(data[, flags])\n\
+"send(data[, flags]) -> count\n\
 \n\
 Send a data string to the socket.  For the optional flags\n\
-argument, see the Unix manual.";
+argument, see the Unix manual.  Return the number of bytes\n\
+sent; this may be less than len(data) if the network is busy.";
+
+
+/* s.sendall(data [,flags]) method */
+
+static PyObject *
+PySocketSock_sendall(PySocketSockObject *s, PyObject *args)
+{
+       char *buf;
+       int len, n, flags = 0, total = 0;
+       if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags))
+               return NULL;
+       Py_BEGIN_ALLOW_THREADS
+       do {
+               n = send(s->sock_fd, buf, len, flags);
+               if (n < 0)
+                       break;
+               total += n;
+               buf += n;
+               len -= n;
+       } while (len > 0);
+       Py_END_ALLOW_THREADS
+       if (n < 0)
+               return PySocket_Err();
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static char sendall_doc[] =
+"sendall(data[, flags])\n\
+\n\
+Send a data string to the socket.  For the optional flags\n\
+argument, see the Unix manual.  This calls send() repeatedly\n\
+until all data is sent.  If an error occurs, it's impossible\n\
+to tell how much data has been sent.";
 
 
 /* s.sendto(data, [flags,] sockaddr) method */
@@ -1524,6 +1560,8 @@ static PyMethodDef PySocketSock_methods[] = {
                        recvfrom_doc},
        {"send",        (PyCFunction)PySocketSock_send, METH_VARARGS,
                        send_doc},
+       {"sendall",     (PyCFunction)PySocketSock_sendall, METH_VARARGS,
+                       sendall_doc},
        {"sendto",      (PyCFunction)PySocketSock_sendto, METH_VARARGS,
                        sendto_doc},
        {"setblocking", (PyCFunction)PySocketSock_setblocking, METH_VARARGS,