04b018aeb24393d9a37a62417de7d2a445fcfc5c
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-network.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <glib.h>
19 #include <gio/gio.h>
20 #include <dlog.h>
21 #include <string.h>
22 #include <stdio.h>
23 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
24 #include <syspopup_caller.h>
25 #endif
26 #include <net_connection.h>
27
28 #include "bluetooth-api.h"
29 #include "bt-service-network.h"
30 #include "bt-service-common.h"
31 #include "bt-service-event.h"
32 #include "bt-service-util.h"
33 #include "bt-internal-types.h"
34
35 void _bt_util_addr_type_to_addr_net_string(char *address,
36                                         unsigned char *addr)
37 {
38         ret_if(address == NULL);
39         ret_if(addr == NULL);
40
41         snprintf(address, BT_ADDRESS_STR_LEN, "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", addr[0],
42                         addr[1], addr[2], addr[3], addr[4], addr[5]);
43 }
44
45 static connection_profile_h __bt_get_net_profile(void *connection,
46                                                 connection_iterator_type_e type,
47                                                 unsigned char *address)
48 {
49         int result;
50         gchar **split_string;
51         char net_address[BT_ADDRESS_STR_LEN + 1] = { 0 };
52         char *profile_name = NULL;
53         connection_profile_iterator_h profile_iter;
54         connection_profile_h profile_h;
55         connection_profile_type_e profile_type;
56
57         retv_if(connection == NULL, NULL);
58         retv_if(address == NULL, NULL);
59
60         BT_DBG("net_conn: %x", connection);
61
62         _bt_util_addr_type_to_addr_net_string(net_address, address);
63
64         result = connection_get_profile_iterator(connection,
65                                                         type,
66                                                         &profile_iter);
67         if (result != CONNECTION_ERROR_NONE) {
68                 BT_ERR("Fail to get profile iterator [%d]", result);
69                 return NULL;
70         }
71
72         while (connection_profile_iterator_has_next(profile_iter)) {
73                         profile_name = NULL;
74                         profile_h = NULL;
75                         split_string = NULL;
76
77                         if (connection_profile_iterator_next(profile_iter,
78                                                 &profile_h) != CONNECTION_ERROR_NONE) {
79                                 BT_ERR("Fail to get profile handle");
80                                 return NULL;
81                         }
82
83                         if (connection_profile_get_type(profile_h,
84                                                 &profile_type) != CONNECTION_ERROR_NONE) {
85                                 BT_ERR("Fail to get profile type");
86                                 continue;
87                         }
88
89                         if (profile_type != CONNECTION_PROFILE_TYPE_BT)
90                                 continue;
91
92                         if (connection_profile_get_name(profile_h,
93                                                 &profile_name) != CONNECTION_ERROR_NONE) {
94                                 BT_ERR("Fail to get profile name");
95                                 return NULL;
96                         }
97
98                         split_string = g_strsplit(profile_name, "_", 3);
99
100                         g_free(profile_name);
101
102                         if (g_strv_length(split_string) < 3)
103                                 continue;
104
105                         if (g_ascii_strcasecmp(split_string[2], net_address) == 0) {
106                                 BT_DBG("matched profile");
107                                 g_strfreev(split_string);
108                                 return profile_h;
109                         }
110
111                         g_strfreev(split_string);
112         }
113
114         return NULL;
115 }
116
117 int _bt_is_network_connected(void *connection, unsigned char *address,
118                                         gboolean *is_connected)
119 {
120         void *handle = NULL;
121         handle = __bt_get_net_profile(connection,
122                                 CONNECTION_ITERATOR_TYPE_CONNECTED,
123                                 address);
124         if(handle)
125                 *is_connected = TRUE;
126         else
127                 *is_connected = FALSE;
128
129         return BLUETOOTH_ERROR_NONE;
130 }
131
132 static void __bt_network_connect_cb(GDBusProxy *proxy, GAsyncResult *res,
133                                         gpointer user_data)
134 {
135         GError *g_error = NULL;
136         GVariant *out_param1 = NULL;
137         GVariant *reply = NULL;
138         bluetooth_device_address_t device_addr = { {0} };
139         int result = BLUETOOTH_ERROR_NONE;
140         bt_function_data_t *func_data;
141         request_info_t *req_info;
142
143         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
144         g_object_unref(proxy);
145
146         if (reply == NULL) {
147                 BT_ERR("Network Connect Dbus Call Error");
148                 if (g_error) {
149                         BT_ERR("Error: %s\n", g_error->message);
150                         g_clear_error(&g_error);
151                 }
152                 result = BLUETOOTH_ERROR_INTERNAL;
153         }
154         g_variant_unref(reply);
155
156         func_data = user_data;
157         if (func_data == NULL) {
158                 /* Send reply */
159                 BT_ERR("func_data == NULL");
160                 goto done;
161         }
162
163         BT_ERR("func_data->req_id: %d", func_data->req_id);
164         req_info = _bt_get_request_info(func_data->req_id);
165         if (req_info == NULL) {
166                 BT_ERR("req_info == NULL");
167                 goto done;
168         }
169
170         if (req_info->context == NULL)
171                 goto done;
172
173         _bt_convert_addr_string_to_type(device_addr.addr,
174                                         func_data->address);
175
176         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
177                                                         &device_addr, sizeof(bluetooth_device_address_t), TRUE, NULL, NULL);
178
179         g_dbus_method_invocation_return_value(req_info->context,
180                         g_variant_new("iv", result, out_param1));
181
182         _bt_delete_request_list(req_info->req_id);
183
184 done:
185         if (func_data) {
186                 g_free(func_data->address);
187                 g_free(func_data);
188         }
189 }
190
191 static void __bt_network_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
192                                         gpointer user_data)
193 {
194         GError *g_error = NULL;
195         GVariant *out_param1 = NULL;
196         GVariant *reply = NULL;
197         bluetooth_device_address_t device_addr = { {0} };
198         int result = BLUETOOTH_ERROR_NONE;
199         bt_function_data_t *func_data;
200         request_info_t *req_info;
201
202         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
203         g_object_unref(proxy);
204
205         if (reply == NULL) {
206                 BT_ERR("Network Disconnect Dbus Call Error");
207                 if (g_error) {
208                         BT_ERR("Error: %s\n", g_error->message);
209                         g_clear_error(&g_error);
210                 }
211                 result = BLUETOOTH_ERROR_INTERNAL;
212         }
213         g_variant_unref(reply);
214
215         func_data = user_data;
216         if (func_data == NULL) {
217                 /* Send reply */
218                 BT_ERR("func_data == NULL");
219                 goto done;
220         }
221         BT_ERR("func_data->req_id: %d", func_data->req_id);
222         req_info = _bt_get_request_info(func_data->req_id);
223         if (req_info == NULL) {
224                 BT_ERR("req_info == NULL");
225                 goto done;
226         }
227
228         if (g_error != NULL) {
229                 BT_ERR("Network Connect Dbus Call Error: %s\n", g_error->message);
230                 result = BLUETOOTH_ERROR_INTERNAL;
231         }
232
233         if (req_info->context == NULL)
234                 goto done;
235
236         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
237                                                         &device_addr, sizeof(bluetooth_device_address_t), TRUE, NULL, NULL);
238
239         g_dbus_method_invocation_return_value(req_info->context,
240                         g_variant_new("iv", result, out_param1));
241
242         _bt_delete_request_list(req_info->req_id);
243
244 done:
245         if (func_data) {
246                 g_free(func_data->address);
247                 g_free(func_data);
248         }
249 }
250
251 int _bt_network_activate(void)
252 {
253         int ret = BLUETOOTH_ERROR_NONE;
254         char *adapter_path;
255         GError *err = NULL;
256         GDBusConnection *conn;
257         GDBusProxy *server_proxy;
258
259         conn = _bt_get_system_gconn();
260         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
261
262         adapter_path = _bt_get_adapter_path();
263         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
264
265         server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
266                         NULL, BT_BLUEZ_NAME,
267                         adapter_path, BT_NETWORK_SERVER_INTERFACE,  NULL, NULL);
268         g_free(adapter_path);
269
270         if (server_proxy == NULL) {
271                 BT_ERR("Failed to get the network server proxy\n");
272                 return BLUETOOTH_ERROR_INTERNAL;
273         }
274
275         g_dbus_proxy_call_sync(server_proxy, "Register",
276                                  g_variant_new("(ss)", NAP_UUID_NAME, NET_BRIDGE_INTERFACE),
277                                  G_DBUS_CALL_FLAGS_NONE,
278                                  -1,
279                                  NULL,
280                                  &err);
281         if (err != NULL) {
282                 g_dbus_error_strip_remote_error(err);
283                 BT_ERR("Network server register Error: %s\n", err->message);
284                 if (g_strcmp0(err->message, "Already Exists") == 0) {
285                         ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
286                 } else {
287                         ret = BLUETOOTH_ERROR_INTERNAL;
288                 }
289                 g_error_free(err);
290         }
291         g_object_unref(server_proxy);
292
293         return ret;
294 }
295
296 int _bt_network_deactivate(void)
297 {
298         char *adapter_path;
299         GError *err = NULL;
300         GDBusConnection *conn;
301         GDBusProxy *server_proxy;
302         int ret = BLUETOOTH_ERROR_NONE;
303
304         conn = _bt_get_system_gconn();
305         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
306
307         adapter_path = _bt_get_adapter_path();
308         retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
309
310         server_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
311                                                                 NULL, BT_BLUEZ_NAME,
312                                                                 adapter_path, BT_NETWORK_SERVER_INTERFACE,  NULL, NULL);
313         g_free(adapter_path);
314
315         if (server_proxy == NULL) {
316                 BT_ERR("Failed to get the network server proxy\n");
317                 return BLUETOOTH_ERROR_INTERNAL;
318         }
319
320         g_dbus_proxy_call_sync(server_proxy, "Unregister",
321                                  g_variant_new("(s)", NAP_UUID_NAME),
322                                  G_DBUS_CALL_FLAGS_NONE,
323                                  -1,
324                                  NULL,
325                                  &err);
326         if (err != NULL) {
327                 g_dbus_error_strip_remote_error(err);
328                 BT_ERR("Network server unregister Error: %s\n", err->message);
329                 if (g_strcmp0(err->message,
330                                 "Operation currently not available") == 0) {
331                         ret = BLUETOOTH_ERROR_ALREADY_DEACTIVATED;
332                 } else {
333                         ret = BLUETOOTH_ERROR_INTERNAL;
334                 }
335                 g_error_free(err);
336         }
337         g_object_unref(server_proxy);
338
339         return ret;
340 }
341
342 int _bt_network_connect(int request_id, int role,
343                 bluetooth_device_address_t *device_address)
344 {
345         const gchar *device_path = NULL;
346         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
347         char remote_role[BLUETOOTH_UUID_STRING_MAX] = { 0 };
348         bt_function_data_t *func_data;
349         GDBusProxy *adapter_proxy;
350         GDBusProxy *profile_proxy;
351         GDBusConnection *conn;
352         GVariant *result = NULL;
353         GError*err = NULL;
354
355         BT_CHECK_PARAMETER(device_address, return);
356
357         switch (role) {
358         case BLUETOOTH_NETWORK_PANU_ROLE:
359                 g_strlcpy(remote_role, PANU_UUID_NAME, BLUETOOTH_UUID_STRING_MAX);
360                 break;
361
362         case BLUETOOTH_NETWORK_NAP_ROLE:
363                 g_strlcpy(remote_role, NAP_UUID_NAME, BLUETOOTH_UUID_STRING_MAX);
364                 break;
365
366         case BLUETOOTH_NETWORK_GN_ROLE:
367                 g_strlcpy(remote_role, GN_UUID_NAME, BLUETOOTH_UUID_STRING_MAX);
368                 break;
369         default:
370                 BT_ERR("Unknown role");
371                 return BLUETOOTH_ERROR_INTERNAL;
372         }
373
374         adapter_proxy = _bt_get_adapter_proxy();
375         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
376
377         conn = _bt_get_system_gconn();
378         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
379
380         _bt_convert_addr_type_to_string(address, device_address->addr);
381
382         result = g_dbus_proxy_call_sync(adapter_proxy, "FindDevice",
383                         g_variant_new("(s)", address),
384                         G_DBUS_CALL_FLAGS_NONE,
385                         -1, NULL, &err);
386         if (result == NULL) {
387                 BT_ERR("Error occurred in call to FindDevice");
388                 if (err) {
389                         BT_ERR("Error: %s", err->message);
390                         g_clear_error(&err);
391                 }
392                 return BLUETOOTH_ERROR_INTERNAL;
393         }
394
395         device_path =  g_variant_get_string(result, NULL);
396         if (device_path == NULL) {
397                 BT_ERR("No paired device");
398                 g_variant_unref(result);
399                 return BLUETOOTH_ERROR_NOT_PAIRED;
400         }
401
402         profile_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
403                         NULL, BT_BLUEZ_NAME,
404                         device_path, BT_NETWORK_CLIENT_INTERFACE,  NULL, NULL);
405
406         g_variant_unref(result);
407         retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
408         func_data = g_malloc0(sizeof(bt_function_data_t));
409
410         func_data->address = g_strdup(address);
411         func_data->req_id = request_id;
412
413         g_dbus_proxy_call(profile_proxy, "Connect",
414                                 g_variant_new("(s)", remote_role),
415                                 G_DBUS_CALL_FLAGS_NONE,
416                                 BT_MAX_DBUS_TIMEOUT,
417                                 NULL,
418                                 (GAsyncReadyCallback)__bt_network_connect_cb,
419                                 func_data);
420
421         return BLUETOOTH_ERROR_NONE;
422 }
423
424 int _bt_network_disconnect(int request_id,
425                 bluetooth_device_address_t *device_address)
426 {
427         const gchar *device_path = NULL;
428         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
429         bt_function_data_t *func_data;
430         GDBusProxy *adapter_proxy;
431         GDBusProxy *profile_proxy;
432         GDBusConnection *conn;
433         GVariant *result = NULL;
434         GError*err = NULL;
435
436         BT_CHECK_PARAMETER(device_address, return);
437
438         adapter_proxy = _bt_get_adapter_proxy();
439         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
440
441         conn = _bt_get_system_gconn();
442         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
443
444         _bt_convert_addr_type_to_string(address, device_address->addr);
445
446         result = g_dbus_proxy_call_sync(adapter_proxy, "FindDevice",
447                                  g_variant_new("(s)", address),
448                                  G_DBUS_CALL_FLAGS_NONE,
449                                  -1, NULL, &err);
450         if (result == NULL) {
451                 BT_ERR("Error occurred in call to FindDevice");
452                 if (err) {
453                         BT_ERR("Error: %s", err->message);
454                         g_clear_error(&err);
455                 }
456                 return BLUETOOTH_ERROR_INTERNAL;
457         }
458
459         device_path =  g_variant_get_string(result, NULL);
460         if (device_path == NULL) {
461                 BT_ERR("No paired device");
462                 return BLUETOOTH_ERROR_NOT_PAIRED;
463         }
464
465         profile_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
466                         NULL, BT_BLUEZ_NAME,
467                         device_path, BT_NETWORK_CLIENT_INTERFACE,  NULL, NULL);
468
469         g_variant_unref(result);
470         retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
471         func_data = g_malloc0(sizeof(bt_function_data_t));
472
473         func_data->address = g_strdup(address);
474         func_data->req_id = request_id;
475
476         g_dbus_proxy_call(profile_proxy, "Disconnect",
477                         NULL,
478                         G_DBUS_CALL_FLAGS_NONE,
479                         BT_MAX_DBUS_TIMEOUT,
480                         NULL,
481                         (GAsyncReadyCallback)__bt_network_disconnect_cb,
482                         func_data);
483
484         return BLUETOOTH_ERROR_NONE;
485 }
486
487 int _bt_network_server_disconnect(int request_id,
488                 bluetooth_device_address_t *device_address)
489 {
490         gchar *adapter_path = NULL;
491         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
492         bt_function_data_t *func_data;
493         GDBusProxy *profile_proxy;
494         GDBusConnection *conn;
495
496         BT_CHECK_PARAMETER(device_address, return);
497
498         conn = _bt_get_system_gconn();
499         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
500
501         adapter_path = _bt_get_adapter_path();
502         if (adapter_path == NULL) {
503                 BT_ERR("No adapter found");
504                 return BLUETOOTH_ERROR_INTERNAL;
505         }
506
507         _bt_convert_addr_type_to_string(address, device_address->addr);
508
509         profile_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
510                         NULL, BT_BLUEZ_NAME,
511                         adapter_path, BT_NETWORK_SERVER_INTERFACE, NULL, NULL);
512         g_free(adapter_path);
513         retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
514         func_data = g_malloc0(sizeof(bt_function_data_t));
515
516         func_data->address = g_strdup(address);
517         func_data->req_id = request_id;
518
519         g_dbus_proxy_call(profile_proxy, "Disconnect",
520                                  g_variant_new("(s)", address),
521                                 G_DBUS_CALL_FLAGS_NONE,
522                                 BT_MAX_DBUS_TIMEOUT,
523                                 NULL,
524                                 (GAsyncReadyCallback)__bt_network_disconnect_cb,
525                                 func_data);
526
527         return BLUETOOTH_ERROR_NONE;
528 }