5 * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 #include <connman/agent.h>
34 static bool connman_state_idle;
35 static dbus_bool_t sessionmode;
37 static DBusMessage *get_properties(DBusConnection *conn,
38 DBusMessage *msg, void *data)
41 DBusMessageIter array, dict;
42 dbus_bool_t offlinemode;
45 dbus_bool_t autoconnectmode;
50 reply = dbus_message_new_method_return(msg);
54 dbus_message_iter_init_append(reply, &array);
56 connman_dbus_dict_open(&array, &dict);
58 str = __connman_notifier_get_state();
59 connman_dbus_dict_append_basic(&dict, "State",
60 DBUS_TYPE_STRING, &str);
62 offlinemode = __connman_technology_get_offlinemode();
63 connman_dbus_dict_append_basic(&dict, "OfflineMode",
64 DBUS_TYPE_BOOLEAN, &offlinemode);
66 connman_dbus_dict_append_basic(&dict, "SessionMode",
70 autoconnectmode = __connman_service_get_auto_connect_mode();
71 connman_dbus_dict_append_basic(&dict, "AutoConnectMode",
76 connman_dbus_dict_close(&array, &dict);
81 static DBusMessage *set_property(DBusConnection *conn,
82 DBusMessage *msg, void *data)
84 DBusMessageIter iter, value;
90 if (!dbus_message_iter_init(msg, &iter))
91 return __connman_error_invalid_arguments(msg);
93 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
94 return __connman_error_invalid_arguments(msg);
96 dbus_message_iter_get_basic(&iter, &name);
97 dbus_message_iter_next(&iter);
99 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
100 return __connman_error_invalid_arguments(msg);
102 dbus_message_iter_recurse(&iter, &value);
104 type = dbus_message_iter_get_arg_type(&value);
106 if (g_str_equal(name, "OfflineMode")) {
107 dbus_bool_t offlinemode;
109 if (type != DBUS_TYPE_BOOLEAN)
110 return __connman_error_invalid_arguments(msg);
112 dbus_message_iter_get_basic(&value, &offlinemode);
114 __connman_technology_set_offlinemode(offlinemode);
115 } else if (g_str_equal(name, "SessionMode")) {
117 if (type != DBUS_TYPE_BOOLEAN)
118 return __connman_error_invalid_arguments(msg);
120 dbus_message_iter_get_basic(&value, &sessionmode);
121 #if defined TIZEN_EXT
122 } else if (g_str_equal(name, "AutoConnectMode") == TRUE) {
125 if (type != DBUS_TYPE_BOOLEAN)
126 return __connman_error_invalid_arguments(msg);
128 dbus_message_iter_get_basic(&value, &automode);
130 __connman_service_set_auto_connect_mode(automode);
133 return __connman_error_invalid_property(msg);
135 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
138 static void append_technology_structs(DBusMessageIter *iter, void *user_data)
140 __connman_technology_list_struct(iter);
143 static DBusMessage *get_technologies(DBusConnection *conn,
144 DBusMessage *msg, void *data)
148 #if !defined TIZEN_EXT
152 reply = dbus_message_new_method_return(msg);
156 __connman_dbus_append_objpath_dict_array(reply,
157 append_technology_structs, NULL);
162 static DBusMessage *remove_provider(DBusConnection *conn,
163 DBusMessage *msg, void *data)
168 DBG("conn %p", conn);
170 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
173 err = __connman_provider_remove_by_path(path);
175 return __connman_error_failed(msg, -err);
177 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
180 static DBusConnection *connection = NULL;
182 static void idle_state(bool idle)
185 DBG("idle %d", idle);
187 connman_state_idle = idle;
189 if (!connman_state_idle)
193 static const struct connman_notifier technology_notifier = {
195 .priority = CONNMAN_NOTIFIER_PRIORITY_HIGH,
196 .idle_state = idle_state,
199 static void append_service_structs(DBusMessageIter *iter, void *user_data)
201 __connman_service_list_struct(iter);
204 static DBusMessage *get_services(DBusConnection *conn,
205 DBusMessage *msg, void *data)
209 reply = dbus_message_new_method_return(msg);
213 __connman_dbus_append_objpath_dict_array(reply,
214 append_service_structs, NULL);
219 #if defined TIZEN_EXT
220 static DBusMessage *get_interfaces(DBusConnection *conn, DBusMessage *msg, void *data)
223 DBusMessageIter iter, array;
224 const char *default_interface = connman_option_get_string("DefaultWifiInterface");
226 DBG("DefaultWifiInterface %s", default_interface);
228 reply = dbus_message_new_method_return(msg);
232 dbus_message_iter_init_append(reply, &iter);
233 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
234 DBUS_TYPE_STRING_AS_STRING, &array);
236 dbus_message_iter_append_basic(&array,
237 DBUS_TYPE_STRING, &default_interface);
239 __connman_technology_append_interfaces(&array,
240 CONNMAN_SERVICE_TYPE_WIFI, default_interface);
242 dbus_message_iter_close_container(&iter, &array);
246 static DBusMessage *get_default_service(DBusConnection *conn,
247 DBusMessage *msg, void *data)
249 struct connman_service *service = connman_service_get_default_connection();
250 DBG("service %p", service);
252 return connman_service_create_dbus_service_reply(msg, service);
255 static DBusMessage *get_connected_service(DBusConnection *conn,
256 DBusMessage *msg, void *data)
259 struct connman_service *service;
261 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &ifname,
264 service = connman_service_get_connected_service(ifname);
265 DBG("Interface Name %s, service %p", ifname, service);
267 return connman_service_create_dbus_service_reply(msg, service);
271 #if defined TIZEN_EXT_INS
272 static void append_ins_structs(DBusMessageIter *iter, void *user_data)
274 __connman_ins_list_struct(iter);
277 static DBusMessage *get_ins(DBusConnection *conn,
278 DBusMessage *msg, void *data)
282 reply = dbus_message_new_method_return(msg);
286 __connman_dbus_append_objpath_dict_array(reply,
287 append_ins_structs, NULL);
293 static void append_peer_structs(DBusMessageIter *iter, void *user_data)
295 __connman_peer_list_struct(iter);
298 static DBusMessage *get_peers(DBusConnection *conn,
299 DBusMessage *msg, void *data)
303 reply = dbus_message_new_method_return(msg);
307 __connman_dbus_append_objpath_dict_array(reply,
308 append_peer_structs, NULL);
312 static DBusMessage *get_tethering_clients(DBusConnection *conn,
313 DBusMessage *msg, void *data)
316 DBusMessageIter iter, array;
318 reply = dbus_message_new_method_return(msg);
322 dbus_message_iter_init_append(reply, &iter);
324 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
325 DBUS_TYPE_STRING_AS_STRING, &array);
327 __connman_tethering_list_clients(&array);
329 dbus_message_iter_close_container(&iter, &array);
333 static DBusMessage *connect_provider(DBusConnection *conn,
334 DBusMessage *msg, void *data)
338 DBG("conn %p", conn);
340 err = __connman_provider_create_and_connect(msg);
342 return __connman_error_failed(msg, -err);
347 static DBusMessage *register_agent(DBusConnection *conn,
348 DBusMessage *msg, void *data)
350 const char *sender, *path;
353 DBG("conn %p", conn);
355 sender = dbus_message_get_sender(msg);
357 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
360 err = connman_agent_register(sender, path);
362 return __connman_error_failed(msg, -err);
364 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
367 static DBusMessage *unregister_agent(DBusConnection *conn,
368 DBusMessage *msg, void *data)
370 const char *sender, *path;
373 DBG("conn %p", conn);
375 sender = dbus_message_get_sender(msg);
377 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
380 err = connman_agent_unregister(sender, path);
382 return __connman_error_failed(msg, -err);
384 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
387 static DBusMessage *register_counter(DBusConnection *conn,
388 DBusMessage *msg, void *data)
390 const char *sender, *path;
391 unsigned int accuracy, period;
394 DBG("conn %p", conn);
396 sender = dbus_message_get_sender(msg);
398 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
399 DBUS_TYPE_UINT32, &accuracy,
400 DBUS_TYPE_UINT32, &period,
403 /* FIXME: add handling of accuracy parameter */
405 err = __connman_counter_register(sender, path, period);
407 return __connman_error_failed(msg, -err);
409 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
412 static DBusMessage *unregister_counter(DBusConnection *conn,
413 DBusMessage *msg, void *data)
415 const char *sender, *path;
418 DBG("conn %p", conn);
420 sender = dbus_message_get_sender(msg);
422 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
425 err = __connman_counter_unregister(sender, path);
427 return __connman_error_failed(msg, -err);
429 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
432 static DBusMessage *create_session(DBusConnection *conn,
433 DBusMessage *msg, void *data)
437 DBG("conn %p", conn);
439 err = __connman_session_create(msg);
441 if (err == -EINPROGRESS)
444 return __connman_error_failed(msg, -err);
447 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
450 static DBusMessage *destroy_session(DBusConnection *conn,
451 DBusMessage *msg, void *data)
455 DBG("conn %p", conn);
457 err = __connman_session_destroy(msg);
459 return __connman_error_failed(msg, -err);
461 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
464 static DBusMessage *request_private_network(DBusConnection *conn,
465 DBusMessage *msg, void *data)
470 DBG("conn %p", conn);
472 sender = dbus_message_get_sender(msg);
474 err = __connman_private_network_request(msg, sender);
476 return __connman_error_failed(msg, -err);
481 static DBusMessage *release_private_network(DBusConnection *conn,
482 DBusMessage *msg, void *data)
487 DBG("conn %p", conn);
489 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
492 err = __connman_private_network_release(path);
494 return __connman_error_failed(msg, -err);
496 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
499 static int parse_peers_service_specs(DBusMessageIter *array,
500 const unsigned char **spec, int *spec_len,
501 const unsigned char **query, int *query_len,
504 *spec = *query = NULL;
505 *spec_len = *query_len = *version = 0;
507 while (dbus_message_iter_get_arg_type(array) ==
508 DBUS_TYPE_DICT_ENTRY) {
509 DBusMessageIter entry, inter, value;
512 dbus_message_iter_recurse(array, &entry);
513 dbus_message_iter_get_basic(&entry, &key);
515 dbus_message_iter_next(&entry);
517 dbus_message_iter_recurse(&entry, &inter);
519 if (!g_strcmp0(key, "BonjourResponse")) {
520 dbus_message_iter_recurse(&inter, &value);
521 dbus_message_iter_get_fixed_array(&value,
523 } else if (!g_strcmp0(key, "BonjourQuery")) {
524 dbus_message_iter_recurse(&inter, &value);
525 dbus_message_iter_get_fixed_array(&value,
527 } else if (!g_strcmp0(key, "UpnpService")) {
528 dbus_message_iter_get_basic(&inter, spec);
529 *spec_len = strlen((const char *)*spec)+1;
530 } else if (!g_strcmp0(key, "UpnpVersion")) {
531 dbus_message_iter_get_basic(&inter, version);
532 } else if (!g_strcmp0(key, "WiFiDisplayIEs")) {
536 dbus_message_iter_recurse(&inter, &value);
537 dbus_message_iter_get_fixed_array(&value,
542 dbus_message_iter_next(array);
545 if ((*query && !*spec && !*version) ||
546 (!*spec && !*query) || (!*spec && *version))
552 static DBusMessage *register_peer_service(DBusConnection *conn,
553 DBusMessage *msg, void *data)
555 const unsigned char *spec, *query;
556 DBusMessageIter iter, array;
557 int spec_len, query_len;
565 owner = dbus_message_get_sender(msg);
567 dbus_message_iter_init(msg, &iter);
568 dbus_message_iter_recurse(&iter, &array);
570 ret = parse_peers_service_specs(&array, &spec, &spec_len,
571 &query, &query_len, &version);
575 dbus_message_iter_next(&iter);
576 dbus_message_iter_get_basic(&iter, &master);
578 ret = __connman_peer_service_register(owner, msg, spec, spec_len,
579 query, query_len, version,master);
581 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
582 if (ret == -EINPROGRESS)
585 return __connman_error_failed(msg, -ret);
588 static DBusMessage *unregister_peer_service(DBusConnection *conn,
589 DBusMessage *msg, void *data)
591 const unsigned char *spec, *query;
592 DBusMessageIter iter, array;
593 int spec_len, query_len;
600 owner = dbus_message_get_sender(msg);
602 dbus_message_iter_init(msg, &iter);
603 dbus_message_iter_recurse(&iter, &array);
605 ret = parse_peers_service_specs(&array, &spec, &spec_len,
606 &query, &query_len, &version);
610 ret = __connman_peer_service_unregister(owner, spec, spec_len,
611 query, query_len, version);
613 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
615 return __connman_error_failed(msg, -ret);
619 #if defined TIZEN_EXT_WIFI_MESH
620 static void append_mesh_peer_structs(DBusMessageIter *iter, void *user_data)
622 __connman_mesh_peer_list_struct(iter);
625 static DBusMessage *get_mesh_peers(DBusConnection *conn,
626 DBusMessage *msg, void *data)
630 reply = dbus_message_new_method_return(msg);
634 __connman_dbus_append_objpath_dict_array(reply,
635 append_mesh_peer_structs, NULL);
639 static DBusMessage *get_connected_mesh_peers(DBusConnection *conn,
640 DBusMessage *msg, void *data)
643 DBusMessageIter iter, array;
645 reply = dbus_message_new_method_return(msg);
649 dbus_message_iter_init_append(reply, &iter);
650 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
651 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
652 DBUS_TYPE_ARRAY_AS_STRING
653 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
654 DBUS_TYPE_STRING_AS_STRING
655 DBUS_TYPE_VARIANT_AS_STRING
656 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
657 DBUS_STRUCT_END_CHAR_AS_STRING, &array);
659 __connman_mesh_connected_peer_list_struct(&array);
660 dbus_message_iter_close_container(&iter, &array);
664 static DBusMessage *get_disconnected_mesh_peers(DBusConnection *conn,
665 DBusMessage *msg, void *data)
668 DBusMessageIter iter, array;
670 reply = dbus_message_new_method_return(msg);
674 dbus_message_iter_init_append(reply, &iter);
675 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
676 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
677 DBUS_TYPE_ARRAY_AS_STRING
678 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
679 DBUS_TYPE_STRING_AS_STRING
680 DBUS_TYPE_VARIANT_AS_STRING
681 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
682 DBUS_STRUCT_END_CHAR_AS_STRING, &array);
684 __connman_mesh_disconnected_peer_list_struct(&array);
685 dbus_message_iter_close_container(&iter, &array);
689 static DBusMessage *mesh_add_peer(DBusConnection *conn,
690 DBusMessage *msg, void *user_data)
695 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
698 DBG("Address %s", addr);
700 err = __connman_mesh_change_peer_status(msg, addr, CONNMAN_MESH_PEER_ADD);
702 return __connman_error_failed(msg, -err);
707 static DBusMessage *mesh_remove_peer(DBusConnection *conn,
708 DBusMessage *msg, void *user_data)
713 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
716 DBG("Address %s", addr);
718 err = __connman_mesh_change_peer_status(msg, addr,
719 CONNMAN_MESH_PEER_REMOVE);
721 return __connman_error_failed(msg, -err);
727 static const GDBusMethodTable manager_methods[] = {
728 { GDBUS_METHOD("GetProperties",
729 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
731 { GDBUS_ASYNC_METHOD("SetProperty",
732 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
733 NULL, set_property) },
734 { GDBUS_METHOD("GetTechnologies",
735 NULL, GDBUS_ARGS({ "technologies", "a(oa{sv})" }),
737 { GDBUS_DEPRECATED_METHOD("RemoveProvider",
738 GDBUS_ARGS({ "provider", "o" }), NULL,
740 { GDBUS_METHOD("GetServices",
741 NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
743 #if defined TIZEN_EXT
744 { GDBUS_METHOD("GetInterfaces",
745 NULL, GDBUS_ARGS({ "interface_list", "as" }),
747 { GDBUS_METHOD("GetDefaultService",
748 NULL, GDBUS_ARGS({ "service", "oa{sv}" }),
749 get_default_service) },
750 { GDBUS_METHOD("GetConnectedService",
751 GDBUS_ARGS({ "ifname", "s" }),
752 GDBUS_ARGS({ "service", "oa{sv}" }),
753 get_connected_service) },
755 #if defined TIZEN_EXT_INS
756 { GDBUS_METHOD("GetINS",
757 NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
760 { GDBUS_METHOD("GetPeers",
761 NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
763 { GDBUS_METHOD("GetTetheringClients",
764 NULL, GDBUS_ARGS({ "tethering_clients", "as" }),
765 get_tethering_clients) },
766 { GDBUS_DEPRECATED_ASYNC_METHOD("ConnectProvider",
767 GDBUS_ARGS({ "provider", "a{sv}" }),
768 GDBUS_ARGS({ "path", "o" }),
770 { GDBUS_METHOD("RegisterAgent",
771 GDBUS_ARGS({ "path", "o" }), NULL,
773 { GDBUS_METHOD("UnregisterAgent",
774 GDBUS_ARGS({ "path", "o" }), NULL,
776 { GDBUS_METHOD("RegisterCounter",
777 GDBUS_ARGS({ "path", "o" }, { "accuracy", "u" },
779 NULL, register_counter) },
780 { GDBUS_METHOD("UnregisterCounter",
781 GDBUS_ARGS({ "path", "o" }), NULL,
782 unregister_counter) },
783 { GDBUS_ASYNC_METHOD("CreateSession",
784 GDBUS_ARGS({ "settings", "a{sv}" },
785 { "notifier", "o" }),
786 GDBUS_ARGS({ "session", "o" }),
788 { GDBUS_METHOD("DestroySession",
789 GDBUS_ARGS({ "session", "o" }), NULL,
791 { GDBUS_ASYNC_METHOD("RequestPrivateNetwork",
792 NULL, GDBUS_ARGS({ "path", "o" },
793 { "settings", "a{sv}" },
795 request_private_network) },
796 { GDBUS_METHOD("ReleasePrivateNetwork",
797 GDBUS_ARGS({ "path", "o" }), NULL,
798 release_private_network) },
799 { GDBUS_ASYNC_METHOD("RegisterPeerService",
800 GDBUS_ARGS({ "specification", "a{sv}" },
801 { "master", "b" }), NULL,
802 register_peer_service) },
803 { GDBUS_METHOD("UnregisterPeerService",
804 GDBUS_ARGS({ "specification", "a{sv}" }), NULL,
805 unregister_peer_service) },
806 #if defined TIZEN_EXT_WIFI_MESH
807 { GDBUS_METHOD("GetMeshPeers",
808 NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
810 { GDBUS_METHOD("GetConnectedMeshPeers",
811 NULL, GDBUS_ARGS({ "peers", "a(a{sv})" }),
812 get_connected_mesh_peers) },
813 { GDBUS_METHOD("GetDisconnectedMeshPeers",
814 NULL, GDBUS_ARGS({ "peers", "a(a{sv})" }),
815 get_disconnected_mesh_peers) },
816 { GDBUS_ASYNC_METHOD("MeshAddPeer", GDBUS_ARGS({ "address", "s" }), NULL,
818 { GDBUS_ASYNC_METHOD("MeshRemovePeer", GDBUS_ARGS({ "address", "s" }), NULL,
824 static const GDBusSignalTable manager_signals[] = {
825 { GDBUS_SIGNAL("PropertyChanged",
826 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
827 { GDBUS_SIGNAL("TechnologyAdded",
828 GDBUS_ARGS({ "path", "o" },
829 { "properties", "a{sv}" })) },
830 { GDBUS_SIGNAL("TechnologyRemoved",
831 GDBUS_ARGS({ "path", "o" })) },
832 { GDBUS_SIGNAL("ServicesChanged",
833 GDBUS_ARGS({ "changed", "a(oa{sv})" },
834 { "removed", "ao" })) },
835 { GDBUS_SIGNAL("PeersChanged",
836 GDBUS_ARGS({ "changed", "a(oa{sv})" },
837 { "removed", "ao" })) },
841 int __connman_manager_init(void)
845 connection = connman_dbus_get_connection();
849 if (connman_notifier_register(&technology_notifier) < 0)
850 connman_error("Failed to register technology notifier");
852 g_dbus_register_interface(connection, CONNMAN_MANAGER_PATH,
853 CONNMAN_MANAGER_INTERFACE,
855 manager_signals, NULL, NULL, NULL);
857 connman_state_idle = true;
862 void __connman_manager_cleanup(void)
869 connman_notifier_unregister(&technology_notifier);
871 g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH,
872 CONNMAN_MANAGER_INTERFACE);
874 dbus_connection_unref(connection);