replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / linux / utils.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 "utils.h"
20 #include "bluez.h"
21
22 #include "logger.h"
23
24 #include <assert.h>
25
26
27 // Logging tag.
28 static char const TAG[] = "BLE_UTILS";
29
30 bool CAGetBlueZManagedObjectProxies(GList ** proxies,
31                                     char const * interface,
32                                     CALEContext * context,
33                                     CALEProxyFilter filter)
34 {
35     assert(interface != NULL);
36     assert(proxies != NULL);
37     assert(context != NULL);
38
39     /*
40       Failure is only reported if an error occurred.  An empty
41       returned list, for example, is not an error since it could
42       be updated at a later time when handling D-Bus signals related
43       to the given interface.
44     */
45     bool success = true;
46
47     oc_mutex_lock(context->lock);
48
49     if (context->objects == NULL)
50     {
51         oc_mutex_unlock(context->lock);
52         return success;
53     }
54
55     /*
56       Iterate over the objects to find those that implement the given
57       BlueZ interface and them to the given list.
58     */
59     for (GList * l = context->objects; l != NULL; l = l->next)
60     {
61         GDBusProxy * const proxy =
62             G_DBUS_PROXY(g_dbus_object_get_interface(
63                 G_DBUS_OBJECT(l->data),
64                 interface));
65
66         if (proxy != NULL)
67         {
68             if (filter == NULL || filter(proxy))
69             {
70                 /*
71                   Add the object information to the list.
72
73                   Note that we prepend instead of append in this case
74                   since it is more efficient to do so for linked lists
75                   like the one used here.
76                 */
77                 *proxies = g_list_prepend(*proxies, proxy);
78             }
79             else
80             {
81                 // Rejected by filter.
82                 g_object_unref(proxy);
83             }
84         }
85     }
86
87     oc_mutex_unlock(context->lock);
88
89     return success;
90 }
91
92 GDBusProxy * CAGetBlueZInterfaceProxy(GVariant * tuple,
93                                       char const * interface,
94                                       GDBusObjectManager * object_manager)
95 {
96     /*
97       The tuple is of the form "(oa{sv})".
98
99       The object path is first tuple element, and the properties the
100       second.  Check if the given interface exists in the properties.
101       Return the object path (the dictionary item key) of the found
102       property (the dictionary item value).
103     */
104     GVariant * const props = g_variant_get_child_value(tuple, 1);
105
106     GVariant * const value =
107         g_variant_lookup_value(props, interface, NULL);
108
109     GDBusProxy * proxy = NULL;
110
111     if (value != NULL)
112     {
113         /*
114           A set of properties corresponding to the given D-Bus
115           interface was found.  Create a proxy to the object that
116           implements that interface.  Store that proxy, the D-Bus
117           object path and properties in the given list.
118         */
119
120         gchar const * path = NULL;
121
122         // The object path is the first tuple element.
123         g_variant_get_child(tuple, 0, "&o", &path);
124
125         /*
126           Create a proxy to the object that implements the given
127           interface.
128         */
129         proxy =
130             G_DBUS_PROXY(
131                 g_dbus_object_manager_get_interface(object_manager,
132                                                     path,
133                                                     interface));
134
135         g_variant_unref(value);
136     }
137
138     g_variant_unref(props);
139
140     return proxy;
141 }
142
143 bool CASetBlueZObjectProperty(GDBusProxy * proxy,
144                               char const * interface,
145                               char const * property,
146                               GVariant * value)
147 {
148     /*
149       Only make the D-Bus call to set the property if we need to
150       change it.
151      */
152     GVariant * const cached_value =
153         g_dbus_proxy_get_cached_property(proxy, property);
154
155     if (cached_value != NULL)
156     {
157         bool const already_set = g_variant_equal(cached_value, value);
158
159         g_variant_unref(cached_value);
160
161         if (already_set)
162         {
163             /*
164               Ownership of the value GVariant was transferred when
165               this function was called.  It won't be used since the
166               property with the same value is already set, so release
167               our reference to it.
168             */
169             g_variant_unref(value);
170
171             return true;
172         }
173     }
174
175     /*
176       Either the property wasn't previously set or it is being
177       changed.  Set property on the given interface.
178     */
179     GError * error = NULL;
180
181     GVariant * const ret =
182         g_dbus_proxy_call_sync(proxy,
183                                "org.freedesktop.DBus.Properties.Set",
184                                g_variant_new("(ssv)",
185                                              interface,
186                                              property,
187                                              value),
188                                G_DBUS_CALL_FLAGS_NONE,
189                                -1,    // timeout (default == -1),
190                                NULL,  // cancellable
191                                &error);
192
193     if (ret == NULL)
194     {
195         OIC_LOG_V(ERROR,
196                   TAG,
197                   "Attempt to set \"%s\" property for "
198                   "\"%s\" interface failed.: %s",
199                   property, interface, error->message);
200
201         g_error_free(error);
202
203         return false;
204     }
205
206     g_variant_unref(ret);
207
208     return true;
209 }
210
211 GVariant * CAMakePropertyDictionary(
212     char const * interface_name,
213     CADBusSkeletonProperty const * properties,
214     size_t count)
215 {
216     /*
217       Create a variant containing the proxy properties, of the form
218       a{sa{sv}}.
219     */
220
221     GVariantBuilder builder;
222
223     // Create the inner (property) dictionary.
224     g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
225
226     CADBusSkeletonProperty const * const end =
227         properties + count;
228
229     for (CADBusSkeletonProperty const * prop = properties;
230          prop != end;
231          ++prop)
232     {
233         g_variant_builder_add(&builder, "{sv}", prop->name, prop->value);
234     }
235
236     GVariant * const props = g_variant_builder_end(&builder);
237
238     // Now create the dictionary with the above property dictionary
239     // embedded.
240     g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sa{sv}}"));
241
242     g_variant_builder_add(&builder, "{s@a{sv}}", interface_name, props);
243
244     return g_variant_builder_end(&builder);
245 }