summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/socket_wrapper/py_socket_wrapper.c876
-rw-r--r--lib/socket_wrapper/socket.py52
-rw-r--r--lib/socket_wrapper/wscript_build10
3 files changed, 938 insertions, 0 deletions
diff --git a/lib/socket_wrapper/py_socket_wrapper.c b/lib/socket_wrapper/py_socket_wrapper.c
new file mode 100644
index 0000000000..405a43a81d
--- /dev/null
+++ b/lib/socket_wrapper/py_socket_wrapper.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright (C) Amitay Isaacs 2011
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ Python interface to socket wrapper library.
+
+ Passes all socket communication over unix domain sockets if the environment
+ variable SOCKET_WRAPPER_DIR is set.
+*/
+
+#include <Python.h>
+#include <pytalloc.h>
+#include "replace/replace.h"
+#include "system/network.h"
+#include "socket_wrapper.h"
+
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#endif
+
+#ifndef Py_TYPE /* Py_TYPE is only available on Python > 2.6 */
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
+
+#ifndef PY_CHECK_TYPE
+#define PY_CHECK_TYPE(type, var, fail) \
+ if (!PyObject_TypeCheck(var, type)) {\
+ PyErr_Format(PyExc_TypeError, __location__ ": Expected type '%s' for '%s' of type '%s'", (type)->tp_name, #var, Py_TYPE(var)->tp_name); \
+ fail; \
+ }
+#endif
+
+staticforward PyTypeObject PySocket;
+
+static PyObject *py_socket_error;
+
+void initsocket_wrapper(void);
+
+static PyObject *py_socket_addr_to_tuple(struct sockaddr *addr, socklen_t len)
+{
+ char host[256];
+ char service[8];
+ int status;
+ PyObject *pyaddr;
+
+ status = getnameinfo(addr, len, host, 255, service, 7, NI_NUMERICHOST|NI_NUMERICSERV);
+ if (status < 0) {
+ PyErr_SetString(py_socket_error, gai_strerror(status));
+ return NULL;
+ }
+
+ pyaddr = PyTuple_New(2);
+ if (pyaddr == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ PyTuple_SetItem(pyaddr, 0, PyString_FromString(host));
+ PyTuple_SetItem(pyaddr, 1, PyInt_FromLong(atoi(service)));
+
+ return pyaddr;
+}
+
+static bool py_socket_tuple_to_addr(PyObject *pyaddr, struct sockaddr *addr, socklen_t *len)
+{
+ const char *host;
+ char *service;
+ in_port_t port;
+ struct addrinfo *ainfo;
+ int status;
+
+ if (!PyTuple_Check(pyaddr)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a tuple");
+ return false;
+ }
+
+ if (!PyArg_ParseTuple(pyaddr, "sH", &host, &port)) {
+ return false;
+ }
+
+ service = talloc_asprintf(NULL, "%d", port);
+ if (service == NULL) {
+ PyErr_NoMemory();
+ return false;
+ }
+
+ status = getaddrinfo(host, service, NULL, &ainfo);
+ if (status < 0) {
+ talloc_free(service);
+ PyErr_SetString(py_socket_error, gai_strerror(status));
+ return false;
+ }
+
+ talloc_free(service);
+
+ memcpy(addr, ainfo->ai_addr, sizeof(struct sockaddr));
+ *len = ainfo->ai_addrlen;
+
+ freeaddrinfo(ainfo);
+ return true;
+}
+
+
+static PyObject *py_socket_accept(pytalloc_Object *self, PyObject *args)
+{
+ int *sock, *new_sock;
+ struct sockaddr addr;
+ socklen_t addrlen;
+ PyObject *pysocket;
+ PyObject *pyaddr;
+ PyObject *pyret;
+
+ sock = pytalloc_get_ptr(self);
+
+ new_sock = talloc_zero(NULL, int);
+ if (new_sock == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ *new_sock = swrap_accept(*sock, &addr, &addrlen);
+ if (*new_sock < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ if ((pysocket = pytalloc_steal(&PySocket, new_sock)) == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ pyret = PyTuple_New(2);
+ if (pyret == NULL) {
+ Py_DECREF(pysocket);
+ return PyErr_NoMemory();
+ }
+
+ pyaddr = py_socket_addr_to_tuple(&addr, addrlen);
+ if (pyaddr == NULL) {
+ Py_DECREF(pysocket);
+ Py_DECREF(pysocket);
+ return NULL;
+ }
+
+ PyTuple_SetItem(pyret, 0, pysocket);
+ PyTuple_SetItem(pyret, 1, pyaddr);
+ return pyret;
+}
+
+static PyObject *py_socket_bind(pytalloc_Object *self, PyObject *args)
+{
+ PyObject *pyaddr;
+ int *sock;
+ int status;
+ struct sockaddr addr;
+ socklen_t addrlen;
+
+ if (!PyArg_ParseTuple(args, "O:bind", &pyaddr)) {
+ return NULL;
+ }
+
+ if (!py_socket_tuple_to_addr(pyaddr, &addr, &addrlen)) {
+ return NULL;
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_bind(*sock, &addr, addrlen);
+ if (status < 0) {
+ PyErr_SetString(py_socket_error, "Unable to bind");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_socket_close(pytalloc_Object *self, PyObject *args)
+{
+ int *sock;
+ int status;
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_close(*sock);
+ if (status < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_socket_connect(pytalloc_Object *self, PyObject *args)
+{
+ int *sock;
+ PyObject *pyaddr;
+ struct sockaddr addr;
+ socklen_t addrlen;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "O:connect", &pyaddr)) {
+ return NULL;
+ }
+
+ if (!py_socket_tuple_to_addr(pyaddr, &addr, &addrlen)) {
+ return NULL;
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_connect(*sock, &addr, addrlen);
+ if (status < 0) {
+ PyErr_SetFromErrno(py_socket_error);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_socket_connect_ex(pytalloc_Object *self, PyObject *args)
+{
+ int *sock;
+ PyObject *pyaddr;
+ struct sockaddr addr;
+ socklen_t addrlen;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "O:connect", &pyaddr)) {
+ return NULL;
+ }
+
+ if (!py_socket_tuple_to_addr(pyaddr, &addr, &addrlen)) {
+ return NULL;
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_connect(*sock, &addr, addrlen);
+ if (status < 0) {
+ return Py_BuildValue("%d", errno);
+ }
+
+ return Py_BuildValue("%d", 0);
+}
+
+static PyObject *py_socket_dup(pytalloc_Object *self, PyObject *args)
+{
+ int *sock, *new_sock;
+ PyObject *pysocket;
+
+ sock = pytalloc_get_ptr(self);
+
+ new_sock = talloc_zero(NULL, int);
+ if (new_sock == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ *new_sock = swrap_dup(*sock);
+ if (*new_sock < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ pysocket = pytalloc_steal(&PySocket, new_sock);
+ if (pysocket == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ return pysocket;
+}
+
+static PyObject *py_socket_dup2(pytalloc_Object *self, PyObject *args)
+{
+ int *sock, *new_sock;
+ PyObject *pysocket;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "O", &pysocket)) {
+ return NULL;
+ }
+
+ PY_CHECK_TYPE(&PySocket, pysocket, return NULL);
+
+ sock = pytalloc_get_ptr(self);
+ new_sock = pytalloc_get_ptr(pysocket);
+
+ status = swrap_dup2(*sock, *new_sock);
+ if (status < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_socket_fileno(pytalloc_Object *self, PyObject *args)
+{
+ PyErr_SetString(py_socket_error, "Not Supported");
+ return NULL;
+}
+
+static PyObject *py_socket_getpeername(pytalloc_Object *self, PyObject *args)
+{
+ int *sock;
+ struct sockaddr addr;
+ socklen_t addrlen;
+ int status;
+ PyObject *pyaddr;
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_getpeername(*sock, &addr, &addrlen);
+ if (status < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ pyaddr = py_socket_addr_to_tuple(&addr, addrlen);
+
+ return pyaddr;
+}
+
+static PyObject *py_socket_getsockname(pytalloc_Object *self, PyObject *args)
+{
+ int *sock;
+ struct sockaddr addr;
+ socklen_t addrlen;
+ int status;
+ PyObject *pyaddr;
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_getsockname(*sock, &addr, &addrlen);
+ if (status < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ pyaddr = py_socket_addr_to_tuple(&addr, addrlen);
+
+ return pyaddr;
+}
+
+static PyObject *py_socket_getsockopt(pytalloc_Object *self, PyObject *args)
+{
+ int level, optname;
+ int *sock;
+ socklen_t optlen = -1, newlen;
+ int optval;
+ bool is_integer = false;
+ char *buffer;
+ PyObject *pyret;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "ii|i:getsockopt", &level, &optname, &optlen)) {
+ return NULL;
+ }
+
+ if (optlen < 0) {
+ optlen = sizeof(int);
+ is_integer = true;
+ }
+
+ buffer = talloc_zero_array(NULL, char, optlen);
+ if (buffer == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_getsockopt(*sock, level, optname, (void *)buffer, &newlen);
+ if (status < 0) {
+ talloc_free(buffer);
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ if (is_integer) {
+ optval = *(int *)buffer;
+ pyret = PyInt_FromLong(optval);
+ } else {
+ pyret = PyString_FromStringAndSize(buffer, optlen);
+ }
+
+ talloc_free(buffer);
+
+ return pyret;
+}
+
+static PyObject *py_socket_gettimeout(pytalloc_Object *self, PyObject *args)
+{
+ PyErr_SetString(py_socket_error, "Not Supported");
+ return NULL;
+}
+
+static PyObject *py_socket_listen(pytalloc_Object *self, PyObject *args)
+{
+ int backlog;
+ int *sock;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "i:listen", &backlog)) {
+ return NULL;
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_listen(*sock, backlog);
+ if (status < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_socket_makefile(pytalloc_Object *self, PyObject *args)
+{
+ PyErr_SetString(py_socket_error, "Not Supported");
+ return NULL;
+}
+
+static PyObject *py_socket_read(pytalloc_Object *self, PyObject *args)
+{
+ int bufsize, len;
+ int *sock;
+ char *buffer;
+ PyObject *pyret;
+
+ if (!PyArg_ParseTuple(args, "i:read", &bufsize)) {
+ return NULL;
+ }
+
+ buffer = talloc_zero_array(NULL, char, bufsize);
+ if (buffer == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ len = swrap_read(*sock, buffer, bufsize);
+ if (len < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ pyret = PyString_FromStringAndSize(buffer, len);
+
+ talloc_free(buffer);
+
+ return pyret;
+}
+
+static PyObject *py_socket_recv(pytalloc_Object *self, PyObject *args)
+{
+ int bufsize, flags, len;
+ int *sock;
+ char *buffer;
+ PyObject *pyret;
+
+ if (!PyArg_ParseTuple(args, "ii:recv", &bufsize, &flags)) {
+ return NULL;
+ }
+
+ buffer = talloc_zero_array(NULL, char, bufsize);
+ if (buffer == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ len = swrap_recv(*sock, buffer, bufsize, flags);
+ if (len < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ pyret = PyString_FromStringAndSize(buffer, len);
+
+ talloc_free(buffer);
+
+ return pyret;
+}
+
+static PyObject *py_socket_recvfrom(pytalloc_Object *self, PyObject *args)
+{
+ int bufsize, flags, len;
+ int *sock;
+ char *buffer;
+ struct sockaddr from;
+ socklen_t fromlen;
+ PyObject *pybuf, *pyaddr, *pyret;
+
+ if (!PyArg_ParseTuple(args, "ii:recvfrom", &bufsize, &flags)) {
+ return NULL;
+ }
+
+ buffer = talloc_zero_array(NULL, char, bufsize);
+ if (buffer == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ fromlen = sizeof(struct sockaddr);
+
+ len = swrap_recvfrom(*sock, buffer, bufsize, flags, &from, &fromlen);
+ if (len < 0) {
+ talloc_free(buffer);
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ pybuf = PyString_FromStringAndSize(buffer, len);
+ if (pybuf == NULL) {
+ talloc_free(buffer);
+ return PyErr_NoMemory();
+ }
+
+ talloc_free(buffer);
+
+ pyaddr = py_socket_addr_to_tuple(&from, fromlen);
+ if (pyaddr == NULL) {
+ Py_DECREF(pybuf);
+ return NULL;
+ }
+
+ pyret = PyTuple_New(2);
+ if (pyret == NULL) {
+ Py_DECREF(pybuf);
+ Py_DECREF(pyaddr);
+ return PyErr_NoMemory();
+ }
+
+ PyTuple_SetItem(pyret, 0, pybuf);
+ PyTuple_SetItem(pyret, 1, pyaddr);
+
+ return pyret;
+}
+
+static PyObject *py_socket_send(pytalloc_Object *self, PyObject *args)
+{
+ char *buffer;
+ int len, flags;
+ int *sock;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "s#i:sendto", &buffer, &len, &flags)) {
+ return NULL;
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_send(*sock, buffer, len, flags);
+ if (status < 0) {
+ PyErr_SetFromErrno(py_socket_error);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_socket_sendall(pytalloc_Object *self, PyObject *args)
+{
+ char *buffer;
+ int len, flags;
+ int *sock;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "s#i:sendall", &buffer, &len, &flags)) {
+ return NULL;
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_send(*sock, buffer, len, flags);
+ if (status < 0) {
+ PyErr_SetFromErrno(py_socket_error);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_socket_sendto(pytalloc_Object *self, PyObject *args)
+{
+ PyObject *pyaddr;
+ char *buffer;
+ int len, flags;
+ int *sock;
+ struct sockaddr addr;
+ socklen_t addrlen;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "s#iO:sendto", &buffer, &len, &flags, &pyaddr)) {
+ return NULL;
+ }
+
+ if (!py_socket_tuple_to_addr(pyaddr, &addr, &addrlen)) {
+ return NULL;
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_sendto(*sock, buffer, len, flags, &addr, addrlen);
+ if (status < 0) {
+ PyErr_SetFromErrno(py_socket_error);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_socket_setblocking(pytalloc_Object *self, PyObject *args)
+{
+ PyErr_SetString(py_socket_error, "Not Supported");
+ return NULL;
+}
+
+static PyObject *py_socket_setsockopt(pytalloc_Object *self, PyObject *args)
+{
+ int level, optname;
+ int *sock;
+ PyObject *pyval;
+ int optval;
+ Py_ssize_t optlen;
+ char *buffer;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "iiO:getsockopt", &level, &optname, &pyval)) {
+ return NULL;
+ }
+
+ if (PyInt_Check(pyval)) {
+ optval = PyInt_AsLong(pyval);
+ buffer = (char *)&optval;
+ optlen = sizeof(int);
+ } else {
+ PyString_AsStringAndSize(pyval, &buffer, &optlen);
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_setsockopt(*sock, level, optname, (void *)buffer, optlen);
+ if (status < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_socket_settimeout(pytalloc_Object *self, PyObject *args)
+{
+ PyErr_SetString(py_socket_error, "Not Supported");
+ return NULL;
+}
+
+static PyObject *py_socket_shutdown(pytalloc_Object *self, PyObject *args)
+{
+ PyErr_SetString(py_socket_error, "Not Supported");
+ return NULL;
+}
+
+static PyObject *py_socket_write(pytalloc_Object *self, PyObject *args)
+{
+ char *buffer;
+ int len;
+ int *sock;
+ int status;
+
+ if (!PyArg_ParseTuple(args, "s#:write", &buffer, &len)) {
+ return NULL;
+ }
+
+ sock = pytalloc_get_ptr(self);
+
+ status = swrap_send(*sock, buffer, len, 0);
+ if (status < 0) {
+ PyErr_SetFromErrno(py_socket_error);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+
+static PyMethodDef py_socket_methods[] = {
+ { "accept", (PyCFunction)py_socket_accept, METH_NOARGS,
+ "accept() -> (socket object, address info)\n\n \
+ Wait for an incoming connection." },
+ { "bind", (PyCFunction)py_socket_bind, METH_VARARGS,
+ "bind(address)\n\n \
+ Bind the socket to a local address." },
+ { "close", (PyCFunction)py_socket_close, METH_NOARGS,
+ "close()\n\n \
+ Close the socket." },
+ { "connect", (PyCFunction)py_socket_connect, METH_VARARGS,
+ "connect(address)\n\n \
+ Connect the socket to a remote address." },
+ { "connect_ex", (PyCFunction)py_socket_connect_ex, METH_VARARGS,
+ "connect_ex(address)\n\n \
+ Connect the socket to a remote address." },
+ { "dup", (PyCFunction)py_socket_dup, METH_VARARGS,
+ "dup() -> socket object\n\n \
+ Return a new socket object connected to the same system resource." },
+ { "dup2", (PyCFunction)py_socket_dup2, METH_VARARGS,
+ "dup2(socket object) -> socket object\n\n \
+ Return a new socket object connected to teh same system resource." },
+ { "fileno", (PyCFunction)py_socket_fileno, METH_NOARGS,
+ "fileno() -> file descriptor\n\n \
+ Return socket's file descriptor." },
+ { "getpeername", (PyCFunction)py_socket_getpeername, METH_NOARGS,
+ "getpeername() -> address info\n\n \
+ Return the address of the remote endpoint." },
+ { "getsockname", (PyCFunction)py_socket_getsockname, METH_NOARGS,
+ "getsockname() -> address info\n\n \
+ Return the address of the local endpoing." },
+ { "getsockopt", (PyCFunction)py_socket_getsockopt, METH_VARARGS,
+ "getsockopt(level, option[, buffersize]) -> value\n\n \
+ Get a socket option." },
+ { "gettimeout", (PyCFunction)py_socket_gettimeout, METH_NOARGS,
+ "gettimeout() -> value\n\n \
+ Return the timeout in seconds associated with socket operations." },
+ { "listen", (PyCFunction)py_socket_listen, METH_VARARGS,
+ "listen(backlog)\n\n \
+ Enable a server to accept connections." },
+ { "makefile", (PyCFunction)py_socket_makefile, METH_NOARGS,
+ "makefile() -> file object\n\n \
+ Return a file object associated with the socket." },
+ { "read", (PyCFunction)py_socket_read, METH_VARARGS,
+ "read(buflen) -> data\n\n \
+ Receive data." },
+ { "recv", (PyCFunction)py_socket_recv, METH_VARARGS,
+ "recv(buflen, flags) -> data\n\n \
+ Receive data." },
+ { "recvfrom", (PyCFunction)py_socket_recvfrom, METH_VARARGS,
+ "recvfrom(buflen, flags) -> (data, sender address)\n\n \
+ Receive data and sender's address." },
+ { "send", (PyCFunction)py_socket_send, METH_VARARGS,
+ "send(data, flags)\n\n \
+ Send data." },
+ { "sendall", (PyCFunction)py_socket_sendall, METH_VARARGS,
+ "sendall(data, flags)\n\n \
+ Send data." },
+ { "sendto", (PyCFunction)py_socket_sendto, METH_VARARGS,
+ "sendto(data, flags, addr)\n\n \
+ Send data to a given address." },
+ { "setblocking", (PyCFunction)py_socket_setblocking, METH_VARARGS,
+ "setblocking(flag)\n\n \
+ Set blocking or non-blocking mode of the socket." },
+ { "setsockopt", (PyCFunction)py_socket_setsockopt, METH_VARARGS,
+ "setsockopt(level, option, value)\n\n \
+ Set a socket option." },
+ { "settimeout", (PyCFunction)py_socket_settimeout, METH_VARARGS,
+ "settimeout(value)\n\n \
+ Set a timeout on socket blocking operations." },
+ { "shutdown", (PyCFunction)py_socket_shutdown, METH_VARARGS,
+ "shutdown(how)\n\n \
+ Shut down one or both halves of the connection." },
+ { "write", (PyCFunction)py_socket_write, METH_VARARGS,
+ "write(data)\n\n \
+ Send data." },
+ { NULL },
+};
+
+
+static PyObject *py_socket_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ int family, sock_type, protocol;
+ int *sock;
+ PyObject *pysocket;
+
+ if (!PyArg_ParseTuple(args, "iii:socket", &family, &sock_type, &protocol)) {
+ return NULL;
+ }
+
+ sock = talloc_zero(NULL, int);
+ if (sock == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ *sock = swrap_socket(family, sock_type, protocol);
+ if (*sock < 0) {
+ return PyErr_SetFromErrno(py_socket_error);
+ }
+
+ if ((pysocket = pytalloc_steal(type, sock)) == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ return pysocket;
+}
+
+
+static PyTypeObject PySocket = {
+ .tp_name = "socket_wrapper.socket",
+ .tp_basicsize = sizeof(pytalloc_Object),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_methods = py_socket_methods,
+ .tp_new = py_socket_new,
+ .tp_doc = "socket(family, type, proto) -> socket object\n\n Open a socket of the give type.",
+};
+
+static PyObject *py_socket_wrapper_dir(PyObject *self)
+{
+ const char *dir;
+
+ dir = socket_wrapper_dir();
+
+ return PyString_FromString(dir);
+}
+
+static PyObject *py_socket_wrapper_default_interface(PyObject *self)
+{
+ unsigned int id;
+
+ id = socket_wrapper_default_iface();
+
+ return PyInt_FromLong(id);
+}
+
+
+static PyMethodDef py_socket_wrapper_methods[] = {
+ { "dir", (PyCFunction)py_socket_wrapper_dir, METH_NOARGS,
+ "dir() -> path\n\n \
+ Return socket_wrapper directory." },
+ { "default_iface", (PyCFunction)py_socket_wrapper_default_interface, METH_NOARGS,
+ "default_iface() -> id\n\n \
+ Return default interface id." },
+ { NULL },
+};
+
+void initsocket_wrapper(void)
+{
+ PyObject *m;
+ char exception_name[] = "socket_wrapper.error";
+
+ PyTypeObject *talloc_type = pytalloc_GetObjectType();
+ if (talloc_type == NULL) {
+ return;
+ }
+
+ PySocket.tp_base = talloc_type;
+ if (PyType_Ready(&PySocket) < 0) {
+ return;
+ }
+
+ m = Py_InitModule3("socket_wrapper", py_socket_wrapper_methods, "Socket wrapper");
+ if (m == NULL) {
+ return;
+ }
+
+ py_socket_error = PyErr_NewException(exception_name, NULL, NULL);
+ Py_INCREF(py_socket_error);
+ PyModule_AddObject(m, "error", py_socket_error);
+
+ Py_INCREF(&PySocket);
+ PyModule_AddObject(m, "socket", (PyObject *)&PySocket);
+}
diff --git a/lib/socket_wrapper/socket.py b/lib/socket_wrapper/socket.py
new file mode 100644
index 0000000000..bba96653af
--- /dev/null
+++ b/lib/socket_wrapper/socket.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+#
+# Wrapper for socket wrapper (based on python socket wrapper)
+# Copyright (C) Amitay Isaacs 2011
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import _socket
+from _socket import *
+
+from samba.socket_wrapper import socket
+
+
+def getfqdn(name=''):
+ """Get fully qualified domain name from name.
+
+ An empty argument is interpreted as meaning the local host.
+
+ First the hostname returned by gethostbyaddr() is checked, then
+ possibly existing aliases. In case no FQDN is available, hostname
+ from gethostname() is returned.
+ """
+ name = name.strip()
+ if not name or name == '0.0.0.0':
+ name = gethostname()
+ try:
+ hostname, aliases, ipaddrs = gethostbyaddr(name)
+ except error:
+ pass
+ else:
+ aliases.insert(0, hostname)
+ for name in aliases:
+ if '.' in name:
+ break
+ else:
+ name = hostname
+ return name
+
+
+_GLOBAL_DEFAULT_TIMEOUT = object()
diff --git a/lib/socket_wrapper/wscript_build b/lib/socket_wrapper/wscript_build
index a81c7aa61a..c4b94147d6 100644
--- a/lib/socket_wrapper/wscript_build
+++ b/lib/socket_wrapper/wscript_build
@@ -7,3 +7,13 @@ bld.SAMBA_LIBRARY('socket_wrapper',
enabled=bld.CONFIG_SET('SOCKET_WRAPPER'),
deps='replace')
+bld.SAMBA_PYTHON('py_socket_wrapper',
+ source='py_socket_wrapper.c',
+ deps='socket_wrapper',
+ public_deps='talloc pytalloc-util',
+ realname='samba/socket_wrapper.so')
+
+bld.SAMBA_SCRIPT('python_socket',
+ pattern='socket.py',
+ installdir='python',
+ installname='samba/socket.py')