blob: 791eedad5ad2d422bfa7f1332703bac8108436dd [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
Scott James Remnantffa6f742013-11-19 12:10:07 -080021union bt_sockaddr {
22 struct sockaddr_l2 l2;
23 struct sockaddr_rc rc;
24 struct sockaddr_hci hci;
25 struct sockaddr_sco sco;
26};
27
Scott James Remnant96927a42013-07-17 18:27:57 -070028static int _get_fileno(PyObject *socket) {
29 PyObject *fileno_object;
30 long fileno;
31
32 fileno_object = PyObject_CallMethod(socket, "fileno", "", NULL);
33 if (!fileno_object)
34 return -1;
35
36 if (!PyInt_Check(fileno_object))
37 return -1;
38
39 /* PyInts are longer than your average int, truncate back to an int */
40 fileno = PyInt_AS_LONG(fileno_object);
41 Py_DECREF(fileno_object);
42 return (int)fileno;
43}
44
45static int _get_timeout(PyObject *socket, double *timeout) {
46 PyObject *timeout_object;
47
48 timeout_object = PyObject_CallMethod(socket, "gettimeout", "", NULL);
49 if (!timeout_object)
50 return 0;
51
52 if (!PyFloat_Check(timeout_object))
53 return 0;
54
55 *timeout = PyFloat_AS_DOUBLE(timeout_object);
56 Py_DECREF(timeout_object);
57 return 1;
58}
59
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070060static int _setbdaddr(const char *straddr, bdaddr_t *bdaddr) {
61 unsigned int b0, b1, b2, b3, b4, b5;
62 int n;
63
64 n = sscanf(straddr, "%X:%X:%X:%X:%X:%X", &b5, &b4, &b3, &b2, &b1, &b0);
65 if (n == 6) {
66 bdaddr->b[0] = b0;
67 bdaddr->b[1] = b1;
68 bdaddr->b[2] = b2;
69 bdaddr->b[3] = b3;
70 bdaddr->b[4] = b4;
71 bdaddr->b[5] = b5;
72 return 1;
73 } else {
74 PyErr_SetString(_btsocket_error, "bad bluetooth address for bind()");
75 return 0;
76 }
77}
78
Scott James Remnantffa6f742013-11-19 12:10:07 -080079static PyObject *parsesocketargs(PyObject *self, PyObject *args,
80 union bt_sockaddr *addr, size_t *addrlen) {
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070081 PyObject *socket_object, *tuple;
Scott James Remnantffa6f742013-11-19 12:10:07 -080082 int proto;
Scott James Remnant96927a42013-07-17 18:27:57 -070083
Scott James Remnantffa6f742013-11-19 12:10:07 -080084 if (!PyArg_ParseTuple(args, "OiO:_btsocket.parsesocketargs",
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070085 &socket_object, &proto, &tuple))
Scott James Remnant96927a42013-07-17 18:27:57 -070086 return NULL;
87
Scott James Remnantffa6f742013-11-19 12:10:07 -080088 memset(addr, 0, sizeof (union bt_sockaddr));
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070089
90 switch (proto) {
91 case BTPROTO_L2CAP: {
92 char *straddr;
93
Scott James Remnantffa6f742013-11-19 12:10:07 -080094 addr->l2.l2_family = AF_BLUETOOTH;
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070095
Scott James Remnantffa6f742013-11-19 12:10:07 -080096 if (!PyArg_ParseTuple(tuple, "si:_btsocket.parsesocketargs",
97 &straddr, &addr->l2.l2_psm))
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070098 return NULL;
Scott James Remnantffa6f742013-11-19 12:10:07 -080099 if (!_setbdaddr(straddr, &addr->l2.l2_bdaddr))
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700100 return NULL;
101
Scott James Remnantffa6f742013-11-19 12:10:07 -0800102 *addrlen = sizeof (struct sockaddr_l2);
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700103 break;
104 }
105 case BTPROTO_RFCOMM: {
106 char *straddr;
107
Scott James Remnantffa6f742013-11-19 12:10:07 -0800108 addr->rc.rc_family = AF_BLUETOOTH;
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700109
Scott James Remnantffa6f742013-11-19 12:10:07 -0800110 if (!PyArg_ParseTuple(tuple, "si:_btsocket.parsesocketargs",
111 &straddr, &addr->rc.rc_channel))
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700112 return NULL;
Scott James Remnantffa6f742013-11-19 12:10:07 -0800113 if (!_setbdaddr(straddr, &addr->rc.rc_bdaddr))
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700114 return NULL;
115
Scott James Remnantffa6f742013-11-19 12:10:07 -0800116 *addrlen = sizeof (struct sockaddr_rc);
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700117 break;
118 }
119 case BTPROTO_HCI: {
Scott James Remnantffa6f742013-11-19 12:10:07 -0800120 addr->hci.hci_family = AF_BLUETOOTH;
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700121
Scott James Remnantffa6f742013-11-19 12:10:07 -0800122 if (!PyArg_ParseTuple(tuple, "HH:_btsocket.parsesocketargs",
123 &addr->hci.hci_dev, &addr->hci.hci_channel))
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700124 return NULL;
125
Scott James Remnantffa6f742013-11-19 12:10:07 -0800126 *addrlen = sizeof (struct sockaddr_hci);
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700127 break;
128 }
129 case BTPROTO_SCO: {
130 char *straddr;
131
Scott James Remnantffa6f742013-11-19 12:10:07 -0800132 addr->sco.sco_family = AF_BLUETOOTH;
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700133
Scott James Remnantffa6f742013-11-19 12:10:07 -0800134 if (!PyArg_ParseTuple(tuple, "s:_btsocket.parsesocketargs",
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700135 &straddr))
136 return NULL;
Scott James Remnantffa6f742013-11-19 12:10:07 -0800137 if (!_setbdaddr(straddr, &addr->sco.sco_bdaddr))
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700138 return NULL;
139
Scott James Remnantffa6f742013-11-19 12:10:07 -0800140 *addrlen = sizeof (struct sockaddr_sco);
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700141 break;
142 }
143 default:
Scott James Remnantffa6f742013-11-19 12:10:07 -0800144 PyErr_SetString(_btsocket_error, "unknown protocol");
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700145 return NULL;
146 }
147
Scott James Remnantffa6f742013-11-19 12:10:07 -0800148 return socket_object;
149}
150
151static PyObject *_btsocket_bind(PyObject *self, PyObject *args) {
152 PyObject *socket_object;
153 union bt_sockaddr addr;
154 size_t addrlen;
155 int fd, result;
156
157 socket_object = parsesocketargs(self, args, &addr, &addrlen);
158 if (!socket_object)
159 return NULL;
160
161 fd = _get_fileno(socket_object);
162 if (fd < 0)
163 return NULL;
164
Scott James Remnant96927a42013-07-17 18:27:57 -0700165 Py_BEGIN_ALLOW_THREADS;
Scott James Remnantfc5a3f72013-08-01 14:39:40 -0700166 result = bind(fd, (struct sockaddr *)&addr, addrlen);
Scott James Remnant96927a42013-07-17 18:27:57 -0700167 Py_END_ALLOW_THREADS;
168
169 if (result < 0)
170 return PyErr_SetFromErrno(_btsocket_error);
171
172 Py_INCREF(Py_None);
173 return Py_None;
174}
175
Scott James Remnantffa6f742013-11-19 12:10:07 -0800176static PyObject *_btsocket_connect(PyObject *self, PyObject *args) {
177 PyObject *socket_object;
178 union bt_sockaddr addr;
179 size_t addrlen;
180 int fd, timeout = 0, did_timeout = 0, result;
181 double timeout_secs;
182
183 socket_object = parsesocketargs(self, args, &addr, &addrlen);
184 if (!socket_object)
185 return NULL;
186
187 fd = _get_fileno(socket_object);
188 if (fd < 0)
189 return NULL;
190
191 timeout = _get_timeout(socket_object, &timeout_secs);
192
193 Py_BEGIN_ALLOW_THREADS;
194 result = connect(fd, (struct sockaddr *)&addr, addrlen);
195
196 if (timeout) {
197 struct pollfd pollfd;
198 int timeout_ms;
199 int n;
200
201 pollfd.fd = fd;
202 pollfd.events = POLLIN;
203
204 /* timeout limits are set by Python */
205 timeout_ms = (int)(timeout_secs * 1000);
206 n = poll(&pollfd, 1, timeout_ms);
207 if (n == 0) {
208 did_timeout = 1;
209 } else if (n < 0) {
210 result = n;
211 } else {
212 /* result from connect() is EINPROGRESS, get the real error */
213 socklen_t resultlen = sizeof result;
214 (void)getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &resultlen);
215 if (result == EISCONN)
216 result = 0;
217 else {
218 errno = result;
219 result = -1;
220 }
221 }
222 }
223 Py_END_ALLOW_THREADS;
224
225 if (did_timeout) {
226 PyErr_SetString(_btsocket_timeout, "timed out");
227 return NULL;
228 }
229 if (result < 0) {
230 PyErr_SetFromErrno(_btsocket_error);
231 return NULL;
232 }
233
234 Py_INCREF(Py_None);
235 return Py_None;
236}
237
Scott James Remnant96927a42013-07-17 18:27:57 -0700238static PyObject *_btsocket_recvmsg(PyObject *self, PyObject *args) {
239 PyObject *socket_object, *buffers, *iterator, *cmsg_list = NULL, *addrval;
240 PyObject *retval = NULL;
241 Py_ssize_t controllen = 0, nbuffers, buf_index = 0;
242 int flags = 0, fd, i, timeout = 0, did_timeout = 0;
243 double timeout_secs;
244 struct iovec *iovs = NULL;
245 Py_buffer *bufs = NULL;
246 void *controlbuf = NULL;
247 struct sockaddr_hci addr;
248 struct msghdr msg = {0};
249 ssize_t len;
250 struct cmsghdr *cmsgh;
251
252 /* Parse arguments, allocating an iovec array matching the incoming buffers
253 list and a matching PyBuffer for each one that we can fetch the incoming
254 buffer into for receiving. */
255 if (!PyArg_ParseTuple(args, "OO|ni:_btsocket.recvmsg_into",
256 &socket_object, &buffers, &controllen, &flags))
257 return NULL;
258
259 fd = _get_fileno(socket_object);
260 if (fd < 0)
261 return NULL;
262
263 timeout = _get_timeout(socket_object, &timeout_secs);
264
265 iterator = PySequence_Fast(buffers, ("recvmsg_into() argument 1 must be an "
266 "iterable"));
267 if (!iterator)
268 return NULL;
269
270 nbuffers = PySequence_Fast_GET_SIZE(iterator);
271 if (nbuffers > INT_MAX) {
272 PyErr_SetString(_btsocket_error, "recvmsg_into() argument 1 is too long");
273 goto finally;
274 }
275
276 if (nbuffers > 0) {
277 iovs = PyMem_New(struct iovec, nbuffers);
278 bufs = PyMem_New(Py_buffer, nbuffers);
279
280 if (!iovs || !bufs) {
281 PyErr_NoMemory();
282 goto finally;
283 }
284 }
285
286 for (buf_index = 0; buf_index < nbuffers; ++buf_index) {
287 if (!PyArg_Parse(PySequence_Fast_GET_ITEM(iterator, buf_index),
288 ("w*;recvmsg_into() argument 1 must be an iterable "
289 "of single-segment read-write buffers"),
290 &bufs[buf_index]))
291 goto finally;
292
293 iovs[buf_index].iov_base = bufs[buf_index].buf;
294 iovs[buf_index].iov_len = bufs[buf_index].len;
295 }
296
297 /* Allocate a control buffer large enough to receive ancillary data. */
298 if (controllen < 0 || controllen > INT_MAX) {
299 PyErr_SetString(_btsocket_error, "recvmsg_into() argument 2 invalid");
300 goto finally;
301 }
302
303 if (controllen > 0) {
304 controlbuf = PyMem_Malloc(controllen);
305 if (!controlbuf) {
306 PyErr_NoMemory();
307 goto finally;
308 }
309 }
310
311 /* Receive data on the socket. */
312 Py_BEGIN_ALLOW_THREADS;
313 msg.msg_name = (struct sockaddr *)&addr;
314 msg.msg_namelen = sizeof addr;
315 msg.msg_iov = iovs;
316 msg.msg_iovlen = nbuffers;
317 msg.msg_control = controlbuf;
318 msg.msg_controllen = controllen;
319
320 if (timeout) {
321 struct pollfd pollfd;
322 int timeout_ms;
323 int n;
324
325 pollfd.fd = fd;
326 pollfd.events = POLLIN;
327
328 /* timeout limits are set by Python */
329 timeout_ms = (int)(timeout_secs * 1000);
330 n = poll(&pollfd, 1, timeout_ms);
331 if (n <= 0)
332 did_timeout = 1;
333 }
334
335 if (!did_timeout)
336 len = recvmsg(fd, &msg, flags);
337 Py_END_ALLOW_THREADS;
338
339 if (did_timeout) {
340 PyErr_SetString(_btsocket_timeout, "timed out");
341 goto finally;
342 }
343 if (len < 0) {
344 PyErr_SetFromErrno(_btsocket_error);
345 goto finally;
346 }
347
348 /* Parse control message data into a list we pass in the return value. */
349 cmsg_list = PyList_New(0);
350 if (!cmsg_list)
351 goto finally;
352
353 for (cmsgh = CMSG_FIRSTHDR(&msg); cmsgh != NULL;
354 cmsgh = CMSG_NXTHDR(&msg, cmsgh)) {
355 size_t cmsgdatalen;
356 PyObject *bytes, *tuple;
357 int tmp;
358
359 /* cmsg_len includes the length of the 'struct cmsghdr' and any padding
360 the kernel sees fit to add. CMSG_LEN(0) gives the value that cmsg_len
361 would have if there were 0 bytes of additional data. Thus by doing
362 cmsg_len - CMSG_LEN(0) we get the actual length of data.
363
364 Never let kernel engineers design APIs. */
365 cmsgdatalen = cmsgh->cmsg_len - CMSG_LEN(0);
366 /* bytes is refcounted, if NULL the Py_BuildValue will fail and tuple will
367 be NULL too - which we catch. If it succeeds, the refcount will be 0
368 until Py_BuildValue succeeds. So there's no need to explicitly free or
369 decref bytes. */
370 bytes = PyBytes_FromStringAndSize((char *)CMSG_DATA(cmsgh), cmsgdatalen);
371 tuple = Py_BuildValue("iiN",
372 (int)cmsgh->cmsg_level, (int)cmsgh->cmsg_type, bytes);
373 if (tuple == NULL)
374 goto finally;
375
376 tmp = PyList_Append(cmsg_list, tuple);
377 Py_DECREF(tuple);
378 if (tmp != 0)
379 goto finally;
380 }
381
382 /* Build the rest of the return value. */
383 addrval = Py_BuildValue("ii", addr.hci_dev, addr.hci_channel);
384 if (!addrval)
385 goto finally;
386
387 retval = Py_BuildValue("NOiN",
388 PyLong_FromSsize_t(len),
389 cmsg_list,
390 (int)msg.msg_flags,
391 addrval);
392
393 /* Clean up in success cases as well as error. */
394finally:
395 Py_XDECREF(cmsg_list);
396 PyMem_Free(controlbuf);
397 /* We can abort out of the allocation loop only, so buffers will only be
398 allocated up to buf_index not nbuffers. */
399 for (i = 0; i < buf_index; ++i)
400 PyBuffer_Release(&bufs[i]);
401 PyMem_Free(bufs);
402 PyMem_Free(iovs);
403 Py_DECREF(iterator);
404 return retval;
405}
406
Artem Rakhov1b654492015-01-21 00:40:44 -0800407static PyObject *_btsocket_listen_and_accept() {
408 int sk, nsk, result;
409 struct sockaddr_l2 srcaddr, addr;
410 socklen_t optlen;
411 struct bt_security btsec;
412 bdaddr_t *ba;
413 char str[18];
414
415 Py_BEGIN_ALLOW_THREADS;
416 sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
417 Py_END_ALLOW_THREADS;
418 if (sk < 0)
419 goto fail;
420
421 /* Set up source address */
422 memset(&srcaddr, 0, sizeof(srcaddr));
423 srcaddr.l2_family = AF_BLUETOOTH;
424 srcaddr.l2_cid = htobs(ATT_CID);
425 srcaddr.l2_bdaddr_type = BDADDR_LE_PUBLIC;
426
427 Py_BEGIN_ALLOW_THREADS;
428 result = bind(sk, (struct sockaddr *) &srcaddr, sizeof(srcaddr));
429 Py_END_ALLOW_THREADS;
430
431 if (result < 0)
432 goto fail;
433
434 /* Set the security level */
435 memset(&btsec, 0, sizeof(btsec));
436 btsec.level = BT_SECURITY_LOW;
437
438 Py_BEGIN_ALLOW_THREADS;
439 result = setsockopt(sk, SOL_BLUETOOTH, BT_SECURITY, &btsec, sizeof(btsec));
440 Py_END_ALLOW_THREADS;
441
442 if (result != 0)
443 goto fail;
444
445 Py_BEGIN_ALLOW_THREADS;
446 result = listen(sk, 10);
447 Py_END_ALLOW_THREADS;
448
449 if (result < 0)
450 goto fail;
451
452 memset(&addr, 0, sizeof(addr));
453 optlen = sizeof(addr);
454
455 Py_BEGIN_ALLOW_THREADS;
456 nsk = accept(sk, (struct sockaddr *) &addr, &optlen);
457 Py_END_ALLOW_THREADS;
458
459 if (nsk < 0)
460 goto fail;
461
462 ba = &addr.l2_bdaddr;
463 sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
464 ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
465
466 close(sk);
467 return Py_BuildValue("(i,s)", nsk, str);
468
469fail:
470 if (sk >= 0)
471 close(sk);
472
473 return PyErr_SetFromErrno(_btsocket_error);
474}
Scott James Remnant96927a42013-07-17 18:27:57 -0700475
476static PyMethodDef _btsocket_methods[] = {
477 { "bind", _btsocket_bind, METH_VARARGS,
478 "Bind a Bluetooth socket to a device and channel" },
Scott James Remnantffa6f742013-11-19 12:10:07 -0800479 { "connect", _btsocket_connect, METH_VARARGS,
480 "Connect a Bluetooth socket to a remote address" },
Scott James Remnant96927a42013-07-17 18:27:57 -0700481 { "recvmsg", _btsocket_recvmsg, METH_VARARGS,
482 "Receive normal and ancillary data from a Bluetooth socket" },
Artem Rakhov1b654492015-01-21 00:40:44 -0800483 { "listen_and_accept", _btsocket_listen_and_accept, METH_NOARGS,
484 "Create a socket for incoming BLE connection" },
Scott James Remnant96927a42013-07-17 18:27:57 -0700485
486 { NULL, NULL, 0, NULL }
487};
488
489PyMODINIT_FUNC
490init_btsocket(void)
491{
492 PyObject *m;
493
494 m = Py_InitModule("_btsocket", _btsocket_methods);
495 if (!m)
496 return;
497
498 _btsocket_error = PyErr_NewException("btsocket.error",
499 PyExc_OSError, NULL);
500 Py_INCREF(_btsocket_error);
501 PyModule_AddObject(m, "error", _btsocket_error);
502
503 _btsocket_timeout = PyErr_NewException("btsocket.timeout",
504 PyExc_OSError, NULL);
505 Py_INCREF(_btsocket_timeout);
506 PyModule_AddObject(m, "timeout", _btsocket_timeout);
507}