2 * Copyright (C) Amitay Isaacs 2011
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the author nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 Python interface to socket wrapper library.
38 Passes all socket communication over unix domain sockets if the environment
39 variable SOCKET_WRAPPER_DIR is set.
44 #include "replace/replace.h"
45 #include "system/network.h"
46 #include "socket_wrapper.h"
48 /* There's no Py_ssize_t in 2.4, apparently */
49 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
50 typedef int Py_ssize_t
;
51 typedef inquiry lenfunc
;
52 typedef intargfunc ssizeargfunc
;
55 #ifndef Py_TYPE /* Py_TYPE is only available on Python > 2.6 */
56 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
60 #define PY_CHECK_TYPE(type, var, fail) \
61 if (!PyObject_TypeCheck(var, type)) {\
62 PyErr_Format(PyExc_TypeError, __location__ ": Expected type '%s' for '%s' of type '%s'", (type)->tp_name, #var, Py_TYPE(var)->tp_name); \
67 staticforward PyTypeObject PySocket
;
69 static PyObject
*py_socket_error
;
71 void initsocket_wrapper(void);
73 static PyObject
*py_socket_addr_to_tuple(struct sockaddr
*addr
, socklen_t len
)
80 status
= getnameinfo(addr
, len
, host
, 255, service
, 7, NI_NUMERICHOST
|NI_NUMERICSERV
);
82 PyErr_SetString(py_socket_error
, gai_strerror(status
));
86 pyaddr
= PyTuple_New(2);
88 return PyErr_NoMemory();
91 PyTuple_SetItem(pyaddr
, 0, PyString_FromString(host
));
92 PyTuple_SetItem(pyaddr
, 1, PyInt_FromLong(atoi(service
)));
97 static bool py_socket_tuple_to_addr(PyObject
*pyaddr
, struct sockaddr
*addr
, socklen_t
*len
)
102 struct addrinfo
*ainfo
;
105 if (!PyTuple_Check(pyaddr
)) {
106 PyErr_SetString(PyExc_TypeError
, "Expected a tuple");
110 if (!PyArg_ParseTuple(pyaddr
, "sH", &host
, &port
)) {
114 service
= talloc_asprintf(NULL
, "%d", port
);
115 if (service
== NULL
) {
120 status
= getaddrinfo(host
, service
, NULL
, &ainfo
);
122 talloc_free(service
);
123 PyErr_SetString(py_socket_error
, gai_strerror(status
));
127 talloc_free(service
);
129 memcpy(addr
, ainfo
->ai_addr
, sizeof(struct sockaddr
));
130 *len
= ainfo
->ai_addrlen
;
137 static PyObject
*py_socket_accept(pytalloc_Object
*self
, PyObject
*args
)
139 int *sock
, *new_sock
;
140 struct sockaddr addr
;
146 sock
= pytalloc_get_ptr(self
);
148 new_sock
= talloc_zero(NULL
, int);
149 if (new_sock
== NULL
) {
150 return PyErr_NoMemory();
153 *new_sock
= swrap_accept(*sock
, &addr
, &addrlen
);
155 return PyErr_SetFromErrno(py_socket_error
);
158 if ((pysocket
= pytalloc_steal(&PySocket
, new_sock
)) == NULL
) {
159 return PyErr_NoMemory();
162 pyret
= PyTuple_New(2);
165 return PyErr_NoMemory();
168 pyaddr
= py_socket_addr_to_tuple(&addr
, addrlen
);
169 if (pyaddr
== NULL
) {
175 PyTuple_SetItem(pyret
, 0, pysocket
);
176 PyTuple_SetItem(pyret
, 1, pyaddr
);
180 static PyObject
*py_socket_bind(pytalloc_Object
*self
, PyObject
*args
)
185 struct sockaddr addr
;
188 if (!PyArg_ParseTuple(args
, "O:bind", &pyaddr
)) {
192 if (!py_socket_tuple_to_addr(pyaddr
, &addr
, &addrlen
)) {
196 sock
= pytalloc_get_ptr(self
);
198 status
= swrap_bind(*sock
, &addr
, addrlen
);
200 PyErr_SetString(py_socket_error
, "Unable to bind");
207 static PyObject
*py_socket_close(pytalloc_Object
*self
, PyObject
*args
)
212 sock
= pytalloc_get_ptr(self
);
214 status
= swrap_close(*sock
);
216 return PyErr_SetFromErrno(py_socket_error
);
222 static PyObject
*py_socket_connect(pytalloc_Object
*self
, PyObject
*args
)
226 struct sockaddr addr
;
230 if (!PyArg_ParseTuple(args
, "O:connect", &pyaddr
)) {
234 if (!py_socket_tuple_to_addr(pyaddr
, &addr
, &addrlen
)) {
238 sock
= pytalloc_get_ptr(self
);
240 status
= swrap_connect(*sock
, &addr
, addrlen
);
242 PyErr_SetFromErrno(py_socket_error
);
249 static PyObject
*py_socket_connect_ex(pytalloc_Object
*self
, PyObject
*args
)
253 struct sockaddr addr
;
257 if (!PyArg_ParseTuple(args
, "O:connect", &pyaddr
)) {
261 if (!py_socket_tuple_to_addr(pyaddr
, &addr
, &addrlen
)) {
265 sock
= pytalloc_get_ptr(self
);
267 status
= swrap_connect(*sock
, &addr
, addrlen
);
269 return Py_BuildValue("%d", errno
);
272 return Py_BuildValue("%d", 0);
275 static PyObject
*py_socket_dup(pytalloc_Object
*self
, PyObject
*args
)
277 int *sock
, *new_sock
;
280 sock
= pytalloc_get_ptr(self
);
282 new_sock
= talloc_zero(NULL
, int);
283 if (new_sock
== NULL
) {
284 return PyErr_NoMemory();
287 *new_sock
= swrap_dup(*sock
);
289 return PyErr_SetFromErrno(py_socket_error
);
292 pysocket
= pytalloc_steal(&PySocket
, new_sock
);
293 if (pysocket
== NULL
) {
294 return PyErr_NoMemory();
300 static PyObject
*py_socket_dup2(pytalloc_Object
*self
, PyObject
*args
)
302 int *sock
, *new_sock
;
306 if (!PyArg_ParseTuple(args
, "O", &pysocket
)) {
310 PY_CHECK_TYPE(&PySocket
, pysocket
, return NULL
);
312 sock
= pytalloc_get_ptr(self
);
313 new_sock
= pytalloc_get_ptr(pysocket
);
315 status
= swrap_dup2(*sock
, *new_sock
);
317 return PyErr_SetFromErrno(py_socket_error
);
323 static PyObject
*py_socket_fileno(pytalloc_Object
*self
, PyObject
*args
)
325 PyErr_SetString(py_socket_error
, "Not Supported");
329 static PyObject
*py_socket_getpeername(pytalloc_Object
*self
, PyObject
*args
)
332 struct sockaddr addr
;
337 sock
= pytalloc_get_ptr(self
);
339 status
= swrap_getpeername(*sock
, &addr
, &addrlen
);
341 return PyErr_SetFromErrno(py_socket_error
);
344 pyaddr
= py_socket_addr_to_tuple(&addr
, addrlen
);
349 static PyObject
*py_socket_getsockname(pytalloc_Object
*self
, PyObject
*args
)
352 struct sockaddr addr
;
357 sock
= pytalloc_get_ptr(self
);
359 status
= swrap_getsockname(*sock
, &addr
, &addrlen
);
361 return PyErr_SetFromErrno(py_socket_error
);
364 pyaddr
= py_socket_addr_to_tuple(&addr
, addrlen
);
369 static PyObject
*py_socket_getsockopt(pytalloc_Object
*self
, PyObject
*args
)
373 socklen_t optlen
= 0, newlen
;
375 bool is_integer
= false;
380 if (!PyArg_ParseTuple(args
, "ii|i:getsockopt", &level
, &optname
, &optlen
)) {
385 optlen
= sizeof(int);
389 buffer
= talloc_zero_array(NULL
, char, optlen
);
390 if (buffer
== NULL
) {
391 return PyErr_NoMemory();
394 sock
= pytalloc_get_ptr(self
);
396 status
= swrap_getsockopt(*sock
, level
, optname
, (void *)buffer
, &newlen
);
399 return PyErr_SetFromErrno(py_socket_error
);
403 optval
= *(int *)buffer
;
404 pyret
= PyInt_FromLong(optval
);
406 pyret
= PyString_FromStringAndSize(buffer
, optlen
);
414 static PyObject
*py_socket_gettimeout(pytalloc_Object
*self
, PyObject
*args
)
416 PyErr_SetString(py_socket_error
, "Not Supported");
420 static PyObject
*py_socket_listen(pytalloc_Object
*self
, PyObject
*args
)
426 if (!PyArg_ParseTuple(args
, "i:listen", &backlog
)) {
430 sock
= pytalloc_get_ptr(self
);
432 status
= swrap_listen(*sock
, backlog
);
434 return PyErr_SetFromErrno(py_socket_error
);
440 static PyObject
*py_socket_makefile(pytalloc_Object
*self
, PyObject
*args
)
442 PyErr_SetString(py_socket_error
, "Not Supported");
446 static PyObject
*py_socket_read(pytalloc_Object
*self
, PyObject
*args
)
453 if (!PyArg_ParseTuple(args
, "i:read", &bufsize
)) {
457 buffer
= talloc_zero_array(NULL
, char, bufsize
);
458 if (buffer
== NULL
) {
459 return PyErr_NoMemory();
462 sock
= pytalloc_get_ptr(self
);
464 len
= swrap_read(*sock
, buffer
, bufsize
);
466 return PyErr_SetFromErrno(py_socket_error
);
469 pyret
= PyString_FromStringAndSize(buffer
, len
);
476 static PyObject
*py_socket_recv(pytalloc_Object
*self
, PyObject
*args
)
478 int bufsize
, flags
, len
;
483 if (!PyArg_ParseTuple(args
, "ii:recv", &bufsize
, &flags
)) {
487 buffer
= talloc_zero_array(NULL
, char, bufsize
);
488 if (buffer
== NULL
) {
489 return PyErr_NoMemory();
492 sock
= pytalloc_get_ptr(self
);
494 len
= swrap_recv(*sock
, buffer
, bufsize
, flags
);
496 return PyErr_SetFromErrno(py_socket_error
);
499 pyret
= PyString_FromStringAndSize(buffer
, len
);
506 static PyObject
*py_socket_recvfrom(pytalloc_Object
*self
, PyObject
*args
)
508 int bufsize
, flags
, len
;
511 struct sockaddr from
;
513 PyObject
*pybuf
, *pyaddr
, *pyret
;
515 if (!PyArg_ParseTuple(args
, "ii:recvfrom", &bufsize
, &flags
)) {
519 buffer
= talloc_zero_array(NULL
, char, bufsize
);
520 if (buffer
== NULL
) {
521 return PyErr_NoMemory();
524 sock
= pytalloc_get_ptr(self
);
526 fromlen
= sizeof(struct sockaddr
);
528 len
= swrap_recvfrom(*sock
, buffer
, bufsize
, flags
, &from
, &fromlen
);
531 return PyErr_SetFromErrno(py_socket_error
);
534 pybuf
= PyString_FromStringAndSize(buffer
, len
);
537 return PyErr_NoMemory();
542 pyaddr
= py_socket_addr_to_tuple(&from
, fromlen
);
543 if (pyaddr
== NULL
) {
548 pyret
= PyTuple_New(2);
552 return PyErr_NoMemory();
555 PyTuple_SetItem(pyret
, 0, pybuf
);
556 PyTuple_SetItem(pyret
, 1, pyaddr
);
561 static PyObject
*py_socket_send(pytalloc_Object
*self
, PyObject
*args
)
568 if (!PyArg_ParseTuple(args
, "s#i:sendto", &buffer
, &len
, &flags
)) {
572 sock
= pytalloc_get_ptr(self
);
574 status
= swrap_send(*sock
, buffer
, len
, flags
);
576 PyErr_SetFromErrno(py_socket_error
);
583 static PyObject
*py_socket_sendall(pytalloc_Object
*self
, PyObject
*args
)
590 if (!PyArg_ParseTuple(args
, "s#i:sendall", &buffer
, &len
, &flags
)) {
594 sock
= pytalloc_get_ptr(self
);
596 status
= swrap_send(*sock
, buffer
, len
, flags
);
598 PyErr_SetFromErrno(py_socket_error
);
605 static PyObject
*py_socket_sendto(pytalloc_Object
*self
, PyObject
*args
)
611 struct sockaddr addr
;
615 if (!PyArg_ParseTuple(args
, "s#iO:sendto", &buffer
, &len
, &flags
, &pyaddr
)) {
619 if (!py_socket_tuple_to_addr(pyaddr
, &addr
, &addrlen
)) {
623 sock
= pytalloc_get_ptr(self
);
625 status
= swrap_sendto(*sock
, buffer
, len
, flags
, &addr
, addrlen
);
627 PyErr_SetFromErrno(py_socket_error
);
634 static PyObject
*py_socket_setblocking(pytalloc_Object
*self
, PyObject
*args
)
636 PyErr_SetString(py_socket_error
, "Not Supported");
640 static PyObject
*py_socket_setsockopt(pytalloc_Object
*self
, PyObject
*args
)
650 if (!PyArg_ParseTuple(args
, "iiO:getsockopt", &level
, &optname
, &pyval
)) {
654 if (PyInt_Check(pyval
)) {
655 optval
= PyInt_AsLong(pyval
);
656 buffer
= (char *)&optval
;
657 optlen
= sizeof(int);
659 PyString_AsStringAndSize(pyval
, &buffer
, &optlen
);
662 sock
= pytalloc_get_ptr(self
);
664 status
= swrap_setsockopt(*sock
, level
, optname
, (void *)buffer
, optlen
);
666 return PyErr_SetFromErrno(py_socket_error
);
672 static PyObject
*py_socket_settimeout(pytalloc_Object
*self
, PyObject
*args
)
674 PyErr_SetString(py_socket_error
, "Not Supported");
678 static PyObject
*py_socket_shutdown(pytalloc_Object
*self
, PyObject
*args
)
680 PyErr_SetString(py_socket_error
, "Not Supported");
684 static PyObject
*py_socket_write(pytalloc_Object
*self
, PyObject
*args
)
691 if (!PyArg_ParseTuple(args
, "s#:write", &buffer
, &len
)) {
695 sock
= pytalloc_get_ptr(self
);
697 status
= swrap_send(*sock
, buffer
, len
, 0);
699 PyErr_SetFromErrno(py_socket_error
);
707 static PyMethodDef py_socket_methods
[] = {
708 { "accept", (PyCFunction
)py_socket_accept
, METH_NOARGS
,
709 "accept() -> (socket object, address info)\n\n \
710 Wait for an incoming connection." },
711 { "bind", (PyCFunction
)py_socket_bind
, METH_VARARGS
,
713 Bind the socket to a local address." },
714 { "close", (PyCFunction
)py_socket_close
, METH_NOARGS
,
716 Close the socket." },
717 { "connect", (PyCFunction
)py_socket_connect
, METH_VARARGS
,
718 "connect(address)\n\n \
719 Connect the socket to a remote address." },
720 { "connect_ex", (PyCFunction
)py_socket_connect_ex
, METH_VARARGS
,
721 "connect_ex(address)\n\n \
722 Connect the socket to a remote address." },
723 { "dup", (PyCFunction
)py_socket_dup
, METH_VARARGS
,
724 "dup() -> socket object\n\n \
725 Return a new socket object connected to the same system resource." },
726 { "dup2", (PyCFunction
)py_socket_dup2
, METH_VARARGS
,
727 "dup2(socket object) -> socket object\n\n \
728 Return a new socket object connected to teh same system resource." },
729 { "fileno", (PyCFunction
)py_socket_fileno
, METH_NOARGS
,
730 "fileno() -> file descriptor\n\n \
731 Return socket's file descriptor." },
732 { "getpeername", (PyCFunction
)py_socket_getpeername
, METH_NOARGS
,
733 "getpeername() -> address info\n\n \
734 Return the address of the remote endpoint." },
735 { "getsockname", (PyCFunction
)py_socket_getsockname
, METH_NOARGS
,
736 "getsockname() -> address info\n\n \
737 Return the address of the local endpoing." },
738 { "getsockopt", (PyCFunction
)py_socket_getsockopt
, METH_VARARGS
,
739 "getsockopt(level, option[, buffersize]) -> value\n\n \
740 Get a socket option." },
741 { "gettimeout", (PyCFunction
)py_socket_gettimeout
, METH_NOARGS
,
742 "gettimeout() -> value\n\n \
743 Return the timeout in seconds associated with socket operations." },
744 { "listen", (PyCFunction
)py_socket_listen
, METH_VARARGS
,
745 "listen(backlog)\n\n \
746 Enable a server to accept connections." },
747 { "makefile", (PyCFunction
)py_socket_makefile
, METH_NOARGS
,
748 "makefile() -> file object\n\n \
749 Return a file object associated with the socket." },
750 { "read", (PyCFunction
)py_socket_read
, METH_VARARGS
,
751 "read(buflen) -> data\n\n \
753 { "recv", (PyCFunction
)py_socket_recv
, METH_VARARGS
,
754 "recv(buflen, flags) -> data\n\n \
756 { "recvfrom", (PyCFunction
)py_socket_recvfrom
, METH_VARARGS
,
757 "recvfrom(buflen, flags) -> (data, sender address)\n\n \
758 Receive data and sender's address." },
759 { "send", (PyCFunction
)py_socket_send
, METH_VARARGS
,
760 "send(data, flags)\n\n \
762 { "sendall", (PyCFunction
)py_socket_sendall
, METH_VARARGS
,
763 "sendall(data, flags)\n\n \
765 { "sendto", (PyCFunction
)py_socket_sendto
, METH_VARARGS
,
766 "sendto(data, flags, addr)\n\n \
767 Send data to a given address." },
768 { "setblocking", (PyCFunction
)py_socket_setblocking
, METH_VARARGS
,
769 "setblocking(flag)\n\n \
770 Set blocking or non-blocking mode of the socket." },
771 { "setsockopt", (PyCFunction
)py_socket_setsockopt
, METH_VARARGS
,
772 "setsockopt(level, option, value)\n\n \
773 Set a socket option." },
774 { "settimeout", (PyCFunction
)py_socket_settimeout
, METH_VARARGS
,
775 "settimeout(value)\n\n \
776 Set a timeout on socket blocking operations." },
777 { "shutdown", (PyCFunction
)py_socket_shutdown
, METH_VARARGS
,
779 Shut down one or both halves of the connection." },
780 { "write", (PyCFunction
)py_socket_write
, METH_VARARGS
,
787 static PyObject
*py_socket_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwargs
)
789 int family
, sock_type
, protocol
;
793 if (!PyArg_ParseTuple(args
, "iii:socket", &family
, &sock_type
, &protocol
)) {
797 sock
= talloc_zero(NULL
, int);
799 return PyErr_NoMemory();
802 *sock
= swrap_socket(family
, sock_type
, protocol
);
804 return PyErr_SetFromErrno(py_socket_error
);
807 if ((pysocket
= pytalloc_steal(type
, sock
)) == NULL
) {
808 return PyErr_NoMemory();
815 static PyTypeObject PySocket
= {
816 .tp_name
= "socket_wrapper.socket",
817 .tp_basicsize
= sizeof(pytalloc_Object
),
818 .tp_flags
= Py_TPFLAGS_DEFAULT
,
819 .tp_methods
= py_socket_methods
,
820 .tp_new
= py_socket_new
,
821 .tp_doc
= "socket(family, type, proto) -> socket object\n\n Open a socket of the give type.",
824 static PyObject
*py_socket_wrapper_dir(PyObject
*self
)
828 dir
= socket_wrapper_dir();
830 return PyString_FromString(dir
);
833 static PyObject
*py_socket_wrapper_default_interface(PyObject
*self
)
837 id
= socket_wrapper_default_iface();
839 return PyInt_FromLong(id
);
843 static PyMethodDef py_socket_wrapper_methods
[] = {
844 { "dir", (PyCFunction
)py_socket_wrapper_dir
, METH_NOARGS
,
846 Return socket_wrapper directory." },
847 { "default_iface", (PyCFunction
)py_socket_wrapper_default_interface
, METH_NOARGS
,
848 "default_iface() -> id\n\n \
849 Return default interface id." },
853 void initsocket_wrapper(void)
856 char exception_name
[] = "socket_wrapper.error";
858 PyTypeObject
*talloc_type
= pytalloc_GetObjectType();
859 if (talloc_type
== NULL
) {
863 PySocket
.tp_base
= talloc_type
;
864 if (PyType_Ready(&PySocket
) < 0) {
868 m
= Py_InitModule3("socket_wrapper", py_socket_wrapper_methods
, "Socket wrapper");
873 py_socket_error
= PyErr_NewException(exception_name
, NULL
, NULL
);
874 Py_INCREF(py_socket_error
);
875 PyModule_AddObject(m
, "error", py_socket_error
);
877 Py_INCREF(&PySocket
);
878 PyModule_AddObject(m
, "socket", (PyObject
*)&PySocket
);