Fix build error for toolchain upgrade
[platform/core/api/multi-device-group.git] / src / mdg_dbus.c
1 /*
2  * Copyright (c) 2018 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 <gio/gio.h>
19 #include <glib.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <net/if.h>
26 #include <sys/types.h>
27 #include <arpa/inet.h>
28
29 #include <mdg.h>
30 #include <mdg_dbus.h>
31 #include <mdg_debug.h>
32 #include <mdg_gdbus.h>
33 #include <mdg_private.h>
34 #include <mdg_util.h>
35
36 /* LCOV_EXCL_START */
37 static void __event_cb(Group *object,
38                        gint event_type, gint ret, GVariant *va, gpointer user_data)
39 {
40         NOTUSED(object);
41         mdg_check_null_ret("user_data", user_data);
42
43         mdg_manager_s *handle = user_data;
44
45         _BEGIN();
46
47         _DBG("Event occured : %d", event_type);
48
49         switch (event_type) {
50         case MDG_EVENT_GROUP_FOUND: {
51                 mdg_group_s *group = NULL;
52
53                 if (handle->group_found_cb.found_cb) {
54                         group = mdg_get_group_from_variant(va);
55
56                         handle->group_found_cb.found_cb(group->type, group,
57                                                         handle->group_found_cb.user_data);
58
59                         mdg_clean_group(group);
60                 } else {
61                         _ERR("The callback not exists");
62                 }
63                 break;
64         }
65         case MDG_EVENT_GROUP_FIND_FINISH: {
66                 if (handle->group_find_finish_cb.finish_cb) {
67                         handle->group_find_finish_cb.finish_cb(ret,
68                                                                handle->group_find_finish_cb.user_data);
69                 } else {
70                         _ERR("The callback not exists");
71                 }
72                 break;
73         }
74         case MDG_EVENT_DEVICE_FOUND: {
75                 mdg_device_s *device = NULL;
76
77                 if (handle->device_found_cb.found_cb) {
78                         device = mdg_get_device_from_variant(va);
79
80                         handle->device_found_cb.found_cb(device,
81                                                          handle->device_found_cb.user_data);
82
83                         mdg_clean_device(device);
84                 } else {
85                         _ERR("The callback not exists");
86                 }
87                 break;
88         }
89         case MDG_EVENT_DEVICE_FIND_FINISH: {
90                 if (handle->device_find_finish_cb.finish_cb) {
91                         handle->device_find_finish_cb.finish_cb(ret,
92                                                                 handle->device_find_finish_cb.user_data);
93                 } else {
94                         _ERR("The callback not exists");
95                 }
96                 break;
97         }
98         case MDG_EVENT_INVITE_DEVICE_FINISH: {
99                 if (handle->device_invite_finish_cb.finish_cb) {
100                         mdg_device_s *device = (mdg_device_s *)(handle->device_invite_finish_cb.device);
101                         if (device != NULL) {
102                                 device->is_invited = true;
103                         }
104                         handle->device_invite_finish_cb.finish_cb(ret, device,
105                                                                   handle->device_invite_finish_cb.user_data);
106
107                         mdg_clean_device(device);
108                 } else {
109                         _ERR("The callback not exists");
110                 }
111                 break;
112         }
113         case MDG_EVENT_EJECT_DEVICE_FINISH: {
114                 if (handle->device_eject_finish_cb.finish_cb) {
115                         handle->device_eject_finish_cb.finish_cb(ret,
116                                                                  handle->device_eject_finish_cb.user_data);
117                 } else {
118                         _ERR("The callback not exists");
119                 }
120                 break;
121         }
122         case MDG_EVENT_SEND_DATA_FINISH: {
123                 char *device_id;
124                 char *channel_id;
125                 int msg_id;
126                 unsigned char *data = NULL;
127                 int data_len = 0;
128
129                 if (handle->send_data_finish_cb.finish_cb) {
130                         mdg_device_s *device = (mdg_device_s *)(handle->send_data_finish_cb.device);
131                         mdg_get_data_from_variant(va, &device_id, &channel_id, &msg_id, &data, &data_len);
132
133                         handle->send_data_finish_cb.finish_cb(ret, device, channel_id, msg_id, data, data_len,
134                                                               handle->send_data_finish_cb.user_data);
135                         mdg_clean_device(device);
136                         if (data != NULL)
137                                 free(data);
138                 } else {
139                         _ERR("The callback not exists");
140                 }
141                 break;
142         }
143         case MDG_EVENT_REQ_CHANNEL_LIST_FINISH: {
144                 char *device_id;
145                 char *channel_id;
146
147                 mdg_get_channel_from_variant(va, &device_id, &channel_id, NULL);
148                 if (handle->request_channel_list_finish_cb.finish_cb) {
149                         handle->request_channel_list_finish_cb.finish_cb(device_id, channel_id,
150                                                                          handle->request_channel_list_finish_cb.user_data);
151                 } else {
152                         _ERR("The callback not exists");
153                 }
154                 break;
155         }
156         case MDG_EVENT_REQ_CHANNEL_OPEN_FINISH: {
157                 int ret = MDG_ERROR_NONE;
158                 char tempaddr[26] = {0,};
159                 char *temp_for_strtok = NULL;
160                 char *ret_ptr = NULL;
161                 mdg_channel_s *channel = calloc(1, sizeof(mdg_channel_s));
162                 if (NULL == channel) {
163                         _ERR("Memory allocation failed");
164                         ret = MDG_ERROR_OUT_OF_MEMORY;
165                         goto REQUEST_OPEN_CHANNEL_FINISH_EXIT;
166                 }
167
168                 mdg_get_channel_from_variant(va, &channel->device_id, &channel->channel_id,
169                         &channel->remote_address);
170
171                 /* create socket */
172                 struct sockaddr_in serveraddr;
173                 channel->client_sockfd = socket(AF_INET, SOCK_STREAM, 0);
174                 if (channel->client_sockfd < 0) {
175                         _ERR("socket() error");
176                         ret = MDG_ERROR_OPERATION_FAILED;
177                         goto REQUEST_OPEN_CHANNEL_FINISH_EXIT;
178                 }
179                 memset(&serveraddr, 0, sizeof(serveraddr));
180
181                 serveraddr.sin_family = AF_INET;
182                 serveraddr.sin_port = htons(8675);
183
184                 sscanf(channel->remote_address, "coaps://%s", (char *)tempaddr);
185                 ret_ptr = strtok_r(tempaddr, ":", &temp_for_strtok);
186                 if (ret_ptr == NULL) {
187                         _ERR("strtok failed");
188                         ret = MDG_ERROR_OPERATION_FAILED;
189                         goto REQUEST_OPEN_CHANNEL_FINISH_EXIT;
190                 }
191
192                 _ERR("Address is %s", ret_ptr);
193
194                 inet_pton(AF_INET, ret_ptr, &serveraddr.sin_addr.s_addr);
195                 ret = connect(channel->client_sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
196
197                 if (ret == -1) {
198                         char buf[128];
199                         strerror_r(errno, buf, 128);
200                         _DBG("Connect error : %s", buf);
201                 } else {
202                         _DBG("Success Connect to %s", ret_ptr);
203                 }
204
205 REQUEST_OPEN_CHANNEL_FINISH_EXIT:
206                 if (handle->request_channel_open_finish_cb.channel_opened_cb) {
207                         handle->request_channel_open_finish_cb.channel_opened_cb(ret, channel,
208                                                                          handle->request_channel_open_finish_cb.user_data);
209                 } else {
210                         _ERR("The callback not exists");
211                 }
212
213                 mdg_clean_channel(channel);
214
215                 break;
216         }
217         case MDG_EVENT_RECEIVE_DATA: {
218                 char *device_id;
219                 char *channel_id;
220                 int msg_id;
221                 unsigned char *data;
222                 int data_len = 0;
223
224                 mdg_get_data_from_variant(va, &device_id, &channel_id, &msg_id, &data, &data_len);
225
226                 mdg_channel_cb_s *channel = NULL;
227
228                 GSList *l;
229                 for (l = handle->channel_cb_list; l != NULL; l = l->next) {
230                         mdg_channel_cb_s *tmp_channel = (mdg_channel_cb_s *)l->data;
231                         if (g_strcmp0(tmp_channel->channel_id, channel_id) == 0)
232                                 channel = tmp_channel;
233                 }
234
235                 if (channel != NULL)
236                         channel->receive_data_cb(0, device_id, channel_id, msg_id, data, data_len, channel->receive_data_cb_user_data);
237
238                 if (data != NULL)
239                         free(data);
240
241                 break;
242         }
243         case MDG_EVENT_INVITED: {
244                 mdg_group_s *group = NULL;
245
246                 if (handle->invited_event_cb.invited_event_cb) {
247                         group = mdg_get_group_from_variant(va);
248
249                         handle->invited_event_cb.invited_event_cb(group, handle->invited_event_cb.user_data);
250
251                         mdg_clean_group(group);
252                 } else {
253                         _ERR("The callback not exists");
254                 }
255                 break;
256         }
257         case MDG_EVENT_EJECTED: {
258                 mdg_group_s *group = NULL;
259
260                 if (handle->ejected_event_cb.ejected_event_cb) {
261                         group = mdg_get_group_from_variant(va);
262
263                         handle->ejected_event_cb.ejected_event_cb(group, handle->ejected_event_cb.user_data);
264
265                         mdg_clean_group(group);
266                 } else {
267                         _ERR("The callback not exists");
268                 }
269                 break;
270         }
271         case MDG_EVENT_RECEIVE_OPEN_CHANNEL: {
272                 int ret = MDG_ERROR_NONE;
273                 mdg_channel_cb_s *channel_cb = NULL;
274                 mdg_channel_s *channel = calloc(1, sizeof(mdg_channel_s));
275                 if (NULL == channel) {
276                         _ERR("Memory allocation failed");
277                         ret = MDG_ERROR_OUT_OF_MEMORY;
278                         goto RECEIVE_OPEN_CHANNEL_EXIT;
279                 }
280
281                 mdg_get_channel_from_variant(va, &channel->device_id, &channel->channel_id,
282                         &channel->remote_address);
283
284                 GSList *l;
285                 for (l = handle->channel_cb_list; l != NULL; l = l->next) {
286                         mdg_channel_cb_s *tmp_channel = (mdg_channel_cb_s *)l->data;
287                         if (g_strcmp0(tmp_channel->channel_id, channel->channel_id) == 0)
288                                 channel_cb = tmp_channel;
289                 }
290
291                 if (channel_cb == NULL) {
292                         _ERR("[%s] The channel is not registered", channel->channel_id);
293                         ret = MDG_ERROR_NO_DATA;
294                         goto RECEIVE_OPEN_CHANNEL_EXIT;
295                 }
296
297                 socklen_t client_len;
298                 char buf[128];
299
300                 struct linger ling;
301                 struct timeval tv_timeo = {3, 0};
302
303                 ling.l_onoff = 1;
304                 ling.l_linger = 0;
305
306                 struct sockaddr_in serveraddr, clientaddr;
307                 char client_ipaddr[INET_ADDRSTRLEN];
308
309                 channel->server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
310                 if (channel->server_sockfd == -1) {
311                         ret = MDG_ERROR_OPERATION_FAILED;
312                         strerror_r(errno, buf, 128);
313                         _ERR("socket error : %s", buf);
314                         goto RECEIVE_OPEN_CHANNEL_EXIT;
315                 }
316
317                 if (setsockopt(channel->server_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, sizeof(tv_timeo)) < 0) {
318                         ret = MDG_ERROR_OPERATION_FAILED;
319                         strerror_r(errno, buf, 128);
320                         _ERR("setsockopt error : %s", buf);
321                         goto RECEIVE_OPEN_CHANNEL_EXIT;
322                 }
323
324                 if (setsockopt(channel->server_sockfd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) < 0) {
325                         ret = MDG_ERROR_OPERATION_FAILED;
326                         strerror_r(errno, buf, 128);
327                         _ERR("setsockopt error : %s", buf);
328                         goto RECEIVE_OPEN_CHANNEL_EXIT;
329                 }
330
331                 serveraddr.sin_family = AF_INET;
332                 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
333                 serveraddr.sin_port = htons(8675);
334                 memset(&serveraddr.sin_zero, 0, sizeof(serveraddr.sin_zero));
335
336                 if (bind(channel->server_sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
337                         ret = MDG_ERROR_OPERATION_FAILED;
338                         strerror_r(errno, buf, 128);
339                         _ERR("bind error : %s", buf);
340                         goto RECEIVE_OPEN_CHANNEL_EXIT;
341                 }
342
343                 if (listen(channel->server_sockfd, 5) != 0) {
344                         ret = MDG_ERROR_OPERATION_FAILED;
345                         strerror_r(errno, buf, 128);
346                         _ERR("listen error : %s", buf);
347                         goto RECEIVE_OPEN_CHANNEL_EXIT;
348                 }
349
350                 client_len = sizeof(clientaddr);
351                 channel->client_sockfd = accept(channel->server_sockfd, (struct sockaddr *)&clientaddr, &client_len);
352                 inet_ntop(AF_INET, &clientaddr.sin_addr.s_addr, client_ipaddr, sizeof(client_ipaddr));
353                 _DBG("Accepted IP : %s, client socket : %d", client_ipaddr, channel->client_sockfd);
354
355                 if (channel->client_sockfd == -1) {
356                         ret = MDG_ERROR_OPERATION_FAILED;
357                         strerror_r(errno, buf, 128);
358                         _ERR("socket error : %s", buf);
359                         goto RECEIVE_OPEN_CHANNEL_EXIT;
360                 }
361
362 RECEIVE_OPEN_CHANNEL_EXIT:
363                 if (channel_cb && channel_cb->opened_cb) {
364                         channel_cb->opened_cb(ret, channel, channel_cb->opened_cb_user_data);
365                 } else {
366                         _ERR("The callback not exists");
367                 }
368
369                 mdg_clean_channel(channel);
370
371                 break;
372         }
373         default:
374                 _ERR("Unknown Event");
375                 break;
376         }
377
378         _END();
379 }
380 /* LCOV_EXCL_STOP */
381
382 static int _enabler_proxy_init(mdg_manager_s *handle)
383 {
384         GError *error = NULL;
385         const gchar *name;
386         int ret;
387
388         handle->enabler_proxy = enabler_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
389                                                                G_DBUS_PROXY_FLAGS_NONE, MDG_DBUS_SERVICE,
390                                                                MDG_DBUS_ENABLER_PATH, NULL, &error);
391         if (NULL == handle->enabler_proxy) {
392                 /* LCOV_EXCL_START */
393                 if (error != NULL) {
394                         _ERR("Failed to connect to the D-BUS daemon [%s]", error->message);
395                         g_error_free(error);
396                 }
397                 return MDG_ERROR_IO_ERROR;
398                 /* LCOV_EXCL_STOP */
399         }
400
401         handle->system_bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
402         if (NULL == handle->system_bus) {
403                 /* LCOV_EXCL_START */
404                 if (error != NULL) {
405                         _ERR("Failed to connect to system bus [%s]", error->message);
406                         g_error_free(error);
407                 }
408                 return MDG_ERROR_IO_ERROR;
409                 /* LCOV_EXCL_STOP */
410         }
411
412         name = g_dbus_connection_get_unique_name(handle->system_bus);
413         _DBG("Unique dbus name %s", name);
414
415         enabler_call_add_ref_sync(handle->enabler_proxy, name, &ret, NULL, &error);
416         if (error) {
417                 /* LCOV_EXCL_START */
418                 _ERR("Failed to add reference [%s]", error->message);
419                 g_error_free(error);
420                 return MDG_ERROR_IO_ERROR;
421                 /* LCOV_EXCL_STOP */
422         }
423
424         return ret;
425 }
426
427 /* LCOV_EXCL_START */
428 static void _dbus_name_owner_notify(GObject *object, GParamSpec *pspec,
429                                     gpointer *user_data)
430 {
431         GDBusProxy *proxy = G_DBUS_PROXY(object);
432         mdg_check_null_ret("user_data", user_data);
433         mdg_manager_s *handle = (mdg_manager_s *)user_data;
434         gchar *name_owner = g_dbus_proxy_get_name_owner(proxy);
435
436         LOGD("Name owner notify [%s]", name_owner);
437
438         if (NULL == name_owner)
439                 gdbus_deinitialize(handle);
440         free(name_owner);
441 }
442 /* LCOV_EXCL_STOP */
443
444 static int _group_proxy_init(mdg_manager_s *handle)
445 {
446         int id = -1;
447         GError *error = NULL;
448
449         handle->group_proxy = group_proxy_new_for_bus_sync(
450             G_BUS_TYPE_SYSTEM,
451             G_DBUS_PROXY_FLAGS_NONE,
452             MDG_DBUS_SERVICE,
453             MDG_DBUS_GROUP_PATH,
454             NULL,
455             &error);
456         if (NULL == handle->group_proxy) {
457                 /* LCOV_EXCL_START */
458                 if (error != NULL) {
459                         _ERR("Failed to connect to the D-BUS daemon [%s]", error->message);
460                         g_error_free(error);
461                 }
462                 return MDG_ERROR_IO_ERROR;
463                 /* LCOV_EXCL_STOP */
464         }
465
466         id = g_signal_connect(handle->group_proxy, "notify::g-name-owner",
467                               G_CALLBACK(_dbus_name_owner_notify), handle);
468         if (0 == id) {
469                 /* LCOV_EXCL_START */
470                 _ERR("g_signal_connect() Fail");
471                 g_object_unref(handle->group_proxy);
472                 handle->group_proxy = NULL;
473                 return MDG_ERROR_IO_ERROR;
474                 /* LCOV_EXCL_STOP */
475         }
476
477         g_signal_connect(handle->group_proxy,
478                          "event", G_CALLBACK(__event_cb), handle);
479
480         return MDG_ERROR_NONE;
481 }
482
483 static void _group_proxy_deinit(mdg_manager_s *handle)
484 {
485         g_object_unref(handle->group_proxy);
486         handle->group_proxy = NULL;
487 }
488
489 static void _enabler_proxy_deinit(mdg_manager_s *handle)
490 {
491         g_object_unref(handle->system_bus);
492         handle->system_bus = NULL;
493
494         g_object_unref(handle->enabler_proxy);
495         handle->enabler_proxy = NULL;
496 }
497
498 int gdbus_initialize(mdg_manager_s *handle)
499 {
500         int ret = MDG_ERROR_NONE;
501
502         _group_proxy_init(handle);
503         _enabler_proxy_init(handle);
504
505         if (handle->group_proxy == NULL)
506                 ret = -1; /* LCOV_EXCL_LINE */
507
508         if (handle->enabler_proxy == NULL)
509                 ret = -1; /* LCOV_EXCL_LINE */
510
511         return ret;
512 }
513
514 int gdbus_deinitialize(mdg_manager_s *handle)
515 {
516         int ret = MDG_ERROR_NONE;
517
518         _group_proxy_deinit(handle);
519         _enabler_proxy_deinit(handle);
520
521         return ret;
522 }