405a43a81dde515e4c2aeddb3cab6432edef6130
[ira/wip.git] / lib / socket_wrapper / py_socket_wrapper.c
1 /*
2  * Copyright (C) Amitay Isaacs 2011
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
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.
16  *
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.
20  *
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
31  * SUCH DAMAGE.
32  *
33  */
34
35 /*
36    Python interface to socket wrapper library.
37
38    Passes all socket communication over unix domain sockets if the environment
39    variable SOCKET_WRAPPER_DIR is set.
40 */
41
42 #include <Python.h>
43 #include <pytalloc.h>
44 #include "replace/replace.h"
45 #include "system/network.h"
46 #include "socket_wrapper.h"
47
48 #ifndef Py_RETURN_NONE
49 #define Py_RETURN_NONE  return Py_INCREF(Py_None), Py_None
50 #endif
51
52 #ifndef Py_TYPE /* Py_TYPE is only available on Python > 2.6 */
53 #define Py_TYPE(ob)             (((PyObject*)(ob))->ob_type)
54 #endif
55
56 #ifndef PY_CHECK_TYPE
57 #define PY_CHECK_TYPE(type, var, fail) \
58         if (!PyObject_TypeCheck(var, type)) {\
59                 PyErr_Format(PyExc_TypeError, __location__ ": Expected type '%s' for '%s' of type '%s'", (type)->tp_name, #var, Py_TYPE(var)->tp_name); \
60                 fail; \
61         }
62 #endif
63
64 staticforward PyTypeObject PySocket;
65
66 static PyObject *py_socket_error;
67
68 void initsocket_wrapper(void);
69
70 static PyObject *py_socket_addr_to_tuple(struct sockaddr *addr, socklen_t len)
71 {
72         char host[256];
73         char service[8];
74         int status;
75         PyObject *pyaddr;
76
77         status = getnameinfo(addr, len, host, 255, service, 7, NI_NUMERICHOST|NI_NUMERICSERV);
78         if (status < 0) {
79                 PyErr_SetString(py_socket_error, gai_strerror(status));
80                 return NULL;
81         }
82
83         pyaddr = PyTuple_New(2);
84         if (pyaddr == NULL) {
85                 return PyErr_NoMemory();
86         }
87
88         PyTuple_SetItem(pyaddr, 0, PyString_FromString(host));
89         PyTuple_SetItem(pyaddr, 1, PyInt_FromLong(atoi(service)));
90
91         return pyaddr;
92 }
93
94 static bool py_socket_tuple_to_addr(PyObject *pyaddr, struct sockaddr *addr, socklen_t *len)
95 {
96         const char *host;
97         char *service;
98         in_port_t port;
99         struct addrinfo *ainfo;
100         int status;
101
102         if (!PyTuple_Check(pyaddr)) {
103                 PyErr_SetString(PyExc_TypeError, "Expected a tuple");
104                 return false;
105         }
106
107         if (!PyArg_ParseTuple(pyaddr, "sH", &host, &port)) {
108                 return false;
109         }
110
111         service = talloc_asprintf(NULL, "%d", port);
112         if (service == NULL) {
113                 PyErr_NoMemory();
114                 return false;
115         }
116
117         status = getaddrinfo(host, service, NULL, &ainfo);
118         if (status < 0) {
119                 talloc_free(service);
120                 PyErr_SetString(py_socket_error, gai_strerror(status));
121                 return false;
122         }
123
124         talloc_free(service);
125
126         memcpy(addr, ainfo->ai_addr, sizeof(struct sockaddr));
127         *len = ainfo->ai_addrlen;
128
129         freeaddrinfo(ainfo);
130         return true;
131 }
132
133
134 static PyObject *py_socket_accept(pytalloc_Object *self, PyObject *args)
135 {
136         int *sock, *new_sock;
137         struct sockaddr addr;
138         socklen_t addrlen;
139         PyObject *pysocket;
140         PyObject *pyaddr;
141         PyObject *pyret;
142
143         sock = pytalloc_get_ptr(self);
144
145         new_sock = talloc_zero(NULL, int);
146         if (new_sock == NULL) {
147                 return PyErr_NoMemory();
148         }
149
150         *new_sock = swrap_accept(*sock, &addr, &addrlen);
151         if (*new_sock < 0) {
152                 return PyErr_SetFromErrno(py_socket_error);
153         }
154
155         if ((pysocket = pytalloc_steal(&PySocket, new_sock)) == NULL) {
156                 return PyErr_NoMemory();
157         }
158
159         pyret = PyTuple_New(2);
160         if (pyret == NULL) {
161                 Py_DECREF(pysocket);
162                 return PyErr_NoMemory();
163         }
164
165         pyaddr = py_socket_addr_to_tuple(&addr, addrlen);
166         if (pyaddr == NULL) {
167                 Py_DECREF(pysocket);
168                 Py_DECREF(pysocket);
169                 return NULL;
170         }
171
172         PyTuple_SetItem(pyret, 0, pysocket);
173         PyTuple_SetItem(pyret, 1, pyaddr);
174         return pyret;
175 }
176
177 static PyObject *py_socket_bind(pytalloc_Object *self, PyObject *args)
178 {
179         PyObject *pyaddr;
180         int *sock;
181         int status;
182         struct sockaddr addr;
183         socklen_t addrlen;
184
185         if (!PyArg_ParseTuple(args, "O:bind", &pyaddr)) {
186                 return NULL;
187         }
188
189         if (!py_socket_tuple_to_addr(pyaddr, &addr, &addrlen)) {
190                 return NULL;
191         }
192
193         sock = pytalloc_get_ptr(self);
194
195         status = swrap_bind(*sock, &addr, addrlen);
196         if (status < 0) {
197                 PyErr_SetString(py_socket_error, "Unable to bind");
198                 return NULL;
199         }
200
201         Py_RETURN_NONE;
202 }
203
204 static PyObject *py_socket_close(pytalloc_Object *self, PyObject *args)
205 {
206         int *sock;
207         int status;
208
209         sock = pytalloc_get_ptr(self);
210
211         status = swrap_close(*sock);
212         if (status < 0) {
213                 return PyErr_SetFromErrno(py_socket_error);
214         }
215
216         Py_RETURN_NONE;
217 }
218
219 static PyObject *py_socket_connect(pytalloc_Object *self, PyObject *args)
220 {
221         int *sock;
222         PyObject *pyaddr;
223         struct sockaddr addr;
224         socklen_t addrlen;
225         int status;
226
227         if (!PyArg_ParseTuple(args, "O:connect", &pyaddr)) {
228                 return NULL;
229         }
230
231         if (!py_socket_tuple_to_addr(pyaddr, &addr, &addrlen)) {
232                 return NULL;
233         }
234
235         sock = pytalloc_get_ptr(self);
236
237         status = swrap_connect(*sock, &addr, addrlen);
238         if (status < 0) {
239                 PyErr_SetFromErrno(py_socket_error);
240                 return NULL;
241         }
242
243         Py_RETURN_NONE;
244 }
245
246 static PyObject *py_socket_connect_ex(pytalloc_Object *self, PyObject *args)
247 {
248         int *sock;
249         PyObject *pyaddr;
250         struct sockaddr addr;
251         socklen_t addrlen;
252         int status;
253
254         if (!PyArg_ParseTuple(args, "O:connect", &pyaddr)) {
255                 return NULL;
256         }
257
258         if (!py_socket_tuple_to_addr(pyaddr, &addr, &addrlen)) {
259                 return NULL;
260         }
261
262         sock = pytalloc_get_ptr(self);
263
264         status = swrap_connect(*sock, &addr, addrlen);
265         if (status < 0) {
266                 return Py_BuildValue("%d", errno);
267         }
268
269         return Py_BuildValue("%d", 0);
270 }
271
272 static PyObject *py_socket_dup(pytalloc_Object *self, PyObject *args)
273 {
274         int *sock, *new_sock;
275         PyObject *pysocket;
276
277         sock = pytalloc_get_ptr(self);
278
279         new_sock = talloc_zero(NULL, int);
280         if (new_sock == NULL) {
281                 return PyErr_NoMemory();
282         }
283
284         *new_sock = swrap_dup(*sock);
285         if (*new_sock < 0) {
286                 return PyErr_SetFromErrno(py_socket_error);
287         }
288
289         pysocket = pytalloc_steal(&PySocket, new_sock);
290         if (pysocket == NULL) {
291                 return PyErr_NoMemory();
292         }
293
294         return pysocket;
295 }
296
297 static PyObject *py_socket_dup2(pytalloc_Object *self, PyObject *args)
298 {
299         int *sock, *new_sock;
300         PyObject *pysocket;
301         int status;
302
303         if (!PyArg_ParseTuple(args, "O", &pysocket)) {
304                 return NULL;
305         }
306
307         PY_CHECK_TYPE(&PySocket, pysocket, return NULL);
308
309         sock = pytalloc_get_ptr(self);
310         new_sock = pytalloc_get_ptr(pysocket);
311
312         status = swrap_dup2(*sock, *new_sock);
313         if (status < 0) {
314                 return PyErr_SetFromErrno(py_socket_error);
315         }
316
317         Py_RETURN_NONE;
318 }
319
320 static PyObject *py_socket_fileno(pytalloc_Object *self, PyObject *args)
321 {
322         PyErr_SetString(py_socket_error, "Not Supported");
323         return NULL;
324 }
325
326 static PyObject *py_socket_getpeername(pytalloc_Object *self, PyObject *args)
327 {
328         int *sock;
329         struct sockaddr addr;
330         socklen_t addrlen;
331         int status;
332         PyObject *pyaddr;
333
334         sock = pytalloc_get_ptr(self);
335
336         status = swrap_getpeername(*sock, &addr, &addrlen);
337         if (status < 0) {
338                 return PyErr_SetFromErrno(py_socket_error);
339         }
340
341         pyaddr = py_socket_addr_to_tuple(&addr, addrlen);
342
343         return pyaddr;
344 }
345
346 static PyObject *py_socket_getsockname(pytalloc_Object *self, PyObject *args)
347 {
348         int *sock;
349         struct sockaddr addr;
350         socklen_t addrlen;
351         int status;
352         PyObject *pyaddr;
353
354         sock = pytalloc_get_ptr(self);
355
356         status = swrap_getsockname(*sock, &addr, &addrlen);
357         if (status < 0) {
358                 return PyErr_SetFromErrno(py_socket_error);
359         }
360
361         pyaddr = py_socket_addr_to_tuple(&addr, addrlen);
362
363         return pyaddr;
364 }
365
366 static PyObject *py_socket_getsockopt(pytalloc_Object *self, PyObject *args)
367 {
368         int level, optname;
369         int *sock;
370         socklen_t optlen = -1, newlen;
371         int optval;
372         bool is_integer = false;
373         char *buffer;
374         PyObject *pyret;
375         int status;
376
377         if (!PyArg_ParseTuple(args, "ii|i:getsockopt", &level, &optname, &optlen)) {
378                 return NULL;
379         }
380
381         if (optlen < 0) {
382                 optlen = sizeof(int);
383                 is_integer = true;
384         }
385
386         buffer = talloc_zero_array(NULL, char, optlen);
387         if (buffer == NULL) {
388                 return PyErr_NoMemory();
389         }
390
391         sock = pytalloc_get_ptr(self);
392
393         status = swrap_getsockopt(*sock, level, optname, (void *)buffer, &newlen);
394         if (status < 0) {
395                 talloc_free(buffer);
396                 return PyErr_SetFromErrno(py_socket_error);
397         }
398
399         if (is_integer) {
400                 optval = *(int *)buffer;
401                 pyret = PyInt_FromLong(optval);
402         } else {
403                 pyret = PyString_FromStringAndSize(buffer, optlen);
404         }
405
406         talloc_free(buffer);
407
408         return pyret;
409 }
410
411 static PyObject *py_socket_gettimeout(pytalloc_Object *self, PyObject *args)
412 {
413         PyErr_SetString(py_socket_error, "Not Supported");
414         return NULL;
415 }
416
417 static PyObject *py_socket_listen(pytalloc_Object *self, PyObject *args)
418 {
419         int backlog;
420         int *sock;
421         int status;
422
423         if (!PyArg_ParseTuple(args, "i:listen", &backlog)) {
424                 return NULL;
425         }
426
427         sock = pytalloc_get_ptr(self);
428
429         status = swrap_listen(*sock, backlog);
430         if (status < 0) {
431                 return PyErr_SetFromErrno(py_socket_error);
432         }
433
434         Py_RETURN_NONE;
435 }
436
437 static PyObject *py_socket_makefile(pytalloc_Object *self, PyObject *args)
438 {
439         PyErr_SetString(py_socket_error, "Not Supported");
440         return NULL;
441 }
442
443 static PyObject *py_socket_read(pytalloc_Object *self, PyObject *args)
444 {
445         int bufsize, len;
446         int *sock;
447         char *buffer;
448         PyObject *pyret;
449
450         if (!PyArg_ParseTuple(args, "i:read", &bufsize)) {
451                 return NULL;
452         }
453
454         buffer = talloc_zero_array(NULL, char, bufsize);
455         if (buffer == NULL) {
456                 return PyErr_NoMemory();
457         }
458
459         sock = pytalloc_get_ptr(self);
460
461         len = swrap_read(*sock, buffer, bufsize);
462         if (len < 0) {
463                 return PyErr_SetFromErrno(py_socket_error);
464         }
465
466         pyret = PyString_FromStringAndSize(buffer, len);
467
468         talloc_free(buffer);
469
470         return pyret;
471 }
472
473 static PyObject *py_socket_recv(pytalloc_Object *self, PyObject *args)
474 {
475         int bufsize, flags, len;
476         int *sock;
477         char *buffer;
478         PyObject *pyret;
479
480         if (!PyArg_ParseTuple(args, "ii:recv", &bufsize, &flags)) {
481                 return NULL;
482         }
483
484         buffer = talloc_zero_array(NULL, char, bufsize);
485         if (buffer == NULL) {
486                 return PyErr_NoMemory();
487         }
488
489         sock = pytalloc_get_ptr(self);
490
491         len = swrap_recv(*sock, buffer, bufsize, flags);
492         if (len < 0) {
493                 return PyErr_SetFromErrno(py_socket_error);
494         }
495
496         pyret = PyString_FromStringAndSize(buffer, len);
497
498         talloc_free(buffer);
499
500         return pyret;
501 }
502
503 static PyObject *py_socket_recvfrom(pytalloc_Object *self, PyObject *args)
504 {
505         int bufsize, flags, len;
506         int *sock;
507         char *buffer;
508         struct sockaddr from;
509         socklen_t fromlen;
510         PyObject *pybuf, *pyaddr, *pyret;
511
512         if (!PyArg_ParseTuple(args, "ii:recvfrom", &bufsize, &flags)) {
513                 return NULL;
514         }
515
516         buffer = talloc_zero_array(NULL, char, bufsize);
517         if (buffer == NULL) {
518                 return PyErr_NoMemory();
519         }
520
521         sock = pytalloc_get_ptr(self);
522
523         fromlen = sizeof(struct sockaddr);
524
525         len = swrap_recvfrom(*sock, buffer, bufsize, flags, &from, &fromlen);
526         if (len < 0) {
527                 talloc_free(buffer);
528                 return PyErr_SetFromErrno(py_socket_error);
529         }
530
531         pybuf = PyString_FromStringAndSize(buffer, len);
532         if (pybuf == NULL) {
533                 talloc_free(buffer);
534                 return PyErr_NoMemory();
535         }
536
537         talloc_free(buffer);
538
539         pyaddr = py_socket_addr_to_tuple(&from, fromlen);
540         if (pyaddr == NULL) {
541                 Py_DECREF(pybuf);
542                 return NULL;
543         }
544
545         pyret = PyTuple_New(2);
546         if (pyret == NULL) {
547                 Py_DECREF(pybuf);
548                 Py_DECREF(pyaddr);
549                 return PyErr_NoMemory();
550         }
551
552         PyTuple_SetItem(pyret, 0, pybuf);
553         PyTuple_SetItem(pyret, 1, pyaddr);
554
555         return pyret;
556 }
557
558 static PyObject *py_socket_send(pytalloc_Object *self, PyObject *args)
559 {
560         char *buffer;
561         int len, flags;
562         int *sock;
563         int status;
564
565         if (!PyArg_ParseTuple(args, "s#i:sendto", &buffer, &len, &flags)) {
566                 return NULL;
567         }
568
569         sock = pytalloc_get_ptr(self);
570
571         status = swrap_send(*sock, buffer, len, flags);
572         if (status < 0) {
573                 PyErr_SetFromErrno(py_socket_error);
574                 return NULL;
575         }
576
577         Py_RETURN_NONE;
578 }
579
580 static PyObject *py_socket_sendall(pytalloc_Object *self, PyObject *args)
581 {
582         char *buffer;
583         int len, flags;
584         int *sock;
585         int status;
586
587         if (!PyArg_ParseTuple(args, "s#i:sendall", &buffer, &len, &flags)) {
588                 return NULL;
589         }
590
591         sock = pytalloc_get_ptr(self);
592
593         status = swrap_send(*sock, buffer, len, flags);
594         if (status < 0) {
595                 PyErr_SetFromErrno(py_socket_error);
596                 return NULL;
597         }
598
599         Py_RETURN_NONE;
600 }
601
602 static PyObject *py_socket_sendto(pytalloc_Object *self, PyObject *args)
603 {
604         PyObject *pyaddr;
605         char *buffer;
606         int len, flags;
607         int *sock;
608         struct sockaddr addr;
609         socklen_t addrlen;
610         int status;
611
612         if (!PyArg_ParseTuple(args, "s#iO:sendto", &buffer, &len, &flags, &pyaddr)) {
613                 return NULL;
614         }
615
616         if (!py_socket_tuple_to_addr(pyaddr, &addr, &addrlen)) {
617                 return NULL;
618         }
619
620         sock = pytalloc_get_ptr(self);
621
622         status = swrap_sendto(*sock, buffer, len, flags, &addr, addrlen);
623         if (status < 0) {
624                 PyErr_SetFromErrno(py_socket_error);
625                 return NULL;
626         }
627
628         Py_RETURN_NONE;
629 }
630
631 static PyObject *py_socket_setblocking(pytalloc_Object *self, PyObject *args)
632 {
633         PyErr_SetString(py_socket_error, "Not Supported");
634         return NULL;
635 }
636
637 static PyObject *py_socket_setsockopt(pytalloc_Object *self, PyObject *args)
638 {
639         int level, optname;
640         int *sock;
641         PyObject *pyval;
642         int optval;
643         Py_ssize_t optlen;
644         char *buffer;
645         int status;
646
647         if (!PyArg_ParseTuple(args, "iiO:getsockopt", &level, &optname, &pyval)) {
648                 return NULL;
649         }
650
651         if (PyInt_Check(pyval)) {
652                 optval = PyInt_AsLong(pyval);
653                 buffer = (char *)&optval;
654                 optlen = sizeof(int);
655         } else {
656                 PyString_AsStringAndSize(pyval, &buffer, &optlen);
657         }
658
659         sock = pytalloc_get_ptr(self);
660
661         status = swrap_setsockopt(*sock, level, optname, (void *)buffer, optlen);
662         if (status < 0) {
663                 return PyErr_SetFromErrno(py_socket_error);
664         }
665
666         Py_RETURN_NONE;
667 }
668
669 static PyObject *py_socket_settimeout(pytalloc_Object *self, PyObject *args)
670 {
671         PyErr_SetString(py_socket_error, "Not Supported");
672         return NULL;
673 }
674
675 static PyObject *py_socket_shutdown(pytalloc_Object *self, PyObject *args)
676 {
677         PyErr_SetString(py_socket_error, "Not Supported");
678         return NULL;
679 }
680
681 static PyObject *py_socket_write(pytalloc_Object *self, PyObject *args)
682 {
683         char *buffer;
684         int len;
685         int *sock;
686         int status;
687
688         if (!PyArg_ParseTuple(args, "s#:write", &buffer, &len)) {
689                 return NULL;
690         }
691
692         sock = pytalloc_get_ptr(self);
693
694         status = swrap_send(*sock, buffer, len, 0);
695         if (status < 0) {
696                 PyErr_SetFromErrno(py_socket_error);
697                 return NULL;
698         }
699
700         Py_RETURN_NONE;
701 }
702
703
704 static PyMethodDef py_socket_methods[] = {
705         { "accept", (PyCFunction)py_socket_accept, METH_NOARGS,
706                 "accept() -> (socket object, address info)\n\n \
707                 Wait for an incoming connection." },
708         { "bind", (PyCFunction)py_socket_bind, METH_VARARGS,
709                 "bind(address)\n\n \
710                 Bind the socket to a local address." },
711         { "close", (PyCFunction)py_socket_close, METH_NOARGS,
712                 "close()\n\n \
713                 Close the socket." },
714         { "connect", (PyCFunction)py_socket_connect, METH_VARARGS,
715                 "connect(address)\n\n \
716                 Connect the socket to a remote address." },
717         { "connect_ex", (PyCFunction)py_socket_connect_ex, METH_VARARGS,
718                 "connect_ex(address)\n\n \
719                 Connect the socket to a remote address." },
720         { "dup", (PyCFunction)py_socket_dup, METH_VARARGS,
721                 "dup() -> socket object\n\n \
722                 Return a new socket object connected to the same system resource." },
723         { "dup2", (PyCFunction)py_socket_dup2, METH_VARARGS,
724                 "dup2(socket object) -> socket object\n\n \
725                 Return a new socket object connected to teh same system resource." },
726         { "fileno", (PyCFunction)py_socket_fileno, METH_NOARGS,
727                 "fileno() -> file descriptor\n\n \
728                 Return socket's file descriptor." },
729         { "getpeername", (PyCFunction)py_socket_getpeername, METH_NOARGS,
730                 "getpeername() -> address info\n\n \
731                 Return the address of the remote endpoint." },
732         { "getsockname", (PyCFunction)py_socket_getsockname, METH_NOARGS,
733                 "getsockname() -> address info\n\n \
734                 Return the address of the local endpoing." },
735         { "getsockopt", (PyCFunction)py_socket_getsockopt, METH_VARARGS,
736                 "getsockopt(level, option[, buffersize]) -> value\n\n \
737                 Get a socket option." },
738         { "gettimeout", (PyCFunction)py_socket_gettimeout, METH_NOARGS,
739                 "gettimeout() -> value\n\n \
740                 Return the timeout in seconds associated with socket operations." },
741         { "listen", (PyCFunction)py_socket_listen, METH_VARARGS,
742                 "listen(backlog)\n\n \
743                 Enable a server to accept connections." },
744         { "makefile", (PyCFunction)py_socket_makefile, METH_NOARGS,
745                 "makefile() -> file object\n\n \
746                 Return a file object associated with the socket." },
747         { "read", (PyCFunction)py_socket_read, METH_VARARGS,
748                 "read(buflen) -> data\n\n \
749                 Receive data." },
750         { "recv", (PyCFunction)py_socket_recv, METH_VARARGS,
751                 "recv(buflen, flags) -> data\n\n \
752                 Receive data." },
753         { "recvfrom", (PyCFunction)py_socket_recvfrom, METH_VARARGS,
754                 "recvfrom(buflen, flags) -> (data, sender address)\n\n \
755                 Receive data and sender's address." },
756         { "send", (PyCFunction)py_socket_send, METH_VARARGS,
757                 "send(data, flags)\n\n \
758                 Send data." },
759         { "sendall", (PyCFunction)py_socket_sendall, METH_VARARGS,
760                 "sendall(data, flags)\n\n \
761                 Send data." },
762         { "sendto", (PyCFunction)py_socket_sendto, METH_VARARGS,
763                 "sendto(data, flags, addr)\n\n \
764                 Send data to a given address." },
765         { "setblocking", (PyCFunction)py_socket_setblocking, METH_VARARGS,
766                 "setblocking(flag)\n\n \
767                 Set blocking or non-blocking mode of the socket." },
768         { "setsockopt", (PyCFunction)py_socket_setsockopt, METH_VARARGS,
769                 "setsockopt(level, option, value)\n\n \
770                 Set a socket option." },
771         { "settimeout", (PyCFunction)py_socket_settimeout, METH_VARARGS,
772                 "settimeout(value)\n\n \
773                 Set a timeout on socket blocking operations." },
774         { "shutdown", (PyCFunction)py_socket_shutdown, METH_VARARGS,
775                 "shutdown(how)\n\n \
776                 Shut down one or both halves of the connection." },
777         { "write", (PyCFunction)py_socket_write, METH_VARARGS,
778                 "write(data)\n\n \
779                 Send data." },
780         { NULL },
781 };
782
783
784 static PyObject *py_socket_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
785 {
786         int family, sock_type, protocol;
787         int *sock;
788         PyObject *pysocket;
789
790         if (!PyArg_ParseTuple(args, "iii:socket", &family, &sock_type, &protocol)) {
791                 return NULL;
792         }
793
794         sock = talloc_zero(NULL, int);
795         if (sock == NULL) {
796                 return PyErr_NoMemory();
797         }
798
799         *sock = swrap_socket(family, sock_type, protocol);
800         if (*sock < 0) {
801                 return PyErr_SetFromErrno(py_socket_error);
802         }
803
804         if ((pysocket = pytalloc_steal(type, sock)) == NULL) {
805                 return PyErr_NoMemory();
806         }
807
808         return pysocket;
809 }
810
811
812 static PyTypeObject PySocket = {
813         .tp_name = "socket_wrapper.socket",
814         .tp_basicsize = sizeof(pytalloc_Object),
815         .tp_flags = Py_TPFLAGS_DEFAULT,
816         .tp_methods = py_socket_methods,
817         .tp_new = py_socket_new,
818         .tp_doc = "socket(family, type, proto) -> socket object\n\n Open a socket of the give type.",
819 };
820
821 static PyObject *py_socket_wrapper_dir(PyObject *self)
822 {
823         const char *dir;
824
825         dir = socket_wrapper_dir();
826
827         return PyString_FromString(dir);
828 }
829
830 static PyObject *py_socket_wrapper_default_interface(PyObject *self)
831 {
832         unsigned int id;
833
834         id = socket_wrapper_default_iface();
835
836         return PyInt_FromLong(id);
837 }
838
839
840 static PyMethodDef py_socket_wrapper_methods[] = {
841         { "dir", (PyCFunction)py_socket_wrapper_dir, METH_NOARGS,
842                 "dir() -> path\n\n \
843                 Return socket_wrapper directory." },
844         { "default_iface", (PyCFunction)py_socket_wrapper_default_interface, METH_NOARGS,
845                 "default_iface() -> id\n\n \
846                 Return default interface id." },
847         { NULL },
848 };
849
850 void initsocket_wrapper(void)
851 {
852         PyObject *m;
853         char exception_name[] = "socket_wrapper.error";
854
855         PyTypeObject *talloc_type = pytalloc_GetObjectType();
856         if (talloc_type == NULL) {
857                 return;
858         }
859
860         PySocket.tp_base = talloc_type;
861         if (PyType_Ready(&PySocket) < 0) {
862                 return;
863         }
864
865         m = Py_InitModule3("socket_wrapper", py_socket_wrapper_methods, "Socket wrapper");
866         if (m == NULL) {
867                 return;
868         }
869
870         py_socket_error = PyErr_NewException(exception_name, NULL, NULL);
871         Py_INCREF(py_socket_error);
872         PyModule_AddObject(m, "error", py_socket_error);
873
874         Py_INCREF(&PySocket);
875         PyModule_AddObject(m, "socket", (PyObject *)&PySocket);
876 }