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_RETURN_NONE
56 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
59 #ifndef Py_TYPE /* Py_TYPE is only available on Python > 2.6 */
60 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
64 #define PY_CHECK_TYPE(type, var, fail) \
65 if (!PyObject_TypeCheck(var, type)) {\
66 PyErr_Format(PyExc_TypeError, __location__ ": Expected type '%s' for '%s' of type '%s'", (type)->tp_name, #var, Py_TYPE(var)->tp_name); \
71 staticforward PyTypeObject PySocket
;
73 static PyObject
*py_socket_error
;
75 void initsocket_wrapper(void);
77 static PyObject
*py_socket_addr_to_tuple(struct sockaddr
*addr
, socklen_t len
)
84 status
= getnameinfo(addr
, len
, host
, 255, service
, 7, NI_NUMERICHOST
|NI_NUMERICSERV
);
86 PyErr_SetString(py_socket_error
, gai_strerror(status
));
90 pyaddr
= PyTuple_New(2);
92 return PyErr_NoMemory();
95 PyTuple_SetItem(pyaddr
, 0, PyString_FromString(host
));
96 PyTuple_SetItem(pyaddr
, 1, PyInt_FromLong(atoi(service
)));
101 static bool py_socket_tuple_to_addr(PyObject
*pyaddr
, struct sockaddr
*addr
, socklen_t
*len
)
106 struct addrinfo
*ainfo
;
109 if (!PyTuple_Check(pyaddr
)) {
110 PyErr_SetString(PyExc_TypeError
, "Expected a tuple");
114 if (!PyArg_ParseTuple(pyaddr
, "sH", &host
, &port
)) {
118 service
= talloc_asprintf(NULL
, "%d", port
);
119 if (service
== NULL
) {
124 status
= getaddrinfo(host
, service
, NULL
, &ainfo
);
126 talloc_free(service
);
127 PyErr_SetString(py_socket_error
, gai_strerror(status
));
131 talloc_free(service
);
133 memcpy(addr
, ainfo
->ai_addr
, sizeof(struct sockaddr
));
134 *len
= ainfo
->ai_addrlen
;
141 static PyObject
*py_socket_accept(pytalloc_Object
*self
, PyObject
*args
)
143 int *sock
, *new_sock
;
144 struct sockaddr addr
;
150 sock
= pytalloc_get_ptr(self
);
152 new_sock
= talloc_zero(NULL
, int);
153 if (new_sock
== NULL
) {
154 return PyErr_NoMemory();
157 *new_sock
= swrap_accept(*sock
, &addr
, &addrlen
);
159 return PyErr_SetFromErrno(py_socket_error
);
162 if ((pysocket
= pytalloc_steal(&PySocket
, new_sock
)) == NULL
) {
163 return PyErr_NoMemory();
166 pyret
= PyTuple_New(2);
169 return PyErr_NoMemory();
172 pyaddr
= py_socket_addr_to_tuple(&addr
, addrlen
);
173 if (pyaddr
== NULL
) {
179 PyTuple_SetItem(pyret
, 0, pysocket
);
180 PyTuple_SetItem(pyret
, 1, pyaddr
);
184 static PyObject
*py_socket_bind(pytalloc_Object
*self
, PyObject
*args
)
189 struct sockaddr addr
;
192 if (!PyArg_ParseTuple(args
, "O:bind", &pyaddr
)) {
196 if (!py_socket_tuple_to_addr(pyaddr
, &addr
, &addrlen
)) {
200 sock
= pytalloc_get_ptr(self
);
202 status
= swrap_bind(*sock
, &addr
, addrlen
);
204 PyErr_SetString(py_socket_error
, "Unable to bind");
211 static PyObject
*py_socket_close(pytalloc_Object
*self
, PyObject
*args
)
216 sock
= pytalloc_get_ptr(self
);
218 status
= swrap_close(*sock
);
220 return PyErr_SetFromErrno(py_socket_error
);
226 static PyObject
*py_socket_connect(pytalloc_Object
*self
, PyObject
*args
)
230 struct sockaddr addr
;
234 if (!PyArg_ParseTuple(args
, "O:connect", &pyaddr
)) {
238 if (!py_socket_tuple_to_addr(pyaddr
, &addr
, &addrlen
)) {
242 sock
= pytalloc_get_ptr(self
);
244 status
= swrap_connect(*sock
, &addr
, addrlen
);
246 PyErr_SetFromErrno(py_socket_error
);
253 static PyObject
*py_socket_connect_ex(pytalloc_Object
*self
, PyObject
*args
)
257 struct sockaddr addr
;
261 if (!PyArg_ParseTuple(args
, "O:connect", &pyaddr
)) {
265 if (!py_socket_tuple_to_addr(pyaddr
, &addr
, &addrlen
)) {
269 sock
= pytalloc_get_ptr(self
);
271 status
= swrap_connect(*sock
, &addr
, addrlen
);
273 return Py_BuildValue("%d", errno
);
276 return Py_BuildValue("%d", 0);
279 static PyObject
*py_socket_dup(pytalloc_Object
*self
, PyObject
*args
)
281 int *sock
, *new_sock
;
284 sock
= pytalloc_get_ptr(self
);
286 new_sock
= talloc_zero(NULL
, int);
287 if (new_sock
== NULL
) {
288 return PyErr_NoMemory();
291 *new_sock
= swrap_dup(*sock
);
293 return PyErr_SetFromErrno(py_socket_error
);
296 pysocket
= pytalloc_steal(&PySocket
, new_sock
);
297 if (pysocket
== NULL
) {
298 return PyErr_NoMemory();
304 static PyObject
*py_socket_dup2(pytalloc_Object
*self
, PyObject
*args
)
306 int *sock
, *new_sock
;
310 if (!PyArg_ParseTuple(args
, "O", &pysocket
)) {
314 PY_CHECK_TYPE(&PySocket
, pysocket
, return NULL
);
316 sock
= pytalloc_get_ptr(self
);
317 new_sock
= pytalloc_get_ptr(pysocket
);
319 status
= swrap_dup2(*sock
, *new_sock
);
321 return PyErr_SetFromErrno(py_socket_error
);
327 static PyObject
*py_socket_fileno(pytalloc_Object
*self
, PyObject
*args
)
329 PyErr_SetString(py_socket_error
, "Not Supported");
333 static PyObject
*py_socket_getpeername(pytalloc_Object
*self
, PyObject
*args
)
336 struct sockaddr addr
;
341 sock
= pytalloc_get_ptr(self
);
343 status
= swrap_getpeername(*sock
, &addr
, &addrlen
);
345 return PyErr_SetFromErrno(py_socket_error
);
348 pyaddr
= py_socket_addr_to_tuple(&addr
, addrlen
);
353 static PyObject
*py_socket_getsockname(pytalloc_Object
*self
, PyObject
*args
)
356 struct sockaddr addr
;
361 sock
= pytalloc_get_ptr(self
);
363 status
= swrap_getsockname(*sock
, &addr
, &addrlen
);
365 return PyErr_SetFromErrno(py_socket_error
);
368 pyaddr
= py_socket_addr_to_tuple(&addr
, addrlen
);
373 static PyObject
*py_socket_getsockopt(pytalloc_Object
*self
, PyObject
*args
)
377 socklen_t optlen
= 0, newlen
;
379 bool is_integer
= false;
384 if (!PyArg_ParseTuple(args
, "ii|i:getsockopt", &level
, &optname
, &optlen
)) {
389 optlen
= sizeof(int);
393 buffer
= talloc_zero_array(NULL
, char, optlen
);
394 if (buffer
== NULL
) {
395 return PyErr_NoMemory();
398 sock
= pytalloc_get_ptr(self
);
400 status
= swrap_getsockopt(*sock
, level
, optname
, (void *)buffer
, &newlen
);
403 return PyErr_SetFromErrno(py_socket_error
);
407 optval
= *(int *)buffer
;
408 pyret
= PyInt_FromLong(optval
);
410 pyret
= PyString_FromStringAndSize(buffer
, optlen
);
418 static PyObject
*py_socket_gettimeout(pytalloc_Object
*self
, PyObject
*args
)
420 PyErr_SetString(py_socket_error
, "Not Supported");
424 static PyObject
*py_socket_listen(pytalloc_Object
*self
, PyObject
*args
)
430 if (!PyArg_ParseTuple(args
, "i:listen", &backlog
)) {
434 sock
= pytalloc_get_ptr(self
);
436 status
= swrap_listen(*sock
, backlog
);
438 return PyErr_SetFromErrno(py_socket_error
);
444 static PyObject
*py_socket_makefile(pytalloc_Object
*self
, PyObject
*args
)
446 PyErr_SetString(py_socket_error
, "Not Supported");
450 static PyObject
*py_socket_read(pytalloc_Object
*self
, PyObject
*args
)
457 if (!PyArg_ParseTuple(args
, "i:read", &bufsize
)) {
461 buffer
= talloc_zero_array(NULL
, char, bufsize
);
462 if (buffer
== NULL
) {
463 return PyErr_NoMemory();
466 sock
= pytalloc_get_ptr(self
);
468 len
= swrap_read(*sock
, buffer
, bufsize
);
470 return PyErr_SetFromErrno(py_socket_error
);
473 pyret
= PyString_FromStringAndSize(buffer
, len
);
480 static PyObject
*py_socket_recv(pytalloc_Object
*self
, PyObject
*args
)
482 int bufsize
, flags
, len
;
487 if (!PyArg_ParseTuple(args
, "ii:recv", &bufsize
, &flags
)) {
491 buffer
= talloc_zero_array(NULL
, char, bufsize
);
492 if (buffer
== NULL
) {
493 return PyErr_NoMemory();
496 sock
= pytalloc_get_ptr(self
);
498 len
= swrap_recv(*sock
, buffer
, bufsize
, flags
);
500 return PyErr_SetFromErrno(py_socket_error
);
503 pyret
= PyString_FromStringAndSize(buffer
, len
);
510 static PyObject
*py_socket_recvfrom(pytalloc_Object
*self
, PyObject
*args
)
512 int bufsize
, flags
, len
;
515 struct sockaddr from
;
517 PyObject
*pybuf
, *pyaddr
, *pyret
;
519 if (!PyArg_ParseTuple(args
, "ii:recvfrom", &bufsize
, &flags
)) {
523 buffer
= talloc_zero_array(NULL
, char, bufsize
);
524 if (buffer
== NULL
) {
525 return PyErr_NoMemory();
528 sock
= pytalloc_get_ptr(self
);
530 fromlen
= sizeof(struct sockaddr
);
532 len
= swrap_recvfrom(*sock
, buffer
, bufsize
, flags
, &from
, &fromlen
);
535 return PyErr_SetFromErrno(py_socket_error
);
538 pybuf
= PyString_FromStringAndSize(buffer
, len
);
541 return PyErr_NoMemory();
546 pyaddr
= py_socket_addr_to_tuple(&from
, fromlen
);
547 if (pyaddr
== NULL
) {
552 pyret
= PyTuple_New(2);
556 return PyErr_NoMemory();
559 PyTuple_SetItem(pyret
, 0, pybuf
);
560 PyTuple_SetItem(pyret
, 1, pyaddr
);
565 static PyObject
*py_socket_send(pytalloc_Object
*self
, PyObject
*args
)
572 if (!PyArg_ParseTuple(args
, "s#i:sendto", &buffer
, &len
, &flags
)) {
576 sock
= pytalloc_get_ptr(self
);
578 status
= swrap_send(*sock
, buffer
, len
, flags
);
580 PyErr_SetFromErrno(py_socket_error
);
587 static PyObject
*py_socket_sendall(pytalloc_Object
*self
, PyObject
*args
)
594 if (!PyArg_ParseTuple(args
, "s#i:sendall", &buffer
, &len
, &flags
)) {
598 sock
= pytalloc_get_ptr(self
);
600 status
= swrap_send(*sock
, buffer
, len
, flags
);
602 PyErr_SetFromErrno(py_socket_error
);
609 static PyObject
*py_socket_sendto(pytalloc_Object
*self
, PyObject
*args
)
615 struct sockaddr addr
;
619 if (!PyArg_ParseTuple(args
, "s#iO:sendto", &buffer
, &len
, &flags
, &pyaddr
)) {
623 if (!py_socket_tuple_to_addr(pyaddr
, &addr
, &addrlen
)) {
627 sock
= pytalloc_get_ptr(self
);
629 status
= swrap_sendto(*sock
, buffer
, len
, flags
, &addr
, addrlen
);
631 PyErr_SetFromErrno(py_socket_error
);
638 static PyObject
*py_socket_setblocking(pytalloc_Object
*self
, PyObject
*args
)
640 PyErr_SetString(py_socket_error
, "Not Supported");
644 static PyObject
*py_socket_setsockopt(pytalloc_Object
*self
, PyObject
*args
)
654 if (!PyArg_ParseTuple(args
, "iiO:getsockopt", &level
, &optname
, &pyval
)) {
658 if (PyInt_Check(pyval
)) {
659 optval
= PyInt_AsLong(pyval
);
660 buffer
= (char *)&optval
;
661 optlen
= sizeof(int);
663 PyString_AsStringAndSize(pyval
, &buffer
, &optlen
);
666 sock
= pytalloc_get_ptr(self
);
668 status
= swrap_setsockopt(*sock
, level
, optname
, (void *)buffer
, optlen
);
670 return PyErr_SetFromErrno(py_socket_error
);
676 static PyObject
*py_socket_settimeout(pytalloc_Object
*self
, PyObject
*args
)
678 PyErr_SetString(py_socket_error
, "Not Supported");
682 static PyObject
*py_socket_shutdown(pytalloc_Object
*self
, PyObject
*args
)
684 PyErr_SetString(py_socket_error
, "Not Supported");
688 static PyObject
*py_socket_write(pytalloc_Object
*self
, PyObject
*args
)
695 if (!PyArg_ParseTuple(args
, "s#:write", &buffer
, &len
)) {
699 sock
= pytalloc_get_ptr(self
);
701 status
= swrap_send(*sock
, buffer
, len
, 0);
703 PyErr_SetFromErrno(py_socket_error
);
711 static PyMethodDef py_socket_methods
[] = {
712 { "accept", (PyCFunction
)py_socket_accept
, METH_NOARGS
,
713 "accept() -> (socket object, address info)\n\n \
714 Wait for an incoming connection." },
715 { "bind", (PyCFunction
)py_socket_bind
, METH_VARARGS
,
717 Bind the socket to a local address." },
718 { "close", (PyCFunction
)py_socket_close
, METH_NOARGS
,
720 Close the socket." },
721 { "connect", (PyCFunction
)py_socket_connect
, METH_VARARGS
,
722 "connect(address)\n\n \
723 Connect the socket to a remote address." },
724 { "connect_ex", (PyCFunction
)py_socket_connect_ex
, METH_VARARGS
,
725 "connect_ex(address)\n\n \
726 Connect the socket to a remote address." },
727 { "dup", (PyCFunction
)py_socket_dup
, METH_VARARGS
,
728 "dup() -> socket object\n\n \
729 Return a new socket object connected to the same system resource." },
730 { "dup2", (PyCFunction
)py_socket_dup2
, METH_VARARGS
,
731 "dup2(socket object) -> socket object\n\n \
732 Return a new socket object connected to teh same system resource." },
733 { "fileno", (PyCFunction
)py_socket_fileno
, METH_NOARGS
,
734 "fileno() -> file descriptor\n\n \
735 Return socket's file descriptor." },
736 { "getpeername", (PyCFunction
)py_socket_getpeername
, METH_NOARGS
,
737 "getpeername() -> address info\n\n \
738 Return the address of the remote endpoint." },
739 { "getsockname", (PyCFunction
)py_socket_getsockname
, METH_NOARGS
,
740 "getsockname() -> address info\n\n \
741 Return the address of the local endpoing." },
742 { "getsockopt", (PyCFunction
)py_socket_getsockopt
, METH_VARARGS
,
743 "getsockopt(level, option[, buffersize]) -> value\n\n \
744 Get a socket option." },
745 { "gettimeout", (PyCFunction
)py_socket_gettimeout
, METH_NOARGS
,
746 "gettimeout() -> value\n\n \
747 Return the timeout in seconds associated with socket operations." },
748 { "listen", (PyCFunction
)py_socket_listen
, METH_VARARGS
,
749 "listen(backlog)\n\n \
750 Enable a server to accept connections." },
751 { "makefile", (PyCFunction
)py_socket_makefile
, METH_NOARGS
,
752 "makefile() -> file object\n\n \
753 Return a file object associated with the socket." },
754 { "read", (PyCFunction
)py_socket_read
, METH_VARARGS
,
755 "read(buflen) -> data\n\n \
757 { "recv", (PyCFunction
)py_socket_recv
, METH_VARARGS
,
758 "recv(buflen, flags) -> data\n\n \
760 { "recvfrom", (PyCFunction
)py_socket_recvfrom
, METH_VARARGS
,
761 "recvfrom(buflen, flags) -> (data, sender address)\n\n \
762 Receive data and sender's address." },
763 { "send", (PyCFunction
)py_socket_send
, METH_VARARGS
,
764 "send(data, flags)\n\n \
766 { "sendall", (PyCFunction
)py_socket_sendall
, METH_VARARGS
,
767 "sendall(data, flags)\n\n \
769 { "sendto", (PyCFunction
)py_socket_sendto
, METH_VARARGS
,
770 "sendto(data, flags, addr)\n\n \
771 Send data to a given address." },
772 { "setblocking", (PyCFunction
)py_socket_setblocking
, METH_VARARGS
,
773 "setblocking(flag)\n\n \
774 Set blocking or non-blocking mode of the socket." },
775 { "setsockopt", (PyCFunction
)py_socket_setsockopt
, METH_VARARGS
,
776 "setsockopt(level, option, value)\n\n \
777 Set a socket option." },
778 { "settimeout", (PyCFunction
)py_socket_settimeout
, METH_VARARGS
,
779 "settimeout(value)\n\n \
780 Set a timeout on socket blocking operations." },
781 { "shutdown", (PyCFunction
)py_socket_shutdown
, METH_VARARGS
,
783 Shut down one or both halves of the connection." },
784 { "write", (PyCFunction
)py_socket_write
, METH_VARARGS
,
791 static PyObject
*py_socket_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwargs
)
793 int family
, sock_type
, protocol
;
797 if (!PyArg_ParseTuple(args
, "iii:socket", &family
, &sock_type
, &protocol
)) {
801 sock
= talloc_zero(NULL
, int);
803 return PyErr_NoMemory();
806 *sock
= swrap_socket(family
, sock_type
, protocol
);
808 return PyErr_SetFromErrno(py_socket_error
);
811 if ((pysocket
= pytalloc_steal(type
, sock
)) == NULL
) {
812 return PyErr_NoMemory();
819 static PyTypeObject PySocket
= {
820 .tp_name
= "socket_wrapper.socket",
821 .tp_basicsize
= sizeof(pytalloc_Object
),
822 .tp_flags
= Py_TPFLAGS_DEFAULT
,
823 .tp_methods
= py_socket_methods
,
824 .tp_new
= py_socket_new
,
825 .tp_doc
= "socket(family, type, proto) -> socket object\n\n Open a socket of the give type.",
828 static PyObject
*py_socket_wrapper_dir(PyObject
*self
)
832 dir
= socket_wrapper_dir();
834 return PyString_FromString(dir
);
837 static PyObject
*py_socket_wrapper_default_interface(PyObject
*self
)
841 id
= socket_wrapper_default_iface();
843 return PyInt_FromLong(id
);
847 static PyMethodDef py_socket_wrapper_methods
[] = {
848 { "dir", (PyCFunction
)py_socket_wrapper_dir
, METH_NOARGS
,
850 Return socket_wrapper directory." },
851 { "default_iface", (PyCFunction
)py_socket_wrapper_default_interface
, METH_NOARGS
,
852 "default_iface() -> id\n\n \
853 Return default interface id." },
857 void initsocket_wrapper(void)
860 char exception_name
[] = "socket_wrapper.error";
862 PyTypeObject
*talloc_type
= pytalloc_GetObjectType();
863 if (talloc_type
== NULL
) {
867 PySocket
.tp_base
= talloc_type
;
868 if (PyType_Ready(&PySocket
) < 0) {
872 m
= Py_InitModule3("socket_wrapper", py_socket_wrapper_methods
, "Socket wrapper");
877 py_socket_error
= PyErr_NewException(exception_name
, NULL
, NULL
);
878 Py_INCREF(py_socket_error
);
879 PyModule_AddObject(m
, "error", py_socket_error
);
881 Py_INCREF(&PySocket
);
882 PyModule_AddObject(m
, "socket", (PyObject
*)&PySocket
);