Add mesh join/left event handler
authorJiwan Kim <ji-wan.kim@samsung.com>
Mon, 13 Mar 2017 10:29:25 +0000 (19:29 +0900)
committersaerome.kim <saerome.kim@samsung.com>
Mon, 17 Jul 2017 02:35:36 +0000 (11:35 +0900)
include/mesh-netlink.h
include/mesh-request.h
introspection/mesh.xml
src/mesh-netlink.c
src/mesh-request.c
src/mesh-service-interface.c

index 07f93ab..8815b66 100644 (file)
@@ -37,4 +37,7 @@ int mesh_netlink_set_mesh_parameter(const char* mesh_if_name,
 int mesh_netlink_get_station_info(const char* mesh_if_name, GList **station_list);
 int mesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list);
 
+int mesh_netlink_register_event_handler();
+int mesh_netlink_unregister_event_handler();
+
 #endif /* __MESH_NETLINK_H__ */
index a783d15..031310f 100644 (file)
@@ -71,9 +71,14 @@ int mesh_request_disable_softap(
 int mesh_request_get_station_info(const char* mesh_interface, GList **station_list);
 int mesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list);
 
+int mesh_request_register_event_handler();
+int mesh_request_unregister_event_handler();
+
 /* Notifications */
 void mesh_notify_scan_done();
 void mesh_notify_joined_network();
 void mesh_notify_left_network();
+void mesh_notify_station_joined(const char* bssid);
+void mesh_notify_station_left(const char* bssid);
 
 #endif /* __MESH_REQUEST_H__ */
index 935b690..bc874ed 100644 (file)
                </signal>\r
        </interface>\r
 </node>\r
-\r
index 8729446..cca2e1c 100644 (file)
@@ -94,6 +94,9 @@ enum plink_state {
 
 static bool scan_in_progress = FALSE;
 
+/* For event handler */
+static mesh_nl_state *event_state = NULL;
+
 #if 0
 gboolean _handle_nl_response_message(GIOChannel *source,
        GIOCondition condition, gpointer data);
@@ -520,8 +523,6 @@ static int no_seq_check(struct nl_msg *msg, void *arg) {
        NOTUSED(msg);
        NOTUSED(arg);
 
-       MESH_LOGD("no_seq_check");
-
        return NL_OK;
 }
 
@@ -613,6 +614,7 @@ static gboolean _on_socket_io_received(GIOChannel *source,
                nl_recvmsgs(state->nl_socket, state->cb);
        }
 
+       /* Close related resources if response received */
        __clean_netlink_message(state);
        __clean_nl80211(state);
        _delete_mesh_nl_state(&state);
@@ -621,6 +623,36 @@ static gboolean _on_socket_io_received(GIOChannel *source,
        return FALSE;
 }
 
+static gboolean _on_socket_event_io_received(GIOChannel *source,
+               GIOCondition condition, gpointer data)
+{
+       mesh_nl_state *state = (mesh_nl_state *)data;
+       int test = 0;
+
+       NOTUSED(source);
+       NOTUSED(condition);
+
+       MESH_LOGD("[Event] I/O received");
+
+       while (nl_recvmsgs_report(state->nl_socket, state->cb) > 0) {
+               MESH_LOGD("  count [%02d]", ++test);
+       }
+
+       /* Do not remove I/O source */
+       return TRUE;
+}
+
+static void _on_remove_event_io_handler()
+{
+       if(event_state) {
+               g_source_remove(event_state->event_source);
+
+               __clean_netlink_message(event_state);
+               __clean_nl80211(event_state);
+               _delete_mesh_nl_state(&event_state);
+       }
+}
+
 #if 0
 /* If async logic is required */
 static gboolean _handle_nl_response_message(GIOChannel *source,
@@ -1621,6 +1653,52 @@ static int _on_receive_mpath_info(struct nl_msg *msg, void *arg)
        return NL_SKIP;
 }
 
+static int _on_receive_mesh_event(struct nl_msg *msg, void *arg)
+{
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct nlattr *tb[NL80211_ATTR_MAX + 1];
+       char ifname[16] = { 0, };
+       char macbuf[6*3];
+
+       NOTUSED(arg);
+
+       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+
+       if (tb[NL80211_ATTR_IFINDEX]) {
+               if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname);
+               MESH_LOGD("%s: ", ifname);
+       }
+
+       switch (gnlh->cmd) {
+       case NL80211_CMD_NEW_STATION:
+               mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
+               MESH_LOGD("[%s] new station [%s]", ifname, macbuf);
+               break;
+       case NL80211_CMD_DEL_STATION:
+               mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
+               MESH_LOGD("[%s] del station [%s]", ifname, macbuf);
+               break;
+       case NL80211_CMD_NEW_MPATH:
+               mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
+               MESH_LOGD("[%s] new mpath [%s]", ifname, macbuf);
+
+               mesh_notify_station_joined((const char*)macbuf);
+               break;
+       case NL80211_CMD_DEL_MPATH:
+               mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
+               MESH_LOGD("[%s] del mpath [%s]", ifname, macbuf);
+
+               mesh_notify_station_left((const char*)macbuf);
+               break;
+       default:
+               MESH_LOGD("event [%d] is not handled", gnlh->cmd);
+               break;
+       }
+
+       return NL_SKIP;
+}
+
 static int _send_nl_trigger_full_scan(const char* mesh_if_name)
 {
        /* Nested message */
@@ -2467,6 +2545,78 @@ nla_put_failure:
        return MESHD_ERROR_OPERATION_FAILED;
 }
 
+static int _send_nl_register_event_handler()
+{
+       int err = MESHD_ERROR_NONE;
+       int ret;
+       GIOChannel *recv_channel = NULL;
+
+       if (event_state) {
+               MESH_LOGE("Already event handler registered !");
+               return MESHD_ERROR_IN_PROGRESS;
+       }
+
+       event_state = _create_mesh_nl_state("");
+
+       ret = __initialize_nl80211(event_state);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to initialize nl80211");
+               scan_in_progress = FALSE;
+               return ret;
+       }
+
+       /* Subscribe multicast group should be proceed before scanning */
+       ret = __prepare_listen_events(event_state);
+       if (ret) {
+               MESH_LOGE("__prepare_listen_events : [%d]", ret);
+               goto DESTROY;
+       }
+
+       ret = __initialize_netlink_message(event_state);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to initialize netlink message");
+               goto DESTROY;
+       }
+
+       /* Set command into message */
+       genlmsg_put(event_state->msg, 0, 0, event_state->nl80211_id, 0, 0, 0, 0);
+
+       /* Set callbacks for event handler */
+       nl_cb_set(event_state->cb, NL_CB_VALID, NL_CB_CUSTOM,
+                       _on_receive_mesh_event, event_state);
+       // No sequence checking for multicast messages.
+       nl_cb_set(event_state->cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
+
+       MESH_LOGD("Register event handler");
+
+       /* Change socket type to non-blocking */
+       ret = nl_socket_set_nonblocking(event_state->nl_socket);
+       if (ret < 0) {
+               MESH_LOGE("Failed to non-blocking socket [%s](%d)", nl_geterror(ret), ret);
+       }
+
+       /* Register I/O callback to wait asynchronously */
+       if (FALSE == event_state->error_occured) {
+               recv_channel = g_io_channel_unix_new(nl_socket_get_fd(event_state->nl_socket));
+               event_state->event_source = g_io_add_watch(recv_channel,
+                               (G_IO_IN | G_IO_ERR), _on_socket_event_io_received, event_state);
+               g_io_channel_unref(recv_channel);
+       } else {
+               MESH_LOGE("Error responded. Failed to register event callback !!");
+               goto DESTROY;
+       }
+
+       /* Resource should be free on I/O callback */
+       return MESHD_ERROR_NONE;
+
+DESTROY:
+       __clean_netlink_message(event_state);
+       __clean_nl80211(event_state);
+       _delete_mesh_nl_state(&event_state);
+
+       return err;
+}
+
 int mesh_netlink_set_type_managed(const char* if_name)
 {
        int ret = MESHD_ERROR_NONE;
@@ -2679,3 +2829,24 @@ int mesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list)
 
        return ret;
 }
+
+int mesh_netlink_register_event_handler()
+{
+       int ret = MESHD_ERROR_NONE;
+
+       MESH_LOGD("Register mesh event handler");
+       ret = _send_nl_register_event_handler();
+
+       return ret;
+}
+
+int mesh_netlink_unregister_event_handler()
+{
+       int ret = MESHD_ERROR_NONE;
+
+       MESH_LOGD("Unregister mesh event handler");
+
+       _on_remove_event_io_handler();
+
+       return ret;
+}
index 7c4e808..ffe9c06 100644 (file)
@@ -588,7 +588,7 @@ int mesh_request_disable_softap(
                return ret;
        }
 
-       return ret;     
+       return ret;
 }
 
 int mesh_request_get_station_info(const char* mesh_interface, GList **station_list)
@@ -603,7 +603,7 @@ int mesh_request_get_station_info(const char* mesh_interface, GList **station_li
                return ret;
        }
 
-       return ret;     
+       return MESHD_ERROR_NONE;
 }
 
 int mesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list)
@@ -618,7 +618,37 @@ int mesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list)
                return ret;
        }
 
-       return ret;     
+       return MESHD_ERROR_NONE;
+}
+
+int mesh_request_register_event_handler()
+{
+       int ret = MESHD_ERROR_NONE;
+
+       MESH_LOGD("Request to register mesh event handler");
+
+       /* Get MPath info */
+       ret = mesh_netlink_register_event_handler();
+       if (MESHD_ERROR_NONE != ret) {
+               return ret;
+       }
+
+       return MESHD_ERROR_NONE;
+}
+
+int mesh_request_unregister_event_handler()
+{
+       int ret = MESHD_ERROR_NONE;
+
+       MESH_LOGD("Request to unregister mesh event handler");
+
+       /* Get MPath info */
+       ret = mesh_netlink_unregister_event_handler();
+       if (MESHD_ERROR_NONE != ret) {
+               return ret;
+       }
+
+       return MESHD_ERROR_NONE;
 }
 
 /* Notifications */
@@ -642,3 +672,17 @@ void mesh_notify_left_network()
 
        net_mesh_emit_left_network(object);
 }
+
+void mesh_notify_station_joined(const char* bssid)
+{
+       NetMesh *object = meshd_dbus_get_object();
+
+       net_mesh_emit_sta_joined(object, bssid);
+}
+
+void mesh_notify_station_left(const char* bssid)
+{
+       NetMesh *object = meshd_dbus_get_object();
+
+       net_mesh_emit_sta_left(object, bssid);
+}
index 1209056..6bb3dd0 100644 (file)
@@ -163,6 +163,12 @@ static gboolean _meshd_dbus_handle_enable(NetMesh *object,
 
        meshd_check_null_ret_error("info", info, FALSE);
 
+       /* Register event handler first */
+       ret = mesh_request_register_event_handler();
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to register mesh event handler !! [%d]", ret);
+       }
+
        ret = mesh_interface_initialize(service->interface_info);
        if (MESHD_ERROR_NONE != ret) {
                MESH_LOGE("Failed to mesh_interface_initialize [%d]", ret);
@@ -188,6 +194,11 @@ static gboolean _meshd_dbus_handle_disable(NetMesh *object,
        /* Make response first */
        net_mesh_complete_disable(object, invocation, ret);
 
+       ret = mesh_request_unregister_event_handler();
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to unregister mesh event handler !! [%d]", ret);
+       }
+
        /* Terminate daemon */
        meshd_service_exit(service);