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);
NOTUSED(msg);
NOTUSED(arg);
- MESH_LOGD("no_seq_check");
-
return NL_OK;
}
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);
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,
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 */
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;
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;
+}
return ret;
}
- return ret;
+ return ret;
}
int mesh_request_get_station_info(const char* mesh_interface, GList **station_list)
return ret;
}
- return ret;
+ return MESHD_ERROR_NONE;
}
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 */
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);
+}