2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <sys/socket.h>
24 #include <netinet/in.h>
26 #include <sys/types.h>
27 #include <arpa/inet.h>
31 #include <mdg_debug.h>
32 #include <mdg_gdbus.h>
33 #include <mdg_private.h>
37 static void __event_cb(Group *object,
38 gint event_type, gint ret, GVariant *va, gpointer user_data)
41 mdg_check_null_ret("user_data", user_data);
43 mdg_manager_s *handle = user_data;
47 _DBG("Event occured : %d", event_type);
50 case MDG_EVENT_GROUP_FOUND: {
51 mdg_group_s *group = NULL;
53 if (handle->group_found_cb.found_cb) {
54 group = mdg_get_group_from_variant(va);
56 handle->group_found_cb.found_cb(group->type, group,
57 handle->group_found_cb.user_data);
59 mdg_clean_group(group);
61 _ERR("The callback not exists");
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);
70 _ERR("The callback not exists");
74 case MDG_EVENT_DEVICE_FOUND: {
75 mdg_device_s *device = NULL;
77 if (handle->device_found_cb.found_cb) {
78 device = mdg_get_device_from_variant(va);
80 handle->device_found_cb.found_cb(device,
81 handle->device_found_cb.user_data);
83 mdg_clean_device(device);
85 _ERR("The callback not exists");
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);
94 _ERR("The callback not exists");
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;
104 handle->device_invite_finish_cb.finish_cb(ret, device,
105 handle->device_invite_finish_cb.user_data);
107 mdg_clean_device(device);
109 _ERR("The callback not exists");
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);
118 _ERR("The callback not exists");
122 case MDG_EVENT_SEND_DATA_FINISH: {
126 unsigned char *data = NULL;
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);
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);
139 _ERR("The callback not exists");
143 case MDG_EVENT_REQ_CHANNEL_LIST_FINISH: {
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);
152 _ERR("The callback not exists");
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;
168 mdg_get_channel_from_variant(va, &channel->device_id, &channel->channel_id,
169 &channel->remote_address);
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;
179 memset(&serveraddr, 0, sizeof(serveraddr));
181 serveraddr.sin_family = AF_INET;
182 serveraddr.sin_port = htons(8675);
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;
192 _ERR("Address is %s", ret_ptr);
194 inet_pton(AF_INET, ret_ptr, &serveraddr.sin_addr.s_addr);
195 ret = connect(channel->client_sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
199 strerror_r(errno, buf, 128);
200 _DBG("Connect error : %s", buf);
202 _DBG("Success Connect to %s", ret_ptr);
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);
210 _ERR("The callback not exists");
213 mdg_clean_channel(channel);
217 case MDG_EVENT_RECEIVE_DATA: {
224 mdg_get_data_from_variant(va, &device_id, &channel_id, &msg_id, &data, &data_len);
226 mdg_channel_cb_s *channel = NULL;
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;
236 channel->receive_data_cb(0, device_id, channel_id, msg_id, data, data_len, channel->receive_data_cb_user_data);
243 case MDG_EVENT_INVITED: {
244 mdg_group_s *group = NULL;
246 if (handle->invited_event_cb.invited_event_cb) {
247 group = mdg_get_group_from_variant(va);
249 handle->invited_event_cb.invited_event_cb(group, handle->invited_event_cb.user_data);
251 mdg_clean_group(group);
253 _ERR("The callback not exists");
257 case MDG_EVENT_EJECTED: {
258 mdg_group_s *group = NULL;
260 if (handle->ejected_event_cb.ejected_event_cb) {
261 group = mdg_get_group_from_variant(va);
263 handle->ejected_event_cb.ejected_event_cb(group, handle->ejected_event_cb.user_data);
265 mdg_clean_group(group);
267 _ERR("The callback not exists");
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;
281 mdg_get_channel_from_variant(va, &channel->device_id, &channel->channel_id,
282 &channel->remote_address);
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;
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;
297 socklen_t client_len;
301 struct timeval tv_timeo = {3, 0};
306 struct sockaddr_in serveraddr, clientaddr;
307 char client_ipaddr[INET_ADDRSTRLEN];
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;
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;
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;
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));
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;
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;
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);
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;
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);
366 _ERR("The callback not exists");
369 mdg_clean_channel(channel);
374 _ERR("Unknown Event");
382 static int _enabler_proxy_init(mdg_manager_s *handle)
384 GError *error = NULL;
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 */
394 _ERR("Failed to connect to the D-BUS daemon [%s]", error->message);
397 return MDG_ERROR_IO_ERROR;
401 handle->system_bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
402 if (NULL == handle->system_bus) {
403 /* LCOV_EXCL_START */
405 _ERR("Failed to connect to system bus [%s]", error->message);
408 return MDG_ERROR_IO_ERROR;
412 name = g_dbus_connection_get_unique_name(handle->system_bus);
413 _DBG("Unique dbus name %s", name);
415 enabler_call_add_ref_sync(handle->enabler_proxy, name, &ret, NULL, &error);
417 /* LCOV_EXCL_START */
418 _ERR("Failed to add reference [%s]", error->message);
420 return MDG_ERROR_IO_ERROR;
427 /* LCOV_EXCL_START */
428 static void _dbus_name_owner_notify(GObject *object, GParamSpec *pspec,
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);
436 LOGD("Name owner notify [%s]", name_owner);
438 if (NULL == name_owner)
439 gdbus_deinitialize(handle);
444 static int _group_proxy_init(mdg_manager_s *handle)
447 GError *error = NULL;
449 handle->group_proxy = group_proxy_new_for_bus_sync(
451 G_DBUS_PROXY_FLAGS_NONE,
456 if (NULL == handle->group_proxy) {
457 /* LCOV_EXCL_START */
459 _ERR("Failed to connect to the D-BUS daemon [%s]", error->message);
462 return MDG_ERROR_IO_ERROR;
466 id = g_signal_connect(handle->group_proxy, "notify::g-name-owner",
467 G_CALLBACK(_dbus_name_owner_notify), handle);
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;
477 g_signal_connect(handle->group_proxy,
478 "event", G_CALLBACK(__event_cb), handle);
480 return MDG_ERROR_NONE;
483 static void _group_proxy_deinit(mdg_manager_s *handle)
485 g_object_unref(handle->group_proxy);
486 handle->group_proxy = NULL;
489 static void _enabler_proxy_deinit(mdg_manager_s *handle)
491 g_object_unref(handle->system_bus);
492 handle->system_bus = NULL;
494 g_object_unref(handle->enabler_proxy);
495 handle->enabler_proxy = NULL;
498 int gdbus_initialize(mdg_manager_s *handle)
500 int ret = MDG_ERROR_NONE;
502 _group_proxy_init(handle);
503 _enabler_proxy_init(handle);
505 if (handle->group_proxy == NULL)
506 ret = -1; /* LCOV_EXCL_LINE */
508 if (handle->enabler_proxy == NULL)
509 ret = -1; /* LCOV_EXCL_LINE */
514 int gdbus_deinitialize(mdg_manager_s *handle)
516 int ret = MDG_ERROR_NONE;
518 _group_proxy_deinit(handle);
519 _enabler_proxy_deinit(handle);