2 * Copyright (c) 2017 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.
18 #include "mesh-util.h"
19 #include "mesh-gdbus.h"
20 #include "mesh-request.h"
24 static GDBusProxy *_gproxy_connman = NULL;
25 static GDBusProxy *_gproxy_connman_mesh = NULL;
26 static GDBusProxy *_gproxy_connman_technology = NULL;
27 static GDBusProxy *_gproxy_connman_ethernet = NULL;
29 static int _meshd_close_gdbus_call(mesh_service *service);
30 static int _mesh_gdbus_get_mesh_network_property(mesh_service *service,
31 const gchar* object_path, mesh_network_info_s *result);
33 static int __channel_to_frequency(int channel, enum nl80211_band band)
39 case NL80211_BAND_2GHZ:
42 else if (channel < 14)
43 return 2407 + channel * 5;
45 case NL80211_BAND_5GHZ:
46 if (channel >= 182 && channel <= 196)
47 return 4000 + channel * 5;
49 return 5000 + channel * 5;
59 static int __frequency_to_channel(int freq)
64 return (freq - 2407) / 5;
65 else if (freq >= 4910 && freq <= 4980)
66 return (freq - 4000) / 5;
67 else if (freq <= 45000)
68 return (freq - 5000) / 5;
69 else if (freq >= 58320 && freq <= 64800)
70 return (freq - 56160) / 2160;
75 static GDBusProxy *_proxy_get_connman(mesh_service *service)
77 GDBusProxy *proxy = NULL;
78 meshd_check_null_ret_error("service", service, NULL);
80 if (NULL == _gproxy_connman) {
81 proxy = g_dbus_proxy_new_sync(service->connection,
82 G_DBUS_PROXY_FLAGS_NONE, NULL,
85 CONNMAN_INTERFACE_MANAGER,
88 proxy = _gproxy_connman;
93 static GDBusProxy *_proxy_get_connman_mesh(mesh_service *service)
95 GDBusProxy *proxy = NULL;
96 meshd_check_null_ret_error("service", service, NULL);
98 if (NULL == _gproxy_connman_mesh) {
99 proxy = g_dbus_proxy_new_sync(service->connection,
100 G_DBUS_PROXY_FLAGS_NONE, NULL,
102 CONNMAN_OBJECT_PATH_MESH,
103 CONNMAN_INTERFACE_MESH,
106 proxy = _gproxy_connman_mesh;
111 static GDBusProxy *_proxy_get_connman_ethernet(mesh_service *service)
113 GDBusProxy *proxy = NULL;
114 meshd_check_null_ret_error("service", service, NULL);
116 if (NULL == _gproxy_connman_ethernet) {
117 proxy = g_dbus_proxy_new_sync(service->connection,
118 G_DBUS_PROXY_FLAGS_NONE, NULL,
119 CONNMAN_SERVER_NAME, /* Name */
120 "/net/connman/technology/ethernet", /* Object Path */
121 CONNMAN_INTERFACE_TECH, /* interface Name */
124 proxy = _gproxy_connman_ethernet;
129 static GDBusProxy *_proxy_get_connman_technology(mesh_service *service)
131 GDBusProxy *proxy = NULL;
132 meshd_check_null_ret_error("service", service, NULL);
134 if (NULL == _gproxy_connman_technology) {
135 proxy = g_dbus_proxy_new_sync(service->connection,
136 G_DBUS_PROXY_FLAGS_NONE, NULL,
138 CONNMAN_OBJECT_PATH_TECH_MESH,
139 CONNMAN_INTERFACE_TECH,
142 proxy = _gproxy_connman_technology;
147 static void _dbus_name_owner_notify(GObject *object, GParamSpec *pspec,
150 GDBusProxy *proxy = G_DBUS_PROXY(object);
151 gchar *name_owner = g_dbus_proxy_get_name_owner(proxy);
152 mesh_service *service = (mesh_service*)user_data;
156 if (NULL == name_owner) {
157 MESH_LOGE("name_owner is not exists !");
158 _meshd_close_gdbus_call(service);
164 static int _meshd_create_gdbus_call(mesh_service *service)
167 GError *error = NULL;
170 return MESHD_ERROR_INVALID_PARAMETER;
172 if (NULL != service->connection)
173 return MESHD_ERROR_ALREADY_REGISTERED;
175 service->connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
176 if (service->connection == NULL) {
178 MESH_LOGE("Failed to connect to the D-BUS daemon [%s]", error->message);
181 return MESHD_ERROR_IO_ERROR;
184 id = g_signal_connect(service->connection, "notify::g-name-owner",
185 G_CALLBACK(_dbus_name_owner_notify), service);
187 MESH_LOGE("g_signal_connect() Fail");
188 g_object_unref(service->connection);
189 service->connection = NULL;
190 return MESHD_ERROR_IO_ERROR;
193 return MESHD_ERROR_NONE;
196 static int _meshd_close_gdbus_call(mesh_service *service)
198 /* CHECK: is connection ref count required? */
199 g_object_unref(service->connection);
200 service->connection = NULL;
202 return MESHD_ERROR_NONE;
205 static void _meshd_signal_handler(GDBusConnection *connection,
206 const gchar *sender_name, const gchar *object_path, const gchar *interface_name,
207 const gchar *signal_name, GVariant *parameters, gpointer user_data)
209 mesh_service *service = (mesh_service*)user_data;
210 mesh_network_info_s network_info = { 0, 0, 0, 0, 0 };
211 int ret = MESHD_ERROR_NONE;
213 meshd_check_null_ret("user_data", user_data);
215 NOTUSED(sender_name);
216 NOTUSED(interface_name);
218 MESH_LOGD("signal received = %s", signal_name);
219 if (0 == g_strcmp0(signal_name, "ScanDone")) {
220 /* TODO: Handle event */
221 mesh_notify_scan_done();
222 } else if (0 == g_strcmp0(signal_name, "PropertyChanged")) {
223 const gchar* var = NULL;
225 GVariant *variant = NULL;
226 meshd_connection_state_e state = MESHD_CONNECTION_STATE_DISCONNECTED;
228 if (NULL == parameters) {
229 MESH_LOGE("Unexpected parameter");
233 g_variant_get(parameters, "(sv)", &key, &variant);
234 if (NULL == variant) {
235 MESH_LOGE("Invalid variant");
240 var = g_variant_get_string(variant, NULL);
241 MESH_LOGD(" %s [%s]", key, var);
242 MESH_LOGD(" %s", object_path);
244 ret = _mesh_gdbus_get_mesh_network_property(service, object_path, &network_info);
245 if (MESHD_ERROR_NONE != ret)
246 MESH_LOGE("Cannot get valid network property !");
248 if (g_strcmp0("association", var) == 0) {
249 /* Joined mesh network */
250 state = MESHD_CONNECTION_STATE_ASSOCIATION;
251 } else if (g_strcmp0("configuration", var) == 0) {
252 /* Trying to get IP address */
253 state = MESHD_CONNECTION_STATE_CONFIGURATION;
254 } else if (g_strcmp0("ready", var) == 0 || g_strcmp0("online", var) == 0) {
255 /* IP address is obtained */
256 state = MESHD_CONNECTION_STATE_CONNECTED;
257 } else if (g_strcmp0("disconnect", var) == 0 || g_strcmp0("failure", var) == 0) {
258 state = MESHD_CONNECTION_STATE_DISCONNECTED;
260 MESH_LOGE(" Unhandled state !");
261 g_free(network_info.mesh_id);
262 g_free(network_info.bssid);
266 mesh_notify_connection_state(network_info.mesh_id, network_info.bssid,
267 network_info.channel, network_info.security, state);
269 g_free(network_info.mesh_id);
270 g_free(network_info.bssid);
274 static void _meshd_subscribe_event(mesh_service *service)
278 meshd_check_null_ret("service", service);
280 id = g_dbus_connection_signal_subscribe(
281 (GDBusConnection *)service->connection,
282 CONNMAN_SERVER_NAME, CONNMAN_INTERFACE_MANAGER,
283 "ScanDone", "/", NULL,
284 G_DBUS_CALL_FLAGS_NONE, _meshd_signal_handler, service, NULL);
286 MESH_LOGE("g_dbus_connection_signal_subscribe(ScanDone) Fail(%d)", errno);
289 service->dbus_sub_ids = g_list_append(service->dbus_sub_ids, GUINT_TO_POINTER(id));
290 MESH_LOGD("[Signal subscribe] : ScanDone (%d)", id);
292 /* To monitor mesh profiles */
293 id = g_dbus_connection_signal_subscribe(
294 (GDBusConnection *)service->connection,
296 CONNMAN_INTERFACE_MESH,
300 G_DBUS_CALL_FLAGS_NONE, _meshd_signal_handler, service, NULL);
302 MESH_LOGE("g_dbus_connection_signal_subscribe(ScanDone) Fail(%d)", errno);
305 service->dbus_sub_ids = g_list_append(service->dbus_sub_ids, GUINT_TO_POINTER(id));
306 MESH_LOGD("[Signal subscribe] : PropertyChanged (%d)", id);
308 /* End of subscription */
311 static void _on_unsubscribe_ids(gpointer data, gpointer user_data)
313 unsigned int id = GPOINTER_TO_UINT(data);
314 mesh_service *service = (mesh_service*)user_data;
316 MESH_LOGD("[Signal unsubscribe] : %d", id);
317 g_dbus_connection_signal_unsubscribe(
318 (GDBusConnection *)service->connection, id);
321 static void _meshd_unsubscribe_event(mesh_service *service)
323 meshd_check_null_ret("service", service);
325 g_list_foreach(service->dbus_sub_ids, _on_unsubscribe_ids, service);
327 g_list_free(service->dbus_sub_ids);
328 service->dbus_sub_ids = NULL;
331 int meshd_dbus_start(mesh_service *service)
335 rv = _meshd_create_gdbus_call(service);
336 if (MESHD_ERROR_NONE != rv)
339 service->ca = g_cancellable_new();
341 /* Create all required proxies here */
342 _gproxy_connman = _proxy_get_connman(service);
343 meshd_check_null_ret_error("_gproxy_connman", _gproxy_connman,
344 MESHD_ERROR_IO_ERROR);
345 g_dbus_proxy_set_default_timeout(
346 G_DBUS_PROXY(_gproxy_connman), MESH_DBUS_PROXY_TIMEOUT);
348 _gproxy_connman_mesh = _proxy_get_connman_mesh(service);
349 meshd_check_null_ret_error("_gproxy_connman_mesh", _gproxy_connman_mesh,
350 MESHD_ERROR_IO_ERROR);
351 g_dbus_proxy_set_default_timeout(
352 G_DBUS_PROXY(_gproxy_connman_mesh), MESH_DBUS_PROXY_TIMEOUT);
354 _gproxy_connman_technology = _proxy_get_connman_technology(service);
355 meshd_check_null_ret_error("_gproxy_connman_technology", _gproxy_connman_technology,
356 MESHD_ERROR_IO_ERROR);
357 g_dbus_proxy_set_default_timeout(
358 G_DBUS_PROXY(_gproxy_connman_technology), MESH_DBUS_PROXY_TIMEOUT);
360 _gproxy_connman_ethernet = _proxy_get_connman_ethernet(service);
361 meshd_check_null_ret_error("_gproxy_connman_ethernet", _gproxy_connman_ethernet,
362 MESHD_ERROR_IO_ERROR);
363 g_dbus_proxy_set_default_timeout(
364 G_DBUS_PROXY(_gproxy_connman_ethernet), MESH_DBUS_PROXY_TIMEOUT);
366 /* Subscribe events */
367 _meshd_subscribe_event(service);
369 return MESHD_ERROR_NONE;
372 int meshd_dbus_stop(mesh_service *service)
377 return MESHD_ERROR_INVALID_PARAMETER;
379 /* Unsubscribe events */
380 _meshd_unsubscribe_event(service);
382 /* Unref all proxies here */
383 if (_gproxy_connman) {
384 g_object_unref(_gproxy_connman);
385 _gproxy_connman = NULL;
387 if (_gproxy_connman_mesh) {
388 g_object_unref(_gproxy_connman_mesh);
389 _gproxy_connman_mesh = NULL;
391 if (_gproxy_connman_technology) {
392 g_object_unref(_gproxy_connman_technology);
393 _gproxy_connman_technology = NULL;
396 g_cancellable_cancel(service->ca);
397 g_object_unref(service->ca);
400 rv = _meshd_close_gdbus_call(service);
404 int mesh_gdbus_create_mesh_interface(mesh_service *service)
406 int ret = MESHD_ERROR_NONE;
407 GVariant *variant = NULL;
408 GError *error = NULL;
409 GVariant *var_dict = NULL;
411 mesh_interface_s *info = NULL;
413 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
414 meshd_check_null_ret_error("connection", service->connection,
415 MESHD_ERROR_INVALID_PARAMETER);
416 meshd_check_null_ret_error("_gproxy_connman_technology",
417 _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
419 info = service->interface_info;
421 g_variant_dict_init(&dict, NULL);
422 g_variant_dict_insert(&dict, "Ifname", "s", info->mesh_interface);
423 g_variant_dict_insert(&dict, "ParentIfname", "s", info->base_interface);
424 g_variant_dict_insert(&dict, "BridgeIfname", "s", info->bridge_interface);
425 var_dict = g_variant_dict_end(&dict);
427 variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
428 g_variant_new("(sv)", "MeshInterfaceAdd", var_dict),
429 G_DBUS_CALL_FLAGS_NONE,
432 MESH_LOGD("Successfully requested. [MeshInterfaceAdd]");
434 ret = MESHD_ERROR_IO_ERROR;
435 MESH_LOGE("Failed DBus call [%s]", error->message);
437 /* Interface not exists */
438 if (g_strrstr(error->message, "No such device"))
439 ret = MESHD_ERROR_INVALID_PARAMETER;
446 int mesh_gdbus_remove_mesh_interface(mesh_service *service)
448 int ret = MESHD_ERROR_NONE;
449 GVariant *variant = NULL;
450 GError *error = NULL;
451 GVariant *var_dict = NULL;
453 mesh_interface_s *info = NULL;
455 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
456 meshd_check_null_ret_error("connection", service->connection,
457 MESHD_ERROR_INVALID_PARAMETER);
458 meshd_check_null_ret_error("_gproxy_connman_technology",
459 _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
461 info = service->interface_info;
463 g_variant_dict_init(&dict, NULL);
464 g_variant_dict_insert(&dict, "Ifname", "s", info->mesh_interface);
465 var_dict = g_variant_dict_end(&dict);
467 variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
468 g_variant_new("(sv)", "MeshInterfaceRemove", var_dict),
469 G_DBUS_CALL_FLAGS_NONE,
472 MESH_LOGD("Successfully requested. [MeshInterfaceRemove]");
474 ret = MESHD_ERROR_IO_ERROR;
475 MESH_LOGE("Failed DBus call [%s]", error->message);
477 /* Interface not exists (Not created yet) */
478 if (g_strrstr(error->message, "No such device"))
479 ret = MESHD_ERROR_NONE;
486 int mesh_gdbus_mesh_scan(mesh_service *service)
488 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
489 meshd_check_null_ret_error("connection", service->connection,
490 MESHD_ERROR_INVALID_PARAMETER);
491 meshd_check_null_ret_error("_gproxy_connman_technology",
492 _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
494 g_dbus_proxy_call(_gproxy_connman_technology, "Scan",
496 G_DBUS_CALL_FLAGS_NONE,
497 -1, NULL, NULL, NULL);
499 MESH_LOGD("Successfully requested. [Scan]");
501 return MESHD_ERROR_NONE;
504 int mesh_gdbus_mesh_specific_scan(mesh_service *service, gchar *mesh_id, gint channel)
506 GVariant *variant = NULL;
507 GError *error = NULL;
508 GVariant *var_dict = NULL;
511 enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
512 gushort freq = __channel_to_frequency(channel, band);
514 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
515 meshd_check_null_ret_error("connection", service->connection,
516 MESHD_ERROR_INVALID_PARAMETER);
517 meshd_check_null_ret_error("_gproxy_connman_technology",
518 _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
520 g_variant_dict_init(&dict, NULL);
521 g_variant_dict_insert(&dict, "Name", "s", mesh_id);
522 g_variant_dict_insert(&dict, "Frequency", "q", freq);
523 var_dict = g_variant_dict_end(&dict);
525 variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
526 g_variant_new("(sv)", "MeshSpecificScan", var_dict),
527 G_DBUS_CALL_FLAGS_NONE,
530 MESH_LOGD("Successfully requested. [MeshSpecificScan]");
532 MESH_LOGE("Failed DBus call [%s]", error->message);
534 return MESHD_ERROR_IO_ERROR;
537 return MESHD_ERROR_NONE;
540 int mesh_gdbus_mesh_cancel_scan(mesh_service *service)
542 int ret = MESHD_ERROR_NONE;
543 GVariant *variant = NULL;
544 GError *error = NULL;
545 GVariant *var_dict = NULL;
548 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
549 meshd_check_null_ret_error("connection", service->connection,
550 MESHD_ERROR_INVALID_PARAMETER);
551 meshd_check_null_ret_error("_gproxy_connman_technology",
552 _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
554 g_variant_dict_init(&dict, NULL);
555 var_dict = g_variant_dict_end(&dict);
557 variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
558 g_variant_new("(sv)", "AbortScan", var_dict),
559 G_DBUS_CALL_FLAGS_NONE,
562 MESH_LOGD("Successfully requested. [AbortScan]");
564 ret = MESHD_ERROR_IO_ERROR;
565 MESH_LOGE("Failed DBus call [%s]", error->message);
567 /* Scan is not in progress */
568 if (g_strrstr(error->message, "Already exists"))
569 ret = MESHD_ERROR_NONE;
577 static void _on_scan_result_destroy(gpointer data)
579 mesh_scan_result_s *scan_item = (mesh_scan_result_s *)data;
582 g_free(scan_item->mesh_id);
583 g_free(scan_item->bssid);
584 g_free(scan_item->object_path);
589 static void _on_peer_info_destroy(gpointer data)
591 mesh_peer_info_s *peer = (mesh_peer_info_s *)data;
594 g_free(peer->address);
598 static void _get_joined_network(mesh_service *service, GVariant *variant)
600 GVariantIter *peer = NULL;
601 GVariantIter *property = NULL;
603 GVariant *val = NULL;
606 const gchar* obj_path = NULL;
607 const gchar* buf = NULL;
609 g_variant_get(variant, "(a(oa{sv}))", &peer);
610 while ((child = g_variant_iter_next_value(peer))) {
611 mesh_network_info_s *joined_info = NULL;
612 gboolean valid_state = TRUE;
614 g_variant_get(child, "(oa{sv})", &obj_path, &property);
615 MESH_LOGD(" Object: [%s]", obj_path);
616 if (NULL == obj_path) {
617 MESH_LOGE("Null object");
621 /* Create an information structure for joined network */
622 joined_info = g_try_new0(mesh_network_info_s, 1);
623 if (NULL == joined_info) {
624 MESH_LOGE("Failed to allocate !");
628 while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
629 if (strcasecmp(key, "Name") == 0) {
630 buf = g_variant_get_string(val, &len);
631 joined_info->mesh_id = g_strdup(buf);
632 } else if (strcasecmp(key, "BSSID") == 0) {
633 buf = g_variant_get_string(val, &len);
634 joined_info->bssid = g_strdup(buf);
635 } else if (strcasecmp(key, "State") == 0) {
636 buf = g_variant_get_string(val, &len);
637 MESH_LOGD(" State : %s", buf);
639 /* Skip ignorable state */
640 if (g_strcmp0(buf, "idle") == 0
641 || g_strcmp0(buf, "disconnect") == 0
642 || g_strcmp0(buf, "failure") == 0) {
645 } else if (g_strcmp0(buf, "association") == 0) {
646 joined_info->state = MESHD_CONNECTION_STATE_ASSOCIATION;
647 } else if (g_strcmp0(buf, "configuration") == 0) {
648 joined_info->state = MESHD_CONNECTION_STATE_CONFIGURATION;
649 } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
650 joined_info->state = MESHD_CONNECTION_STATE_CONNECTED;
652 } else if (strcasecmp(key, "Security") == 0) {
653 buf = g_variant_get_string(val, &len);
654 if (g_strcmp0("sae", buf) == 0)
655 joined_info->security = MESHD_SECURITY_SAE;
657 joined_info->security = MESHD_SECURITY_NONE;
658 } else if (strcasecmp(key, "Frequency") == 0) {
659 joined_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
663 /* Skip ignorable state */
664 if (FALSE == valid_state) {
665 g_free(joined_info->mesh_id);
666 g_free(joined_info->bssid);
670 MESH_LOGD(" Mesh ID : %s", joined_info->mesh_id);
671 MESH_LOGD(" BSSID : %s", joined_info->bssid);
672 MESH_LOGD(" Channel : %d", joined_info->channel);
673 MESH_LOGD(" Security : %s",
674 (MESHD_SECURITY_SAE == joined_info->security) ? "SAE" : "NONE");
675 service->joined_network = joined_info;
677 g_variant_iter_free(property);
679 /* If found, stop loop iteration */
682 g_variant_iter_free(peer);
685 static void _get_mesh_peers(mesh_service *service, GVariant *variant)
687 GVariantIter *peer = NULL;
688 GVariantIter *property = NULL;
690 GVariant *val = NULL;
693 const gchar* obj_path = NULL;
695 g_variant_get(variant, "(a(oa{sv}))", &peer);
696 while ((child = g_variant_iter_next_value(peer))) {
697 mesh_scan_result_s *scan_info = NULL;
699 scan_info = g_try_new0(mesh_scan_result_s, 1);
700 if (NULL == scan_info) {
701 MESH_LOGE("Failed to allocate !");
705 g_variant_get(child, "(oa{sv})", &obj_path, &property);
706 if (NULL == obj_path) {
707 MESH_LOGE("Null object");
711 MESH_LOGD(" Obj path : [%s]", obj_path);
712 scan_info->object_path = g_strdup(obj_path);
714 while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
715 if (strcasecmp(key, "Name") == 0) {
716 const char *buf = g_variant_get_string(val, &len);
717 scan_info->mesh_id = g_strdup(buf);
718 MESH_LOGD(" Mesh ID : %s", scan_info->mesh_id);
719 } else if (strcasecmp(key, "BSSID") == 0) {
720 const char *buf = g_variant_get_string(val, &len);
721 scan_info->bssid = g_strdup(buf);
722 MESH_LOGD(" BSSID : %s", scan_info->bssid);
723 } else if (strcasecmp(key, "State") == 0) {
724 const char *buf = g_variant_get_string(val, &len);
725 MESH_LOGD(" State : %s", buf);
727 if (g_strcmp0(buf, "idle") == 0
728 || g_strcmp0(buf, "disconnect") == 0
729 || g_strcmp0(buf, "failure") == 0) {
730 scan_info->state = MESHD_CONNECTION_STATE_DISCONNECTED;
731 } else if (g_strcmp0(buf, "association") == 0) {
732 scan_info->state = MESHD_CONNECTION_STATE_ASSOCIATION;
733 } else if (g_strcmp0(buf, "configuration") == 0) {
734 scan_info->state = MESHD_CONNECTION_STATE_CONFIGURATION;
735 } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
736 scan_info->state = MESHD_CONNECTION_STATE_CONNECTED;
738 } else if (strcasecmp(key, "Security") == 0) {
739 const char *buf = g_variant_get_string(val, &len);
740 MESH_LOGD(" Security : %s", buf);
741 if (g_strcmp0("sae", buf) == 0)
742 scan_info->security = MESHD_SECURITY_SAE;
744 scan_info->security = MESHD_SECURITY_NONE;
745 } else if (strcasecmp(key, "Frequency") == 0) {
746 scan_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
747 MESH_LOGD(" Channel : %d", scan_info->channel);
748 } else if (strcasecmp(key, "Favorite") == 0) {
749 const char *buf = g_variant_get_string(val, &len);
750 MESH_LOGD(" Favorite : %s", buf);
751 } else if (strcasecmp(key, "Strength") == 0) {
752 scan_info->rssi = (gint)g_variant_get_byte(val);
753 MESH_LOGD(" RSSI : %d", scan_info->rssi);
757 service->scanned_mesh_network =
758 g_list_prepend(service->scanned_mesh_network, scan_info);
760 g_variant_iter_free(property);
762 g_variant_iter_free(peer);
765 static void _get_connected_mesh_peers(mesh_service *service, GVariant *variant)
767 GVariantIter *peer = NULL;
768 GVariant *val = NULL;
771 GVariant *dict = NULL;
773 g_variant_get(variant, "(a(a{sv}))", &peer);
774 while ((child = g_variant_iter_next_value(peer))) {
775 mesh_peer_info_s *peer_info = NULL;
777 peer_info = g_try_new0(mesh_peer_info_s, 1);
778 if (NULL == peer_info) {
779 MESH_LOGE("Failed to allocate !");
783 /* a{sv} <- (a{sv}) */
784 dict = g_variant_get_child_value(child, 0);
785 val = g_variant_lookup_value(dict, "PeerAddress", NULL);
787 const char *buf = g_variant_get_string(val, &len);
788 peer_info->address = g_strdup(buf);
789 MESH_LOGD(" Address : %s", peer_info->address);
790 g_variant_unref(val);
792 MESH_LOGE("Unable to get address !");
797 service->connected_mesh_peers =
798 g_list_prepend(service->connected_mesh_peers, peer_info);
800 g_variant_iter_free(peer);
803 int mesh_gdbus_get_mesh_networks(mesh_service *service)
805 GVariant *variant = NULL;
806 GError *error = NULL;
808 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
809 meshd_check_null_ret_error("connection", service->connection,
810 MESHD_ERROR_INVALID_PARAMETER);
811 meshd_check_null_ret_error("_gproxy_connman",
812 _gproxy_connman, MESHD_ERROR_IO_ERROR);
814 variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
816 G_DBUS_CALL_FLAGS_NONE,
819 MESH_LOGD("Successfully requested. [GetMeshPeers]");
821 if (service->scanned_mesh_network) {
822 g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
823 service->scanned_mesh_network = NULL;
826 _get_mesh_peers(service, variant);
828 /* List item is saved with reversed order for efficiency. */
829 service->scanned_mesh_network =
830 g_list_reverse(service->scanned_mesh_network);
832 MESH_LOGE("Failed DBus call [%s]", error->message);
834 return MESHD_ERROR_IO_ERROR;
837 return MESHD_ERROR_NONE;
840 int mesh_gdbus_get_joined_mesh_network(mesh_service *service)
842 GVariant *variant = NULL;
843 GError *error = NULL;
845 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
846 meshd_check_null_ret_error("connection", service->connection,
847 MESHD_ERROR_INVALID_PARAMETER);
848 meshd_check_null_ret_error("_gproxy_connman",
849 _gproxy_connman, MESHD_ERROR_IO_ERROR);
851 variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
853 G_DBUS_CALL_FLAGS_NONE,
856 MESH_LOGD("Successfully requested. [GetMeshPeers]");
858 if (service->joined_network) {
859 g_free(service->joined_network->mesh_id);
860 g_free(service->joined_network->bssid);
861 g_free(service->joined_network);
862 service->joined_network = NULL;
865 _get_joined_network(service, variant);
867 MESH_LOGE("Failed DBus call [%s]", error->message);
869 return MESHD_ERROR_IO_ERROR;
872 return MESHD_ERROR_NONE;
875 int mesh_gdbus_get_connected_peers(mesh_service *service)
877 GVariant *variant = NULL;
878 GError *error = NULL;
880 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
881 meshd_check_null_ret_error("connection", service->connection,
882 MESHD_ERROR_INVALID_PARAMETER);
883 meshd_check_null_ret_error("_gproxy_connman",
884 _gproxy_connman, MESHD_ERROR_IO_ERROR);
886 variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetConnectedMeshPeers",
888 G_DBUS_CALL_FLAGS_NONE,
891 MESH_LOGD("Successfully requested. [GetConnectedMeshPeers]");
893 if (service->connected_mesh_peers) {
894 g_list_free_full(service->connected_mesh_peers, _on_peer_info_destroy);
895 service->connected_mesh_peers = NULL;
898 _get_connected_mesh_peers(service, variant);
900 /* List item is saved with reversed order for efficiency. */
901 service->connected_mesh_peers =
902 g_list_reverse(service->connected_mesh_peers);
904 MESH_LOGE("Failed DBus call [%s]", error->message);
906 return MESHD_ERROR_IO_ERROR;
909 return MESHD_ERROR_NONE;
912 static void _get_mesh_property(GVariant *variant, mesh_network_info_s *result)
914 GVariantIter *property = NULL;
916 GVariant *val = NULL;
919 MESH_LOGD("Type [%s]", g_variant_get_type_string(variant));
921 g_variant_get(variant, "(a{sv})", &property);
923 while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
924 if (strcasecmp(key, "Name") == 0) {
925 const char *buf = g_variant_get_string(val, &len);
926 result->mesh_id = g_strdup(buf);
927 MESH_LOGD(" Mesh ID : %s", result->mesh_id);
928 } else if (strcasecmp(key, "BSSID") == 0) {
929 const char *buf = g_variant_get_string(val, &len);
930 result->bssid = g_strdup(buf);
931 MESH_LOGD(" BSSID : %s", result->bssid);
932 } else if (strcasecmp(key, "State") == 0) {
933 const char *buf = g_variant_get_string(val, &len);
934 MESH_LOGD(" State : %s", buf);
936 if (g_strcmp0(buf, "idle") == 0
937 || g_strcmp0(buf, "disconnect") == 0
938 || g_strcmp0(buf, "failure") == 0) {
939 result->state = MESHD_CONNECTION_STATE_DISCONNECTED;
940 } else if (g_strcmp0(buf, "association") == 0) {
941 result->state = MESHD_CONNECTION_STATE_ASSOCIATION;
942 } else if (g_strcmp0(buf, "configuration") == 0) {
943 result->state = MESHD_CONNECTION_STATE_CONFIGURATION;
944 } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
945 result->state = MESHD_CONNECTION_STATE_CONNECTED;
947 } else if (strcasecmp(key, "Security") == 0) {
948 const char *buf = g_variant_get_string(val, &len);
949 MESH_LOGD(" Security : %s", buf);
950 if (g_strcmp0("sae", buf) == 0)
951 result->security = MESHD_SECURITY_SAE;
953 result->security = MESHD_SECURITY_NONE;
954 } else if (strcasecmp(key, "Frequency") == 0) {
955 result->channel = __frequency_to_channel(g_variant_get_uint16(val));
956 MESH_LOGD(" Channel : %d", result->channel);
957 } else if (strcasecmp(key, "Favorite") == 0) {
958 const char *buf = g_variant_get_string(val, &len);
959 MESH_LOGD(" Favorite : %s", buf);
960 } else if (strcasecmp(key, "Strength") == 0) {
961 gint rssi = (gint)g_variant_get_byte(val);
962 MESH_LOGD(" RSSI : %d", rssi);
965 g_variant_iter_free(property);
968 static int _mesh_gdbus_get_mesh_network_property(mesh_service *service,
969 const gchar* object_path, mesh_network_info_s *result)
971 GVariant *variant = NULL;
972 GError *error = NULL;
974 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
975 meshd_check_null_ret_error("connection", service->connection,
976 MESHD_ERROR_INVALID_PARAMETER);
977 meshd_check_null_ret_error("result", result, MESHD_ERROR_INVALID_PARAMETER);
979 variant = g_dbus_connection_call_sync(service->connection,
982 CONNMAN_INTERFACE_MESH,
985 G_DBUS_CALL_FLAGS_NONE,
988 MESH_LOGD("Successfully requested. [GetProperties]");
991 _get_mesh_property(variant, result);
993 LOGE("Failed DBus call [%s]", error->message);
995 return MESHD_ERROR_IO_ERROR;
998 return MESHD_ERROR_NONE;
1001 int mesh_gdbus_create_network(mesh_service *service, gchar *mesh_id,
1002 gint channel, meshd_security_type_e sec)
1004 GVariant *variant = NULL;
1005 GError *error = NULL;
1006 GVariant *var_dict = NULL;
1007 GVariantBuilder builder;
1008 const gchar* security = (MESHD_SECURITY_SAE == sec) ? "sae" : "none";
1010 enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
1011 gushort freq = __channel_to_frequency(channel, band);
1013 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1014 meshd_check_null_ret_error("connection", service->connection,
1015 MESHD_ERROR_INVALID_PARAMETER);
1016 meshd_check_null_ret_error("_gproxy_connman_technology",
1017 _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
1019 g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
1020 g_variant_builder_open(&builder, G_VARIANT_TYPE("a{sv}"));
1022 g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1023 g_variant_builder_add(&builder, "s", "Name");
1024 g_variant_builder_add(&builder, "v", g_variant_new_string(mesh_id));
1025 g_variant_builder_close(&builder); /* {sv} */
1027 g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1028 g_variant_builder_add(&builder, "s", "Frequency");
1029 g_variant_builder_add(&builder, "v", g_variant_new_uint16(freq));
1030 g_variant_builder_close(&builder); /* {sv} */
1032 g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1033 g_variant_builder_add(&builder, "s", "Security");
1034 g_variant_builder_add(&builder, "v", g_variant_new_string(security));
1035 g_variant_builder_close(&builder); /* {sv} */
1037 g_variant_builder_close(&builder); /* a{sv} */
1039 var_dict = g_variant_builder_end(&builder);
1041 variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
1042 g_variant_new("(sv)", "MeshCreateNetwork", var_dict),
1043 G_DBUS_CALL_FLAGS_NONE,
1046 MESH_LOGD("Successfully requested. [MeshCreateNetwork]");
1048 MESH_LOGE("Failed DBus call [%s]", error->message);
1049 g_error_free(error);
1050 return MESHD_ERROR_IO_ERROR;
1053 return MESHD_ERROR_NONE;
1056 int mesh_gdbus_set_passphrase(mesh_service *service, mesh_scan_result_s *info, gchar *passphrase)
1058 GVariant *variant = NULL;
1059 GError *error = NULL;
1061 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1062 meshd_check_null_ret_error("passphrase", passphrase, MESHD_ERROR_INVALID_PARAMETER);
1064 variant = g_dbus_connection_call_sync(service->connection,
1065 CONNMAN_SERVER_NAME,
1067 CONNMAN_INTERFACE_MESH,
1069 g_variant_new("(sv)", "Passphrase", g_variant_new_string(passphrase)),
1071 G_DBUS_CALL_FLAGS_NONE,
1074 MESH_LOGD("Successfully requested. [SetProperty]");
1076 LOGE("Failed DBus call [%s]", error->message);
1077 g_error_free(error);
1078 return MESHD_ERROR_IO_ERROR;
1081 return MESHD_ERROR_NONE;
1085 static void on_response_connect_network(GObject *source_object,
1086 GAsyncResult *res, gpointer user_data)
1088 int ret = MESHD_ERROR_NONE;
1089 GError *error = NULL;
1090 GVariant *variant = NULL;
1094 variant = g_dbus_connection_call_finish(
1095 G_DBUS_CONNECTION(source_object), res, &error);
1097 MESH_LOGD("Successfully requested. [Connect]");
1099 /* TODO: Unregister property change event */
1101 ret = MESHD_ERROR_IO_ERROR;
1102 LOGE("Failed DBus call [%s]", error->message);
1104 if (g_strrstr(error->message, "Already exists"))
1105 ret = MESHD_ERROR_ALREADY_REGISTERED;
1106 else if (g_strrstr(error->message, "In progress"))
1107 ret = MESHD_ERROR_IN_PROGRESS;
1109 ret = MESHD_ERROR_IO_ERROR;
1111 g_error_free(error);
1116 int mesh_gdbus_connect_network(mesh_service *service, mesh_scan_result_s *info)
1118 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1119 meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
1121 g_dbus_connection_call(service->connection,
1122 CONNMAN_SERVER_NAME,
1124 CONNMAN_INTERFACE_MESH,
1127 G_DBUS_CALL_FLAGS_NONE,
1129 NULL, /* G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED */
1131 MESH_LOGD("Successfully requested. [Connect]");
1133 return MESHD_ERROR_NONE;
1136 int mesh_gdbus_disconnect_network(mesh_service *service, mesh_scan_result_s *info)
1138 GVariant *variant = NULL;
1139 GError *error = NULL;
1141 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1142 meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
1144 variant = g_dbus_connection_call_sync(service->connection,
1145 CONNMAN_SERVER_NAME,
1147 CONNMAN_INTERFACE_MESH,
1150 G_DBUS_CALL_FLAGS_NONE,
1153 MESH_LOGD("Successfully requested. [Disconnect]");
1155 LOGE("Failed DBus call [%s]", error->message);
1156 g_error_free(error);
1157 return MESHD_ERROR_IO_ERROR;
1160 return MESHD_ERROR_NONE;
1163 int mesh_gdbus_remove_network(mesh_service *service, mesh_scan_result_s *info)
1165 GVariant *variant = NULL;
1166 GError *error = NULL;
1168 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1169 meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
1171 variant = g_dbus_connection_call_sync(service->connection,
1172 CONNMAN_SERVER_NAME,
1174 CONNMAN_INTERFACE_MESH,
1177 G_DBUS_CALL_FLAGS_NONE,
1180 MESH_LOGD("Successfully requested. [Remove]");
1182 LOGE("Failed DBus call [%s]", error->message);
1183 g_error_free(error);
1184 return MESHD_ERROR_IO_ERROR;
1187 return MESHD_ERROR_NONE;
1191 int mesh_gdbus_enable_ethernet_interface(mesh_service *service, bool state)
1193 int ret = MESHD_ERROR_NONE;
1194 GVariant *variant = NULL;
1195 GError *error = NULL;
1196 mesh_interface_s *info = NULL;
1198 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1199 meshd_check_null_ret_error("connection", service->connection,
1200 MESHD_ERROR_INVALID_PARAMETER);
1201 meshd_check_null_ret_error("_gproxy_connman_technology",
1202 _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
1204 info = service->interface_info;
1205 meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
1207 variant = g_dbus_proxy_call_sync(_gproxy_connman_ethernet, "SetProperty",
1208 g_variant_new("(sv)", "Powered", g_variant_new_boolean(state)),
1209 G_DBUS_CALL_FLAGS_NONE,
1212 MESH_LOGD("Successfully requested. [Powered]");
1214 ret = MESHD_ERROR_IO_ERROR;
1215 MESH_LOGE("Failed DBus call [%s]", error->message);
1217 /* Interface not exists (Not created yet) */
1218 if (g_strrstr(error->message, "No such device"))
1219 ret = MESHD_ERROR_NONE;
1220 g_error_free(error);
1226 int mesh_gdbus_set_mesh_gate(mesh_service *service)
1228 int ret = MESHD_ERROR_NONE;
1229 GVariant *variant = NULL;
1230 GError *error = NULL;
1231 GVariant *var_dict = NULL;
1233 mesh_interface_s *info = NULL;
1235 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1236 meshd_check_null_ret_error("connection", service->connection,
1237 MESHD_ERROR_INVALID_PARAMETER);
1238 meshd_check_null_ret_error("_gproxy_connman_technology",
1239 _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
1241 info = service->interface_info;
1243 g_variant_dict_init(&dict, NULL);
1244 g_variant_dict_insert(&dict, "GateAnnounce", "b", info->gate_announce);
1245 g_variant_dict_insert(&dict, "HWMPRootMode", "q", info->hwmp_root_mode);
1246 g_variant_dict_insert(&dict, "STP", "q", info->stp);
1247 var_dict = g_variant_dict_end(&dict);
1249 variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
1250 g_variant_new("(sv)", "SetMeshGate", var_dict),
1251 G_DBUS_CALL_FLAGS_NONE,
1254 MESH_LOGD("Successfully requested. [SetMeshGate]");
1256 ret = MESHD_ERROR_IO_ERROR;
1257 MESH_LOGE("Failed DBus call [%s]", error->message);
1259 /* Interface not exists */
1260 if (g_strrstr(error->message, "No such device"))
1261 ret = MESHD_ERROR_INVALID_PARAMETER;
1262 g_error_free(error);