Send connman mailing list submissions to connman@lists.01.org To subscribe or unsubscribe via the World Wide Web, visit https://lists.01.org/mailman/listinfo/connman or, via email, send a message with subject or body 'help' to connman-requ...@lists.01.org
You can reach the person managing the list at connman-ow...@lists.01.org When replying, please edit your Subject line so it is more specific than "Re: Contents of connman digest..." Today's Topics: 1. Re: Crash when running connmand along iwd (Daniel Wagner) 2. Re: [PATCHv6 6/6] wps: add new WPS API for technology (Daniel Wagner) 3. [PATCH] wifi: implemented feature of tracking tethering clients (Vasyl Vavrychuk) ---------------------------------------------------------------------- Message: 1 Date: Sun, 28 Oct 2018 22:10:22 +0100 From: Daniel Wagner <w...@monom.org> To: Doron Behar <doron.be...@gmail.com> Cc: connman@lists.01.org Subject: Re: Crash when running connmand along iwd Message-ID: <fa08ae9e-cdb1-060e-0477-73fa92739...@monom.org> Content-Type: text/plain; charset=utf-8; format=flowed On 10/28/2018 09:45 PM, Doron Behar wrote: > Confirmed, thanks. Okay. > You have no idea how much I am thrilled connman is being developed and > that it takes Linux networking to such a wonderful and comfortable > place. Thanks! > Can't wait for the next release. You are right, the last release is already a few months ago and we have a bunch of bug fixes and a couple of new features ready. > Thanks again for creating this beautifully designed software. :) Thanks, Daniel ------------------------------ Message: 2 Date: Sun, 28 Oct 2018 22:21:52 +0100 From: Daniel Wagner <w...@monom.org> To: natsuki.it...@sony.com Cc: connman@lists.01.org Subject: Re: [PATCHv6 6/6] wps: add new WPS API for technology Message-ID: <f515471a-e7b8-7285-f438-777c6d7fd...@monom.org> Content-Type: text/plain; charset=utf-8; format=flowed Hi Natsuki-san, On 10/11/2018 06:07 PM, natsuki.it...@sony.com wrote: > +void connman_technology_add_wps_offered(struct connman_technology > *technology, > + const char *path) > +{ > + char *dup_path = g_strdup(path); > + > + if (!dup_path) > + return; This check is not necessary, because g_strdup() will panic call abort() when it fails to allocate memory. So we never get here in this case. > + technology->wps_offered = > + g_slist_append(technology->wps_offered, dup_path); > +} > + > +static void append_wps_service_structs(DBusMessageIter *iter, void > *user_data) > +{ > + struct connman_technology *technology = user_data; > + GSList *list; > + > + for (list = technology->wps_offered; list; list = list->next) { > + const char *ident = list->data; > + struct connman_service *service; > + > + service = __connman_service_lookup_from_ident(ident); > + if (!service) > + continue; > + __connman_service_append_struct(service, iter); > + } > +} > + > +static DBusMessage > +*create_reply_start_sta_wps_success( > + struct connman_technology *technology, > + DBusMessage *reply) Go with this formatting: static DBusMessage *create_reply_start_sta_wps_success( struct connman_technolog *technology, DBusMessage *reply) > +{ > + DBusMessage *msg; > + > + msg = dbus_message_new_method_return(reply); > + if (!msg) > + return NULL; > + > + __connman_dbus_append_objpath_dict_array(msg, > + append_wps_service_structs, > + technology); > + > + return msg; > +} > + > +static void free_wps_offered(gpointer data, gpointer user_data) > +{ > + if (!data) > + return; > + > + g_free(data); > +} > + > +void > +connman_technology_reply_start_sta_wps(struct connman_technology *technology, > + int error) > +{ > + DBusMessage *reply; > + > + if (!technology->wps_reply) > + return; > + > + if (!error) { > + reply = create_reply_start_sta_wps_success(technology, > + technology->wps_reply); > + } else > + reply = __connman_error_failed(technology->wps_reply, -error); > + > + g_dbus_send_message(connection, reply); > + > + dbus_message_unref(technology->wps_reply); > + technology->wps_reply = NULL; > + > + g_slist_foreach(technology->wps_offered, free_wps_offered, NULL); > + g_slist_free(technology->wps_offered); You can write this as g_slist_free_full(technology->wps_offered, g_free); and remove free_wps_offered() completely. > + technology->wps_offered = NULL; > +} > + > +static int start_wps(struct connman_technology *technology, > + DBusMessage *msg, enum connman_technology_wps_mode mode) > +{ > + GSList *tech_drivers; > + DBusMessageIter iter; > + enum connman_peer_wps_method wps_method; > + const char *auth; > + int err, result = -EOPNOTSUPP; > + > + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) > + return -EOPNOTSUPP; > + > + __sync_synchronize(); Please remove __sync_synchronize(). This has no effect in a single threaded application. > + if (!technology->enabled) > + return -EACCES; > + > + if (!dbus_message_iter_init(msg, &iter)) > + return -EINVAL; > + > + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) > + return -EINVAL; > + > + dbus_message_iter_get_basic(&iter, &auth); > + > + wps_method = __connman_check_wps_method(auth); > + if (wps_method == CONNMAN_PEER_WPS_UNKNOWN) > + return -EINVAL; > + if (wps_method == CONNMAN_PEER_WPS_PBC) > + auth = NULL; > + > + for (tech_drivers = technology->driver_list; tech_drivers; > + tech_drivers = g_slist_next(tech_drivers)) { > + struct connman_technology_driver *driver = tech_drivers->data; > + > + if (!driver || > + !driver->start_wps || > + driver->type != CONNMAN_SERVICE_TYPE_WIFI) > + continue; hmm, at least write this way: if (!driver || !driver->start_wps || driver->type != CONNMAN_SERVICE_TYPE_WIFI) continue; > + > + err = driver->start_wps(technology, mode, auth); > + > + if (result == -EINPROGRESS) > + continue; > + > + if (err == -EINPROGRESS) > + result = err; > + } > + > + return result; > +} > + > +static DBusMessage *start_ap_wps(DBusConnection *conn, DBusMessage *msg, > + void *user_data) > +{ > + struct connman_technology *technology = user_data; > + int err; > + > + /* It is required to enable tethering before starting WPS in AP mode */ > + if (!technology->tethering) { > + DBG("Error: Tethering is required"); This doesn't look like a real error. I suggest you just remove this DBG because you send out this: > + return __connman_error_permission_denied(msg); which is observable. Thanks, Daniel ------------------------------ Message: 3 Date: Mon, 29 Oct 2018 00:37:26 +0200 From: Vasyl Vavrychuk <vasyl.vavryc...@globallogic.com> To: connman@lists.01.org Cc: Daniel Wagner <w...@monom.org>, Vasyl Vavrychuk <vasyl.vavryc...@globallogic.com> Subject: [PATCH] wifi: implemented feature of tracking tethering clients Message-ID: <20181028223726.18661-1-vasyl.vavryc...@globallogic.com> wpa_supplicant supports StaAuthorized StaDeauthorized D-Bus signal that we handle and store information. Then stored information about connected tethering clients is exposed via GetTetheringClients method and TetheringClientsChanged signal of manager. --- Makefile.am | 3 +- client/commands.c | 27 ++++++++ client/tethering.c | 62 +++++++++++++++++++ client/tethering.h | 38 ++++++++++++ doc/manager-api.txt | 12 ++++ gsupplicant/gsupplicant.h | 4 ++ gsupplicant/supplicant.c | 64 +++++++++++++++++++ include/tethering.h | 36 +++++++++++ plugins/wifi.c | 29 +++++++++ src/connman.h | 3 + src/manager.c | 24 ++++++++ src/tethering.c | 126 ++++++++++++++++++++++++++++++++++++++ 12 files changed, 427 insertions(+), 1 deletion(-) create mode 100644 client/tethering.c create mode 100644 client/tethering.h create mode 100644 include/tethering.h diff --git a/Makefile.am b/Makefile.am index d6dfbf1c..4614cb90 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,7 +12,7 @@ include_HEADERS = include/log.h include/plugin.h \ include/storage.h include/provision.h \ include/session.h include/ipaddress.h include/agent.h \ include/inotify.h include/peer.h include/machine.h \ - include/acd.h + include/acd.h include/tethering.h nodist_include_HEADERS = include/version.h @@ -308,6 +308,7 @@ client_connmanctl_SOURCES = client/dbus_helpers.h client/dbus_helpers.c \ client/input.h client/input.c \ client/agent.h client/agent.c \ client/peers.h client/peers.c \ + client/tethering.h client/tethering.c \ client/vpnconnections.h client/vpnconnections.c \ client/main.c diff --git a/client/commands.c b/client/commands.c index bf3531fd..26d2c509 100644 --- a/client/commands.c +++ b/client/commands.c @@ -318,6 +318,18 @@ static int peers_list(DBusMessageIter *iter, return 0; } +static int tethering_clients_list(DBusMessageIter *iter, + const char *error, void *user_data) +{ + if (!error) { + __connmanctl_tethering_clients_list(iter); + fprintf(stdout, "\n"); + } else + fprintf(stderr, "Error: %s\n", error); + + return 0; +} + static int object_properties(DBusMessageIter *iter, const char *error, void *user_data) { @@ -639,6 +651,19 @@ static int cmd_tether(char *args[], int num, struct connman_option *options) return tether_set(args[1], set_tethering); } +static int cmd_tethering_clients(char *args[], int num, struct connman_option *options) +{ + char *path; + + if (num > 1) + return -E2BIG; + + return __connmanctl_dbus_method_call(connection, + CONNMAN_SERVICE, CONNMAN_PATH, + "net.connman.Manager", "GetTetheringClients", + tethering_clients_list, NULL, NULL, NULL); +} + static int scan_return(DBusMessageIter *iter, const char *error, void *user_data) { @@ -2730,6 +2755,8 @@ static const struct { NULL, cmd_tether, "Enable, disable tethering, set SSID and passphrase for wifi", lookup_tether }, + { "tethering_clients", NULL, NULL, cmd_tethering_clients, + "Display tethering clients", NULL }, { "services", "[<service>]", service_options, cmd_services, "Display services", lookup_service_arg }, { "peers", "[peer]", NULL, cmd_peers, diff --git a/client/tethering.c b/client/tethering.c new file mode 100644 index 00000000..ce3688a4 --- /dev/null +++ b/client/tethering.c @@ -0,0 +1,62 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2014 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <stdio.h> + +#include "tethering.h" + +void __connmanctl_tethering_clients_list(DBusMessageIter *iter) +{ + DBusMessageIter array; + char *addr = NULL; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { + dbus_message_iter_get_basic(&array, &addr); + + fprintf(stdout, "%s", addr); + + if (dbus_message_iter_has_next(&array)) + fprintf(stdout, "\n"); + + dbus_message_iter_next(&array); + } + + dbus_message_iter_next(iter); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { + dbus_message_iter_get_basic(&array, &addr); + + fprintf(stdout, "\n%s %s", "removed", addr); + + if (dbus_message_iter_has_next(&array)) + fprintf(stdout, "\n"); + + dbus_message_iter_next(&array); + } +} diff --git a/client/tethering.h b/client/tethering.h new file mode 100644 index 00000000..c6b58de1 --- /dev/null +++ b/client/tethering.h @@ -0,0 +1,38 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2014 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMANCTL_TETHERING_H +#define __CONNMANCTL_TETHERING_H + +#include <dbus/dbus.h> + +#ifdef __cplusplus +extern "C" { +#endif + +void __connmanctl_tethering_clients_list(DBusMessageIter *iter); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONNMANCTL_TETHERING_H */ diff --git a/doc/manager-api.txt b/doc/manager-api.txt index 2d2739ff..bfb07bd3 100644 --- a/doc/manager-api.txt +++ b/doc/manager-api.txt @@ -46,6 +46,11 @@ Methods dict GetProperties() Possible Errors: [service].Error.InvalidArguments + array{string} GetTetheringClients() [experimental] + + Returns a sorted list of MAC addresses of clients + connected to tethered technologies. + object ConnectProvider(dict provider) [deprecated] Connect to a VPN specified by the given provider @@ -255,6 +260,13 @@ Signals TechnologyAdded(object path, dict properties) object changes. For that it is required to watch the PropertyChanged signal of the peer object. + TetheringClientsChanged(array{string}, array{string}) [experimental] + + This signal indicates a change in the tethering clients. + List of all tethering clients currently registered connman is + passed via the first array. And a list of tethering clients that + have been removed via the second array. + PropertyChanged(string name, variant value) This signal indicates a changed value of the given diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h index db61595b..bfb52db7 100644 --- a/gsupplicant/gsupplicant.h +++ b/gsupplicant/gsupplicant.h @@ -352,6 +352,10 @@ struct _GSupplicantCallbacks { void (*network_changed) (GSupplicantNetwork *network, const char *property); void (*network_associated) (GSupplicantNetwork *network); + void (*sta_authorized) (GSupplicantInterface *interface, + const char *addr); + void (*sta_deauthorized) (GSupplicantInterface *interface, + const char *addr); void (*peer_found) (GSupplicantPeer *peer); void (*peer_lost) (GSupplicantPeer *peer); void (*peer_changed) (GSupplicantPeer *peer, diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c index 0cb621b9..12391482 100644 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -614,6 +614,30 @@ static void callback_network_associated(GSupplicantNetwork *network) callbacks_pointer->network_associated(network); } +static void callback_sta_authorized(GSupplicantInterface *interface, + const char *addr) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->sta_authorized) + return; + + callbacks_pointer->sta_authorized(interface, addr); +} + +static void callback_sta_deauthorized(GSupplicantInterface *interface, + const char *addr) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->sta_deauthorized) + return; + + callbacks_pointer->sta_deauthorized(interface, addr); +} + static void callback_peer_found(GSupplicantPeer *peer) { if (!callbacks_pointer) @@ -2731,6 +2755,44 @@ static void signal_network_removed(const char *path, DBusMessageIter *iter) interface_network_removed(iter, interface); } +static void signal_sta_authorized(const char *path, DBusMessageIter *iter) +{ + GSupplicantInterface *interface; + DBusMessageIter array; + const char *addr = NULL; + + SUPPLICANT_DBG(""); + + interface = g_hash_table_lookup(interface_table, path); + if (!interface) + return; + + dbus_message_iter_get_basic(iter, &addr); + if (!addr) + return; + + callback_sta_authorized(interface, addr); +} + +static void signal_sta_deauthorized(const char *path, DBusMessageIter *iter) +{ + GSupplicantInterface *interface; + DBusMessageIter array; + const char *addr = NULL; + + SUPPLICANT_DBG(""); + + interface = g_hash_table_lookup(interface_table, path); + if (!interface) + return; + + dbus_message_iter_get_basic(iter, &addr); + if (!addr) + return; + + callback_sta_deauthorized(interface, addr); +} + static void signal_bss_changed(const char *path, DBusMessageIter *iter) { GSupplicantInterface *interface; @@ -3505,6 +3567,8 @@ static struct { { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved", signal_bss_removed }, { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded", signal_network_added }, { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved", signal_network_removed }, + { SUPPLICANT_INTERFACE ".Interface", "StaAuthorized", signal_sta_authorized }, + { SUPPLICANT_INTERFACE ".Interface", "StaDeauthorized", signal_sta_deauthorized }, { SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed }, diff --git a/include/tethering.h b/include/tethering.h new file mode 100644 index 00000000..0d29b235 --- /dev/null +++ b/include/tethering.h @@ -0,0 +1,36 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2007-2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMAN_TETHERING_H +#define __CONNMAN_TETHERING_H + +#ifdef __cplusplus +extern "C" { +#endif + +void __connman_tethering_client_register(const char *addr); +void __connman_tethering_client_unregister(const char *addr); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONNMAN_TETHERING_H */ diff --git a/plugins/wifi.c b/plugins/wifi.c index e437daeb..6fa20312 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -55,6 +55,7 @@ #include <connman/provision.h> #include <connman/utsname.h> #include <connman/machine.h> +#include <connman/tethering.h> #include <gsupplicant/gsupplicant.h> @@ -2985,6 +2986,32 @@ static void network_associated(GSupplicantNetwork *network) interface_state(interface); } +static void sta_authorized(GSupplicantInterface *interface, + const char *addr) +{ + struct wifi_data *wifi = g_supplicant_interface_get_data(interface); + + DBG("wifi %p station %s authorized", wifi, addr); + + if (!wifi || !wifi->tethering) + return; + + __connman_tethering_client_register(addr); +} + +static void sta_deauthorized(GSupplicantInterface *interface, + const char *addr) +{ + struct wifi_data *wifi = g_supplicant_interface_get_data(interface); + + DBG("wifi %p station %s deauthorized", wifi, addr); + + if (!wifi || !wifi->tethering) + return; + + __connman_tethering_client_unregister(addr); +} + static void apply_peer_services(GSupplicantPeer *peer, struct connman_peer *connman_peer) { @@ -3205,6 +3232,8 @@ static const GSupplicantCallbacks callbacks = { .network_removed = network_removed, .network_changed = network_changed, .network_associated = network_associated, + .sta_authorized = sta_authorized, + .sta_deauthorized = sta_deauthorized, .peer_found = peer_found, .peer_lost = peer_lost, .peer_changed = peer_changed, diff --git a/src/connman.h b/src/connman.h index 13553833..dfcacc62 100644 --- a/src/connman.h +++ b/src/connman.h @@ -630,12 +630,15 @@ bool __connman_config_get_bool(GKeyFile *key_file, bool __connman_config_address_provisioned(const char *address, const char *netmask); +#include <connman/tethering.h> + int __connman_tethering_init(void); void __connman_tethering_cleanup(void); const char *__connman_tethering_get_bridge(void); int __connman_tethering_set_enabled(void); void __connman_tethering_set_disabled(void); +void __connman_tethering_list_clients(DBusMessageIter *array); int __connman_private_network_request(DBusMessage *msg, const char *owner); int __connman_private_network_release(const char *path); diff --git a/src/manager.c b/src/manager.c index d15ce203..b2de863c 100644 --- a/src/manager.c +++ b/src/manager.c @@ -214,6 +214,27 @@ static DBusMessage *get_peers(DBusConnection *conn, return reply; } +static DBusMessage *get_tethering_clients(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + DBusMessage *reply; + DBusMessageIter iter, array; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &array); + + __connman_tethering_list_clients(&array); + + dbus_message_iter_close_container(&iter, &array); + return reply; +} + static DBusMessage *connect_provider(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -519,6 +540,9 @@ static const GDBusMethodTable manager_methods[] = { { GDBUS_METHOD("GetPeers", NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }), get_peers) }, + { GDBUS_METHOD("GetTetheringClients", + NULL, GDBUS_ARGS({ "tethering_clients", "as" }), + get_tethering_clients) }, { GDBUS_DEPRECATED_ASYNC_METHOD("ConnectProvider", GDBUS_ARGS({ "provider", "a{sv}" }), GDBUS_ARGS({ "path", "o" }), diff --git a/src/tethering.c b/src/tethering.c index d222afca..61951075 100644 --- a/src/tethering.c +++ b/src/tethering.c @@ -61,6 +61,13 @@ static struct connman_ippool *dhcp_ippool = NULL; static DBusConnection *connection; static GHashTable *pn_hash; +static GHashTable *clients_table = NULL; + +struct _clients_notify { + int id; + GHashTable *remove; +} *clients_notify; + struct connman_private_network { char *owner; char *path; @@ -181,6 +188,18 @@ static void tethering_restart(struct connman_ippool *pool, void *user_data) __connman_tethering_set_enabled(); } +static void unregister_client(gpointer key, + gpointer value, gpointer user_data) +{ + const char *addr = key; + __connman_tethering_client_unregister(addr); +} + +static void unregister_all_clients(void) +{ + g_hash_table_foreach(clients_table, unregister_client, NULL); +} + int __connman_tethering_set_enabled(void) { int index; @@ -301,6 +320,8 @@ void __connman_tethering_set_disabled(void) if (__sync_fetch_and_sub(&tethering_enabled, 1) != 1) return; + unregister_all_clients(); + __connman_ipv6pd_cleanup(); index = connman_inet_ifindex(BRIDGE_NAME); @@ -327,6 +348,21 @@ void __connman_tethering_set_disabled(void) DBG("tethering stopped"); } +static void append_client(gpointer key, gpointer value, + gpointer user_data) +{ + const char *addr = key; + DBusMessageIter *array = user_data; + + dbus_message_iter_append_basic(array, DBUS_TYPE_STRING, + &addr); +} + +void __connman_tethering_list_clients(DBusMessageIter *array) +{ + g_hash_table_foreach(clients_table, append_client, array); +} + static void setup_tun_interface(unsigned int flags, unsigned change, void *data) { @@ -440,6 +476,70 @@ static void ippool_disconnect(struct connman_ippool *pool, void *user_data) g_hash_table_remove(pn_hash, pn->path); } +static gboolean client_send_changed(gpointer data) +{ + DBusMessage *signal; + DBusMessageIter iter, array; + + DBG(""); + + clients_notify->id = 0; + + signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE, "TetheringClientsChanged"); + if (!signal) + return FALSE; + + dbus_message_iter_init_append(signal, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &array); + + g_hash_table_foreach(clients_table, append_client, &array); + + dbus_message_iter_close_container(&iter, &array); + + dbus_message_iter_init_append(signal, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &array); + + g_hash_table_foreach(clients_notify->remove, append_client, &array); + + dbus_message_iter_close_container(&iter, &array); + + dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); + + g_hash_table_remove_all(clients_notify->remove); + + return FALSE; +} + +static void client_schedule_changed(void) +{ + if (clients_notify->id != 0) + return; + + clients_notify->id = g_timeout_add(100, client_send_changed, NULL); +} + +static void client_added(const char *addr) +{ + DBG("client %s", addr); + + g_hash_table_remove(clients_notify->remove, addr); + + client_schedule_changed(); +} + +static void client_removed(const char *addr) +{ + DBG("client %s", addr); + + g_hash_table_replace(clients_notify->remove, g_strdup(addr), NULL); + + client_schedule_changed(); +} + int __connman_private_network_request(DBusMessage *msg, const char *owner) { struct connman_private_network *pn; @@ -529,6 +629,18 @@ int __connman_private_network_release(const char *path) return 0; } +void __connman_tethering_client_register(const char *addr) +{ + g_hash_table_insert(clients_table, g_strdup(addr), NULL); + client_added(addr); +} + +void __connman_tethering_client_unregister(const char *addr) +{ + g_hash_table_remove(clients_table, g_strdup(addr)); + client_removed(addr); +} + int __connman_tethering_init(void) { DBG(""); @@ -542,6 +654,12 @@ int __connman_tethering_init(void) pn_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, remove_private_network); + clients_table = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + + clients_notify = g_new0(struct _clients_notify, 1); + clients_notify->remove = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); return 0; } @@ -562,5 +680,13 @@ void __connman_tethering_cleanup(void) return; g_hash_table_destroy(pn_hash); + + g_hash_table_destroy(clients_notify->remove); + g_free(clients_notify); + clients_notify = NULL; + + g_hash_table_destroy(clients_table); + clients_table = NULL; + dbus_connection_unref(connection); } -- 2.19.1 ------------------------------ Subject: Digest Footer _______________________________________________ connman mailing list connman@lists.01.org https://lists.01.org/mailman/listinfo/connman ------------------------------ End of connman Digest, Vol 36, Issue 25 ***************************************