Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / linux / caleinterface.c
1 /******************************************************************
2  *
3  * Copyright 2015 Intel Corporation All Rights Reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  ******************************************************************/
18
19 #include "caleinterface.h"
20 #include "bluez.h"
21 #include "central.h"
22 #include "peripheral.h"
23 #include "client.h"
24 #include "server.h"
25 #include "utils.h"
26
27 #include "cagattservice.h"
28 #include "oic_malloc.h"
29 #include "oic_string.h"
30 #include "logger.h"
31
32 #include <string.h>
33 #include <strings.h>  // For strcasecmp().
34 #include <assert.h>
35
36
37 #define MICROSECS_PER_SEC 1000000
38
39 // Logging tag.
40 static char const TAG[] = "BLE_INTERFACE";
41
42 /*
43     The IoTivity adapter interface currently doesn't provide a means to
44     pass context down to the transport layer so rely on a file scope
45     context instead.
46 */
47 static CALEContext g_context = {
48     .lock = NULL
49 };
50
51 // -----------------------------------------------------------------------
52 // Functions internal to this BLE adapter implementation.
53 // -----------------------------------------------------------------------
54 static bool CALESetUpBlueZObjects(CALEContext * context);
55
56 static bool CALECheckStarted()
57 {
58     ca_mutex_lock(g_context.lock);
59
60     bool const started =
61         (g_context.event_loop != NULL
62          && g_main_loop_is_running(g_context.event_loop));
63
64     ca_mutex_unlock(g_context.lock);
65
66     /**
67      * @todo Fix potential TOCTOU race condition.  A LE transport
68      *       adapter could have been started or stopped between the
69      *       mutex unlock and boolean check.
70      */
71     return started;
72 }
73
74 static void CALEDumpDBusSignalParameters(char const * sender_name,
75                                          char const * object_path,
76                                          char const * interface_name,
77                                          char const * signal_name,
78                                          GVariant   * parameters)
79 {
80     (void)sender_name;
81     (void)object_path;
82     (void)interface_name;
83     (void)signal_name;
84     (void)parameters;
85 #ifdef TB_LOG
86     gchar * const param_dump =
87         g_variant_print(parameters, TRUE);
88
89     OIC_LOG_V(DEBUG,
90               TAG,
91               "%s()\n"
92               "\tsender_name: %s\n"
93               "\tobject_path: %s\n"
94               "\tinterface_name: %s\n"
95               "\tsignal_name: %s\n"
96               "\tparameters: %s\n",
97               __func__,
98               sender_name,
99               object_path,
100               interface_name,
101               signal_name,
102               param_dump);
103
104     g_free(param_dump);
105 #endif  // TB_LOG
106 }
107
108 static void CALEOnInterfaceProxyPropertiesChanged(
109     GDBusObjectManagerClient * manager,
110     GDBusObjectProxy         * object_proxy,
111     GDBusProxy               * interface_proxy,
112     GVariant                 * changed_properties,
113     gchar const * const      * invalidated_properties,
114     gpointer                   user_data)
115 {
116     (void)manager;
117     (void)object_proxy;
118     (void)invalidated_properties;
119
120     char const * const interface_name =
121         g_dbus_proxy_get_interface_name(interface_proxy);
122
123     bool const is_adapter_interface =
124         (strcmp(BLUEZ_ADAPTER_INTERFACE, interface_name) == 0);
125
126     if (!is_adapter_interface)
127     {
128         /*
129           Only specific org.bluez.Adapter1 property changes are
130           currently supported.
131         */
132         return;
133     }
134
135     OIC_LOG_V(DEBUG,
136               TAG,
137               "%s properties Changed on %s:\n",
138               interface_name,
139               g_dbus_proxy_get_object_path(interface_proxy));
140
141     CALEContext * const context = user_data;
142
143     GVariantIter iter;
144     gchar const * key   = NULL;
145     GVariant    * value = NULL;
146
147     /**
148      * @todo Since we're only looking up one value here,
149      *       i.e. "Powered", can't we just use
150      *       g_variant_lookup_value() instead of this while() loop?
151      */
152     g_variant_iter_init(&iter, changed_properties);
153     while (g_variant_iter_next(&iter, "{&sv}", &key, &value))
154     {
155         if (strcmp(key, "Powered") == 0)
156         {
157             /*
158               Report a change in the availability of the bluetooth
159               adapter.
160             */
161             gboolean const powered = g_variant_get_boolean(value);
162             CAAdapterState_t const status =
163                 (powered ? CA_ADAPTER_ENABLED : CA_ADAPTER_DISABLED);
164
165             /**
166              * @todo Should we acquire the context lock here to
167              *       prevent the @c CALEDeviceStateChangedCallback
168              *       from being potentially yanked out from under us
169              *       if the CA adapters are stopped/terminated as
170              *       we're about to invoke this callback?
171              *
172              * @todo Unfortunately the CA LE interface defined in
173              *       caleinterface.h assumes that only one BLE adapter
174              *       will exist on a given host.  However, this
175              *       implementation can handle multiple BLE adapters.
176              *       The CA LE interface should be updated so that it
177              *       can handle multiple BLE adapters.
178              */
179             context->on_device_state_changed(status);
180         }
181
182 #ifdef TB_LOG
183         gchar * const s = g_variant_print(value, TRUE);
184         OIC_LOG_V(DEBUG, TAG, "  %s -> %s", key, s);
185         g_free(s);
186 #endif  // TB_LOG
187
188         g_variant_unref(value);
189     }
190 }
191
192 static void CALEHandleInterfaceAdded(GList ** proxy_list,
193                                      char const * interface,
194                                      GVariant * parameters)
195 {
196     /**
197      * @note The @a parameters are of the form "(oa{sv})".
198      */
199     GDBusProxy * const proxy =
200         CAGetBlueZInterfaceProxy(parameters,
201                                  interface,
202                                  g_context.object_manager);
203
204     if (proxy == NULL)
205     {
206         return;
207     }
208
209     ca_mutex_lock(g_context.lock);
210
211     /*
212       Add the object information to the list.
213
214       Note that we prepend instead of append in this case since it
215       is more efficient to do so for linked lists like the one used
216       here.
217     */
218     *proxy_list = g_list_prepend(*proxy_list, proxy);
219
220     ca_mutex_unlock(g_context.lock);
221
222     /**
223      * Let the thread that may be blocked waiting for Devices to be
224      * discovered know that at least one was found.
225      *
226      * @todo It doesn't feel good putting this @c org.bluez.Device1
227      *       specific code here since this function is meant to be
228      *       BlueZ interface neutral.  Look into ways of moving this
229      *       out of here.
230      */
231     if (strcmp(interface, BLUEZ_DEVICE_INTERFACE) == 0)
232     {
233         ca_cond_signal(g_context.condition);
234     }
235 }
236
237 static void CALEOnInterfacesAdded(GDBusConnection * connection,
238                                   char const * sender_name,
239                                   char const * object_path,
240                                   char const * interface_name,
241                                   char const * signal_name,
242                                   GVariant   * parameters,
243                                   gpointer     user_data)
244 {
245     (void)connection;
246     (void)user_data;
247     CALEDumpDBusSignalParameters(sender_name,
248                                  object_path,
249                                  interface_name,
250                                  signal_name,
251                                  parameters);
252
253     // The signal should always be InterfacesAdded.
254     assert(strcmp(signal_name, "InterfacesAdded") == 0);
255
256     // Handle addition of a new org.bluez.Adapter1 interface.
257     CALEHandleInterfaceAdded(&g_context.adapters,
258                              BLUEZ_ADAPTER_INTERFACE,
259                              parameters);
260
261     // Handle addition of a new org.bluez.Device1 interface.
262     CALEHandleInterfaceAdded(&g_context.devices,
263                              BLUEZ_DEVICE_INTERFACE,
264                              parameters);
265 }
266
267 static void CALEOnInterfacesRemoved(GDBusConnection * connection,
268                                     char const * sender_name,
269                                     char const * object_path,
270                                     char const * interface_name,
271                                     char const * signal_name,
272                                     GVariant   * parameters,
273                                     gpointer     user_data)
274 {
275     (void)connection;
276     (void)user_data;
277     CALEDumpDBusSignalParameters(sender_name,
278                                  object_path,
279                                  interface_name,
280                                  signal_name,
281                                  parameters);
282
283     // The signal should always be InterfacesRemoved.
284     assert(strcmp(signal_name, "InterfacesRemoved") == 0);
285
286     /*
287       The object path is first tuple element, and the interface names
288       the second.  Check if "org.bluez.Adapter1" exists in the
289       interface array.  If it does, remove the corresponding
290       information from the adapter_infos list.
291     */
292     GVariant * const interfaces =
293         g_variant_get_child_value(parameters, 1);
294
295     GVariantIter * iter = NULL;
296     g_variant_get(interfaces, "as", &iter);
297
298     /**
299      * Iterate over the array and remove all BlueZ interface proxies
300      * with a matching D-Bus object path from the corresponding list.
301      *
302      * @todo Determine whether we should optimize this nested loop.
303      *       It may not be worthwhile to do so since the lists being
304      *       iterated over should be very short.
305      */
306     for (GVariant * child = g_variant_iter_next_value(iter);
307          child != NULL;
308          child = g_variant_iter_next_value(iter))
309     {
310         char const * interface = NULL;
311         g_variant_get(child, "&s", &interface);
312
313         GList ** list = NULL;
314
315         if (strcmp(interface, BLUEZ_ADAPTER_INTERFACE) == 0)
316         {
317             list = &g_context.adapters;
318         }
319         else if (strcmp(interface, BLUEZ_DEVICE_INTERFACE) == 0)
320         {
321             list = &g_context.devices;
322         }
323         else
324         {
325             continue;
326         }
327
328         // The object path is the first tuple element.
329         gchar const * path = NULL;
330         g_variant_get_child(parameters, 0, "&o", &path);
331
332         ca_mutex_lock(g_context.lock);
333
334         for (GList * l = *list; l != NULL; l = g_list_next(l))
335         {
336             GDBusProxy * const proxy = G_DBUS_PROXY(l->data);
337
338             if (strcmp(path,
339                        g_dbus_proxy_get_object_path(proxy)) == 0)
340             {
341                 /**
342                  * @todo If a BlueZ Device was removed, update the
343                  *       characteristic map, accordingly.
344                  */
345
346                 // Found a match!
347                 g_object_unref(proxy);
348
349                 *list = g_list_delete_link(*list, l);
350
351                 break;
352             }
353         }
354
355         ca_mutex_unlock(g_context.lock);
356
357         g_variant_unref(child);
358     }
359
360     if (iter != NULL)
361     {
362         g_variant_iter_free(iter);
363     }
364 }
365
366 static void CALESubscribeToSignals(CALEContext * context,
367                                    GDBusConnection * connection,
368                                    GDBusObjectManager * object_manager)
369 {
370     static char const om_interface[] =
371         "org.freedesktop.DBus.ObjectManager";
372
373     /*
374       Subscribe to D-Bus signals that will allow us to detect changes
375       in BlueZ adapter and device properties.
376      */
377     guint const interfaces_added_sub_id =
378         g_dbus_connection_signal_subscribe(
379             connection,
380             NULL,  // sender
381             om_interface,
382             "InterfacesAdded",
383             NULL,  // object path
384             NULL,  // arg0
385             G_DBUS_SIGNAL_FLAGS_NONE,
386             CALEOnInterfacesAdded,
387             NULL,  // user_data
388             NULL);
389
390     guint const interfaces_removed_sub_id =
391         g_dbus_connection_signal_subscribe(
392             connection,
393             NULL,  // sender
394             om_interface,
395             "InterfacesRemoved",
396             NULL,  // object path
397             NULL,  // arg0
398             G_DBUS_SIGNAL_FLAGS_NONE,
399             CALEOnInterfacesRemoved,
400             NULL,  // user_data
401             NULL);
402
403     g_signal_connect(object_manager,
404                      "interface-proxy-properties-changed",
405                      G_CALLBACK(CALEOnInterfaceProxyPropertiesChanged),
406                      context);
407
408     ca_mutex_lock(context->lock);
409
410     context->interfaces_added_sub_id   = interfaces_added_sub_id;
411     context->interfaces_removed_sub_id = interfaces_removed_sub_id;
412
413     ca_mutex_unlock(context->lock);
414 }
415
416 static bool CALESetUpDBus(CALEContext * context)
417 {
418     assert(context != NULL);
419
420     bool success = false;
421
422     GError * error = NULL;
423
424     /*
425       Set up connection to the D-Bus system bus, where the BlueZ
426       daemon is found.
427     */
428     GDBusConnection * const connection =
429         g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
430
431     if (connection == NULL)
432     {
433         OIC_LOG_V(ERROR,
434                   TAG,
435                   "Connection to D-Bus system bus failed: %s.",
436                   error->message);
437
438         g_error_free(error);
439
440         return success;
441     }
442
443     // Create a proxy to the BlueZ D-Bus ObjectManager.
444     static char const object_manager_path[] = "/";
445
446     GDBusObjectManager * const object_manager =
447         g_dbus_object_manager_client_new_sync(
448             connection,
449             G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
450             BLUEZ_NAME,
451             object_manager_path,
452             NULL,   // get_proxy_type_func
453             NULL,   // get_proxy_type_user_data
454             NULL,   // get_proxy_type_destroy_notify
455             NULL,   // cancellable
456             &error);
457
458     if (object_manager == NULL)
459     {
460         OIC_LOG_V(ERROR,
461                   TAG,
462                   "Unable to create D-Bus ObjectManager client: %s",
463                   error->message);
464
465         g_error_free(error);
466
467         g_object_unref(connection);
468
469         return success;
470     }
471
472     CALESubscribeToSignals(context, connection, object_manager);
473
474     ca_mutex_lock(context->lock);
475     context->connection     = connection;
476     context->object_manager = object_manager;
477     ca_mutex_unlock(context->lock);
478
479     success = CALESetUpBlueZObjects(context);
480
481     return success;
482 }
483
484 static void CALETearDownDBus(CALEContext * context)
485 {
486     assert(context != NULL);
487
488     /*
489       Minimize the time we hold the global lock by only clearing the
490       global state, and pushing resource finalization outside the global
491       lock.
492     */
493     ca_mutex_lock(context->lock);
494
495     GDBusConnection * const connection = context->connection;
496     context->connection = NULL;
497
498     GDBusObjectManager * const object_manager = context->object_manager;
499     context->object_manager = NULL;
500
501     GList * const objects = context->objects;
502     context->objects = NULL;
503
504     GList * const adapters = context->adapters;
505     context->adapters = NULL;
506
507     GList * const devices = context->devices;
508     context->devices = NULL;
509
510     guint const interfaces_added   = context->interfaces_added_sub_id;
511     guint const interfaces_removed = context->interfaces_removed_sub_id;
512
513     context->interfaces_added_sub_id   = 0;
514     context->interfaces_removed_sub_id = 0;
515
516     ca_mutex_unlock(context->lock);
517
518     // Destroy the device proxies list.
519     g_list_free_full(devices, g_object_unref);
520
521     // Destroy the adapter proxies list.
522     g_list_free_full(adapters, g_object_unref);
523
524     // Destroy the list of objects obtained from the ObjectManager.
525     g_list_free_full(objects, g_object_unref);
526
527     // Destroy the ObjectManager proxy.
528     if (object_manager != NULL)
529     {
530         g_object_unref(object_manager);
531     }
532
533     // Tear down the D-Bus connection to the system bus.
534     if (connection != NULL)
535     {
536         g_dbus_connection_signal_unsubscribe(connection,
537                                              interfaces_added);
538         g_dbus_connection_signal_unsubscribe(connection,
539                                              interfaces_removed);
540         g_object_unref(connection);
541     }
542 }
543
544 static bool CALEDeviceFilter(GDBusProxy * device)
545 {
546     bool accepted = false;
547
548     /*
549       Filter out any devices that don't support the OIC Transport
550       Profile service.
551     */
552     GVariant * const prop =
553         g_dbus_proxy_get_cached_property(device, "UUIDs");
554
555     if (prop == NULL)
556     {
557         // No remote services available on the device.
558         return accepted;
559     }
560
561     gsize length = 0;
562     char const ** const UUIDs = g_variant_get_strv(prop, &length);
563
564     /*
565       It would have been nice to use g_strv_contains() here, but we
566       would need to run it twice: once for the uppercase form of the
567       UUID and once for for the lowercase form.  Just run the loop
568       manually, and use strcasecmp() instead.
569     */
570     char const * const * const end = UUIDs + length;
571     for (char const * const * u = UUIDs; u != end; ++u)
572     {
573         if (strcasecmp(*u, CA_GATT_SERVICE_UUID) == 0)
574         {
575             accepted = true;
576             break;
577         }
578     }
579
580     g_free(UUIDs);
581     g_variant_unref(prop);
582
583     return accepted;
584 }
585
586 static bool CALESetUpBlueZObjects(CALEContext * context)
587 {
588     bool success = false;
589
590     // Get the list of BlueZ D-Bus objects.
591     GList * const objects =
592         g_dbus_object_manager_get_objects(context->object_manager);
593
594     if (objects == NULL) {
595         OIC_LOG(ERROR,
596                 TAG,
597                 "Unable to get objects from ObjectManager.");
598
599         return success;
600     }
601
602     ca_mutex_lock(context->lock);
603     context->objects = objects;
604     ca_mutex_unlock(context->lock);
605
606     /*
607       Create a proxies to the org.bluez.Adapter1 D-Bus objects that
608       will later be used to obtain local bluetooth adapter properties,
609       as well as by the BLE central code to discover peripherals.
610     */
611     GList * adapters = NULL;
612     success = CAGetBlueZManagedObjectProxies(&adapters,
613                                              BLUEZ_ADAPTER_INTERFACE,
614                                              context,
615                                              NULL);
616
617     // An empty adapters list is NULL.
618     if (success && adapters != NULL)
619     {
620         ca_mutex_lock(context->lock);
621         context->adapters = adapters;
622         ca_mutex_unlock(context->lock);
623     }
624
625     /*
626       Create a proxies to the org.bluez.Device1 D-Bus objects that
627       will later be used to establish connections.
628     */
629     GList * devices = NULL;
630     success = CAGetBlueZManagedObjectProxies(&devices,
631                                              BLUEZ_DEVICE_INTERFACE,
632                                              context,
633                                              CALEDeviceFilter);
634
635     // An empty device list is NULL.
636     if (success && devices != NULL)
637     {
638         ca_mutex_lock(context->lock);
639         context->devices = devices;
640         ca_mutex_unlock(context->lock);
641     }
642
643     return success;
644 }
645
646 /**
647  * Inform thread waiting for the event loop to start that the loop has
648  * started.  This is done in the context of the event loop itself so
649  * that we can be certain that the event loop is indeed running.
650  */
651 static gboolean CALEEventLoopStarted(gpointer user_data)
652 {
653     sem_t * const sem = user_data;
654
655     (void) sem_post(sem);
656
657     return G_SOURCE_REMOVE;
658 }
659
660 static void CALEStartEventLoop(void * data)
661 {
662     CALEContext * const context = data;
663
664     assert(context != NULL);
665
666     // Create the event loop.
667     GMainContext * const loop_context = g_main_context_new();
668     GMainLoop * const event_loop = g_main_loop_new(loop_context, FALSE);
669
670     g_main_context_push_thread_default(loop_context);
671
672     /*
673       We have to do the BlueZ object manager client initialization and
674       signal subscription here so that the corresponding asynchronous
675       signal handling occurs in the same thread as the one running the
676       GLib event loop.
677     */
678     if (CALESetUpDBus(&g_context))
679     {
680         ca_mutex_lock(context->lock);
681
682         assert(context->event_loop == NULL);
683         context->event_loop = event_loop;
684
685         ca_mutex_unlock(context->lock);
686
687         /*
688           Add an idle handler that notifies a thread waiting for the
689           GLib event loop to run that the event loop is actually
690           running.  We do this in the context of the event loop itself
691           to avoid race conditions.
692         */
693         GSource * const source = g_idle_source_new();
694         g_source_set_priority(source, G_PRIORITY_HIGH_IDLE);
695         g_source_set_callback(source,
696                               CALEEventLoopStarted,
697                               &context->le_started,  // data
698                               NULL);                 // notify
699         (void) g_source_attach(source, loop_context);
700         g_source_unref(source);
701
702         g_main_loop_run(event_loop);  // Blocks until loop is quit.
703
704         CALETearDownDBus(&g_context);
705     }
706
707     /*
708       Clean up in the same thread to avoid having to explicitly bump
709       the ref count to retain ownership.
710     */
711     g_main_context_unref(loop_context);
712     g_main_loop_unref(event_loop);
713 }
714
715 static void CALEStopEventLoop(CALEContext * context)
716 {
717     ca_mutex_lock(context->lock);
718
719     GMainLoop * const event_loop = context->event_loop;
720     context->event_loop = NULL;
721
722     ca_mutex_unlock(context->lock);
723
724     if (event_loop != NULL)
725     {
726         g_main_loop_quit(event_loop);
727
728         GMainContext * const loop_context =
729             g_main_loop_get_context(event_loop);
730
731         if (loop_context != NULL)
732         {
733             g_main_context_wakeup(loop_context);
734         }
735     }
736 }
737
738 /**
739  * Wait for @a list to be non-empty.
740  *
741  * @param[in] list    List that should not be empty.
742  * @param[in] retries Number of times to retry if the @a timeout is
743  *                    reached.
744  * @param[in] timeout Timeout in microseconds to wait between retries.
745  */
746 static bool CALEWaitForNonEmptyList(GList * const * list,
747                                     int retries,
748                                     uint64_t timeout)
749 {
750     bool success = false;
751
752     ca_mutex_lock(g_context.lock);
753
754     for (int i = 0; *list == NULL && i < retries; ++i)
755     {
756         if (ca_cond_wait_for(g_context.condition,
757                              g_context.lock,
758                              timeout) == CA_WAIT_SUCCESS)
759         {
760             /*
761               Condition variable was signaled before the timeout was
762               reached.
763             */
764             success = true;
765         }
766     }
767
768     ca_mutex_unlock(g_context.lock);
769
770     return success;
771 }
772
773 // -----------------------------------------------------------------------
774
775 CAResult_t CAInitializeLEAdapter(const ca_thread_pool_t threadPool)
776 {
777     (void)threadPool;
778 #if !GLIB_CHECK_VERSION(2,36,0)
779     /*
780       Initialize the GLib type system.
781
782       As of GLib 2.36, it is no longer necessary to explicitly call
783       g_type_init().
784     */
785     g_type_init();
786 #endif
787
788     return CA_STATUS_OK;
789 }
790
791 CAResult_t CAStartLEAdapter()
792 {
793     /*
794       This function is called by the connectivity abstraction when
795       CASelectNetwork(CA_ADAPTER_GATT_BTLE) is called by the user.
796     */
797
798     OIC_LOG(DEBUG, TAG, __func__);
799
800     CAResult_t result = CA_STATUS_FAILED;
801
802     // Only start if we were previously stopped.
803     if (CALECheckStarted())
804     {
805         return result;
806     }
807
808     /**
809      * Spawn a thread to run the GLib event loop that will drive D-Bus
810      * signal handling.
811      *
812      * @note Ideally this should be done in the @c CAInitializeLE()
813      *       function so that we can detect local bluetooth adapter
814      *       changes right away, without having to first start this LE
815      *       adapter/transport via @cCASelectNetwork().  However, a
816      *       limitation in the CA termination code that destroys the
817      *       thread pool before the transport adapters prevents us
818      *       from doing that without potentially triggering a
819      *       @c pthread_join() call that blocks indefinitely due to
820      *       this event loop not being stopped.  See the comments in
821      *       the @c CAGetLEInterfaceInformation() function below for
822      *       further details.
823      */
824     result = ca_thread_pool_add_task(g_context.client_thread_pool,
825                                      CALEStartEventLoop,
826                                      &g_context);
827
828     /*
829       Wait for the GLib event loop to actually run before returning.
830
831       This addresses corner cases where operations are incorrectly
832       permitted to run in parallel before the event loop is run. For
833       example, the LE transport could have been stopped in a thread
834       parallel to the one starting the event loop start.  In that case
835       the GLib event loop may never exit since the stop operation that
836       causes the event loop to exit occurred before event loop
837       started.  That ultimately causes the CA layer termination to
838       block indefinitely on a pthread_join().  The solution is to only
839       return from the LE transport start operation once we know the
840       event loop is up and running.
841     */
842     struct timespec abs_timeout;
843     if (result == CA_STATUS_OK
844         && clock_gettime(CLOCK_REALTIME, &abs_timeout) == 0)
845     {
846         static time_t const relative_timeout = 2;  // seconds
847         abs_timeout.tv_sec += relative_timeout;
848
849         int const wait_result =
850             sem_timedwait(&g_context.le_started, &abs_timeout);
851
852         if (wait_result == 0)
853         {
854             result = CA_STATUS_OK;
855         }
856     }
857
858     return result;
859 }
860
861 CAResult_t CAStopLEAdapter()
862 {
863     /*
864       This function is called by the connectivity abstraction when
865       CAUnselectNetwork(CA_ADAPTER_GATT_BTLE) is called by the user.
866     */
867
868     OIC_LOG(DEBUG, TAG, "Stop Linux BLE adapter.");
869
870     // Only stop if we were previously started.
871     if (!CALECheckStarted())
872     {
873         return CA_STATUS_FAILED;
874     }
875
876     CALEStopEventLoop(&g_context);
877
878     return CA_STATUS_OK;
879 }
880
881
882 CAResult_t CAGetLEAdapterState()
883 {
884     CAResult_t result = CA_ADAPTER_NOT_ENABLED;
885
886     ca_mutex_lock(g_context.lock);
887
888     for (GList * l = g_context.adapters; l != NULL; l = l->next)
889     {
890         GDBusProxy * const adapter = G_DBUS_PROXY(l->data);
891         GVariant * const prop =
892             g_dbus_proxy_get_cached_property(adapter, "Powered");
893
894         if (prop == NULL)
895         {
896             // This should never happen!
897             result = CA_STATUS_FAILED;
898             break;
899         }
900
901         gboolean const powered = g_variant_get_boolean(prop);
902         g_variant_unref(prop);
903
904         if (powered)
905         {
906             result = CA_STATUS_OK;
907             break;
908
909             /*
910               No need to continue iterating since we have at least
911               one enabled Bluetooth adapter.
912             */
913         }
914     }
915
916     ca_mutex_unlock(g_context.lock);
917
918     return result;
919 }
920
921 CAResult_t CAInitializeLENetworkMonitor()
922 {
923     /**
924      * @note "Network monitor" operations are started in the
925      *       @c CAStartLEAdapter() function rather than this function
926      *       due to glib/D-Bus signal handling threads related
927      *       issues.
928      *
929      * @see @c CAStartLEAdapter() for further details.
930      */
931
932     g_context.lock      = ca_mutex_new();
933     g_context.condition = ca_cond_new();
934
935     static int const PSHARED        = 0;  // shared between threads
936     static unsigned int const VALUE = 0;  // force sem_wait() to block
937
938     if (sem_init(&g_context.le_started, PSHARED, VALUE) != 0)
939     {
940         return CA_STATUS_FAILED;
941     }
942
943     /*
944       The CA LE interface doesn't expose a CAInitializeLEGattServer()
945       function so perform initialization here.
946      */
947     CAPeripheralInitialize();
948
949     return CA_STATUS_OK;
950 }
951
952 void CATerminateLENetworkMonitor()
953 {
954     /**
955      * @note "Network monitor" operations are stopped in @c CALEStop()
956      *       since they are started in @c CAStartLEAdapter() rather
957      *       than @c CAInitializeLENetworkMonitor().
958      *
959      * @see @c CAStartLEAdapter() for further details.
960      */
961
962     /*
963       Since the CA LE interface doesn't expose a
964       CAInitializeLEGattServer() function, finalize the LE server
965       (peripheral) here rather than in CATerminateLEGattServer() to
966       ensure finalization is correctly paired with initialization.
967      */
968     CAPeripheralFinalize();
969
970     (void) sem_destroy(&g_context.le_started);
971
972     ca_mutex_lock(g_context.lock);
973
974     g_context.on_device_state_changed = NULL;
975     g_context.on_server_received_data = NULL;
976     g_context.on_client_received_data = NULL;
977     g_context.client_thread_pool      = NULL;
978     g_context.server_thread_pool      = NULL;
979     g_context.on_client_error         = NULL;
980     g_context.on_server_error         = NULL;
981
982     ca_cond_free(g_context.condition);
983     g_context.condition = NULL;
984
985     ca_mutex_unlock(g_context.lock);
986
987     ca_mutex_free(g_context.lock);
988     g_context.lock = NULL;
989 }
990
991 CAResult_t CASetLEAdapterStateChangedCb(
992     CALEDeviceStateChangedCallback callback)
993 {
994     ca_mutex_lock(g_context.lock);
995     g_context.on_device_state_changed = callback;
996     ca_mutex_unlock(g_context.lock);
997
998     return CA_STATUS_OK;
999 }
1000
1001 CAResult_t CASetLENWConnectionStateChangedCb(CALEConnectionStateChangedCallback callback)
1002 {
1003     (void)callback;
1004     return CA_NOT_SUPPORTED;
1005 }
1006
1007 CAResult_t CAGetLEAddress(char **local_address)
1008 {
1009     OIC_LOG(DEBUG, TAG, "Get Linux BLE local device information.");
1010
1011     if (local_address == NULL)
1012     {
1013         return CA_STATUS_INVALID_PARAM;
1014     }
1015
1016     /**
1017      * @bug Attempting to get LE interface information before this
1018      *      connectivity abstraction adapter has started (e.g. via
1019      *      @c CASelectNetwork()) could result in an inaccurate list
1020      *      of LE interfaces.  For example, detection of hot-plugged
1021      *      bluetooth adapters will only work after the LE IoTivity
1022      *      network has been selected.  If the LE IoTivity network
1023      *      hasn't been selected, the hot-plugged bluetooth adapter
1024      *      will not be reflected in the @c CALocalConnectivity_t list
1025      *      returned by this function.
1026      *      @par
1027      *      This issue caused by the fact that the event loop that
1028      *      handles such events can only be run after this LE
1029      *      adapter/transport is started.  The event loop cannot be
1030      *      started earlier, e.g. during @c CAInitialize(), due to a
1031      *      limitation in the CA transport termination code that
1032      *      requires thread pools to be destroyed before transport
1033      *      termination.  If the event loop was added as a task to the
1034      *      thread pool during @c CAInitialize(), it's possible that
1035      *      the thread running that event loop could be blocked
1036      *      waiting for events during a later call to
1037      *      @c CATerminate() if @c CASelectNetwork() was not called
1038      *      beforehand.  The thread pool destruction that occurs
1039      *      during @c CATerminate() waits for threads in the pool to
1040      *      exit.  However, in this case the event loop thread is
1041      *      still blocked waiting for events since it may not have
1042      *      been stopped since the transport itself was not stopped,
1043      *      meaning termination will also be blocked.
1044      *      @par
1045      *      Other than refactoring to the termination code to allow
1046      *      thread pools to be started during @c CAInitialize(), the
1047      *      only other choice we have to prevent the hang at
1048      *      termination is to move the event loop creation and
1049      *      termination to the @c CAAdapterStart() and
1050      *      @c CAAdapterStop() implementations, respectively, which is
1051      *      why we have this bug.
1052      */
1053     if (!CALECheckStarted())
1054       return CA_ADAPTER_NOT_ENABLED;
1055
1056     *local_address = NULL;
1057
1058     ca_mutex_lock(g_context.lock);
1059
1060     for (GList * l = g_context.adapters; l != NULL; l = l->next)
1061     {
1062         GDBusProxy * const adapter = G_DBUS_PROXY(l->data);
1063
1064         /*
1065           The local bluetooth adapter MAC address is stored in the
1066           org.bluez.Adapter1.Address property.
1067         */
1068         GVariant * const prop =
1069             g_dbus_proxy_get_cached_property(adapter, "Address");
1070
1071         /*
1072           Unless the org.bluez.Adapter1.Address property no longer
1073           exists, prop should not be NULL!  We have bigger problems if
1074           this assert() is ever tripped since that would mean the
1075           org.bluez.Adapter1 D-Bus interface changed.
1076         */
1077         assert(prop != NULL);
1078
1079         gchar const * const address = g_variant_get_string(prop, NULL);
1080
1081         *local_address = OICStrdup(address);
1082
1083         /*
1084           No longer need the property variant.  The address has been
1085           copied.
1086         */
1087         g_variant_unref(prop);
1088
1089         /**
1090          * @todo Unfortunately the CA LE interface defined in
1091          *       caleinterface.h assumes that only one BLE adapter
1092          *       will exist on a given host.  However, this
1093          *       implementation can handle multiple BLE adapters.  The
1094          *       CA LE interface should be updated so that it can
1095          *       handle multiple BLE adapters.  For now we'll just
1096          *       return the address for the first BLE adapter in the
1097          *       list.
1098          */
1099         break;
1100     }
1101
1102     ca_mutex_unlock(g_context.lock);
1103
1104     return *local_address != NULL ? CA_STATUS_OK : CA_STATUS_FAILED;
1105 }
1106
1107 CAResult_t CAStartLEGattServer()
1108 {
1109     return CAPeripheralStart(&g_context);
1110 }
1111
1112 CAResult_t CAStopLEGattServer()
1113 {
1114     return CAPeripheralStop();
1115 }
1116
1117 CAResult_t CAInitializeLEGattServer()
1118 {
1119     return CA_STATUS_OK;
1120 }
1121
1122 void CATerminateLEGattServer()
1123 {
1124     /*
1125       See CATerminateLENetworkMonitor() to understand why the LE
1126       peripheral is not finalized here.
1127      */
1128 }
1129
1130 void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback)
1131 {
1132     ca_mutex_lock(g_context.lock);
1133     g_context.on_server_received_data = callback;
1134     ca_mutex_unlock(g_context.lock);
1135 }
1136
1137 CAResult_t CAUpdateCharacteristicsToGattClient(char const * address,
1138                                                uint8_t const * value,
1139                                                uint32_t valueLen)
1140 {
1141     return CAGattServerSendResponseNotification(address,
1142                                                 value,
1143                                                 valueLen);
1144 }
1145
1146 CAResult_t CAUpdateCharacteristicsToAllGattClients(uint8_t const * value,
1147                                                    uint32_t valueLen)
1148 {
1149     return CAGattServerSendResponseNotificationToAll(value, valueLen);
1150 }
1151
1152 CAResult_t CAStartLEGattClient()
1153 {
1154     CAResult_t result = CACentralStart(&g_context);
1155
1156     if (result != CA_STATUS_OK)
1157     {
1158         return result;
1159     }
1160
1161     ca_mutex_lock(g_context.lock);
1162     bool found_peripherals = (g_context.devices != NULL);
1163     ca_mutex_unlock(g_context.lock);
1164
1165     if (!found_peripherals)
1166     {
1167         // Wait for LE peripherals to be discovered.
1168
1169         // Number of times to wait for discovery to complete.
1170         static int const retries = 5;
1171
1172         static uint64_t const timeout =
1173             2 * MICROSECS_PER_SEC;  // Microseconds
1174
1175         if (!CALEWaitForNonEmptyList(&g_context.devices,
1176                                      retries,
1177                                      timeout))
1178         {
1179             return result;
1180         }
1181     }
1182
1183     /*
1184       Stop discovery so that we can connect to LE peripherals.
1185       Otherwise, the bluetooth subsystem will claim the adapter is
1186       busy.
1187     */
1188
1189     result = CACentralStopDiscovery(&g_context);
1190
1191     if (result != CA_STATUS_OK)
1192     {
1193         return result;
1194     }
1195
1196     bool const connected = CACentralConnectToAll(&g_context);
1197
1198     if (!connected)
1199     {
1200         return result;
1201     }
1202
1203     /**
1204      * @todo Verify notifications have been enabled on all response
1205      *       characteristics.
1206      */
1207
1208     return CAGattClientInitialize(&g_context);
1209 }
1210
1211 void CAStopLEGattClient()
1212 {
1213     CAGattClientDestroy();
1214     (void) CACentralStop(&g_context);
1215 }
1216
1217 CAResult_t CAInitializeLEGattClient()
1218 {
1219     return CA_STATUS_OK;
1220 }
1221
1222 void CATerminateLEGattClient()
1223 {
1224 }
1225
1226 CAResult_t CAUpdateCharacteristicsToGattServer(
1227     char const * remoteAddress,
1228     uint8_t const * data,
1229     uint32_t dataLen,
1230     CALETransferType_t type,
1231     int32_t position)
1232 {
1233     (void) position;
1234
1235     if (type != LE_UNICAST)
1236     {
1237         return CA_STATUS_INVALID_PARAM;
1238     }
1239
1240     /*
1241       We can assume that we're already connected to the BLE device
1242       with the given remote address - we wouldn't have a remote
1243       address otherwise - so there is no need to start scanning for
1244       BLE devices.
1245     */
1246
1247     return CAGattClientSendData(remoteAddress,
1248                                 data,
1249                                 dataLen,
1250                                 &g_context);
1251 }
1252
1253 CAResult_t CAUpdateCharacteristicsToAllGattServers(uint8_t const * data,
1254                                                    uint32_t length)
1255 {
1256     /*
1257       Now send the request through all BLE connections through the
1258       corresponding OIC GATT request characterstics.
1259     */
1260     return CAGattClientSendDataToAll(data, length, &g_context);
1261
1262     /**
1263      * @todo Should we restart discovery after the send?
1264      */
1265 }
1266
1267 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
1268 {
1269     ca_mutex_lock(g_context.lock);
1270     g_context.on_client_received_data = callback;
1271     ca_mutex_unlock(g_context.lock);
1272 }
1273
1274 void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle)
1275 {
1276     ca_mutex_lock(g_context.lock);
1277     g_context.server_thread_pool = handle;
1278     ca_mutex_unlock(g_context.lock);
1279 }
1280
1281 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
1282 {
1283     ca_mutex_lock(g_context.lock);
1284     g_context.client_thread_pool = handle;
1285     ca_mutex_unlock(g_context.lock);
1286 }
1287
1288 CAResult_t CAUnSetLEAdapterStateChangedCb()
1289 {
1290     ca_mutex_lock(g_context.lock);
1291     g_context.on_device_state_changed = NULL;
1292     ca_mutex_unlock(g_context.lock);
1293
1294     return CA_STATUS_OK;
1295 }
1296
1297 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
1298 {
1299     ca_mutex_lock(g_context.lock);
1300     g_context.on_client_error = callback;
1301     ca_mutex_unlock(g_context.lock);
1302 }
1303
1304 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
1305 {
1306     ca_mutex_lock(g_context.lock);
1307     g_context.on_server_error = callback;
1308     ca_mutex_unlock(g_context.lock);
1309 }