Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / python / sendmsg.c
1 /*
2  * Copyright (c) Twisted Matrix Laboratories.
3  * See LICENSE for details.
4  */
5
6 #define PY_SSIZE_T_CLEAN 1
7 #include <Python.h>
8
9 #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
10 /* This may cause some warnings, but if you want to get rid of them, upgrade
11  * your Python version.  */
12 typedef int Py_ssize_t;
13 #endif
14
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <signal.h>
18
19 /*
20  * As per
21  * <http://pubs.opengroup.org/onlinepubs/007904875/basedefs/sys/socket.h.html
22  * #tag_13_61_05>:
23  *
24  *     "To forestall portability problems, it is recommended that applications
25  *     not use values larger than (2**31)-1 for the socklen_t type."
26  */
27
28 #define SOCKLEN_MAX 0x7FFFFFFF
29
30 PyObject *sendmsg_socket_error;
31
32 static PyObject *sendmsg_sendmsg(PyObject *self, PyObject *args, PyObject *keywds);
33 static PyObject *sendmsg_recvmsg(PyObject *self, PyObject *args, PyObject *keywds);
34 static PyObject *sendmsg_getsockfam(PyObject *self, PyObject *args, PyObject *keywds);
35
36 static char sendmsg_doc[] = "\
37 Bindings for sendmsg(2), recvmsg(2), and a minimal helper for inspecting\n\
38 address family of a socket.\n\
39 ";
40
41 static char sendmsg_sendmsg_doc[] = "\
42 Wrap the C sendmsg(2) function for sending \"messages\" on a socket.\n\
43 \n\
44 @param fd: The file descriptor of the socket over which to send a message.\n\
45 @type fd: C{int}\n\
46 \n\
47 @param data: Bytes to write to the socket.\n\
48 @type data: C{str}\n\
49 \n\
50 @param flags: Flags to affect how the message is sent.  See the C{MSG_}\n\
51     constants in the sendmsg(2) manual page.  By default no flags are set.\n\
52 @type flags: C{int}\n\
53 \n\
54 @param ancillary: Extra data to send over the socket outside of the normal\n\
55     datagram or stream mechanism.  By default no ancillary data is sent.\n\
56 @type ancillary: C{list} of C{tuple} of C{int}, C{int}, and C{str}.\n\
57 \n\
58 @raise OverflowError: Raised if too much ancillary data is given.\n\
59 @raise socket.error: Raised if the underlying syscall indicates an error.\n\
60 \n\
61 @return: The return value of the underlying syscall, if it succeeds.\n\
62 ";
63
64 static char sendmsg_recvmsg_doc[] = "\
65 Wrap the C recvmsg(2) function for receiving \"messages\" on a socket.\n\
66 \n\
67 @param fd: The file descriptor of the socket over which to receve a message.\n\
68 @type fd: C{int}\n\
69 \n\
70 @param flags: Flags to affect how the message is sent.  See the C{MSG_}\n\
71     constants in the sendmsg(2) manual page.  By default no flags are set.\n\
72 @type flags: C{int}\n\
73 \n\
74 @param maxsize: The maximum number of bytes to receive from the socket\n\
75     using the datagram or stream mechanism.  The default maximum is 8192.\n\
76 @type maxsize: C{int}\n\
77 \n\
78 @param cmsg_size: The maximum number of bytes to receive from the socket\n\
79     outside of the normal datagram or stream mechanism.  The default maximum is 4096.\n\
80 \n\
81 @raise OverflowError: Raised if too much ancillary data is given.\n\
82 @raise socket.error: Raised if the underlying syscall indicates an error.\n\
83 \n\
84 @return: A C{tuple} of three elements: the bytes received using the\n\
85     datagram/stream mechanism, flags as an C{int} describing the data\n\
86     received, and a C{list} of C{tuples} giving ancillary received data.\n\
87 ";
88
89 static char sendmsg_getsockfam_doc[] = "\
90 Retrieve the address family of a given socket.\n\
91 \n\
92 @param fd: The file descriptor of the socket the address family of which\n\
93     to retrieve.\n\
94 @type fd: C{int}\n\
95 \n\
96 @raise socket.error: Raised if the underlying getsockname call indicates\n\
97     an error.\n\
98 \n\
99 @return: A C{int} representing the address family of the socket.  For\n\
100     example, L{socket.AF_INET}, L{socket.AF_INET6}, or L{socket.AF_UNIX}.\n\
101 ";
102
103 static PyMethodDef sendmsg_methods[] = {
104     {"send1msg", (PyCFunction) sendmsg_sendmsg, METH_VARARGS | METH_KEYWORDS,
105      sendmsg_sendmsg_doc},
106     {"recv1msg", (PyCFunction) sendmsg_recvmsg, METH_VARARGS | METH_KEYWORDS,
107      sendmsg_recvmsg_doc},
108     {"getsockfam", (PyCFunction) sendmsg_getsockfam,
109      METH_VARARGS | METH_KEYWORDS, sendmsg_getsockfam_doc},
110     {NULL, NULL, 0, NULL}
111 };
112
113
114 PyMODINIT_FUNC initsendmsg(void) {
115     PyObject *module;
116
117     sendmsg_socket_error = NULL; /* Make sure that this has a known value
118                                     before doing anything that might exit. */
119
120     module = Py_InitModule3("sendmsg", sendmsg_methods, sendmsg_doc);
121
122     if (!module) {
123         return;
124     }
125
126     /*
127       The following is the only value mentioned by POSIX:
128       http://www.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
129     */
130
131     if (-1 == PyModule_AddIntConstant(module, "SCM_RIGHTS", SCM_RIGHTS)) {
132         return;
133     }
134
135
136     /* BSD, Darwin, Hurd */
137 #if defined(SCM_CREDS)
138     if (-1 == PyModule_AddIntConstant(module, "SCM_CREDS", SCM_CREDS)) {
139         return;
140     }
141 #endif
142
143     /* Linux */
144 #if defined(SCM_CREDENTIALS)
145     if (-1 == PyModule_AddIntConstant(module, "SCM_CREDENTIALS", SCM_CREDENTIALS)) {
146         return;
147     }
148 #endif
149
150     /* Apparently everywhere, but not standardized. */
151 #if defined(SCM_TIMESTAMP)
152     if (-1 == PyModule_AddIntConstant(module, "SCM_TIMESTAMP", SCM_TIMESTAMP)) {
153         return;
154     }
155 #endif
156
157     module = PyImport_ImportModule("socket");
158     if (!module) {
159         return;
160     }
161
162     sendmsg_socket_error = PyObject_GetAttrString(module, "error");
163     if (!sendmsg_socket_error) {
164         return;
165     }
166 }
167
168 static PyObject *sendmsg_sendmsg(PyObject *self, PyObject *args, PyObject *keywds) {
169
170     int fd;
171     int flags = 0;
172     Py_ssize_t sendmsg_result;
173     struct msghdr message_header;
174     struct iovec iov[1];
175     PyObject *ancillary = NULL;
176     PyObject *iterator = NULL;
177     PyObject *item = NULL;
178     PyObject *result_object = NULL;
179
180     static char *kwlist[] = {"fd", "data", "flags", "ancillary", NULL};
181
182     if (!PyArg_ParseTupleAndKeywords(
183             args, keywds, "it#|iO:sendmsg", kwlist,
184             &fd,
185             &iov[0].iov_base,
186             &iov[0].iov_len,
187             &flags,
188             &ancillary)) {
189         return NULL;
190     }
191
192     message_header.msg_name = NULL;
193     message_header.msg_namelen = 0;
194
195     message_header.msg_iov = iov;
196     message_header.msg_iovlen = 1;
197
198     message_header.msg_control = NULL;
199     message_header.msg_controllen = 0;
200
201     message_header.msg_flags = 0;
202
203     if (ancillary) {
204
205         if (!PyList_Check(ancillary)) {
206             PyErr_Format(PyExc_TypeError,
207                          "send1msg argument 3 expected list, got %s",
208                          ancillary->ob_type->tp_name);
209             goto finished;
210         }
211
212         iterator = PyObject_GetIter(ancillary);
213
214         if (iterator == NULL) {
215             goto finished;
216         }
217
218         size_t all_data_len = 0;
219
220         /* First we need to know how big the buffer needs to be in order to
221            have enough space for all of the messages. */
222         while ( (item = PyIter_Next(iterator)) ) {
223             int type, level;
224             Py_ssize_t data_len;
225             size_t prev_all_data_len;
226             char *data;
227
228             if (!PyTuple_Check(item)) {
229                 PyErr_Format(PyExc_TypeError,
230                              "send1msg argument 3 expected list of tuple, "
231                              "got list containing %s",
232                              item->ob_type->tp_name);
233                 goto finished;
234             }
235
236             if (!PyArg_ParseTuple(
237                         item, "iit#:sendmsg ancillary data (level, type, data)",
238                         &level, &type, &data, &data_len)) {
239                 goto finished;
240             }
241
242             prev_all_data_len = all_data_len;
243             all_data_len += CMSG_SPACE(data_len);
244
245             Py_DECREF(item);
246             item = NULL;
247
248             if (all_data_len < prev_all_data_len) {
249                 PyErr_Format(PyExc_OverflowError,
250                              "Too much msg_control to fit in a size_t: %zu",
251                              prev_all_data_len);
252                 goto finished;
253             }
254         }
255
256         Py_DECREF(iterator);
257         iterator = NULL;
258
259         /* Allocate the buffer for all of the ancillary elements, if we have
260          * any.  */
261         if (all_data_len) {
262             if (all_data_len > SOCKLEN_MAX) {
263                 PyErr_Format(PyExc_OverflowError,
264                              "Too much msg_control to fit in a socklen_t: %zu",
265                              all_data_len);
266                 goto finished;
267             }
268             message_header.msg_control = PyMem_Malloc(all_data_len);
269             if (!message_header.msg_control) {
270                 PyErr_NoMemory();
271                 goto finished;
272             }
273         } else {
274             message_header.msg_control = NULL;
275         }
276         message_header.msg_controllen = (socklen_t) all_data_len;
277
278         iterator = PyObject_GetIter(ancillary); /* again */
279
280         if (!iterator) {
281             goto finished;
282         }
283
284         /* Unpack the tuples into the control message. */
285         struct cmsghdr *control_message = CMSG_FIRSTHDR(&message_header);
286         while ( (item = PyIter_Next(iterator)) ) {
287             int data_len, type, level;
288             size_t data_size;
289             unsigned char *data, *cmsg_data;
290
291             /* We explicitly allocated enough space for all ancillary data
292                above; if there isn't enough room, all bets are off. */
293             assert(control_message);
294
295             if (!PyArg_ParseTuple(item,
296                                   "iit#:sendmsg ancillary data (level, type, data)",
297                                   &level,
298                                   &type,
299                                   &data,
300                                   &data_len)) {
301                 goto finished;
302             }
303
304             control_message->cmsg_level = level;
305             control_message->cmsg_type = type;
306             data_size = CMSG_LEN(data_len);
307
308             if (data_size > SOCKLEN_MAX) {
309                 PyErr_Format(PyExc_OverflowError,
310                              "CMSG_LEN(%d) > SOCKLEN_MAX", data_len);
311                 goto finished;
312             }
313
314             control_message->cmsg_len = (socklen_t) data_size;
315
316             cmsg_data = CMSG_DATA(control_message);
317             memcpy(cmsg_data, data, data_len);
318
319             Py_DECREF(item);
320             item = NULL;
321
322             control_message = CMSG_NXTHDR(&message_header, control_message);
323         }
324         Py_DECREF(iterator);
325         iterator = NULL;
326
327         if (PyErr_Occurred()) {
328             goto finished;
329         }
330     }
331
332     sendmsg_result = sendmsg(fd, &message_header, flags);
333
334     if (sendmsg_result < 0) {
335         PyErr_SetFromErrno(sendmsg_socket_error);
336         goto finished;
337     }
338
339     result_object = Py_BuildValue("n", sendmsg_result);
340
341  finished:
342
343     if (item) {
344         Py_DECREF(item);
345         item = NULL;
346     }
347     if (iterator) {
348         Py_DECREF(iterator);
349         iterator = NULL;
350     }
351     if (message_header.msg_control) {
352         PyMem_Free(message_header.msg_control);
353         message_header.msg_control = NULL;
354     }
355     return result_object;
356 }
357
358 static PyObject *sendmsg_recvmsg(PyObject *self, PyObject *args, PyObject *keywds) {
359     int fd = -1;
360     int flags = 0;
361     int maxsize = 8192;
362     int cmsg_size = 4096;
363     size_t cmsg_space;
364     size_t cmsg_overhead;
365     Py_ssize_t recvmsg_result;
366
367     struct msghdr message_header;
368     struct cmsghdr *control_message;
369     struct iovec iov[1];
370     char *cmsgbuf;
371     PyObject *ancillary;
372     PyObject *final_result = NULL;
373
374     static char *kwlist[] = {"fd", "flags", "maxsize", "cmsg_size", NULL};
375
376     if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|iii:recvmsg", kwlist,
377                                      &fd, &flags, &maxsize, &cmsg_size)) {
378         return NULL;
379     }
380
381     cmsg_space = CMSG_SPACE(cmsg_size);
382
383     /* overflow check */
384     if (cmsg_space > SOCKLEN_MAX) {
385         PyErr_Format(PyExc_OverflowError,
386                      "CMSG_SPACE(cmsg_size) greater than SOCKLEN_MAX: %d",
387                      cmsg_size);
388         return NULL;
389     }
390
391     message_header.msg_name = NULL;
392     message_header.msg_namelen = 0;
393
394     iov[0].iov_len = maxsize;
395     iov[0].iov_base = PyMem_Malloc(maxsize);
396
397     if (!iov[0].iov_base) {
398         PyErr_NoMemory();
399         return NULL;
400     }
401
402     message_header.msg_iov = iov;
403     message_header.msg_iovlen = 1;
404
405     cmsgbuf = PyMem_Malloc(cmsg_space);
406
407     if (!cmsgbuf) {
408         PyMem_Free(iov[0].iov_base);
409         PyErr_NoMemory();
410         return NULL;
411     }
412
413     memset(cmsgbuf, 0, cmsg_space);
414     message_header.msg_control = cmsgbuf;
415     /* see above for overflow check */
416     message_header.msg_controllen = (socklen_t) cmsg_space;
417
418     recvmsg_result = recvmsg(fd, &message_header, flags);
419     if (recvmsg_result < 0) {
420         PyErr_SetFromErrno(sendmsg_socket_error);
421         goto finished;
422     }
423
424     ancillary = PyList_New(0);
425     if (!ancillary) {
426         goto finished;
427     }
428
429     for (control_message = CMSG_FIRSTHDR(&message_header);
430          control_message;
431          control_message = CMSG_NXTHDR(&message_header,
432                                        control_message)) {
433         PyObject *entry;
434
435         /* Some platforms apparently always fill out the ancillary data
436            structure with a single bogus value if none is provided; ignore it,
437            if that is the case. */
438
439         if ((!(control_message->cmsg_level)) &&
440             (!(control_message->cmsg_type))) {
441             continue;
442         }
443
444         /*
445          * Figure out how much of the cmsg size is cmsg structure overhead - in
446          * other words, how much is not part of the application data.  This lets
447          * us compute the right application data size below.  There should
448          * really be a CMSG_ macro for this.
449          */
450         cmsg_overhead = (char*)CMSG_DATA(control_message) - (char*)control_message;
451
452         entry = Py_BuildValue(
453             "(iis#)",
454             control_message->cmsg_level,
455             control_message->cmsg_type,
456             CMSG_DATA(control_message),
457             (Py_ssize_t) (control_message->cmsg_len - cmsg_overhead));
458
459         if (!entry) {
460             Py_DECREF(ancillary);
461             goto finished;
462         }
463
464         if (PyList_Append(ancillary, entry) < 0) {
465             Py_DECREF(ancillary);
466             Py_DECREF(entry);
467             goto finished;
468         } else {
469             Py_DECREF(entry);
470         }
471     }
472
473     final_result = Py_BuildValue(
474         "s#iO",
475         iov[0].iov_base,
476         recvmsg_result,
477         message_header.msg_flags,
478         ancillary);
479
480     Py_DECREF(ancillary);
481
482   finished:
483     PyMem_Free(iov[0].iov_base);
484     PyMem_Free(cmsgbuf);
485     return final_result;
486 }
487
488 static PyObject *sendmsg_getsockfam(PyObject *self, PyObject *args,
489                                     PyObject *keywds) {
490     int fd;
491     struct sockaddr sa;
492     static char *kwlist[] = {"fd", NULL};
493     if (!PyArg_ParseTupleAndKeywords(args, keywds, "i", kwlist, &fd)) {
494         return NULL;
495     }
496     socklen_t sz = sizeof(sa);
497     if (getsockname(fd, &sa, &sz)) {
498         PyErr_SetFromErrno(sendmsg_socket_error);
499         return NULL;
500     }
501     return Py_BuildValue("i", sa.sa_family);
502 }