summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_struct.c154
-rw-r--r--Modules/arraymodule.c6
-rw-r--r--Modules/socketmodule.c452
3 files changed, 436 insertions, 176 deletions
diff --git a/Modules/_struct.c b/Modules/_struct.c
index fb3e497..1ae2320 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -15,6 +15,7 @@ static PyTypeObject PyStructType;
typedef int Py_ssize_t;
#endif
+
/* PY_USE_INT_WHEN_POSSIBLE is an experimental flag that changes the
struct API to return int instead of long when possible. This is
often a significant performance improvement. */
@@ -24,7 +25,6 @@ typedef int Py_ssize_t;
/* The translation function for each format character is table driven */
-
typedef struct _formatdef {
char format;
int size;
@@ -1315,50 +1315,36 @@ s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
return s_unpack_internal(soself, buffer + offset);
}
-PyDoc_STRVAR(s_pack__doc__,
-"pack(v1, v2, ...) -> string\n\
-\n\
-Return a string containing values v1, v2, ... packed according to this\n\
-Struct's format. See struct.__doc__ for more on format strings.");
-static PyObject *
-s_pack(PyObject *self, PyObject *args)
+/*
+ * Guts of the pack function.
+ *
+ * Takes a struct object, a tuple of arguments, and offset in that tuple of
+ * argument for where to start processing the arguments for packing, and a
+ * character buffer for writing the packed string. The caller must insure
+ * that the buffer may contain the required length for packing the arguments.
+ * 0 is returned on success, 1 is returned if there is an error.
+ *
+ */
+static int
+s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf)
{
- PyStructObject *soself;
- PyObject *result;
- char *restart;
formatcode *code;
Py_ssize_t i;
-
- soself = (PyStructObject *)self;
- assert(PyStruct_Check(self));
- assert(soself->s_codes != NULL);
- if (args == NULL || !PyTuple_Check(args) ||
- PyTuple_GET_SIZE(args) != soself->s_len)
- {
- PyErr_Format(StructError,
- "pack requires exactly %d arguments", soself->s_len);
- return NULL;
- }
-
- result = PyString_FromStringAndSize((char *)NULL, soself->s_size);
- if (result == NULL)
- return NULL;
-
- restart = PyString_AS_STRING(result);
- memset(restart, '\0', soself->s_size);
- i = 0;
+
+ memset(buf, '\0', soself->s_size);
+ i = offset;
for (code = soself->s_codes; code->fmtdef != NULL; code++) {
Py_ssize_t n;
PyObject *v;
const formatdef *e = code->fmtdef;
- char *res = restart + code->offset;
+ char *res = buf + code->offset;
if (e->format == 's') {
v = PyTuple_GET_ITEM(args, i++);
if (!PyString_Check(v)) {
PyErr_SetString(StructError,
"argument for 's' must be a string");
- goto fail;
+ return -1;
}
n = PyString_GET_SIZE(v);
if (n > code->size)
@@ -1370,7 +1356,7 @@ s_pack(PyObject *self, PyObject *args)
if (!PyString_Check(v)) {
PyErr_SetString(StructError,
"argument for 'p' must be a string");
- goto fail;
+ return -1;
}
n = PyString_GET_SIZE(v);
if (n > (code->size - 1))
@@ -1383,16 +1369,109 @@ s_pack(PyObject *self, PyObject *args)
} else {
v = PyTuple_GET_ITEM(args, i++);
if (e->pack(res, v, e) < 0)
- goto fail;
+ return -1;
}
}
+ /* Success */
+ return 0;
+}
+
+
+PyDoc_STRVAR(s_pack__doc__,
+"pack(v1, v2, ...) -> string\n\
+\n\
+Return a string containing values v1, v2, ... packed according to this\n\
+Struct's format. See struct.__doc__ for more on format strings.");
+
+static PyObject *
+s_pack(PyObject *self, PyObject *args)
+{
+ PyStructObject *soself;
+ PyObject *result;
+
+ /* Validate arguments. */
+ soself = (PyStructObject *)self;
+ assert(PyStruct_Check(self));
+ assert(soself->s_codes != NULL);
+ if (args == NULL || !PyTuple_Check(args) ||
+ PyTuple_GET_SIZE(args) != soself->s_len)
+ {
+ PyErr_Format(StructError,
+ "pack requires exactly %d arguments", soself->s_len);
+ return NULL;
+ }
+
+ /* Allocate a new string */
+ result = PyString_FromStringAndSize((char *)NULL, soself->s_size);
+ if (result == NULL)
+ return NULL;
+
+ /* Call the guts */
+ if ( s_pack_internal(soself, args, 0, PyString_AS_STRING(result)) != 0 ) {
+ Py_DECREF(result);
+ return NULL;
+ }
+
return result;
+}
-fail:
- Py_DECREF(result);
- return NULL;
+PyDoc_STRVAR(s_pack_to__doc__,
+"pack_to(buffer, offset, v1, v2, ...)\n\
+\n\
+Pack the values v2, v2, ... according to this Struct's format, write \n\
+the packed bytes into the given buffer at the given offset. Note that \n\
+the offset is not an optional argument. See struct.__doc__ for \n\
+more on format strings.");
+
+static PyObject *
+s_pack_to(PyObject *self, PyObject *args)
+{
+ PyStructObject *soself;
+ char *buffer;
+ Py_ssize_t buffer_len, offset;
+
+ /* Validate arguments. +1 is for the first arg as buffer. */
+ soself = (PyStructObject *)self;
+ assert(PyStruct_Check(self));
+ assert(soself->s_codes != NULL);
+ if (args == NULL || !PyTuple_Check(args) ||
+ PyTuple_GET_SIZE(args) != (soself->s_len + 2))
+ {
+ PyErr_Format(StructError,
+ "pack_to requires exactly %d arguments",
+ (soself->s_len + 2));
+ return NULL;
+ }
+
+ /* Extract a writable memory buffer from the first argument */
+ if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0),
+ (void**)&buffer, &buffer_len) == -1 ) {
+ return NULL;
+ }
+ assert( buffer_len >= 0 );
+
+ /* Extract the offset from the first argument */
+ offset = PyInt_AsLong(PyTuple_GET_ITEM(args, 1));
+
+ /* Support negative offsets. */
+ if (offset < 0)
+ offset += buffer_len;
+
+ /* Check boundaries */
+ if (offset < 0 || (buffer_len - offset) < soself->s_size) {
+ PyErr_Format(StructError,
+ "pack_to requires a buffer of at least %d bytes",
+ soself->s_size);
+ return NULL;
+ }
+ /* Call the guts */
+ if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) {
+ return NULL;
+ }
+
+ return Py_None;
}
@@ -1400,6 +1479,7 @@ fail:
static struct PyMethodDef s_methods[] = {
{"pack", (PyCFunction)s_pack, METH_VARARGS, s_pack__doc__},
+ {"pack_to", (PyCFunction)s_pack_to, METH_VARARGS, s_pack_to__doc__},
{"unpack", (PyCFunction)s_unpack, METH_O, s_unpack__doc__},
{"unpack_from", (PyCFunction)s_unpack_from, METH_KEYWORDS, s_unpack_from__doc__},
{NULL, NULL} /* sentinel */
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 52a7f5e..af12769 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -1975,9 +1975,9 @@ static PyTypeObject Arraytype = {
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)array_repr, /* tp_repr */
- 0, /* tp_as _number*/
- &array_as_sequence, /* tp_as _sequence*/
- &array_as_mapping, /* tp_as _mapping*/
+ 0, /* tp_as_number*/
+ &array_as_sequence, /* tp_as_sequence*/
+ &array_as_mapping, /* tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index b77f41e..164a5d1 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -104,7 +104,10 @@ gettimeout() -- return timeout or None\n\
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 @@ shutdown(how) -- shut down traffic in one or both directions\n\
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 @@ shutdown(how) -- shut down traffic in one or both directions\n\
#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 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
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 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
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 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
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. */
@@ -2135,95 +2138,126 @@ The mode and buffersize arguments are as for the built-in open() function.");
#endif /* NO_DUP */
-
-/* s.recv(nbytes [,flags]) method */
-
-static PyObject *
-sock_recv(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.
+ */
+static int
+sock_recv_guts(PySocketSockObject *s, char* cbuf, int len, int flags)
{
- int len, n = 0, flags = 0, timeout;
- PyObject *buf;
+ int timeout, outlen = 0;
#ifdef __VMS
- int read_length;
+ int remaining, nread;
char *read_buf;
#endif
- if (!PyArg_ParseTuple(args, "i|i:recv", &len, &flags))
- return NULL;
-
- if (len < 0) {
- PyErr_SetString(PyExc_ValueError,
- "negative buffersize in recv");
- return NULL;
+ if (!IS_SELECTABLE(s)) {
+ select_error();
+ return -1;
}
- buf = PyString_FromStringAndSize((char *) 0, len);
- if (buf == NULL)
- return NULL;
-
- if (!IS_SELECTABLE(s))
- return select_error();
-
#ifndef __VMS
Py_BEGIN_ALLOW_THREADS
timeout = internal_select(s, 0);
if (!timeout)
- n = recv(s->sock_fd, PyString_AS_STRING(buf), len, flags);
+ outlen = recv(s->sock_fd, cbuf, len, flags);
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();
+ if (outlen < 0) {
+ /* Note: the call to errorhandler() ALWAYS indirectly returned
+ NULL, so ignore its return value */
+ s->errorhandler();
+ return -1;
}
- if (n != len)
- _PyString_Resize(&buf, n);
#else
- read_buf = PyString_AsString(buf);
- read_length = len;
- while (read_length != 0) {
+ read_buf = cbuf;
+ remaining = len;
+ while (remaining != 0) {
unsigned int segment;
- segment = read_length /SEGMENT_SIZE;
+ segment = remaining /SEGMENT_SIZE;
if (segment != 0) {
segment = SEGMENT_SIZE;
}
else {
- segment = read_length;
+ segment = remaining;
}
Py_BEGIN_ALLOW_THREADS
timeout = internal_select(s, 0);
if (!timeout)
- n = recv(s->sock_fd, read_buf, segment, flags);
+ nread = recv(s->sock_fd, read_buf, segment, flags);
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();
+ if (nread < 0) {
+ s->errorhandler();
+ return -1;
}
- if (n != read_length) {
- read_buf += n;
+ if (nread != remaining) {
+ read_buf += nread;
break;
}
- read_length -= segment;
+ remaining -= segment;
read_buf += segment;
}
- if (_PyString_Resize(&buf, (read_buf - PyString_AsString(buf))) < 0)
- {
- return NULL;
- }
+ outlen = read_buf - cbuf;
#endif /* !__VMS */
+
+ return outlen;
+}
+
+
+/* s.recv(nbytes [,flags]) method */
+
+static PyObject *
+sock_recv(PySocketSockObject *s, PyObject *args)
+{
+ int recvlen, flags = 0, outlen;
+ PyObject *buf;
+
+ if (!PyArg_ParseTuple(args, "i|i:recv", &recvlen, &flags))
+ return NULL;
+
+ if (recvlen < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "negative buffersize in recv");
+ return NULL;
+ }
+
+ /* Allocate a new string. */
+ buf = PyString_FromStringAndSize((char *) 0, recvlen);
+ if (buf == NULL)
+ return NULL;
+
+ /* Call the guts */
+ outlen = sock_recv_guts(s, PyString_AsString(buf), recvlen, flags);
+ if (outlen < 0) {
+ /* An error occured, release the string and return an
+ error. */
+ Py_DECREF(buf);
+ return NULL;
+ }
+ 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. */
+ return NULL;
+ }
+
return buf;
}
@@ -2236,29 +2270,90 @@ at least one byte is available or until the remote end is closed. When\n\
the remote end is closed and all data is read, return the empty string.");
-/* s.recvfrom(nbytes [,flags]) method */
+/* s.recv_buf(buffer, [nbytes [,flags]]) method */
-static PyObject *
-sock_recvfrom(PySocketSockObject *s, PyObject *args)
+static PyObject*
+sock_recv_buf(PySocketSockObject *s, PyObject *args, PyObject *kwds)
{
- sock_addr_t addrbuf;
- PyObject *buf = NULL;
- PyObject *addr = NULL;
- PyObject *ret = NULL;
- int len, n = 0, flags = 0, timeout;
- socklen_t addrlen;
+ static char *kwlist[] = {"buffer", "nbytes", "flags", 0};
- if (!PyArg_ParseTuple(args, "i|i:recvfrom", &len, &flags))
+ int recvlen = 0, flags = 0, readlen;
+ char *buf;
+ int buflen;
+
+ /* Get the buffer's memory */
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#|ii:recv", kwlist,
+ &buf, &buflen, &recvlen, &flags))
return NULL;
+ assert(buf != 0 && buflen > 0);
- if (!getsockaddrlen(s, &addrlen))
+ if (recvlen < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "negative buffersize in recv");
return NULL;
- buf = PyString_FromStringAndSize((char *) 0, len);
- if (buf == NULL)
+ }
+ if (recvlen == 0) {
+ /* If nbytes was not specified, use the buffer's length */
+ recvlen = buflen;
+ }
+
+ /* Check if the buffer is large enough */
+ if (buflen < recvlen) {
+ PyErr_SetString(PyExc_ValueError,
+ "buffer too small for requested bytes");
return NULL;
+ }
- if (!IS_SELECTABLE(s))
- return select_error();
+ /* Call the guts */
+ readlen = sock_recv_guts(s, buf, recvlen, flags);
+ if (readlen < 0) {
+ /* Return an error. */
+ return NULL;
+ }
+
+ /* Return the number of bytes read. Note that we do not do anything
+ special here in the case that readlen < recvlen. */
+ return PyInt_FromLong(readlen);
+}
+
+PyDoc_STRVAR(recv_buf_doc,
+"recv_buf(buffer, [nbytes[, flags]]) -> nbytes_read\n\
+\n\
+A version of recv() that stores its data into a buffer rather than creating \n\
+a new string. Receive up to buffersize bytes from the socket. If buffersize \n\
+is not specified (or 0), receive up to the size available in the given buffer.\n\
+\n\
+See recv() for documentation about the flags.");
+
+
+/*
+ * 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;
+ int n = 0, timeout;
+ socklen_t addrlen;
+
+ *addr = NULL;
+
+ if (!getsockaddrlen(s, &addrlen))
+ return -1;
+
+ if (!IS_SELECTABLE(s)) {
+ select_error();
+ return -1;
+ }
Py_BEGIN_ALLOW_THREADS
memset(&addrbuf, 0, addrlen);
@@ -2266,41 +2361,71 @@ sock_recvfrom(PySocketSockObject *s, PyObject *args)
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;
+
+ buf = PyString_FromStringAndSize((char *) 0, recvlen);
+ if (buf == NULL)
return NULL;
- if (!(addr = makesockaddr(s->sock_fd, (struct sockaddr *) &addrbuf,
- addrlen, s->sock_proto)))
+ 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;
}
@@ -2309,6 +2434,57 @@ PyDoc_STRVAR(recvfrom_doc,
\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 *
@@ -2503,59 +2679,63 @@ of the socket (flag == SHUT_WR), or both ends (flag == SHUT_RDWR).");
/* 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},
-#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},
+ {"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},
#ifndef NO_DUP
- {"makefile", (PyCFunction)sock_makefile, METH_VARARGS,
- makefile_doc},
-#endif
- {"recv", (PyCFunction)sock_recv, METH_VARARGS,
- recv_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},
+ {"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},
+ {"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 */
};
@@ -3401,7 +3581,7 @@ socket_inet_aton(PyObject *self, PyObject *args)
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 */
@@ -3476,7 +3656,7 @@ socket_inet_pton(PyObject *self, PyObject *args)
"can't use AF_INET6, IPv6 is disabled");
return NULL;
}
-#endif
+#endif
retval = inet_pton(af, ip, packed);
if (retval < 0) {
@@ -3499,7 +3679,7 @@ socket_inet_pton(PyObject *self, PyObject *args)
return NULL;
}
}
-
+
PyDoc_STRVAR(inet_ntop_doc,
"inet_ntop(af, packed_ip) -> string formatted IP address\n\
\n\
@@ -3517,7 +3697,7 @@ socket_inet_ntop(PyObject *self, PyObject *args)
#else
char ip[INET_ADDRSTRLEN + 1];
#endif
-
+
/* Guarantee NUL-termination for PyString_FromString() below */
memset((void *) &ip[0], '\0', sizeof(ip));
@@ -3595,7 +3775,7 @@ socket_getaddrinfo(PyObject *self, PyObject *args)
} 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;
}