From 23ceb5e590a1f439480fde1098cc3f04a970a010 Mon Sep 17 00:00:00 2001 From: Jiwan Kim Date: Mon, 6 Mar 2017 15:40:00 +0900 Subject: [PATCH] Add functions to get scan result - for 'get_found_mesh_networks' method --- include/mesh-netlink.h | 1 + include/mesh-request.h | 1 + include/mesh.h | 11 ++++ introspection/mesh.xml | 2 +- src/mesh-netlink.c | 119 ++++++++++++++++++++++++++++++++++--------- src/mesh-request.c | 15 ++++++ src/mesh-service-interface.c | 93 +++++++++++++++++++++++++-------- 7 files changed, 195 insertions(+), 47 deletions(-) diff --git a/include/mesh-netlink.h b/include/mesh-netlink.h index db9f2e9..cc55bf2 100644 --- a/include/mesh-netlink.h +++ b/include/mesh-netlink.h @@ -28,6 +28,7 @@ int mesh_netlink_trigger_full_scan(const char* mesh_if_name); int mesh_netlink_trigger_specific_scan(const char* mesh_if_name, const char* mesh_id, int channel); int mesh_netlink_cancel_scan(const char* mesh_if_name); +int mesh_netlink_get_scan_result(const char* mesh_if_name, GList **scan_list); int mesh_netlink_set_mesh_parameter(const char* mesh_if_name, const char* param_name, unsigned int value); diff --git a/include/mesh-request.h b/include/mesh-request.h index fc70b1d..7fbab89 100644 --- a/include/mesh-request.h +++ b/include/mesh-request.h @@ -33,6 +33,7 @@ int mesh_request_scan(const char* mesh_interface); int mesh_request_specific_scan(const char* mesh_interface, const char* mesh_id, int mesh_channel); int mesh_request_cancel_scan(const char* mesh_interface); +int mesh_request_get_scan_result(const char* mesh_interface, GList **scan_list); /* Saved network */ int mesh_request_add_mesh_network(mesh_service *service, diff --git a/include/mesh.h b/include/mesh.h index ccc2048..6d65285 100644 --- a/include/mesh.h +++ b/include/mesh.h @@ -44,6 +44,16 @@ typedef struct { gint mesh_channel; /**< The channel number of mesh network */ } mesh_interface_s; +/**< Mesh network scan result structure */ +typedef struct { + gchar *mesh_id; /**< The mesh id */ + gint mesh_id_len; /**< Length of mesh id */ + gchar *bssid; /**< BSSID */ + gint rssi; /**< RSSI */ + gint channel; /**< Channel */ + gint data_rate; /**< Data rate */ +} mesh_scan_result_s; + /**< mesh service structure */ typedef struct _mesh_service { GMainLoop *main_loop; /**< Service main-loop */ @@ -52,6 +62,7 @@ typedef struct _mesh_service { mesh_interface_s *interface_info; /**< Name of network interfaces */ gboolean mesh_activated; /**< Stored if mesh network is activated */ GList *saved_mesh_network; /**< Saved mesh network list */ + GList *scanned_mesh_network; /**< Scanned mesh network list */ } mesh_service; #endif /* __MESH_H__ */ diff --git a/introspection/mesh.xml b/introspection/mesh.xml index 304763f..996aa12 100644 --- a/introspection/mesh.xml +++ b/introspection/mesh.xml @@ -25,7 +25,7 @@ - + diff --git a/src/mesh-netlink.c b/src/mesh-netlink.c index 2dda0cd..ae81762 100644 --- a/src/mesh-netlink.c +++ b/src/mesh-netlink.c @@ -70,6 +70,7 @@ typedef struct { gchar* scanning_interface; bool error_occured; + GList **scan_list; } mesh_nl_state; typedef struct { @@ -84,9 +85,6 @@ gboolean _handle_nl_response_message(GIOChannel *source, GIOCondition condition, gpointer data); #endif -static int _send_nl_get_scan_result(const char* if_name); -static int _on_receive_bss_information(struct nl_msg *msg, void *arg); - static int __channel_to_frequency(int channel, enum nl80211_band band) { if (channel <= 0) @@ -113,6 +111,22 @@ static int __channel_to_frequency(int channel, enum nl80211_band band) return 0; } +static int __frequency_to_channel(int freq) +{ + if (freq == 2484) + return 14; + else if (freq < 2484) + return (freq - 2407) / 5; + else if (freq >= 4910 && freq <= 4980) + return (freq - 4000) / 5; + else if (freq <= 45000) + return (freq - 5000) / 5; + else if (freq >= 58320 && freq <= 64800) + return (freq - 56160) / 2160; + else + return 0; +} + static int __initialize_nl80211(mesh_nl_state *state) { int err = MESHD_ERROR_NONE; @@ -446,7 +460,6 @@ static void register_handler(int (*handler)(struct nl_msg *, void *), void *data mesh_nl_event_callback = handler; mesh_nl_event_callback_data = data; } -#endif static gboolean _dump_scan_results(gpointer user_data) { @@ -462,6 +475,7 @@ static gboolean _dump_scan_results(gpointer user_data) g_free(if_name); return G_SOURCE_REMOVE; } +#endif static int valid_handler(struct nl_msg *msg, void *arg) { @@ -472,21 +486,15 @@ static int valid_handler(struct nl_msg *msg, void *arg) if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED) { MESH_LOGD(" Got NL80211_CMD_SCAN_ABORTED."); state->callback_state = MESH_NL_CALLBACK_FINISHED; - scan_in_progress = FALSE; /* Notify scan done status */ mesh_notify_scan_done(); } else if (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS) { - guint id = 0; MESH_LOGD(" Got NL80211_CMD_NEW_SCAN_RESULTS."); state->callback_state = MESH_NL_CALLBACK_FINISHED; - scan_in_progress = FALSE; /* Notify scan done status */ mesh_notify_scan_done(); - - id = g_idle_add(_dump_scan_results, g_strdup(state->scanning_interface)); - MESH_LOGD("request scan result dump [id:%d]", id); } else { MESH_LOGD(" Got [%d]", gnlh->cmd); } @@ -868,12 +876,18 @@ static void mac_addr_n2a(char *mac_addr, unsigned char *arg) } // ASCII -static void print_ssid_escaped(const uint8_t len, const uint8_t *data) +static char* _get_meshid(const uint8_t len, const uint8_t *data) { int i; char buf[64] = {0, }; + char *result = g_try_malloc0(sizeof(char) * len+1); + if (NULL == result) { + MESH_LOGE("Failed to allocate"); + return NULL; + } for (i = 0; i < len; i++) { + result[i] = data[i]; if (/*isprint(data[i]) && */data[i] != ' ' && data[i] != '\\') //printf("%c", data[i]); buf[i] = data[i]; @@ -885,7 +899,10 @@ static void print_ssid_escaped(const uint8_t len, const uint8_t *data) //printf("\\x%.2x", data[i]); buf[i] = '?'; } + result[len] = '\0'; MESH_LOGD(" : %s", buf); + + return result; } static int _on_receive_bss_information(struct nl_msg *msg, void *arg) @@ -894,11 +911,14 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg) struct nlattr *bss[NL80211_BSS_MAX + 1]; struct genlmsghdr *general_header = nlmsg_data(nlmsg_hdr(msg)); mesh_nl_state *state = (mesh_nl_state *)arg; + mesh_scan_result_s *scan_info = NULL; char mac_addr[20], ifname[20]; + char *mesh_id = NULL; + guint mesh_id_len = 0; int signal_mbm = 0; unsigned char signal_un = 0; - int frequency; + int frequency = 0; int is_mesh_bss = FALSE; static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC }, @@ -909,7 +929,10 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg) [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC }, }; - NOTUSED(state); + if (NULL == state) { + MESH_LOGE("Invalid state data"); + goto FINISH; + } nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(general_header, 0), @@ -936,7 +959,8 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg) switch (ie[0]) { case MESH_ELEMENT_ID: /* MESH ID */ MESH_LOGD("MESH ID"); - print_ssid_escaped(len, ie+2); + mesh_id = _get_meshid(len, ie+2); + mesh_id_len = len; is_mesh_bss = TRUE; break; default: @@ -977,9 +1001,23 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg) MESH_LOGD(" signal: %d/100", signal_un); } + scan_info = g_try_new0(mesh_scan_result_s, 1); + if (NULL == scan_info) { + MESH_LOGE("Failed to allocate scan info !"); + goto FINISH; + } + + scan_info->mesh_id = g_memdup(mesh_id, mesh_id_len + 1); + scan_info->bssid = g_strdup(mac_addr); + scan_info->rssi = (signal_mbm != 0) ? signal_mbm : signal_un; + scan_info->channel = __frequency_to_channel(frequency); + scan_info->data_rate = 0; + *(state->scan_list) = g_list_prepend(*(state->scan_list), scan_info); + MESH_LOGD(""); FINISH: + g_free(mesh_id); return NL_SKIP; } @@ -1106,7 +1144,7 @@ DESTROY: return err; } -static int _send_nl_get_scan_result(const char* if_name) +static int _send_nl_get_scan_result(const char* if_name, GList **scan_list) { mesh_nl_state state = { .nl80211_id = -1, @@ -1116,7 +1154,8 @@ static int _send_nl_get_scan_result(const char* if_name) .msg = NULL, .cb = NULL, .s_cb = NULL, - .scanning_interface = (char*)if_name + .scanning_interface = (char*)if_name, + .scan_list = scan_list }; int err = MESHD_ERROR_NONE; int device_index = 0; @@ -1197,7 +1236,8 @@ static int _send_nl_trigger_specific_scan(const char* mesh_if_name, int i = 1; int test = 0; unsigned int freq = 0; - unsigned char mesh_ie[2]; + unsigned char *mesh_ie = NULL; + size_t mesh_id_len = 0; GIOChannel *recv_channel = NULL; if (scan_in_progress) { @@ -1261,20 +1301,24 @@ static int _send_nl_trigger_specific_scan(const char* mesh_if_name, freq = __channel_to_frequency(mesh_channel, band); NLA_PUT_U32(freqs, i, freq); - /* Set SSID to scan*/ - if (mesh_id) - NLA_PUT(ssids, i++, strlen(mesh_id), mesh_id); - else - NLA_PUT(ssids, 1, 0, ""); + /* Set default SSID to scan */ + NLA_PUT(ssids, 1, 0, ""); /* Set frequency and SSID into message */ nla_put_nested(state->msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs); nla_put_nested(state->msg, NL80211_ATTR_SCAN_SSIDS, ssids); - /* IMPORTANT: Add mesh_id to get mesh bss properly */ + /* IMPORTANT: Set mesh_id to find */ + mesh_id_len = strlen(mesh_id); + mesh_ie = g_try_malloc0(2 + mesh_id_len); + if (NULL == mesh_ie) { + err = MESHD_ERROR_OUT_OF_MEMORY; + goto DESTROY; + } mesh_ie[0] = MESH_ELEMENT_ID; /* Mesh element ID */ - mesh_ie[1] = 0; - NLA_PUT(state->msg, NL80211_ATTR_IE, 2, mesh_ie); + mesh_ie[1] = mesh_id_len; + memcpy(&mesh_ie[2], mesh_id, mesh_id_len); + NLA_PUT(state->msg, NL80211_ATTR_IE, 2 + mesh_id_len, mesh_ie); /* Set callbacks for scan */ nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, state); @@ -1708,6 +1752,31 @@ int mesh_netlink_cancel_scan(const char* mesh_if_name) return ret; } +int mesh_netlink_get_scan_result(const char* mesh_if_name, GList **scan_list) +{ + int ret = MESHD_ERROR_NONE; + + if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) { + MESH_LOGE("Invalid parameter [%p]", mesh_if_name); + return MESHD_ERROR_INVALID_PARAMETER; + } + if (NULL == scan_list) { + MESH_LOGE("Invalid parameter [%p]", scan_list); + return MESHD_ERROR_INVALID_PARAMETER; + } + + MESH_LOGD("Get scan result on [%s]", mesh_if_name); + ret = _send_nl_get_scan_result(mesh_if_name, scan_list); + + /* List item is saved with reversed order for efficiency. */ + *scan_list = g_list_reverse(*scan_list); + + /* Enter to scan idle state */ + scan_in_progress = FALSE; + + return ret; +} + int mesh_netlink_set_mesh_parameter(const char* mesh_if_name, const char* param_name, unsigned int value) { diff --git a/src/mesh-request.c b/src/mesh-request.c index 7d03d2c..67a339a 100644 --- a/src/mesh-request.c +++ b/src/mesh-request.c @@ -111,6 +111,21 @@ int mesh_request_cancel_scan(const char* mesh_interface) return ret; } +int mesh_request_get_scan_result(const char* mesh_interface, GList **scan_list) +{ + int ret = MESHD_ERROR_NONE; + + if (NULL == mesh_interface) { + MESH_LOGE("Invalid parameter"); + return MESHD_ERROR_INVALID_PARAMETER; + } + + /* Request cancel scan */ + ret = mesh_netlink_get_scan_result(mesh_interface, scan_list); + + return ret; +} + int mesh_request_disable_mesh_gate(const char* mesh_interface) { int ret = MESHD_ERROR_NONE; diff --git a/src/mesh-service-interface.c b/src/mesh-service-interface.c index 1477957..c9de49b 100644 --- a/src/mesh-service-interface.c +++ b/src/mesh-service-interface.c @@ -293,21 +293,35 @@ static gboolean _meshd_dbus_handle_cancel_scan(NetMesh *object, return TRUE; } +static void _on_scan_result_destroy(gpointer data) +{ + mesh_scan_result_s *scan_item = (mesh_scan_result_s *)data; + + if (scan_item) { + g_free(scan_item->mesh_id); + g_free(scan_item->bssid); + } +} + static gboolean _meshd_dbus_handle_get_found_mesh_networks(NetMesh *object, - GDBusMethodInvocation *invocation) + GDBusMethodInvocation *invocation, + gpointer user_data) { int ret = MESHD_ERROR_NONE; + mesh_service *service = (mesh_service *)user_data; + mesh_interface_s *info = service->interface_info; GVariantBuilder builder; GVariant* networks; + GList *iter = NULL; + mesh_scan_result_s *scan_item = NULL; - MESH_LOGD("Not implemented yet !"); + MESH_LOGD("Request to get scanned mesh network list"); /* TODO: Return scan results */ - /* * struct mesh_found_network_s { - * char *meshid; + * char *mesh_id; * char *bssid; * int channel; * int rssi; @@ -315,24 +329,60 @@ static gboolean _meshd_dbus_handle_get_found_mesh_networks(NetMesh *object, *}; */ - MESH_LOGD("Not implemented yet !"); + ret = mesh_request_get_scan_result(info->mesh_interface, &service->scanned_mesh_network); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to mesh_request_cancel_scan"); - /* TODO: Get station infomation and make variant data */ + g_dbus_method_invocation_return_error(invocation, + G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed"); + } else { + /* TODO: Get station information and make variant data */ + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + + /* For each network item */ + g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&builder, "{sv}", "mesh_id", g_variant_new_string("meshnet")); + g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:cf")); + g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-65)); + g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(161)); + g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(300)); + g_variant_builder_close(&builder); + + g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&builder, "{sv}", "mesh_id", g_variant_new_string("meshnet")); + g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:ce")); + g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-50)); + g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(6)); + g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(150)); + g_variant_builder_close(&builder); + + iter = service->scanned_mesh_network; + while (iter != NULL) { + scan_item = (mesh_scan_result_s*)iter->data; + + g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&builder, "{sv}", "mesh_id", + g_variant_new_string(scan_item->mesh_id)); + g_variant_builder_add(&builder, "{sv}", "bssid", + g_variant_new_string(scan_item->bssid)); + g_variant_builder_add(&builder, "{sv}", "rssi", + g_variant_new_uint32(scan_item->rssi)); + g_variant_builder_add(&builder, "{sv}", "channel", + g_variant_new_uint32(scan_item->channel)); + g_variant_builder_add(&builder, "{sv}", "data_rate", + g_variant_new_uint32(scan_item->data_rate)); + g_variant_builder_close(&builder); + + iter = g_list_next(iter); + } - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add(&builder, "{sv}", "meshid", g_variant_new_string("meshnet")); - g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:cf")); - g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-65)); - g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(161)); - g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(300)); - g_variant_builder_add(&builder, "{sv}", "meshid", g_variant_new_string("meshnet")); - g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:ce")); - g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-50)); - g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(6)); - g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(150)); - networks = g_variant_builder_end(&builder); - - net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret); + /* Clear scan list */ + g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy); + service->scanned_mesh_network = NULL; + + networks = g_variant_builder_end(&builder); + net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret); + } return TRUE; } @@ -426,7 +476,7 @@ static gboolean _meshd_dbus_handle_set_softap(NetMesh *object, MESH_LOGD("key = %s", key); MESH_LOGD("mode = %s", mode); MESH_LOGD("channel = %d", channel); - MESH_LOGD("visibilty = %d", visibility); + MESH_LOGD("visibility = %d", visibility); MESH_LOGD("max_sta = %d", max_sta); MESH_LOGD("security = %d", security); @@ -765,6 +815,7 @@ static gboolean _meshd_dbus_interface_init(mesh_service *service) service->dbus_id = id; service->interface_info = g_new0(mesh_interface_s, 1); + service->scanned_mesh_network = NULL; return TRUE; } -- 2.7.4