upgrade obexd to 0.47
[profile/ivi/obexd.git] / plugins / bluetooth.c
1 /*
2  *
3  *  OBEX Server
4  *
5  *  Copyright (C) 2007-2010  Nokia Corporation
6  *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
7  *
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <errno.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <inttypes.h>
33 #include <sys/socket.h>
34
35 #include <glib.h>
36 #include <gdbus.h>
37
38 #include "obexd.h"
39 #include "plugin.h"
40 #include "server.h"
41 #include "obex.h"
42 #include "transport.h"
43 #include "service.h"
44 #include "log.h"
45 #include "btio.h"
46
47 #define BT_RX_MTU 32767
48 #define BT_TX_MTU 32767
49
50 #define TIMEOUT 60*1000 /* Timeout for user response (miliseconds) */
51
52 struct pending_request {
53         DBusPendingCall *call;
54         struct bluetooth_service *service;
55         char *adapter_path;
56         char address[18];
57         unsigned int watch;
58         GIOChannel *io;
59 };
60
61 struct bluetooth_service {
62         struct obex_server *server;
63         struct obex_service_driver *driver;
64         uint32_t handle;
65 };
66
67 struct adapter_any {
68         char *path;             /* Adapter ANY path */
69         GSList *services;       /* List of services to register records */
70 };
71
72 static DBusConnection *connection = NULL;
73 static struct adapter_any *any = NULL;
74
75 static void add_record_reply(DBusPendingCall *call, void *user_data)
76 {
77         struct bluetooth_service *service = user_data;
78         DBusMessage *reply = dbus_pending_call_steal_reply(call);
79         DBusError derr;
80         uint32_t handle;
81
82         dbus_error_init(&derr);
83         if (dbus_set_error_from_message(&derr, reply)) {
84                 error("bluetooth: Replied with an error: %s, %s",
85                                 derr.name, derr.message);
86                 dbus_error_free(&derr);
87                 handle = 0;
88         } else {
89                 dbus_message_get_args(reply, NULL,
90                                 DBUS_TYPE_UINT32, &handle,
91                                 DBUS_TYPE_INVALID);
92
93                 service->handle = handle;
94
95                 DBG("Registered: %s, handle: 0x%x",
96                                 service->driver->name, service->handle);
97         }
98
99         dbus_message_unref(reply);
100 }
101
102 static int add_record(const char *path, const char *xml,
103                         struct bluetooth_service *service)
104 {
105         DBusMessage *msg;
106         DBusPendingCall *call;
107         int ret = 0;
108
109         msg = dbus_message_new_method_call("org.bluez", path,
110                                         "org.bluez.Service", "AddRecord");
111
112         dbus_message_append_args(msg, DBUS_TYPE_STRING, &xml,
113                         DBUS_TYPE_INVALID);
114
115         if (dbus_connection_send_with_reply(connection,
116                                 msg, &call, -1) == FALSE) {
117                 ret = -1;
118                 goto failed;
119         }
120
121         dbus_pending_call_set_notify(call, add_record_reply, service, NULL);
122         dbus_pending_call_unref(call);
123
124 failed:
125         dbus_message_unref(msg);
126         return ret;
127 }
128
129 static struct bluetooth_service *find_service(
130                                         struct obex_service_driver *driver)
131 {
132         GSList *l;
133
134         for (l = any->services; l; l = l->next) {
135                 struct bluetooth_service *service = l->data;
136
137                 if (service->driver == driver)
138                         return service;
139         }
140
141         return NULL;
142 }
143
144 static void register_record(struct obex_server *server)
145 {
146         const GSList *l;
147
148         if (connection == NULL)
149                 return;
150
151         for (l = server->drivers; l; l = l->next) {
152                 struct obex_service_driver *driver = l->data;
153                 struct bluetooth_service *service;
154                 char *xml;
155
156                 service = find_service(driver);
157                 if (service == NULL) {
158                         service = g_new0(struct bluetooth_service, 1);
159                         service->driver = driver;
160                         service->server = server;
161                         any->services = g_slist_append(any->services, service);
162                 }
163
164                 /* Service already has a record registered */
165                 if (service->handle != 0)
166                         continue;
167
168                 /* Adapter ANY is not available yet: Add record later */
169                 if (any->path == NULL)
170                         continue;
171
172                 if (driver->port != 0)
173                         xml = g_markup_printf_escaped(driver->record,
174                                                         driver->channel,
175                                                         driver->name,
176                                                         driver->port);
177                 else
178                         xml = g_markup_printf_escaped(driver->record,
179                                                         driver->channel,
180                                                         driver->name);
181
182                 add_record(any->path, xml, service);
183                 g_free(xml);
184         }
185 }
186
187 static void find_adapter_any_reply(DBusPendingCall *call, void *user_data)
188 {
189         DBusMessage *reply = dbus_pending_call_steal_reply(call);
190         const char *path;
191         GSList *l;
192         DBusError derr;
193
194         dbus_error_init(&derr);
195         if (dbus_set_error_from_message(&derr, reply)) {
196                 error("bluetooth: Replied with an error: %s, %s",
197                                 derr.name, derr.message);
198                 dbus_error_free(&derr);
199                 goto done;
200         }
201
202         dbus_message_get_args(reply, NULL,
203                         DBUS_TYPE_OBJECT_PATH, &path,
204                         DBUS_TYPE_INVALID);
205         any->path = g_strdup(path);
206
207         for (l = any->services; l; l = l->next) {
208                 struct bluetooth_service *service = l->data;
209                 struct obex_service_driver *driver = service->driver;
210                 char *xml;
211
212                 if (driver->port != 0)
213                         xml = g_markup_printf_escaped(driver->record,
214                                                         driver->channel,
215                                                         driver->name,
216                                                         driver->port);
217                 else
218                         xml = g_markup_printf_escaped(driver->record,
219                                                         driver->channel,
220                                                         driver->name);
221
222                 add_record(any->path, xml, service);
223                 g_free(xml);
224         }
225
226 done:
227         dbus_message_unref(reply);
228 }
229
230 static DBusPendingCall *find_adapter(const char *pattern,
231                                 DBusPendingCallNotifyFunction function,
232                                 void *user_data)
233 {
234         DBusMessage *msg;
235         DBusPendingCall *call;
236
237         DBG("FindAdapter(%s)", pattern);
238
239         msg = dbus_message_new_method_call("org.bluez", "/",
240                                         "org.bluez.Manager", "FindAdapter");
241         if (!msg)
242                 return NULL;
243
244         dbus_message_append_args(msg, DBUS_TYPE_STRING, &pattern,
245                         DBUS_TYPE_INVALID);
246
247         if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
248                 dbus_message_unref(msg);
249                 return NULL;
250         }
251
252         dbus_pending_call_set_notify(call, function, user_data, NULL);
253
254         dbus_message_unref(msg);
255
256         return call;
257 }
258
259 static void name_acquired(DBusConnection *conn, void *user_data)
260 {
261         DBusPendingCall *call;
262
263         call = find_adapter("any", find_adapter_any_reply, NULL);
264         if (call)
265                 dbus_pending_call_unref(call);
266 }
267
268 static void name_released(DBusConnection *conn, void *user_data)
269 {
270         GSList *l;
271
272         /* reset handles so the services got register next time */
273         for (l = any->services; l; l = l->next) {
274                 struct bluetooth_service *service = l->data;
275
276                 service->handle = 0;
277         }
278
279         g_free(any->path);
280         any->path = NULL;
281
282 }
283
284 static void service_cancel(struct pending_request *pending)
285 {
286         DBusMessage *msg;
287
288         msg = dbus_message_new_method_call("org.bluez",
289                                         pending->adapter_path,
290                                         "org.bluez.Service",
291                                         "CancelAuthorization");
292
293         g_dbus_send_message(connection, msg);
294 }
295
296 static void pending_request_free(struct pending_request *pending)
297 {
298         if (pending->call)
299                 dbus_pending_call_unref(pending->call);
300         g_io_channel_unref(pending->io);
301         g_free(pending->adapter_path);
302         g_free(pending);
303 }
304
305 static void connect_event(GIOChannel *io, GError *err, void *user_data)
306 {
307         int sk = g_io_channel_unix_get_fd(io);
308         struct bluetooth_service *service = user_data;
309         struct obex_server *server = service->server;
310         int type;
311         int omtu = BT_TX_MTU;
312         int imtu = BT_RX_MTU;
313         gboolean stream = TRUE;
314         socklen_t len = sizeof(int);
315
316         if (err)
317                 goto drop;
318
319         if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
320                 goto done;
321
322         if (type != SOCK_SEQPACKET)
323                 goto done;
324
325         stream = FALSE;
326
327         /* Read MTU if io is an L2CAP socket */
328         bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu,
329                                                 BT_IO_OPT_IMTU, &imtu,
330                                                 BT_IO_OPT_INVALID);
331
332 done:
333         if (obex_server_new_connection(server, io, omtu, imtu, stream) < 0)
334                 g_io_channel_shutdown(io, TRUE, NULL);
335
336         return;
337
338 drop:
339         error("%s", err->message);
340         g_io_channel_shutdown(io, TRUE, NULL);
341         return;
342 }
343
344 static void service_reply(DBusPendingCall *call, void *user_data)
345 {
346         struct pending_request *pending = user_data;
347         GIOChannel *io = pending->io;
348         struct bluetooth_service *service = pending->service;
349         DBusMessage *reply = dbus_pending_call_steal_reply(call);
350         DBusError derr;
351         GError *err = NULL;
352
353         dbus_error_init(&derr);
354         if (dbus_set_error_from_message(&derr, reply)) {
355                 error("bluetooth: RequestAuthorization error: %s, %s",
356                                 derr.name, derr.message);
357
358                 if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY))
359                         service_cancel(pending);
360
361                 dbus_error_free(&derr);
362                 g_io_channel_shutdown(io, TRUE, NULL);
363                 goto done;
364         }
365
366         DBG("RequestAuthorization succeeded");
367
368         if (!bt_io_accept(io, connect_event, service, NULL, &err)) {
369                 error("%s", err->message);
370                 g_error_free(err);
371                 g_io_channel_shutdown(io, TRUE, NULL);
372         }
373
374 done:
375         g_source_remove(pending->watch);
376         pending_request_free(pending);
377         dbus_message_unref(reply);
378 }
379
380 static gboolean service_error(GIOChannel *io, GIOCondition cond,
381                         void *user_data)
382 {
383         struct pending_request *pending = user_data;
384
385         service_cancel(pending);
386
387         dbus_pending_call_cancel(pending->call);
388
389         pending_request_free(pending);
390
391         return FALSE;
392 }
393
394 static void find_adapter_reply(DBusPendingCall *call, void *user_data)
395 {
396         struct pending_request *pending = user_data;
397         DBusMessage *reply = dbus_pending_call_steal_reply(call);
398         DBusMessage *msg;
399         DBusPendingCall *pcall;
400         const char *path, *paddr = pending->address;
401         DBusError derr;
402
403         dbus_error_init(&derr);
404         if (dbus_set_error_from_message(&derr, reply)) {
405                 error("Replied with an error: %s, %s",
406                                 derr.name, derr.message);
407                 dbus_error_free(&derr);
408                 goto failed;
409         }
410
411         dbus_message_get_args(reply, NULL,
412                         DBUS_TYPE_OBJECT_PATH, &path,
413                         DBUS_TYPE_INVALID);
414
415         DBG("FindAdapter -> %s", path);
416         pending->adapter_path = g_strdup(path);
417         dbus_message_unref(reply);
418
419         msg = dbus_message_new_method_call("org.bluez", path,
420                         "org.bluez.Service", "RequestAuthorization");
421
422         dbus_message_append_args(msg, DBUS_TYPE_STRING, &paddr,
423                         DBUS_TYPE_UINT32, &pending->service->handle,
424                         DBUS_TYPE_INVALID);
425
426         if (!dbus_connection_send_with_reply(connection,
427                                         msg, &pcall, TIMEOUT)) {
428                 dbus_message_unref(msg);
429                 goto failed;
430         }
431
432         dbus_message_unref(msg);
433
434         DBG("RequestAuthorization(%s, %x)", paddr,
435                         pending->service->handle);
436
437         if (!dbus_pending_call_set_notify(pcall, service_reply, pending,
438                                                                 NULL)) {
439                 dbus_pending_call_unref(pcall);
440                 goto failed;
441         }
442
443         dbus_pending_call_unref(pending->call);
444         pending->call = pcall;
445
446         /* Catches errors before authorization response comes */
447         pending->watch = g_io_add_watch(pending->io,
448                                         G_IO_HUP | G_IO_ERR | G_IO_NVAL,
449                                         service_error, pending);
450
451         return;
452
453 failed:
454         g_io_channel_shutdown(pending->io, TRUE, NULL);
455         pending_request_free(pending);
456 }
457
458 static int request_service_authorization(struct bluetooth_service *service,
459                                                         GIOChannel *io,
460                                                         const char *source,
461                                                         const char *address)
462 {
463         struct pending_request *pending;
464
465         if (connection == NULL || any->path == NULL)
466                 return -1;
467
468         pending = g_new0(struct pending_request, 1);
469         pending->call = find_adapter(source, find_adapter_reply, pending);
470         if (!pending->call) {
471                 g_free(pending);
472                 return -ENOMEM;
473         }
474
475         pending->service = service;
476         pending->io = g_io_channel_ref(io);
477         memcpy(pending->address, address, sizeof(pending->address));
478
479         return 0;
480 }
481
482 static void confirm_connection(GIOChannel *io, const char *source,
483                                         const char *address, void *user_data)
484 {
485
486         struct obex_service_driver *driver = user_data;
487         struct bluetooth_service *service;
488         GError *err = NULL;
489
490         service = find_service(driver);
491         if (service == NULL) {
492                 error("bluetooth: Unable to find service");
493                 goto drop;
494         }
495
496         if (driver->secure) {
497                 if (request_service_authorization(service, io, source,
498                                                                 address) < 0)
499                         goto drop;
500
501                 return;
502         }
503
504         if (!bt_io_accept(io, connect_event, service, NULL, &err)) {
505                 error("%s", err->message);
506                 g_error_free(err);
507                 goto drop;
508         }
509
510         return;
511
512 drop:
513         g_io_channel_shutdown(io, TRUE, NULL);
514 }
515
516 static void confirm_rfcomm(GIOChannel *io, void *user_data)
517 {
518         GError *err = NULL;
519         char source[18];
520         char address[18];
521         uint8_t channel;
522
523         bt_io_get(io, BT_IO_RFCOMM, &err,
524                         BT_IO_OPT_SOURCE, source,
525                         BT_IO_OPT_DEST, address,
526                         BT_IO_OPT_CHANNEL, &channel,
527                         BT_IO_OPT_INVALID);
528         if (err) {
529                 error("%s", err->message);
530                 g_error_free(err);
531                 g_io_channel_shutdown(io, TRUE, NULL);
532                 return;
533         }
534
535         info("bluetooth: New connection from: %s, channel %u", address,
536                                                                 channel);
537
538         confirm_connection(io, source, address, user_data);
539 }
540
541 static void confirm_l2cap(GIOChannel *io, void *user_data)
542 {
543         GError *err = NULL;
544         char source[18];
545         char address[18];
546         uint16_t psm;
547
548         bt_io_get(io, BT_IO_L2CAP, &err,
549                         BT_IO_OPT_SOURCE, source,
550                         BT_IO_OPT_DEST, address,
551                         BT_IO_OPT_PSM, &psm,
552                         BT_IO_OPT_INVALID);
553         if (err) {
554                 error("%s", err->message);
555                 g_error_free(err);
556                 g_io_channel_shutdown(io, TRUE, NULL);
557                 return;
558         }
559
560         info("bluetooth: New connection from: %s, psm %u", address, psm);
561
562         confirm_connection(io, source, address, user_data);
563 }
564
565 static GSList *start(struct obex_server *server,
566                                 struct obex_service_driver *service)
567 {
568         BtIOSecLevel sec_level;
569         GSList *l = NULL;
570         GIOChannel *io;
571         GError *err = NULL;
572         uint16_t psm;
573
574         if (service->secure == TRUE)
575                 sec_level = BT_IO_SEC_MEDIUM;
576         else
577                 sec_level = BT_IO_SEC_LOW;
578
579         io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_rfcomm,
580                                 service, NULL, &err,
581                                 BT_IO_OPT_CHANNEL, service->channel,
582                                 BT_IO_OPT_SEC_LEVEL, sec_level,
583                                 BT_IO_OPT_INVALID);
584         if (io == NULL) {
585                 error("bluetooth: unable to listen in channel %d: %s",
586                                 service->channel, err->message);
587                 g_error_free(err);
588         } else {
589                 l = g_slist_prepend(l, io);
590                 DBG("listening on channel %d", service->channel);
591         }
592
593         if (service->port == 0)
594                 return l;
595
596         psm = service->port == OBEX_PORT_RANDOM ? 0 : service->port;
597
598         io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_l2cap,
599                         service, NULL, &err,
600                         BT_IO_OPT_PSM, psm,
601                         BT_IO_OPT_MODE, BT_IO_MODE_ERTM,
602                         BT_IO_OPT_OMTU, BT_TX_MTU,
603                         BT_IO_OPT_IMTU, BT_RX_MTU,
604                         BT_IO_OPT_SEC_LEVEL, sec_level,
605                         BT_IO_OPT_INVALID);
606         if (io == NULL) {
607                 error("bluetooth: unable to listen in psm %d: %s",
608                                 service->port, err->message);
609                 g_error_free(err);
610                 service->port = 0;
611         } else {
612                 l = g_slist_prepend(l, io);
613                 bt_io_get(io, BT_IO_L2CAP, &err, BT_IO_OPT_PSM, &service->port,
614                                                         BT_IO_OPT_INVALID);
615                 DBG("listening on psm %d", service->port);
616         }
617
618         return l;
619 }
620
621 static void *bluetooth_start(struct obex_server *server, int *err)
622 {
623         GSList *ios = NULL;
624         const GSList *l;
625
626         for (l = server->drivers; l; l = l->next) {
627                 struct obex_service_driver *service = l->data;
628                 GSList *l;
629
630                 l = start(server, service);
631                 if (l == NULL)
632                         continue;
633
634                 ios = g_slist_concat(ios, l);
635         }
636
637         register_record(server);
638
639         return ios;
640 }
641
642 static void stop(gpointer data)
643 {
644         GIOChannel *io = data;
645
646         g_io_channel_shutdown(io, TRUE, NULL);
647         g_io_channel_unref(io);
648 }
649
650 static void bluetooth_stop(void *data)
651 {
652         GSList *ios = data;
653
654         g_slist_free_full(ios, stop);
655 }
656
657 static int bluetooth_getpeername(GIOChannel *io, char **name)
658 {
659         int sk = g_io_channel_unix_get_fd(io);
660         GError *gerr = NULL;
661         char address[18];
662         int type;
663         socklen_t len = sizeof(int);
664
665         if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
666                 return -errno;
667
668         if (type == SOCK_STREAM)
669                 bt_io_get(io, BT_IO_RFCOMM, &gerr,
670                                 BT_IO_OPT_DEST, address,
671                                 BT_IO_OPT_INVALID);
672         else
673                 bt_io_get(io, BT_IO_L2CAP, &gerr,
674                                 BT_IO_OPT_DEST, address,
675                                 BT_IO_OPT_INVALID);
676
677         if (gerr) {
678                 error("%s", gerr->message);
679                 g_error_free(gerr);
680                 return -EINVAL;
681         }
682
683         *name = g_strdup(address);
684
685         return 0;
686 }
687
688 static struct obex_transport_driver driver = {
689         .name = "bluetooth",
690         .start = bluetooth_start,
691         .getpeername = bluetooth_getpeername,
692         .stop = bluetooth_stop
693 };
694
695 static unsigned int listener_id = 0;
696
697 static int bluetooth_init(void)
698 {
699         any = g_new0(struct adapter_any, 1);
700
701         connection = g_dbus_setup_private(DBUS_BUS_SYSTEM, NULL, NULL);
702         if (connection == NULL)
703                 return -EPERM;
704
705         listener_id = g_dbus_add_service_watch(connection, "org.bluez",
706                                 name_acquired, name_released, NULL, NULL);
707
708         return obex_transport_driver_register(&driver);
709 }
710
711 static void bluetooth_exit(void)
712 {
713         g_dbus_remove_watch(connection, listener_id);
714
715         if (any) {
716                 g_slist_free_full(any->services, g_free);
717                 g_free(any->path);
718                 g_free(any);
719         }
720
721         if (connection)
722                 dbus_connection_unref(connection);
723
724         obex_transport_driver_unregister(&driver);
725 }
726
727 OBEX_PLUGIN_DEFINE(bluetooth, bluetooth_init, bluetooth_exit)