These handlers make the link between the requested connection and the
interface of the group instanciated in case of a successful group
negociation.
---
 gsupplicant/gsupplicant.h |   5 ++
 gsupplicant/supplicant.c  | 160 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 161 insertions(+), 4 deletions(-)

diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
index 99f9d90..6f79125 100644
--- a/gsupplicant/gsupplicant.h
+++ b/gsupplicant/gsupplicant.h
@@ -80,6 +80,9 @@ extern "C" {
 
 #define G_SUPPLICANT_WPS_CONFIG_PBC    0x0080
 
+#define G_SUPPLICANT_GROUP_ROLE_CLIENT (1 << 0)
+#define G_SUPPLICANT_GROUP_ROLE_GO      (1 << 1)
+
 typedef enum {
        G_SUPPLICANT_MODE_UNKNOWN,
        G_SUPPLICANT_MODE_INFRA,
@@ -239,9 +242,11 @@ int 
g_supplicant_interface_set_p2p_device_config(GSupplicantInterface *interface
 /* Network and Peer API */
 struct _GSupplicantNetwork;
 struct _GSupplicantPeer;
+struct _GSupplicantGroup;
 
 typedef struct _GSupplicantNetwork GSupplicantNetwork;
 typedef struct _GSupplicantPeer GSupplicantPeer;
+typedef struct _GSupplicantGroup GSupplicantGroup;
 
 GSupplicantInterface *g_supplicant_network_get_interface(GSupplicantNetwork 
*network);
 const char *g_supplicant_network_get_name(GSupplicantNetwork *network);
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
index 85b51b3..3871994 100644
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -31,6 +31,7 @@
 #include <syslog.h>
 #include <ctype.h>
 #include <stdbool.h>
+#include <netinet/if_ether.h>
 
 #include <glib.h>
 #include <gdbus.h>
@@ -169,6 +170,7 @@ struct _GSupplicantInterface {
        GSupplicantWpsState wps_state;
        GHashTable *network_table;
        GHashTable *peer_table;
+       GHashTable *group_table;
        GHashTable *net_mapping;
        GHashTable *bss_mapping;
        void *data;
@@ -220,12 +222,19 @@ struct _GSupplicantNetwork {
 struct _GSupplicantPeer {
        GSupplicantInterface *interface;
        char *path;
-       unsigned char device_address[6];
+       unsigned char device_address[ETH_ALEN];
+       unsigned char iface_address[ETH_ALEN];
        char *name;
        char *identifier;
        unsigned int wps_capabilities;
 };
 
+struct _GSupplicantGroup {
+       GSupplicantInterface *interface;
+       char *path;
+       int role;
+};
+
 static inline void debug(const char *format, ...)
 {
        char str[256];
@@ -478,6 +487,14 @@ static void callback_peer_lost(GSupplicantPeer *peer)
        callbacks_pointer->peer_lost(peer);
 }
 
+static void remove_group(gpointer data)
+{
+       GSupplicantGroup *group = data;
+
+       g_free(group->path);
+       g_free(group);
+}
+
 static void remove_interface(gpointer data)
 {
        GSupplicantInterface *interface = data;
@@ -486,6 +503,7 @@ static void remove_interface(gpointer data)
        g_hash_table_destroy(interface->net_mapping);
        g_hash_table_destroy(interface->network_table);
        g_hash_table_destroy(interface->peer_table);
+       g_hash_table_destroy(interface->group_table);
 
        if (interface->scan_callback) {
                SUPPLICANT_DBG("call interface %p callback %p scanning %d",
@@ -1936,6 +1954,8 @@ static GSupplicantInterface *interface_alloc(const char 
*path)
                                        g_str_equal, NULL, remove_network);
        interface->peer_table = g_hash_table_new_full(g_str_hash,
                                        g_str_equal, NULL, remove_peer);
+       interface->group_table = g_hash_table_new_full(g_str_hash,
+                                       g_str_equal, NULL, remove_group);
        interface->net_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                                NULL, NULL);
        interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -2425,12 +2445,12 @@ static void signal_wps_event(const char *path, 
DBusMessageIter *iter)
 
 static void create_peer_identifier(GSupplicantPeer *peer)
 {
-       const unsigned char test[6] = {};
+       const unsigned char test[ETH_ALEN] = {};
 
        if (!peer)
                return;
 
-       if (!memcmp(peer->device_address, test, 6)) {
+       if (!memcmp(peer->device_address, test, ETH_ALEN)) {
                peer->identifier = g_strdup(peer->name);
                return;
        }
@@ -2472,7 +2492,7 @@ static void peer_property(const char *key, 
DBusMessageIter *iter,
                dbus_message_iter_recurse(iter, &array);
                dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
 
-               if (len == 6)
+               if (len == ETH_ALEN)
                        memcpy(peer->device_address, dev_addr, len);
        } else if (g_strcmp0(key, "DeviceName") == 0) {
                const char *str = NULL;
@@ -2555,6 +2575,133 @@ static void signal_peer_lost(const char *path, 
DBusMessageIter *iter)
        g_hash_table_remove(interface->peer_table, obj_path);
 }
 
+struct group_sig_data {
+       const char *peer_obj_path;
+       unsigned char iface_address[ETH_ALEN];
+       const char *interface_obj_path;
+       const char *group_obj_path;
+       int role;
+};
+
+static void group_sig_property(const char *key, DBusMessageIter *iter,
+                                                       void *user_data)
+{
+       struct group_sig_data *data = user_data;
+
+       if (!key)
+               return;
+
+       if (g_strcmp0(key, "peer_interface_addr") == 0) {
+               unsigned char *dev_addr;
+               DBusMessageIter array;
+               int len;
+
+               dbus_message_iter_recurse(iter, &array);
+               dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
+
+               if (len == ETH_ALEN)
+                       memcpy(data->iface_address, dev_addr, len);
+
+       } else if (g_strcmp0(key, "role") == 0) {
+               const char *str = NULL;
+
+               dbus_message_iter_get_basic(iter, &str);
+               if (g_strcmp0(str, "GO") == 0)
+                       data->role = G_SUPPLICANT_GROUP_ROLE_GO;
+               else
+                       data->role = G_SUPPLICANT_GROUP_ROLE_CLIENT;
+       } else if (g_strcmp0(key, "peer_object") == 0)
+               dbus_message_iter_get_basic(iter, &data->peer_obj_path);
+       else if (g_strcmp0(key, "interface_object") == 0)
+               dbus_message_iter_get_basic(iter, &data->interface_obj_path);
+       else if (g_strcmp0(key, "group_object") == 0)
+               dbus_message_iter_get_basic(iter, &data->group_obj_path);
+
+}
+
+static void signal_group_success(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       struct group_sig_data data = {};
+       GSupplicantPeer *peer;
+
+       SUPPLICANT_DBG("");
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       supplicant_dbus_property_foreach(iter, group_sig_property, &data);
+       if (!data.peer_obj_path)
+               return;
+
+       peer = g_hash_table_lookup(interface->peer_table, data.peer_obj_path);
+       if (!peer)
+               return;
+
+       memcpy(peer->iface_address, data.iface_address, ETH_ALEN);
+}
+
+static void signal_group_failure(const char *path, DBusMessageIter *iter)
+{
+       SUPPLICANT_DBG("");
+}
+
+static void signal_group_started(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       struct group_sig_data data = {};
+       GSupplicantGroup *group;
+
+       SUPPLICANT_DBG("");
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       supplicant_dbus_property_foreach(iter, group_sig_property, &data);
+       if (!data.interface_obj_path || !data.group_obj_path)
+               return;
+
+       interface = g_hash_table_lookup(interface_table,
+                                               data.interface_obj_path);
+       if (!interface)
+               return;
+
+       group = g_hash_table_lookup(interface->group_table,
+                                               data.group_obj_path);
+       if (group)
+               return;
+
+       group = g_try_new0(GSupplicantGroup, 1);
+       if (!group)
+               return;
+
+       group->interface = interface;
+       group->path = g_strdup(data.group_obj_path);
+       group->role = data.role;
+
+       g_hash_table_insert(interface->group_table, group->path, group);
+}
+
+static void signal_group_finished(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       struct group_sig_data data = {};
+
+       SUPPLICANT_DBG("");
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       supplicant_dbus_property_foreach(iter, group_sig_property, &data);
+       if (!data.interface_obj_path || !data.group_obj_path)
+               return;
+
+       g_hash_table_remove(interface->group_table, data.group_obj_path);
+}
+
 static struct {
        const char *interface;
        const char *member;
@@ -2582,6 +2729,11 @@ static struct {
        { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", 
signal_peer_found },
        { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost",  
signal_peer_lost  },
 
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationSuccess", 
signal_group_success },
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationFailure", 
signal_group_failure },
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupStarted", 
signal_group_started },
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupFinished", 
signal_group_finished },
+
        { }
 };
 
-- 
1.8.5.5

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to