[Python-checkins] r46162 - in python/branches/blais-bytebuf: Lib/socket.py Lib/test/test_socket.py Modules/socketmodule.c
martin.blais
python-checkins at python.org
Wed May 24 13:11:28 CEST 2006
Author: martin.blais
Date: Wed May 24 13:11:27 2006
New Revision: 46162
Modified:
python/branches/blais-bytebuf/Lib/socket.py
python/branches/blais-bytebuf/Lib/test/test_socket.py
python/branches/blais-bytebuf/Modules/socketmodule.c
Log:
Implemented recvfrom_buf
Modified: python/branches/blais-bytebuf/Lib/socket.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/socket.py (original)
+++ python/branches/blais-bytebuf/Lib/socket.py Wed May 24 13:11:27 2006
@@ -140,7 +140,9 @@
__doc__ = _realsocket.__doc__
- __slots__ = ["_sock", "send", "recv", "recv_buf", "sendto", "recvfrom",
+ __slots__ = ["_sock",
+ "recv", "recv_buf", "recvfrom_buf",
+ "send", "sendto", "recvfrom",
"__weakref__"]
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
@@ -152,6 +154,7 @@
self.recv_buf = self._sock.recv_buf
self.sendto = self._sock.sendto
self.recvfrom = self._sock.recvfrom
+ self.recvfrom_buf = self._sock.recvfrom_buf
def close(self):
self._sock = _closedsocket()
Modified: python/branches/blais-bytebuf/Lib/test/test_socket.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/test/test_socket.py (original)
+++ python/branches/blais-bytebuf/Lib/test/test_socket.py Wed May 24 13:11:27 2006
@@ -866,24 +866,25 @@
buf = array.array('c', ' '*1024)
nbytes = self.cli_conn.recv_buf(buf)
self.assertEqual(nbytes, len(MSG))
- trunc = buf.tostring()[:len(MSG)]
- self.assertEqual(trunc, MSG)
+ msg = buf.tostring()[:len(MSG)]
+ self.assertEqual(msg, MSG)
def _testRecv(self):
# Send using a read-only buffer.
buf = buffer(MSG)
self.serv_conn.send(buf)
- def testRecvBB(self):
- # Receive into the buffer of an array class.
+ def testRecv2(self):
+ # Receive into a bytebuf.
buf = bytebuf.bytebuf(1024)
nbytes = self.cli_conn.recv_buf(buf)
self.assertEqual(nbytes, len(MSG))
- trunc = str(buf)[:len(MSG)]
- self.assertEqual(trunc, MSG)
+ msg = str(buf)[:len(MSG)]
+ self.assertEqual(msg, MSG)
- def _testRecvBB(self):
- # Send using a read-only buffer.
+ def _testRecv2(self):
+ # Send using a bytebuf.
+## FIXME: todo
## buf = bytebuf.bytebuf(MSG)
self.serv_conn.send(MSG)
@@ -897,13 +898,31 @@
## def _testOverFlowRecv(self):
## self.serv_conn.send(MSG)
-## def testRecvFrom(self):
-## # Testing large recvfrom() over TCP
-## msg, addr = self.cli_conn.recvfrom(1024)
-## self.assertEqual(msg, MSG)
+ def testRecvFrom(self):
+ # Testing large recvfrom() over TCP
+ buf = array.array('c', ' '*1024)
+ nbytes, addr = self.cli_conn.recvfrom_buf(buf)
+ self.assertEqual(nbytes, len(MSG))
+ msg = buf.tostring()[:len(MSG)]
+ self.assertEqual(msg, MSG)
-## def _testRecvFrom(self):
-## self.serv_conn.send(MSG)
+ def _testRecvFrom(self):
+ buf = buffer(MSG)
+ self.serv_conn.send(buf)
+
+ def testRecvFrom2(self):
+ # Testing large recvfrom() over TCP
+ buf = bytebuf.bytebuf(1024)
+ nbytes, addr = self.cli_conn.recvfrom_buf(buf)
+ self.assertEqual(nbytes, len(MSG))
+ msg = str(buf)[:len(MSG)]
+ self.assertEqual(msg, MSG)
+
+ def _testRecvFrom2(self):
+ # Send using a bytebuf.
+## FIXME: todo
+## buf = bytebuf.bytebuf(MSG)
+ self.serv_conn.send(MSG)
## def testOverFlowRecvFrom(self):
## # Testing recvfrom() in chunks over TCP
Modified: python/branches/blais-bytebuf/Modules/socketmodule.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/socketmodule.c (original)
+++ python/branches/blais-bytebuf/Modules/socketmodule.c Wed May 24 13:11:27 2006
@@ -104,7 +104,10 @@
listen(n) -- start listening for incoming connections\n\
makefile([mode, [bufsize]]) -- return a file object for the socket [*]\n\
recv(buflen[, flags]) -- receive data\n\
-recvfrom(buflen[, flags]) -- receive data and sender's address\n\
+recv_buf(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\n\
+recvfrom(buflen[, flags]) -- receive data and sender\'s address\n\
+recvfrom_buf(buffer[, nbytes, [, flags])\n\
+ -- receive data and sender\'s address (into a buffer)\n\
sendall(data[, flags]) -- send all data\n\
send(data[, flags]) -- send data, may not send all of it\n\
sendto(data[, flags], addr) -- send data to a given address\n\
@@ -205,7 +208,7 @@
functions are declared correctly if compiling with
MIPSPro 7.x in ANSI C mode (default) */
-/* XXX Using _SGIAPI is the wrong thing,
+/* XXX Using _SGIAPI is the wrong thing,
but I don't know what the right thing is. */
#undef _SGIAPI /* to avoid warning */
#define _SGIAPI 1
@@ -223,8 +226,8 @@
#include <netdb.h>
#endif
-/* Irix 6.5 fails to define this variable at all. This is needed
- for both GCC and SGI's compiler. I'd say that the SGI headers
+/* Irix 6.5 fails to define this variable at all. This is needed
+ for both GCC and SGI's compiler. I'd say that the SGI headers
are just busted. Same thing for Solaris. */
#if (defined(__sgi) || defined(sun)) && !defined(INET_ADDRSTRLEN)
#define INET_ADDRSTRLEN 16
@@ -1194,10 +1197,10 @@
args->ob_type->tp_name);
return 0;
}
- if (!PyArg_ParseTuple(args, "eti:getsockaddrarg",
+ if (!PyArg_ParseTuple(args, "eti:getsockaddrarg",
"idna", &host, &port))
return 0;
- result = setipaddr(host, (struct sockaddr *)addr,
+ result = setipaddr(host, (struct sockaddr *)addr,
sizeof(*addr), AF_INET);
PyMem_Free(host);
if (result < 0)
@@ -1225,12 +1228,12 @@
args->ob_type->tp_name);
return 0;
}
- if (!PyArg_ParseTuple(args, "eti|ii",
+ if (!PyArg_ParseTuple(args, "eti|ii",
"idna", &host, &port, &flowinfo,
&scope_id)) {
return 0;
}
- result = setipaddr(host, (struct sockaddr *)addr,
+ result = setipaddr(host, (struct sockaddr *)addr,
sizeof(*addr), AF_INET6);
PyMem_Free(host);
if (result < 0)
@@ -1839,7 +1842,7 @@
int res_size = sizeof res;
/* It must be in the exception set */
assert(FD_ISSET(s->sock_fd, &fds_exc));
- if (0 == getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
+ if (0 == getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
(char *)&res, &res_size))
/* getsockopt also clears WSAGetLastError,
so reset it back. */
@@ -2323,29 +2326,34 @@
See recv() for documentation about the flags.");
-/* s.recvfrom(nbytes [,flags]) method */
-
-static PyObject *
-sock_recvfrom(PySocketSockObject *s, PyObject *args)
+/*
+ * This is the guts of the recv() and recv_buf() methods, which reads into a
+ * char buffer. If you have any inc/def ref to do to the objects that contain
+ * the buffer, do it in the caller. This function returns the number of bytes
+ * succesfully read. If there was an error, it returns -1. Note that it is
+ * also possible that we return a number of bytes smaller than the request
+ * bytes.
+ *
+ * 'addr' is a return value for the address object. Note that you must decref
+ * it yourself.
+ */
+static int
+sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, int len, int flags,
+ PyObject** addr)
{
sock_addr_t addrbuf;
- PyObject *buf = NULL;
- PyObject *addr = NULL;
- PyObject *ret = NULL;
- int len, n = 0, flags = 0, timeout;
+ int n = 0, timeout;
socklen_t addrlen;
- if (!PyArg_ParseTuple(args, "i|i:recvfrom", &len, &flags))
- return NULL;
+ *addr = NULL;
if (!getsockaddrlen(s, &addrlen))
- return NULL;
- buf = PyString_FromStringAndSize((char *) 0, len);
- if (buf == NULL)
- return NULL;
+ return -1;
- if (!IS_SELECTABLE(s))
- return select_error();
+ if (!IS_SELECTABLE(s)) {
+ select_error();
+ return -1;
+ }
Py_BEGIN_ALLOW_THREADS
memset(&addrbuf, 0, addrlen);
@@ -2353,41 +2361,71 @@
if (!timeout) {
#ifndef MS_WINDOWS
#if defined(PYOS_OS2) && !defined(PYCC_GCC)
- n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
+ n = recvfrom(s->sock_fd, cbuf, len, flags,
(struct sockaddr *) &addrbuf, &addrlen);
#else
- n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
+ n = recvfrom(s->sock_fd, cbuf, len, flags,
(void *) &addrbuf, &addrlen);
#endif
#else
- n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
+ n = recvfrom(s->sock_fd, cbuf, len, flags,
(struct sockaddr *) &addrbuf, &addrlen);
#endif
}
Py_END_ALLOW_THREADS
if (timeout) {
- Py_DECREF(buf);
PyErr_SetString(socket_timeout, "timed out");
- return NULL;
+ return -1;
}
if (n < 0) {
- Py_DECREF(buf);
- return s->errorhandler();
+ s->errorhandler();
+ return -1;
}
- if (n != len && _PyString_Resize(&buf, n) < 0)
+ if (!(*addr = makesockaddr(s->sock_fd, (struct sockaddr *) &addrbuf,
+ addrlen, s->sock_proto)))
+ return -1;
+
+ return n;
+}
+
+/* s.recvfrom(nbytes [,flags]) method */
+
+static PyObject *
+sock_recvfrom(PySocketSockObject *s, PyObject *args)
+{
+ PyObject *buf = NULL;
+ PyObject *addr = NULL;
+ PyObject *ret = NULL;
+ int recvlen, outlen, flags = 0;
+
+ if (!PyArg_ParseTuple(args, "i|i:recvfrom", &recvlen, &flags))
return NULL;
- if (!(addr = makesockaddr(s->sock_fd, (struct sockaddr *) &addrbuf,
- addrlen, s->sock_proto)))
+ buf = PyString_FromStringAndSize((char *) 0, recvlen);
+ if (buf == NULL)
+ return NULL;
+
+ outlen = sock_recvfrom_guts(s, PyString_AS_STRING(buf),
+ recvlen, flags, &addr);
+ if (outlen < 0) {
goto finally;
+ }
+
+ if (outlen != recvlen) {
+ /* We did not read as many bytes as we anticipated, resize the
+ string if possible and be succesful. */
+ if (_PyString_Resize(&buf, outlen) < 0)
+ /* Oopsy, not so succesful after all. */
+ goto finally;
+ }
ret = PyTuple_Pack(2, buf, addr);
finally:
- Py_XDECREF(addr);
Py_XDECREF(buf);
+ Py_XDECREF(addr);
return ret;
}
@@ -2396,6 +2434,57 @@
\n\
Like recv(buffersize, flags) but also return the sender's address info.");
+
+/* s.recvfrom_buf(buffer[, nbytes [,flags]]) method */
+
+static PyObject *
+sock_recvfrom_buf(PySocketSockObject *s, PyObject *args, PyObject* kwds)
+{
+ static char *kwlist[] = {"buffer", "nbytes", "flags", 0};
+
+ int recvlen = 0, flags = 0, readlen;
+ char *buf;
+ int buflen;
+
+ PyObject *addr = NULL;
+ PyObject *ret = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#|ii:recvfrom", kwlist,
+ &buf, &buflen, &recvlen, &flags))
+ return NULL;
+ assert(buf != 0 && buflen > 0);
+
+ if (recvlen < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "negative buffersize in recv");
+ return NULL;
+ }
+ if (recvlen == 0) {
+ /* If nbytes was not specified, use the buffer's length */
+ recvlen = buflen;
+ }
+
+ readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr);
+ if (readlen < 0) {
+ /* Return an error */
+ goto finally;
+ }
+
+ /* Return the number of bytes read and the address. Note that we do
+ not do anything special here in the case that readlen < recvlen. */
+ ret = PyTuple_Pack(2, PyInt_FromLong(readlen), addr);
+
+finally:
+ Py_XDECREF(addr);
+ return ret;
+}
+
+PyDoc_STRVAR(recvfrom_buf_doc,
+"recvfrom_buf(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\
+\n\
+Like recv_buf(buffer[, nbytes[, flags]]) but also return the sender's address info.");
+
+
/* s.send(data [,flags]) method */
static PyObject *
@@ -2590,61 +2679,63 @@
/* List of methods for socket objects */
static PyMethodDef sock_methods[] = {
- {"accept", (PyCFunction)sock_accept, METH_NOARGS,
- accept_doc},
- {"bind", (PyCFunction)sock_bind, METH_O,
- bind_doc},
- {"close", (PyCFunction)sock_close, METH_NOARGS,
- close_doc},
- {"connect", (PyCFunction)sock_connect, METH_O,
- connect_doc},
- {"connect_ex", (PyCFunction)sock_connect_ex, METH_O,
- connect_ex_doc},
+ {"accept", (PyCFunction)sock_accept, METH_NOARGS,
+ accept_doc},
+ {"bind", (PyCFunction)sock_bind, METH_O,
+ bind_doc},
+ {"close", (PyCFunction)sock_close, METH_NOARGS,
+ close_doc},
+ {"connect", (PyCFunction)sock_connect, METH_O,
+ connect_doc},
+ {"connect_ex", (PyCFunction)sock_connect_ex, METH_O,
+ connect_ex_doc},
#ifndef NO_DUP
- {"dup", (PyCFunction)sock_dup, METH_NOARGS,
- dup_doc},
+ {"dup", (PyCFunction)sock_dup, METH_NOARGS,
+ dup_doc},
#endif
- {"fileno", (PyCFunction)sock_fileno, METH_NOARGS,
- fileno_doc},
+ {"fileno", (PyCFunction)sock_fileno, METH_NOARGS,
+ fileno_doc},
#ifdef HAVE_GETPEERNAME
- {"getpeername", (PyCFunction)sock_getpeername,
- METH_NOARGS, getpeername_doc},
+ {"getpeername", (PyCFunction)sock_getpeername,
+ METH_NOARGS, getpeername_doc},
#endif
- {"getsockname", (PyCFunction)sock_getsockname,
- METH_NOARGS, getsockname_doc},
- {"getsockopt", (PyCFunction)sock_getsockopt, METH_VARARGS,
- getsockopt_doc},
- {"listen", (PyCFunction)sock_listen, METH_O,
- listen_doc},
+ {"getsockname", (PyCFunction)sock_getsockname,
+ METH_NOARGS, getsockname_doc},
+ {"getsockopt", (PyCFunction)sock_getsockopt, METH_VARARGS,
+ getsockopt_doc},
+ {"listen", (PyCFunction)sock_listen, METH_O,
+ listen_doc},
#ifndef NO_DUP
- {"makefile", (PyCFunction)sock_makefile, METH_VARARGS,
- makefile_doc},
+ {"makefile", (PyCFunction)sock_makefile, METH_VARARGS,
+ makefile_doc},
#endif
- {"recv", (PyCFunction)sock_recv, METH_VARARGS,
- recv_doc},
- {"recv_buf", (PyCFunction)sock_recv_buf, METH_VARARGS | METH_KEYWORDS,
- recv_buf_doc},
- {"recvfrom", (PyCFunction)sock_recvfrom, METH_VARARGS,
- recvfrom_doc},
- {"send", (PyCFunction)sock_send, METH_VARARGS,
- send_doc},
- {"sendall", (PyCFunction)sock_sendall, METH_VARARGS,
- sendall_doc},
- {"sendto", (PyCFunction)sock_sendto, METH_VARARGS,
- sendto_doc},
- {"setblocking", (PyCFunction)sock_setblocking, METH_O,
- setblocking_doc},
- {"settimeout", (PyCFunction)sock_settimeout, METH_O,
- settimeout_doc},
- {"gettimeout", (PyCFunction)sock_gettimeout, METH_NOARGS,
- gettimeout_doc},
- {"setsockopt", (PyCFunction)sock_setsockopt, METH_VARARGS,
- setsockopt_doc},
- {"shutdown", (PyCFunction)sock_shutdown, METH_O,
- shutdown_doc},
+ {"recv", (PyCFunction)sock_recv, METH_VARARGS,
+ recv_doc},
+ {"recv_buf", (PyCFunction)sock_recv_buf, METH_VARARGS | METH_KEYWORDS,
+ recv_buf_doc},
+ {"recvfrom", (PyCFunction)sock_recvfrom, METH_VARARGS,
+ recvfrom_doc},
+ {"recvfrom_buf", (PyCFunction)sock_recvfrom_buf, METH_VARARGS | METH_KEYWORDS,
+ recvfrom_buf_doc},
+ {"send", (PyCFunction)sock_send, METH_VARARGS,
+ send_doc},
+ {"sendall", (PyCFunction)sock_sendall, METH_VARARGS,
+ sendall_doc},
+ {"sendto", (PyCFunction)sock_sendto, METH_VARARGS,
+ sendto_doc},
+ {"setblocking", (PyCFunction)sock_setblocking, METH_O,
+ setblocking_doc},
+ {"settimeout", (PyCFunction)sock_settimeout, METH_O,
+ settimeout_doc},
+ {"gettimeout", (PyCFunction)sock_gettimeout, METH_NOARGS,
+ gettimeout_doc},
+ {"setsockopt", (PyCFunction)sock_setsockopt, METH_VARARGS,
+ setsockopt_doc},
+ {"shutdown", (PyCFunction)sock_shutdown, METH_O,
+ shutdown_doc},
#ifdef RISCOS
- {"sleeptaskw", (PyCFunction)sock_sleeptaskw, METH_O,
- sleeptaskw_doc},
+ {"sleeptaskw", (PyCFunction)sock_sleeptaskw, METH_O,
+ sleeptaskw_doc},
#endif
{NULL, NULL} /* sentinel */
};
@@ -3490,7 +3581,7 @@
if (strcmp(ip_addr, "255.255.255.255") == 0) {
packed_addr = 0xFFFFFFFF;
} else {
-
+
packed_addr = inet_addr(ip_addr);
if (packed_addr == INADDR_NONE) { /* invalid address */
@@ -3565,7 +3656,7 @@
"can't use AF_INET6, IPv6 is disabled");
return NULL;
}
-#endif
+#endif
retval = inet_pton(af, ip, packed);
if (retval < 0) {
@@ -3588,7 +3679,7 @@
return NULL;
}
}
-
+
PyDoc_STRVAR(inet_ntop_doc,
"inet_ntop(af, packed_ip) -> string formatted IP address\n\
\n\
@@ -3606,7 +3697,7 @@
#else
char ip[INET_ADDRSTRLEN + 1];
#endif
-
+
/* Guarantee NUL-termination for PyString_FromString() below */
memset((void *) &ip[0], '\0', sizeof(ip));
@@ -3684,7 +3775,7 @@
} else if (PyString_Check(hobj)) {
hptr = PyString_AsString(hobj);
} else {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_TypeError,
"getaddrinfo() argument 1 must be string or None");
return NULL;
}
More information about the Python-checkins
mailing list