blob: a4e4b621c0e405ddb58e9e24899404510ba6e030 [file] [log] [blame]
Scott James Remnantfc5a3f72013-08-01 14:39:40 -07001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
Scott James Remnant96927a42013-07-17 18:27:57 -07002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#include <Python.h>
7
8#include <sys/types.h>
9#include <sys/socket.h>
10#include <poll.h>
11
12#include "bluetooth.h"
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070013#include "l2cap.h"
14#include "rfcomm.h"
Scott James Remnant96927a42013-07-17 18:27:57 -070015#include "hci.h"
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070016#include "sco.h"
Scott James Remnant96927a42013-07-17 18:27:57 -070017
18static PyObject *_btsocket_error;
19static PyObject *_btsocket_timeout;
20
21static int _get_fileno(PyObject *socket) {
22 PyObject *fileno_object;
23 long fileno;
24
25 fileno_object = PyObject_CallMethod(socket, "fileno", "", NULL);
26 if (!fileno_object)
27 return -1;
28
29 if (!PyInt_Check(fileno_object))
30 return -1;
31
32 /* PyInts are longer than your average int, truncate back to an int */
33 fileno = PyInt_AS_LONG(fileno_object);
34 Py_DECREF(fileno_object);
35 return (int)fileno;
36}
37
38static int _get_timeout(PyObject *socket, double *timeout) {
39 PyObject *timeout_object;
40
41 timeout_object = PyObject_CallMethod(socket, "gettimeout", "", NULL);
42 if (!timeout_object)
43 return 0;
44
45 if (!PyFloat_Check(timeout_object))
46 return 0;
47
48 *timeout = PyFloat_AS_DOUBLE(timeout_object);
49 Py_DECREF(timeout_object);
50 return 1;
51}
52
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070053static int _setbdaddr(const char *straddr, bdaddr_t *bdaddr) {
54 unsigned int b0, b1, b2, b3, b4, b5;
55 int n;
56
57 n = sscanf(straddr, "%X:%X:%X:%X:%X:%X", &b5, &b4, &b3, &b2, &b1, &b0);
58 if (n == 6) {
59 bdaddr->b[0] = b0;
60 bdaddr->b[1] = b1;
61 bdaddr->b[2] = b2;
62 bdaddr->b[3] = b3;
63 bdaddr->b[4] = b4;
64 bdaddr->b[5] = b5;
65 return 1;
66 } else {
67 PyErr_SetString(_btsocket_error, "bad bluetooth address for bind()");
68 return 0;
69 }
70}
71
Scott James Remnant96927a42013-07-17 18:27:57 -070072static PyObject *_btsocket_bind(PyObject *self, PyObject *args) {
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070073 PyObject *socket_object, *tuple;
74 union {
75 struct sockaddr_l2 l2;
76 struct sockaddr_rc rc;
77 struct sockaddr_hci hci;
78 struct sockaddr_sco sco;
79 } addr;
80 size_t addrlen;
81 int proto, fd, result;
Scott James Remnant96927a42013-07-17 18:27:57 -070082
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070083 if (!PyArg_ParseTuple(args, "OiO:_btsocket.bind",
84 &socket_object, &proto, &tuple))
Scott James Remnant96927a42013-07-17 18:27:57 -070085 return NULL;
86
87 fd = _get_fileno(socket_object);
88 if (fd < 0)
89 return NULL;
90
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070091 memset(&addr, 0, sizeof addr);
92
93 switch (proto) {
94 case BTPROTO_L2CAP: {
95 char *straddr;
96
97 addr.l2.l2_family = AF_BLUETOOTH;
98
99 if (!PyArg_ParseTuple(tuple, "si:_btsocket.bind",
100 &straddr, &addr.l2.l2_psm))
101 return NULL;
102 if (!_setbdaddr(straddr, &addr.l2.l2_bdaddr))
103 return NULL;
104
105 addrlen = sizeof (struct sockaddr_l2);
106 break;
107 }
108 case BTPROTO_RFCOMM: {
109 char *straddr;
110
111 addr.rc.rc_family = AF_BLUETOOTH;
112
113 if (!PyArg_ParseTuple(tuple, "si:_btsocket.bind",
114 &straddr, &addr.rc.rc_channel))
115 return NULL;
116 if (!_setbdaddr(straddr, &addr.rc.rc_bdaddr))
117 return NULL;
118
119 addrlen = sizeof (struct sockaddr_rc);
120 break;
121 }
122 case BTPROTO_HCI: {
123 addr.hci.hci_family = AF_BLUETOOTH;
124
125 if (!PyArg_ParseTuple(tuple, "HH:_btsocket.bind",
126 &addr.hci.hci_dev, &addr.hci.hci_channel))
127 return NULL;
128
129 addrlen = sizeof (struct sockaddr_hci);
130 break;
131 }
132 case BTPROTO_SCO: {
133 char *straddr;
134
135 addr.sco.sco_family = AF_BLUETOOTH;
136
137 if (!PyArg_ParseTuple(tuple, "s:_btsocket.bind",
138 &straddr))
139 return NULL;
140 if (!_setbdaddr(straddr, &addr.sco.sco_bdaddr))
141 return NULL;
142
143 addrlen = sizeof (struct sockaddr_sco);
144 break;
145 }
146 default:
147 PyErr_SetString(_btsocket_error, "unknown protocol for bind()");
148 return NULL;
149 }
150
Scott James Remnant96927a42013-07-17 18:27:57 -0700151 Py_BEGIN_ALLOW_THREADS;
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700152 result = bind(fd, (struct sockaddr *)&addr, addrlen);
Scott James Remnant96927a42013-07-17 18:27:57 -0700153 Py_END_ALLOW_THREADS;
154
155 if (result < 0)
156 return PyErr_SetFromErrno(_btsocket_error);
157
158 Py_INCREF(Py_None);
159 return Py_None;
160}
161
162static PyObject *_btsocket_recvmsg(PyObject *self, PyObject *args) {
163 PyObject *socket_object, *buffers, *iterator, *cmsg_list = NULL, *addrval;
164 PyObject *retval = NULL;
165 Py_ssize_t controllen = 0, nbuffers, buf_index = 0;
166 int flags = 0, fd, i, timeout = 0, did_timeout = 0;
167 double timeout_secs;
168 struct iovec *iovs = NULL;
169 Py_buffer *bufs = NULL;
170 void *controlbuf = NULL;
171 struct sockaddr_hci addr;
172 struct msghdr msg = {0};
173 ssize_t len;
174 struct cmsghdr *cmsgh;
175
176 /* Parse arguments, allocating an iovec array matching the incoming buffers
177 list and a matching PyBuffer for each one that we can fetch the incoming
178 buffer into for receiving. */
179 if (!PyArg_ParseTuple(args, "OO|ni:_btsocket.recvmsg_into",
180 &socket_object, &buffers, &controllen, &flags))
181 return NULL;
182
183 fd = _get_fileno(socket_object);
184 if (fd < 0)
185 return NULL;
186
187 timeout = _get_timeout(socket_object, &timeout_secs);
188
189 iterator = PySequence_Fast(buffers, ("recvmsg_into() argument 1 must be an "
190 "iterable"));
191 if (!iterator)
192 return NULL;
193
194 nbuffers = PySequence_Fast_GET_SIZE(iterator);
195 if (nbuffers > INT_MAX) {
196 PyErr_SetString(_btsocket_error, "recvmsg_into() argument 1 is too long");
197 goto finally;
198 }
199
200 if (nbuffers > 0) {
201 iovs = PyMem_New(struct iovec, nbuffers);
202 bufs = PyMem_New(Py_buffer, nbuffers);
203
204 if (!iovs || !bufs) {
205 PyErr_NoMemory();
206 goto finally;
207 }
208 }
209
210 for (buf_index = 0; buf_index < nbuffers; ++buf_index) {
211 if (!PyArg_Parse(PySequence_Fast_GET_ITEM(iterator, buf_index),
212 ("w*;recvmsg_into() argument 1 must be an iterable "
213 "of single-segment read-write buffers"),
214 &bufs[buf_index]))
215 goto finally;
216
217 iovs[buf_index].iov_base = bufs[buf_index].buf;
218 iovs[buf_index].iov_len = bufs[buf_index].len;
219 }
220
221 /* Allocate a control buffer large enough to receive ancillary data. */
222 if (controllen < 0 || controllen > INT_MAX) {
223 PyErr_SetString(_btsocket_error, "recvmsg_into() argument 2 invalid");
224 goto finally;
225 }
226
227 if (controllen > 0) {
228 controlbuf = PyMem_Malloc(controllen);
229 if (!controlbuf) {
230 PyErr_NoMemory();
231 goto finally;
232 }
233 }
234
235 /* Receive data on the socket. */
236 Py_BEGIN_ALLOW_THREADS;
237 msg.msg_name = (struct sockaddr *)&addr;
238 msg.msg_namelen = sizeof addr;
239 msg.msg_iov = iovs;
240 msg.msg_iovlen = nbuffers;
241 msg.msg_control = controlbuf;
242 msg.msg_controllen = controllen;
243
244 if (timeout) {
245 struct pollfd pollfd;
246 int timeout_ms;
247 int n;
248
249 pollfd.fd = fd;
250 pollfd.events = POLLIN;
251
252 /* timeout limits are set by Python */
253 timeout_ms = (int)(timeout_secs * 1000);
254 n = poll(&pollfd, 1, timeout_ms);
255 if (n <= 0)
256 did_timeout = 1;
257 }
258
259 if (!did_timeout)
260 len = recvmsg(fd, &msg, flags);
261 Py_END_ALLOW_THREADS;
262
263 if (did_timeout) {
264 PyErr_SetString(_btsocket_timeout, "timed out");
265 goto finally;
266 }
267 if (len < 0) {
268 PyErr_SetFromErrno(_btsocket_error);
269 goto finally;
270 }
271
272 /* Parse control message data into a list we pass in the return value. */
273 cmsg_list = PyList_New(0);
274 if (!cmsg_list)
275 goto finally;
276
277 for (cmsgh = CMSG_FIRSTHDR(&msg); cmsgh != NULL;
278 cmsgh = CMSG_NXTHDR(&msg, cmsgh)) {
279 size_t cmsgdatalen;
280 PyObject *bytes, *tuple;
281 int tmp;
282
283 /* cmsg_len includes the length of the 'struct cmsghdr' and any padding
284 the kernel sees fit to add. CMSG_LEN(0) gives the value that cmsg_len
285 would have if there were 0 bytes of additional data. Thus by doing
286 cmsg_len - CMSG_LEN(0) we get the actual length of data.
287
288 Never let kernel engineers design APIs. */
289 cmsgdatalen = cmsgh->cmsg_len - CMSG_LEN(0);
290 /* bytes is refcounted, if NULL the Py_BuildValue will fail and tuple will
291 be NULL too - which we catch. If it succeeds, the refcount will be 0
292 until Py_BuildValue succeeds. So there's no need to explicitly free or
293 decref bytes. */
294 bytes = PyBytes_FromStringAndSize((char *)CMSG_DATA(cmsgh), cmsgdatalen);
295 tuple = Py_BuildValue("iiN",
296 (int)cmsgh->cmsg_level, (int)cmsgh->cmsg_type, bytes);
297 if (tuple == NULL)
298 goto finally;
299
300 tmp = PyList_Append(cmsg_list, tuple);
301 Py_DECREF(tuple);
302 if (tmp != 0)
303 goto finally;
304 }
305
306 /* Build the rest of the return value. */
307 addrval = Py_BuildValue("ii", addr.hci_dev, addr.hci_channel);
308 if (!addrval)
309 goto finally;
310
311 retval = Py_BuildValue("NOiN",
312 PyLong_FromSsize_t(len),
313 cmsg_list,
314 (int)msg.msg_flags,
315 addrval);
316
317 /* Clean up in success cases as well as error. */
318finally:
319 Py_XDECREF(cmsg_list);
320 PyMem_Free(controlbuf);
321 /* We can abort out of the allocation loop only, so buffers will only be
322 allocated up to buf_index not nbuffers. */
323 for (i = 0; i < buf_index; ++i)
324 PyBuffer_Release(&bufs[i]);
325 PyMem_Free(bufs);
326 PyMem_Free(iovs);
327 Py_DECREF(iterator);
328 return retval;
329}
330
331
332static PyMethodDef _btsocket_methods[] = {
333 { "bind", _btsocket_bind, METH_VARARGS,
334 "Bind a Bluetooth socket to a device and channel" },
335 { "recvmsg", _btsocket_recvmsg, METH_VARARGS,
336 "Receive normal and ancillary data from a Bluetooth socket" },
337
338 { NULL, NULL, 0, NULL }
339};
340
341PyMODINIT_FUNC
342init_btsocket(void)
343{
344 PyObject *m;
345
346 m = Py_InitModule("_btsocket", _btsocket_methods);
347 if (!m)
348 return;
349
350 _btsocket_error = PyErr_NewException("btsocket.error",
351 PyExc_OSError, NULL);
352 Py_INCREF(_btsocket_error);
353 PyModule_AddObject(m, "error", _btsocket_error);
354
355 _btsocket_timeout = PyErr_NewException("btsocket.timeout",
356 PyExc_OSError, NULL);
357 Py_INCREF(_btsocket_timeout);
358 PyModule_AddObject(m, "timeout", _btsocket_timeout);
359}