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
***************************************

Reply via email to