5 * Copyright (C) 2014 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
29 #include <gdhcp/gdhcp.h>
31 #include <connman/agent.h>
35 static DBusConnection *connection = NULL;
37 static GHashTable *peers_table = NULL;
39 static struct connman_peer_driver *peer_driver;
41 struct _peers_notify {
47 struct _peer_service {
48 enum connman_peer_service_type type;
55 struct connman_device *device;
56 struct connman_device *sub_device;
60 enum connman_peer_state state;
61 struct connman_ipconfig *ipconfig;
64 bool connection_master;
65 struct connman_ippool *ip_pool;
66 GDHCPServer *dhcp_server;
70 static void stop_dhcp_server(struct connman_peer *peer)
74 if (peer->dhcp_server)
75 g_dhcp_server_unref(peer->dhcp_server);
77 peer->dhcp_server = NULL;
80 __connman_ippool_unref(peer->ip_pool);
84 static void dhcp_server_debug(const char *str, void *data)
86 connman_info("%s: %s\n", (const char *) data, str);
89 static gboolean dhcp_server_started(gpointer data)
91 struct connman_peer *peer = data;
93 connman_peer_set_state(peer, CONNMAN_PEER_STATE_READY);
94 connman_peer_unref(peer);
99 static int start_dhcp_server(struct connman_peer *peer)
101 const char *start_ip, *end_ip;
102 GDHCPServerError dhcp_error;
103 const char *broadcast;
114 if (peer->sub_device)
115 index = connman_device_get_index(peer->sub_device);
117 index = connman_device_get_index(peer->device);
119 peer->ip_pool = __connman_ippool_create(index, 2, 1, NULL, NULL);
123 gateway = __connman_ippool_get_gateway(peer->ip_pool);
124 subnet = __connman_ippool_get_subnet_mask(peer->ip_pool);
125 broadcast = __connman_ippool_get_broadcast(peer->ip_pool);
126 start_ip = __connman_ippool_get_start_ip(peer->ip_pool);
127 end_ip = __connman_ippool_get_end_ip(peer->ip_pool);
129 prefixlen = connman_ipaddress_calc_netmask_len(subnet);
131 err = __connman_inet_modify_address(RTM_NEWADDR,
132 NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
133 gateway, NULL, prefixlen, broadcast);
137 peer->dhcp_server = g_dhcp_server_new(G_DHCP_IPV4, index, &dhcp_error);
138 if (!peer->dhcp_server)
141 g_dhcp_server_set_debug(peer->dhcp_server,
142 dhcp_server_debug, "Peer DHCP server");
143 g_dhcp_server_set_lease_time(peer->dhcp_server, 3600);
144 g_dhcp_server_set_option(peer->dhcp_server, G_DHCP_SUBNET, subnet);
145 g_dhcp_server_set_option(peer->dhcp_server, G_DHCP_ROUTER, gateway);
146 g_dhcp_server_set_option(peer->dhcp_server, G_DHCP_DNS_SERVER, NULL);
147 g_dhcp_server_set_ip_range(peer->dhcp_server, start_ip, end_ip);
149 err = g_dhcp_server_start(peer->dhcp_server);
153 g_timeout_add_seconds(0, dhcp_server_started, connman_peer_ref(peer));
158 stop_dhcp_server(peer);
162 static void reply_pending(struct connman_peer *peer, int error)
167 connman_dbus_reply_pending(peer->pending, error, NULL);
168 peer->pending = NULL;
171 static void peer_free(gpointer data)
173 struct connman_peer *peer = data;
175 reply_pending(peer, ENOENT);
177 connman_peer_unregister(peer);
184 if (peer->ipconfig) {
185 __connman_ipconfig_set_ops(peer->ipconfig, NULL);
186 __connman_ipconfig_set_data(peer->ipconfig, NULL);
187 __connman_ipconfig_unref(peer->ipconfig);
188 peer->ipconfig = NULL;
191 stop_dhcp_server(peer);
194 connman_device_unref(peer->device);
199 connman_peer_reset_services(peer);
201 g_free(peer->identifier);
207 static const char *state2string(enum connman_peer_state state)
210 case CONNMAN_PEER_STATE_UNKNOWN:
212 case CONNMAN_PEER_STATE_IDLE:
214 case CONNMAN_PEER_STATE_ASSOCIATION:
215 return "association";
216 case CONNMAN_PEER_STATE_CONFIGURATION:
217 return "configuration";
218 case CONNMAN_PEER_STATE_READY:
220 case CONNMAN_PEER_STATE_DISCONNECT:
222 case CONNMAN_PEER_STATE_FAILURE:
229 static bool is_connecting(struct connman_peer *peer)
231 if (peer->state == CONNMAN_PEER_STATE_ASSOCIATION ||
232 peer->state == CONNMAN_PEER_STATE_CONFIGURATION ||
239 static bool is_connected(struct connman_peer *peer)
241 if (peer->state == CONNMAN_PEER_STATE_READY)
247 static bool allow_property_changed(struct connman_peer *peer)
249 if (g_hash_table_lookup_extended(peers_notify->add, peer->path,
256 static void append_dhcp_server_ipv4(DBusMessageIter *iter, void *user_data)
258 struct connman_peer *peer = user_data;
259 const char *str = "dhcp";
266 gateway = __connman_ippool_get_gateway(peer->ip_pool);
267 subnet = __connman_ippool_get_subnet_mask(peer->ip_pool);
269 connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
270 connman_dbus_dict_append_basic(iter, "Address",
271 DBUS_TYPE_STRING, &gateway);
272 connman_dbus_dict_append_basic(iter, "Netmask",
273 DBUS_TYPE_STRING, &subnet);
274 connman_dbus_dict_append_basic(iter, "Gateway",
275 DBUS_TYPE_STRING, &gateway);
278 static void append_ipv4(DBusMessageIter *iter, void *user_data)
280 struct connman_peer *peer = user_data;
282 if (!is_connected(peer))
285 if (peer->connection_master)
286 append_dhcp_server_ipv4(iter, peer);
287 else if (peer->ipconfig)
288 __connman_ipconfig_append_ipv4(peer->ipconfig, iter);
291 static void append_peer_service(DBusMessageIter *iter,
292 struct _peer_service *service)
294 DBusMessageIter dict;
296 connman_dbus_dict_open(iter, &dict);
298 switch (service->type) {
299 case CONNMAN_PEER_SERVICE_UNKNOWN:
300 /* Should never happen */
302 case CONNMAN_PEER_SERVICE_WIFI_DISPLAY:
303 connman_dbus_dict_append_fixed_array(&dict,
304 "WiFiDisplayIEs", DBUS_TYPE_BYTE,
305 &service->data, service->length);
309 connman_dbus_dict_close(iter, &dict);
312 static void append_peer_services(DBusMessageIter *iter, void *user_data)
314 struct connman_peer *peer = user_data;
315 DBusMessageIter container;
318 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
321 if (!peer->services) {
322 DBusMessageIter dict;
324 connman_dbus_dict_open(&container, &dict);
325 connman_dbus_dict_close(&container, &dict);
327 for (list = peer->services; list; list = list->next)
328 append_peer_service(&container, list->data);
331 dbus_message_iter_close_container(iter, &container);
334 static void append_properties(DBusMessageIter *iter, struct connman_peer *peer)
336 const char *state = state2string(peer->state);
337 DBusMessageIter dict;
339 connman_dbus_dict_open(iter, &dict);
341 connman_dbus_dict_append_basic(&dict, "State",
342 DBUS_TYPE_STRING, &state);
343 connman_dbus_dict_append_basic(&dict, "Name",
344 DBUS_TYPE_STRING, &peer->name);
345 connman_dbus_dict_append_dict(&dict, "IPv4", append_ipv4, peer);
346 connman_dbus_dict_append_array(&dict, "Services",
347 DBUS_TYPE_DICT_ENTRY,
348 append_peer_services, peer);
349 connman_dbus_dict_close(iter, &dict);
352 static void settings_changed(struct connman_peer *peer)
354 if (!allow_property_changed(peer))
357 connman_dbus_property_changed_dict(peer->path,
358 CONNMAN_PEER_INTERFACE, "IPv4",
362 static DBusMessage *get_peer_properties(DBusConnection *conn,
363 DBusMessage *msg, void *data)
365 struct connman_peer *peer = data;
366 DBusMessageIter dict;
369 reply = dbus_message_new_method_return(msg);
373 dbus_message_iter_init_append(reply, &dict);
374 append_properties(&dict, peer);
379 static void append_peer_struct(gpointer key, gpointer value,
382 DBusMessageIter *array = user_data;
383 struct connman_peer *peer = value;
384 DBusMessageIter entry;
386 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
388 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
390 append_properties(&entry, peer);
391 dbus_message_iter_close_container(array, &entry);
394 static void state_changed(struct connman_peer *peer)
398 state = state2string(peer->state);
399 if (!state || !allow_property_changed(peer))
402 connman_dbus_property_changed_basic(peer->path,
403 CONNMAN_PEER_INTERFACE, "State",
404 DBUS_TYPE_STRING, &state);
407 static void append_existing_and_new_peers(gpointer key,
408 gpointer value, gpointer user_data)
410 struct connman_peer *peer = value;
411 DBusMessageIter *iter = user_data;
412 DBusMessageIter entry, dict;
414 if (!peer || !peer->registered)
417 if (g_hash_table_lookup(peers_notify->add, peer->path)) {
418 DBG("new %s", peer->path);
420 append_peer_struct(key, peer, iter);
421 g_hash_table_remove(peers_notify->add, peer->path);
422 } else if (!g_hash_table_lookup(peers_notify->remove, peer->path)) {
423 DBG("existing %s", peer->path);
425 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
427 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
429 connman_dbus_dict_open(&entry, &dict);
430 connman_dbus_dict_close(&entry, &dict);
432 dbus_message_iter_close_container(iter, &entry);
436 static void peer_append_all(DBusMessageIter *iter, void *user_data)
438 g_hash_table_foreach(peers_table, append_existing_and_new_peers, iter);
441 static void append_removed(gpointer key, gpointer value, gpointer user_data)
443 DBusMessageIter *iter = user_data;
446 DBG("removed %s", objpath);
447 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath);
450 static void peer_append_removed(DBusMessageIter *iter, void *user_data)
452 g_hash_table_foreach(peers_notify->remove, append_removed, iter);
455 static gboolean peer_send_changed(gpointer data)
461 peers_notify->id = 0;
463 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
464 CONNMAN_MANAGER_INTERFACE, "PeersChanged");
468 __connman_dbus_append_objpath_dict_array(signal,
469 peer_append_all, NULL);
470 __connman_dbus_append_objpath_array(signal,
471 peer_append_removed, NULL);
473 dbus_connection_send(connection, signal, NULL);
474 dbus_message_unref(signal);
476 g_hash_table_remove_all(peers_notify->remove);
477 g_hash_table_remove_all(peers_notify->add);
482 static void peer_schedule_changed(void)
484 if (peers_notify->id != 0)
487 peers_notify->id = g_timeout_add(100, peer_send_changed, NULL);
490 static void peer_added(struct connman_peer *peer)
492 DBG("peer %p", peer);
494 g_hash_table_remove(peers_notify->remove, peer->path);
495 g_hash_table_replace(peers_notify->add, peer->path, peer);
497 peer_schedule_changed();
500 static void peer_removed(struct connman_peer *peer)
502 DBG("peer %p", peer);
504 g_hash_table_remove(peers_notify->add, peer->path);
505 g_hash_table_replace(peers_notify->remove, g_strdup(peer->path), NULL);
507 peer_schedule_changed();
510 static const char *get_dbus_sender(struct connman_peer *peer)
515 return dbus_message_get_sender(peer->pending);
518 static enum connman_peer_wps_method check_wpspin(struct connman_peer *peer,
524 return CONNMAN_PEER_WPS_PBC;
526 len = strlen(wpspin);
528 return CONNMAN_PEER_WPS_PBC;
531 return CONNMAN_PEER_WPS_UNKNOWN;
532 for (i = 0; i < 8; i++) {
533 if (!isdigit((unsigned char) wpspin[i]))
534 return CONNMAN_PEER_WPS_UNKNOWN;
537 return CONNMAN_PEER_WPS_PIN;
540 static void request_authorization_cb(struct connman_peer *peer,
541 bool choice_done, const char *wpspin,
542 const char *error, void *user_data)
544 enum connman_peer_wps_method wps_method;
547 DBG("RequestInput return, %p", peer);
551 "net.connman.Agent.Error.Canceled") == 0 ||
553 "net.connman.Agent.Error.Rejected") == 0) {
559 if (!choice_done || !peer_driver->connect) {
564 wps_method = check_wpspin(peer, wpspin);
566 err = peer_driver->connect(peer, wps_method, wpspin);
567 if (err == -EINPROGRESS)
571 reply_pending(peer, EIO);
572 connman_peer_set_state(peer, CONNMAN_PEER_STATE_IDLE);
575 static int peer_connect(struct connman_peer *peer)
579 if (peer_driver->connect)
580 err = peer_driver->connect(peer,
581 CONNMAN_PEER_WPS_UNKNOWN, NULL);
583 if (err == -ENOKEY) {
584 err = __connman_agent_request_peer_authorization(peer,
585 request_authorization_cb, true,
586 get_dbus_sender(peer), NULL);
592 static int peer_disconnect(struct connman_peer *peer)
596 connman_agent_cancel(peer);
597 reply_pending(peer, ECONNABORTED);
599 connman_peer_set_state(peer, CONNMAN_PEER_STATE_DISCONNECT);
601 if (peer->connection_master)
602 stop_dhcp_server(peer);
604 __connman_dhcp_stop(peer->ipconfig);
606 if (peer_driver->disconnect)
607 err = peer_driver->disconnect(peer);
609 connman_peer_set_state(peer, CONNMAN_PEER_STATE_IDLE);
614 static DBusMessage *connect_peer(DBusConnection *conn,
615 DBusMessage *msg, void *user_data)
617 struct connman_peer *peer = user_data;
621 DBG("peer %p", peer);
624 return __connman_error_in_progress(msg);
626 list = g_hash_table_get_values(peers_table);
628 for (; list; list = list->next) {
629 struct connman_peer *temp = list->data;
631 if (temp == peer || temp->device != peer->device)
634 if (is_connecting(temp) || is_connected(temp)) {
635 if (peer_disconnect(temp) == -EINPROGRESS) {
637 return __connman_error_in_progress(msg);
644 peer->pending = dbus_message_ref(msg);
646 err = peer_connect(peer);
647 if (err == -EINPROGRESS)
651 dbus_message_unref(peer->pending);
652 peer->pending = NULL;
654 return __connman_error_failed(msg, -err);
657 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
660 static DBusMessage *disconnect_peer(DBusConnection *conn,
661 DBusMessage *msg, void *user_data)
663 struct connman_peer *peer = user_data;
666 DBG("peer %p", peer);
668 err = peer_disconnect(peer);
669 if (err < 0 && err != -EINPROGRESS)
670 return __connman_error_failed(msg, -err);
672 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
675 struct connman_peer *connman_peer_create(const char *identifier)
677 struct connman_peer *peer;
679 peer = g_malloc0(sizeof(struct connman_peer));
680 peer->identifier = g_strdup(identifier);
681 peer->state = CONNMAN_PEER_STATE_IDLE;
688 struct connman_peer *connman_peer_ref_debug(struct connman_peer *peer,
689 const char *file, int line, const char *caller)
691 DBG("%p ref %d by %s:%d:%s()", peer, peer->refcount + 1,
694 __sync_fetch_and_add(&peer->refcount, 1);
699 void connman_peer_unref_debug(struct connman_peer *peer,
700 const char *file, int line, const char *caller)
702 DBG("%p ref %d by %s:%d:%s()", peer, peer->refcount - 1,
705 if (__sync_fetch_and_sub(&peer->refcount, 1) != 1)
708 if (!peer->registered && !peer->path)
709 return peer_free(peer);
711 g_hash_table_remove(peers_table, peer->path);
714 const char *connman_peer_get_identifier(struct connman_peer *peer)
719 return peer->identifier;
722 void connman_peer_set_name(struct connman_peer *peer, const char *name)
725 peer->name = g_strdup(name);
728 void connman_peer_set_device(struct connman_peer *peer,
729 struct connman_device *device)
731 if (!peer || !device)
734 peer->device = device;
735 connman_device_ref(device);
738 struct connman_device *connman_peer_get_device(struct connman_peer *peer)
746 void connman_peer_set_sub_device(struct connman_peer *peer,
747 struct connman_device *device)
749 if (!peer || !device || peer->sub_device)
752 peer->sub_device = device;
755 void connman_peer_set_as_master(struct connman_peer *peer, bool master)
757 if (!peer || !is_connecting(peer))
760 peer->connection_master = master;
763 static void dhcp_callback(struct connman_ipconfig *ipconfig,
764 struct connman_network *network,
765 bool success, gpointer data)
767 struct connman_peer *peer = data;
773 DBG("lease acquired for ipconfig %p", ipconfig);
775 err = __connman_ipconfig_address_add(ipconfig);
782 __connman_ipconfig_address_remove(ipconfig);
783 connman_peer_set_state(peer, CONNMAN_PEER_STATE_FAILURE);
786 static int start_dhcp_client(struct connman_peer *peer)
788 if (peer->sub_device)
789 __connman_ipconfig_set_index(peer->ipconfig,
790 connman_device_get_index(peer->sub_device));
792 __connman_ipconfig_enable(peer->ipconfig);
794 return __connman_dhcp_start(peer->ipconfig, NULL, dhcp_callback, peer);
797 static void report_error_cb(void *user_context, bool retry, void *user_data)
799 struct connman_peer *peer = user_context;
803 err = peer_connect(peer);
805 if (err == 0 || err == -EINPROGRESS)
809 reply_pending(peer, ENOTCONN);
811 peer_disconnect(peer);
813 if (!peer->connection_master) {
814 __connman_dhcp_stop(peer->ipconfig);
815 __connman_ipconfig_disable(peer->ipconfig);
817 stop_dhcp_server(peer);
819 peer->connection_master = false;
820 peer->sub_device = NULL;
823 static int manage_peer_error(struct connman_peer *peer)
827 err = __connman_agent_report_peer_error(peer, peer->path,
828 "connect-failed", report_error_cb,
829 get_dbus_sender(peer), NULL);
830 if (err != -EINPROGRESS) {
831 report_error_cb(peer, false, NULL);
838 int connman_peer_set_state(struct connman_peer *peer,
839 enum connman_peer_state new_state)
841 enum connman_peer_state old_state = peer->state;
844 DBG("peer (%s) old state %d new state %d", peer->name,
845 old_state, new_state);
847 if (old_state == new_state)
851 case CONNMAN_PEER_STATE_UNKNOWN:
853 case CONNMAN_PEER_STATE_IDLE:
854 if (is_connecting(peer) || is_connected(peer))
855 return peer_disconnect(peer);
856 peer->sub_device = NULL;
858 case CONNMAN_PEER_STATE_ASSOCIATION:
860 case CONNMAN_PEER_STATE_CONFIGURATION:
861 if (peer->connection_master)
862 err = start_dhcp_server(peer);
864 err = start_dhcp_client(peer);
866 return connman_peer_set_state(peer,
867 CONNMAN_PEER_STATE_FAILURE);
869 case CONNMAN_PEER_STATE_READY:
870 reply_pending(peer, 0);
872 case CONNMAN_PEER_STATE_DISCONNECT:
873 if (peer->connection_master)
874 stop_dhcp_server(peer);
875 peer->connection_master = false;
876 peer->sub_device = NULL;
879 case CONNMAN_PEER_STATE_FAILURE:
880 if (manage_peer_error(peer) == 0)
885 peer->state = new_state;
891 int connman_peer_request_connection(struct connman_peer *peer)
893 return __connman_agent_request_peer_authorization(peer,
894 request_authorization_cb, false,
898 static void peer_service_free(gpointer data)
900 struct _peer_service *service = data;
905 g_free(service->data);
909 void connman_peer_reset_services(struct connman_peer *peer)
914 g_slist_free_full(peer->services, peer_service_free);
915 peer->services = NULL;
918 void connman_peer_services_changed(struct connman_peer *peer)
920 if (!peer || !peer->registered || !allow_property_changed(peer))
923 connman_dbus_property_changed_array(peer->path,
924 CONNMAN_PEER_INTERFACE, "Services",
925 DBUS_TYPE_DICT_ENTRY, append_peer_services, peer);
928 void connman_peer_add_service(struct connman_peer *peer,
929 enum connman_peer_service_type type,
930 const unsigned char *data, int data_length)
932 struct _peer_service *service;
934 if (!peer || !data || type == CONNMAN_PEER_SERVICE_UNKNOWN)
937 service = g_malloc0(sizeof(struct _peer_service));
938 service->type = type;
939 service->data = g_memdup(data, data_length * sizeof(unsigned char));
940 service->length = data_length;
942 peer->services = g_slist_prepend(peer->services, service);
945 static void peer_up(struct connman_ipconfig *ipconfig, const char *ifname)
947 DBG("%s up", ifname);
950 static void peer_down(struct connman_ipconfig *ipconfig, const char *ifname)
952 DBG("%s down", ifname);
955 static void peer_lower_up(struct connman_ipconfig *ipconfig,
958 DBG("%s lower up", ifname);
961 static void peer_lower_down(struct connman_ipconfig *ipconfig,
964 struct connman_peer *peer = __connman_ipconfig_get_data(ipconfig);
966 DBG("%s lower down", ifname);
968 __connman_ipconfig_disable(ipconfig);
969 connman_peer_set_state(peer, CONNMAN_PEER_STATE_DISCONNECT);
972 static void peer_ip_bound(struct connman_ipconfig *ipconfig,
975 struct connman_peer *peer = __connman_ipconfig_get_data(ipconfig);
977 DBG("%s ip bound", ifname);
979 settings_changed(peer);
980 connman_peer_set_state(peer, CONNMAN_PEER_STATE_READY);
983 static void peer_ip_release(struct connman_ipconfig *ipconfig,
986 struct connman_peer *peer = __connman_ipconfig_get_data(ipconfig);
988 DBG("%s ip release", ifname);
990 settings_changed(peer);
993 static const struct connman_ipconfig_ops peer_ip_ops = {
996 .lower_up = peer_lower_up,
997 .lower_down = peer_lower_down,
998 .ip_bound = peer_ip_bound,
999 .ip_release = peer_ip_release,
1001 .route_unset = NULL,
1004 static struct connman_ipconfig *create_ipconfig(int index, void *user_data)
1006 struct connman_ipconfig *ipconfig;
1008 ipconfig = __connman_ipconfig_create(index,
1009 CONNMAN_IPCONFIG_TYPE_IPV4);
1013 __connman_ipconfig_set_method(ipconfig, CONNMAN_IPCONFIG_METHOD_DHCP);
1014 __connman_ipconfig_set_data(ipconfig, user_data);
1015 __connman_ipconfig_set_ops(ipconfig, &peer_ip_ops);
1020 static const GDBusMethodTable peer_methods[] = {
1021 { GDBUS_METHOD("GetProperties",
1022 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1023 get_peer_properties) },
1024 { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, connect_peer) },
1025 { GDBUS_METHOD("Disconnect", NULL, NULL, disconnect_peer) },
1029 static const GDBusSignalTable peer_signals[] = {
1030 { GDBUS_SIGNAL("PropertyChanged",
1031 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1035 static char *get_peer_path(struct connman_device *device,
1036 const char *identifier)
1038 return g_strdup_printf("%s/peer/peer_%s_%s", CONNMAN_PATH,
1039 connman_device_get_ident(device), identifier);
1042 int connman_peer_register(struct connman_peer *peer)
1046 DBG("peer %p", peer);
1048 if (peer->path && peer->registered)
1051 index = connman_device_get_index(peer->device);
1052 peer->ipconfig = create_ipconfig(index, peer);
1053 if (!peer->ipconfig)
1056 peer->path = get_peer_path(peer->device, peer->identifier);
1057 DBG("path %s", peer->path);
1059 g_hash_table_insert(peers_table, peer->path, peer);
1061 g_dbus_register_interface(connection, peer->path,
1062 CONNMAN_PEER_INTERFACE,
1063 peer_methods, peer_signals,
1065 peer->registered = true;
1071 void connman_peer_unregister(struct connman_peer *peer)
1073 DBG("peer %p", peer);
1075 if (!peer->path || !peer->registered)
1078 connman_agent_cancel(peer);
1079 reply_pending(peer, EIO);
1081 g_dbus_unregister_interface(connection, peer->path,
1082 CONNMAN_PEER_INTERFACE);
1083 peer->registered = false;
1087 struct connman_peer *connman_peer_get(struct connman_device *device,
1088 const char *identifier)
1090 char *ident = get_peer_path(device, identifier);
1091 struct connman_peer *peer;
1093 peer = g_hash_table_lookup(peers_table, ident);
1099 int connman_peer_driver_register(struct connman_peer_driver *driver)
1101 if (peer_driver && peer_driver != driver)
1104 peer_driver = driver;
1106 __connman_peer_service_set_driver(driver);
1111 void connman_peer_driver_unregister(struct connman_peer_driver *driver)
1113 if (peer_driver != driver)
1118 __connman_peer_service_set_driver(NULL);
1121 void __connman_peer_list_struct(DBusMessageIter *array)
1123 g_hash_table_foreach(peers_table, append_peer_struct, array);
1126 const char *__connman_peer_get_path(struct connman_peer *peer)
1128 if (!peer || !peer->registered)
1134 int __connman_peer_init(void)
1138 connection = connman_dbus_get_connection();
1140 peers_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1143 peers_notify = g_new0(struct _peers_notify, 1);
1144 peers_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
1145 peers_notify->remove = g_hash_table_new_full(g_str_hash, g_str_equal,
1150 void __connman_peer_cleanup(void)
1154 g_hash_table_destroy(peers_table);
1156 dbus_connection_unref(connection);