Implement methods
authorJiwan Kim <ji-wan.kim@samsung.com>
Wed, 8 Mar 2017 05:36:24 +0000 (14:36 +0900)
committersaerome.kim <saerome.kim@samsung.com>
Mon, 17 Jul 2017 02:35:36 +0000 (11:35 +0900)
- enable_mesh
- disable_mesh
- set_gate
- unset_gate
- get_joined_mesh_network
- Scan can be done before mesh interface is created
  (with base interface(i.e. wlan0))

CMakeLists.txt
include/mesh-interface.h
include/mesh-netlink.h
include/mesh-network.h
include/mesh-request.h
packaging/meshd.spec
src/mesh-interface.c
src/mesh-netlink.c
src/mesh-network.c
src/mesh-request.c
src/mesh-service-interface.c

index cea4705..7c7d70e 100644 (file)
@@ -7,7 +7,7 @@ MESSAGE(===================================================================)
 
 MESSAGE(" - Checking...packages dependency")
 INCLUDE(FindPkgConfig)
-SET(PKG_MODULES gio-2.0 gio-unix-2.0 dlog libnl-3.0 libnl-genl-3.0 vconf dbus-1)
+SET(PKG_MODULES gio-2.0 gio-unix-2.0 dlog libnl-3.0 libnl-genl-3.0 dbus-1 capi-network-connection)
 pkg_check_modules(daemon_pkgs REQUIRED ${PKG_MODULES})
 
 MESSAGE(" - Adding external C flags")
index 0a51021..bd6c00d 100644 (file)
@@ -29,5 +29,7 @@ int mesh_interface_set(const char* interface, const char* ip_addr,
                mesh_set_interface_type_e type);
 //int mesh_interface_set_mac_addr(const char* interface, const char* mac_addr);
 int mesh_interface_initialize(mesh_interface_s *info);
+int mesh_interface_check_external_exists(
+               const char* external_interface, bool *state);
 
 #endif /* __MESH_INTERFACE_H__ */
index cc55bf2..b9f657d 100644 (file)
 
 int mesh_netlink_set_type_managed(const char* interface);
 int mesh_netlink_create_mesh_interface(const char* base_if_name,
-               const char* mesh_if_name, const char* mesh_id);
+               const char* mesh_if_name);
 int mesh_netlink_delete_mesh_interface(const char* mesh_if_name);
 int mesh_netlink_set_mesh_channel(const char* base_if_name, int channel);
+int mesh_netlink_join_mesh(const char* base_if_name, const char* mesh_id);
+
 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);
index ab10298..80d3f94 100644 (file)
@@ -28,4 +28,7 @@ int mesh_network_forget_saved_mesh_network(GList **saved_network, const char *me
                int mesh_channel, int security);
 int mesh_network_clear_saved_mesh_network(GList **saved_network);
 
+int mesh_network_get_first_mesh_network(GList *saved_network,
+               mesh_network_info_s *info);
+
 #endif /* __MESH_NETWORK_H__ */
index af91ced..f637e4c 100644 (file)
 int mesh_request_dhcp(const char* interface);
 
 int mesh_request_enable_mesh(const char* base_interface,
-               const char* mesh_interface, const char* mesh_id, int mesh_channel);
+               const char* mesh_interface);
 int mesh_request_disable_mesh(const char* mesh_interface);
 
+int mesh_request_join_mesh(const char* mesh_interface, GList *saved_network,
+               mesh_network_info_s **joined_network);
+
 int mesh_request_set_mesh_gate(const char* bridge_interface,
                const char* mesh_interface, const char* external_interface);
 int mesh_request_unset_mesh_gate(const char* bridge_interface,
@@ -32,7 +35,7 @@ int mesh_request_unset_mesh_gate(const char* bridge_interface,
 
 /* Bridge network */
 int mesh_request_create_bridge(const char* bridge_interface,
-               const char* mesh_interface, const char* external_interface);
+               const char* mesh_interface);
 int mesh_request_remove_bridge(const char* bridge_interface);
 int mesh_request_add_bridge_interface(const char* bridge_interface,
                const char* interface);
@@ -53,6 +56,7 @@ int mesh_request_select_saved_mesh_network(GList **saved_network,
                const char *mesh_id, int channel, int security);
 int mesh_request_forget_saved_mesh_network(GList **saved_network,
                const char *mesh_id, int channel, int security);
+int mesh_request_clear_saved_mesh_network(GList **saved_network);
 
 /* Notifications */
 void mesh_notify_scan_done();
index c565758..f161bf2 100644 (file)
@@ -12,7 +12,7 @@ BuildRequires: pkgconfig(glib-2.0)
 BuildRequires: pkgconfig(gio-2.0)
 BuildRequires: pkgconfig(gio-unix-2.0)
 BuildRequires: pkgconfig(dlog)
-BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(capi-network-connection)
 BuildRequires: pkgconfig(libnl-3.0)
 BuildRequires: pkgconfig(dbus-1)
 BuildRequires: cmake
index 61ba23d..b07b501 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <errno.h>
 
+#include <net_connection.h>
+
 #include "mesh.h"
 #include "mesh-log.h"
 #include "mesh-util.h"
@@ -170,6 +172,27 @@ static char* _get_interface_not_exists_in_seq(const char* prefix)
        return res;
 }
 
+/* Returns interface name in sequence order which is exists */
+static bool _check_interface_exists(const char* if_name)
+{
+       int ret;
+       char buf[32];
+       int i = 0;
+       const int IF_INDEX_MAX = 9;
+
+       for (i = 0; i <= IF_INDEX_MAX; i++) {
+               snprintf(buf, sizeof(buf), "/sys/class/net/%s", if_name);
+
+               ret = access(buf, F_OK);
+               if (ret >= 0) {
+                       /* This name is exists. */
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 int mesh_interface_initialize(mesh_interface_s *info)
 {
        info->bridge_interface = _get_interface_not_exists_in_seq("br");
@@ -201,3 +224,42 @@ int mesh_interface_initialize(mesh_interface_s *info)
 
        return MESHD_ERROR_NONE;
 }
+
+int mesh_interface_check_external_exists(const char* external_interface, bool *state)
+{
+       /* TODO: Current logic checks only ethernet interface.
+                       This logic should consider wireless interface if can */
+       int ret = MESHD_ERROR_NONE;
+       connection_h handle;
+       connection_ethernet_cable_state_e cable_state =
+                       CONNECTION_ETHERNET_CABLE_DETACHED;
+
+       if (NULL == external_interface || NULL == state) {
+               return MESHD_ERROR_INVALID_PARAMETER;
+       }
+
+       bool ex = _check_interface_exists(external_interface);
+       if (FALSE == ex) {
+               MESH_LOGE("External interface[%s] was not found.", external_interface);
+               return MESHD_ERROR_INVALID_PARAMETER;
+       }
+
+       ret = connection_create(&handle);
+       if (CONNECTION_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to get connection handle");
+               return MESHD_ERROR_OPERATION_FAILED;
+       }
+
+       ret = connection_get_ethernet_cable_state(handle, &cable_state);
+       if (CONNECTION_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to get ethernet cable state");
+               return MESHD_ERROR_OPERATION_FAILED;
+       }
+
+       *state = FALSE;
+       if (CONNECTION_ETHERNET_CABLE_ATTACHED == cable_state) {
+               *state = TRUE;
+       }
+
+       return MESHD_ERROR_NONE;
+}
\ No newline at end of file
index ae81762..4a57563 100644 (file)
@@ -711,7 +711,7 @@ nla_put_failure:
 }
 
 static int _send_nl_create_mesh_interface(const char* base_if_name,
-               const char* mesh_if_name, const char* mesh_id)
+               const char* mesh_if_name)
 {
        mesh_nl_state state = {
                .nl80211_id = -1,
@@ -763,7 +763,6 @@ static int _send_nl_create_mesh_interface(const char* base_if_name,
        }
        NLA_PUT_STRING(state.msg, NL80211_ATTR_IFNAME, mesh_if_name);
        NLA_PUT_U32(state.msg, NL80211_ATTR_IFTYPE, type);
-       NLA_PUT(state.msg, NL80211_ATTR_MESH_ID, strlen(mesh_id), mesh_id);
 
        /* Send message into kernel */
        ret = nl_send_auto(state.nl_socket, state.msg);
@@ -1536,6 +1535,81 @@ nla_put_failure:
        return MESHD_ERROR_OPERATION_FAILED;
 }
 
+static int _send_nl_join_mesh(const char* mesh_if_name, const char* mesh_id)
+{
+       mesh_nl_state state = {
+               .nl80211_id = -1,
+               .callback_state = MESH_NL_CALLBACK_TRYING,
+               .event_source = 0,
+               .nl_socket = NULL,
+               .msg = NULL,
+               .cb = NULL,
+               .s_cb = NULL,
+               .scanning_interface = NULL,
+               .error_occured = FALSE,
+       };
+       int err = MESHD_ERROR_NONE;
+       int device_index = 0;
+       int ret;
+       int test = 0;
+
+       ret = __initialize_nl80211(&state);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to initialize nl80211");
+               return ret;
+       }
+
+       ret = __initialize_netlink_message(&state);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to initialize netlink message");
+               goto DESTROY;
+       }
+
+       /* Set command into message */
+       genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
+                   0, NL80211_CMD_JOIN_MESH, 0);
+
+       /* Add attributes into message */
+       ret = __get_device_index_from_string(mesh_if_name, &device_index);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to get mesh device index");
+               err = ret;
+               goto DESTROY;
+       }
+       NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
+
+       NLA_PUT(state.msg, NL80211_ATTR_MESH_ID, strlen(mesh_id), mesh_id);
+
+       /* Send message into kernel */
+       ret = nl_send_auto(state.nl_socket, state.msg);
+       if (ret < 0) {
+               MESH_LOGE("Failed to nl_send_auto() [%s](%d)",
+                               nl_geterror(ret), ret);
+               err = MESHD_ERROR_OPERATION_FAILED;
+               goto DESTROY;
+       }
+
+       /* sync response */
+       state.callback_state = MESH_NL_CALLBACK_TRYING;
+       while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
+               MESH_LOGD("  count [%02d]", ++test);
+               nl_recvmsgs(state.nl_socket, state.cb);
+       }
+
+DESTROY:
+       __clean_netlink_message(&state);
+       __clean_nl80211(&state);
+
+       return err;
+
+nla_put_failure:
+       MESH_LOGE("Failed to message build");
+       __clean_netlink_message(&state);
+       __clean_nl80211(&state);
+
+       return MESHD_ERROR_OPERATION_FAILED;
+}
+
 static int _send_nl_set_mesh_parameter(const char* mesh_if_name,
                const char* param_name, unsigned int value)
 {
@@ -1650,7 +1724,7 @@ int mesh_netlink_set_type_managed(const char* if_name)
 }
 
 int mesh_netlink_create_mesh_interface(const char* base_if_name,
-               const char* mesh_if_name, const char* mesh_id)
+               const char* mesh_if_name)
 {
        int ret = MESHD_ERROR_NONE;
 
@@ -1662,14 +1736,10 @@ int mesh_netlink_create_mesh_interface(const char* base_if_name,
                MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
                return MESHD_ERROR_INVALID_PARAMETER;
        }
-       if (NULL == mesh_id || strlen(mesh_id) > IFNAMSIZ) {
-               MESH_LOGE("Invalid parameter [%p]", mesh_id);
-               return MESHD_ERROR_INVALID_PARAMETER;
-       }
 
-       MESH_LOGD("Create mesh interface [%s](%s) base on [%s]",
-                       mesh_if_name, mesh_id, base_if_name);
-       ret = _send_nl_create_mesh_interface(base_if_name, mesh_if_name, mesh_id);
+       MESH_LOGD("Create mesh interface [%s] base on [%s]",
+                       mesh_if_name, base_if_name);
+       ret = _send_nl_create_mesh_interface(base_if_name, mesh_if_name);
 
        return ret;
 }
@@ -1705,6 +1775,25 @@ int mesh_netlink_set_mesh_channel(const char* mesh_if_name, int channel)
        return ret;
 }
 
+int mesh_netlink_join_mesh(const char* mesh_if_name, const char* mesh_id)
+{
+       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 == mesh_id || strlen(mesh_id) > IFNAMSIZ) {
+               MESH_LOGE("Invalid parameter [%p]", mesh_id);
+               return MESHD_ERROR_INVALID_PARAMETER;
+       }
+
+       MESH_LOGD("Join into mesh ID [%s]", mesh_if_name);
+       ret = _send_nl_join_mesh(mesh_if_name, mesh_id);
+
+       return ret;
+}
+
 int mesh_netlink_trigger_full_scan(const char* mesh_if_name)
 {
        int ret = MESHD_ERROR_NONE;
index 1fe446f..28be2be 100644 (file)
@@ -112,6 +112,38 @@ int mesh_network_get_saved_mesh_network(GList **saved_network)
        return ret;
 }
 
+int mesh_network_get_first_mesh_network(GList *saved_network,
+               mesh_network_info_s *info)
+{
+       int ret = MESHD_ERROR_NONE;
+       GList *iter = NULL;
+       int index = 1;
+       mesh_network_info_s *found;
+
+       meshd_check_null_ret_error("saved_network", saved_network,
+                       MESHD_ERROR_INVALID_PARAMETER);
+       meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
+
+       iter = saved_network;
+       while (iter != NULL) {
+               found = (mesh_network_info_s*)iter->data;
+
+               info->mesh_id = found->mesh_id;
+               info->channel = found->channel;
+               info->security = found->security;
+
+               MESH_LOGD("[%d] item :", index);
+               MESH_LOGD("   Mesh ID : [%s]", info->mesh_id);
+               MESH_LOGD("   channel : [%d]", info->channel);
+               MESH_LOGD("  security : [%d]", info->security);
+               MESH_LOGD("");
+
+               break;
+       }
+
+       return ret;
+}
+
 int mesh_network_select_saved_mesh_network(GList **saved_network,
                const char *mesh_id, int mesh_channel, int security)
 {
index be0b74a..8a02f3b 100644 (file)
@@ -142,11 +142,11 @@ int mesh_request_disable_mesh(const char* mesh_interface)
 }
 
 int mesh_request_enable_mesh(const char* base_interface,
-               const char* mesh_interface, const char* mesh_id, int mesh_channel)
+               const char* mesh_interface)
 {
        int ret = MESHD_ERROR_NONE;
 
-       if (NULL == base_interface || NULL == mesh_interface || NULL == mesh_id) {
+       if (NULL == base_interface || NULL == mesh_interface) {
                MESH_LOGE("Invalid interface name");
                return MESHD_ERROR_INVALID_PARAMETER;
        }
@@ -165,20 +165,12 @@ int mesh_request_enable_mesh(const char* base_interface,
        }
 
        /* Create new mesh interface */
-       ret = mesh_netlink_create_mesh_interface(base_interface, mesh_interface,
-                       mesh_id);
+       ret = mesh_netlink_create_mesh_interface(base_interface, mesh_interface);
        if(MESHD_ERROR_NONE != ret) {
                MESH_LOGE("Failed to mesh_netlink_add_mesh_interface");
                return ret;
        }
 
-       /* Set mesh channel */
-       ret = mesh_netlink_set_mesh_channel(mesh_interface, mesh_channel);
-       if(MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to mesh_netlink_set_mesh_channel");
-               return ret;
-       }
-
        /* Make base interface down */
        ret = mesh_interface_set(base_interface, NULL, MESH_INTERFACE_DOWN);
        if(MESHD_ERROR_NONE != ret) {
@@ -196,26 +188,93 @@ int mesh_request_enable_mesh(const char* base_interface,
        return MESHD_ERROR_NONE;
 }
 
+int mesh_request_join_mesh(const char* mesh_interface, GList *saved_network,
+               mesh_network_info_s **joined_network)
+{
+       int ret = MESHD_ERROR_NONE;
+       mesh_network_info_s info;
+
+       /* Get mesh_id and channel from saved network */
+       ret = mesh_network_get_first_mesh_network(saved_network, &info);
+       if(MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to mesh_network_get_first_mesh_network");
+               return ret;
+       }
+
+       /* Set mesh channel */
+       ret = mesh_netlink_set_mesh_channel(mesh_interface, info.channel);
+       if(MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to mesh_netlink_set_mesh_channel");
+               return ret;
+       }
+
+       /* Join specific mesh network */
+       ret = mesh_netlink_join_mesh(mesh_interface, info.mesh_id);
+       if(MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to mesh_netlink_join_mesh");
+               return ret;
+       }
+
+       if (joined_network) {
+               if (*joined_network) {
+                       g_free((*joined_network)->mesh_id);
+                       g_free(*joined_network);
+               }
+
+               *joined_network = g_try_new0(mesh_network_info_s, 1);
+               if (NULL == *joined_network) {
+                       MESH_LOGE("Failed to allocate memory");
+               } else {
+                       (*joined_network)->mesh_id = g_strdup(info.mesh_id);
+                       (*joined_network)->channel = info.channel;
+                       (*joined_network)->security = info.security;
+               }
+       }
+
+       return MESHD_ERROR_NONE;
+}
+
 int mesh_request_set_mesh_gate(const char* bridge_interface,
                const char* mesh_interface, const char* external_interface)
 {
        int ret = MESHD_ERROR_NONE;
+       bool state = FALSE;
 
-/* TODO: Add external network into bridge */
-       NOTUSED(bridge_interface);
-       NOTUSED(external_interface);
-
-       /* Set mesh parameters */
-       ret = mesh_netlink_set_mesh_parameter(mesh_interface,
-                       "mesh_hwmp_rootmode", 4);
+       ret = mesh_interface_check_external_exists(external_interface, &state);
        if (MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 4");
+               MESH_LOGE("Failed to get external interface state !");
+               return MESHD_ERROR_OPERATION_FAILED;
        }
 
-       ret = mesh_netlink_set_mesh_parameter(mesh_interface,
-                       "mesh_gate_announcements", 1);
-       if (MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to set [mesh_gate_announcements] : 1");
+       if (state) {
+               /* Turn STP on */
+               ret = mesh_bridge_set_stp(bridge_interface, TRUE);
+               if(MESHD_ERROR_NONE != ret) {
+                       MESH_LOGE("Failed to turn STP on !");
+                       return ret;
+               }
+
+               /* Add external interface into bridge */
+               ret = mesh_request_add_bridge_interface(bridge_interface, external_interface);
+               if (MESHD_ERROR_NONE != ret) {
+                       return ret;
+               }
+
+               /* Set mesh parameters */
+               ret = mesh_netlink_set_mesh_parameter(mesh_interface,
+                               "mesh_hwmp_rootmode", 4);
+               if (MESHD_ERROR_NONE != ret) {
+                       MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 4");
+               }
+
+               ret = mesh_netlink_set_mesh_parameter(mesh_interface,
+                               "mesh_gate_announcements", 1);
+               if (MESHD_ERROR_NONE != ret) {
+                       MESH_LOGE("Failed to set [mesh_gate_announcements] : 1");
+               }
+       } else {
+               MESH_LOGE("External interface is not available !");
+               return MESHD_ERROR_OPERATION_FAILED;
        }
 
        return MESHD_ERROR_NONE;
@@ -226,21 +285,30 @@ int mesh_request_unset_mesh_gate(const char* bridge_interface,
 {
        int ret = MESHD_ERROR_NONE;
 
-/* TODO: remove external network from bridge */
-       NOTUSED(bridge_interface);
-       NOTUSED(external_interface);
-
        /* Set mesh parameters */
        ret = mesh_netlink_set_mesh_parameter(mesh_interface,
                        "mesh_hwmp_rootmode", 0);
        if (MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 4");
+               MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 0");
        }
 
        ret = mesh_netlink_set_mesh_parameter(mesh_interface,
                        "mesh_gate_announcements", 0);
        if (MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to set [mesh_gate_announcements] : 1");
+               MESH_LOGE("Failed to set [mesh_gate_announcements] : 0");
+       }
+
+       /* Remove external network from bridge */
+       ret = mesh_request_remove_bridge_interface(bridge_interface, external_interface);
+       if (MESHD_ERROR_NONE != ret) {
+               return ret;
+       }
+
+       /* Turn STP off */
+       ret = mesh_bridge_set_stp(bridge_interface, FALSE);
+       if(MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to turn STP off!");
+               return ret;
        }
 
        return MESHD_ERROR_NONE;
@@ -274,7 +342,7 @@ int mesh_request_remove_bridge(const char* bridge_interface)
 }
 
 int mesh_request_create_bridge(const char* bridge_interface,
-               const char* mesh_interface, const char* external_interface)
+               const char* mesh_interface)
 {
        int ret = MESHD_ERROR_NONE;
 
@@ -283,7 +351,7 @@ int mesh_request_create_bridge(const char* bridge_interface,
                return MESHD_ERROR_INVALID_PARAMETER;
        }
 
-       MESH_LOGD("Setting bridge...");
+       MESH_LOGD("Creating bridge [%s]...", bridge_interface);
 
        /* Create bridge interface */
        ret = mesh_bridge_create(bridge_interface);
@@ -292,13 +360,6 @@ int mesh_request_create_bridge(const char* bridge_interface,
                return ret;
        }
 
-       /* Turn STP on */
-       ret = mesh_bridge_set_stp(bridge_interface, TRUE);
-       if(MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to set stp !");
-               return ret;
-       }
-
        /* Add mesh interface into bridge */
        ret = mesh_bridge_add_interface(bridge_interface, mesh_interface);
        if(MESHD_ERROR_NONE != ret) {
@@ -307,50 +368,68 @@ int mesh_request_create_bridge(const char* bridge_interface,
                return ret;
        }
 
-       if (external_interface) {
-               /* Add external interface into bridge */
-               ret = mesh_bridge_add_interface(bridge_interface, external_interface);
-               if(MESHD_ERROR_NONE != ret) {
-                       MESH_LOGE("Failed to add interface[%s] into bridge[%s] !",
-                               external_interface, bridge_interface);
-                       return ret;
-               }
+       /* Make bridge interface UP */
+       ret = mesh_interface_set(bridge_interface, NULL, MESH_INTERFACE_UP);
+       if(MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to change bridge interface state");
+               return ret;
        }
 
-       /* Make mesh interface down */
-       ret = mesh_interface_set(mesh_interface, NULL, MESH_INTERFACE_DOWN);
+       return MESHD_ERROR_NONE;
+}
+
+int mesh_request_add_bridge_interface(const char* bridge_interface,
+               const char* interface)
+{
+       int ret = MESHD_ERROR_NONE;
+
+       if (NULL == bridge_interface || NULL == interface) {
+               MESH_LOGE("Invalid parameters");
+               return MESHD_ERROR_INVALID_PARAMETER;
+       }
+
+       MESH_LOGD("Adding interface[%s] into bridge[%s]...", interface, bridge_interface);
+
+       /* Add external interface into bridge */
+       ret = mesh_bridge_add_interface(bridge_interface, interface);
        if(MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to change mesh interface state");
+               MESH_LOGE("Failed to add interface !");
                return ret;
        }
 
-       /* Make mesh interface up with cleared IP */
-       ret = mesh_interface_set(mesh_interface, "0.0.0.0", MESH_INTERFACE_UP);
+       /* Make external interface down */
+       ret = mesh_interface_set(interface, NULL, MESH_INTERFACE_DOWN);
        if(MESHD_ERROR_NONE != ret) {
                MESH_LOGE("Failed to change external interface state");
                return ret;
        }
 
-       if (external_interface) {
-               /* Make external interface down */
-               ret = mesh_interface_set(external_interface, NULL, MESH_INTERFACE_DOWN);
-               if(MESHD_ERROR_NONE != ret) {
-                       MESH_LOGE("Failed to change external interface state");
-                       return ret;
-               }
+       /* Make external interface up with cleared IP */
+       ret = mesh_interface_set(interface, "0.0.0.0", MESH_INTERFACE_UP);
+       if(MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to change external interface state");
+               return ret;
+       }
 
-               /* Make external interface up with cleared IP */
-               ret = mesh_interface_set(external_interface, "0.0.0.0", MESH_INTERFACE_UP);
-               if(MESHD_ERROR_NONE != ret) {
-                       MESH_LOGE("Failed to change external interface state");
-                       return ret;
-               }
+       return MESHD_ERROR_NONE;
+}
+
+int mesh_request_remove_bridge_interface(const char* bridge_interface,
+               const char* interface)
+{
+       int ret = MESHD_ERROR_NONE;
+
+       if (NULL == bridge_interface || NULL == interface) {
+               MESH_LOGE("Invalid parameters");
+               return MESHD_ERROR_INVALID_PARAMETER;
        }
 
-       /* Make bridge interface UP */
-       ret = mesh_interface_set(bridge_interface, NULL, MESH_INTERFACE_UP);
+       MESH_LOGD("Removing interface[%s] from bridge[%s]...", interface, bridge_interface);
+
+       /* Remove external interface into bridge */
+       ret = mesh_bridge_del_interface(bridge_interface, interface);
        if(MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to change bridge interface state");
+               MESH_LOGE("Failed to remove interface !");
                return ret;
        }
 
@@ -437,6 +516,21 @@ int mesh_request_forget_saved_mesh_network(GList **saved_network,
        return MESHD_ERROR_NONE;
 }
 
+int mesh_request_clear_saved_mesh_network(GList **saved_network)
+{
+       int ret = MESHD_ERROR_NONE;
+
+       MESH_LOGD("Remove all saved mesh network...");
+
+       ret = mesh_network_clear_saved_mesh_network(saved_network);
+       if(MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to clear saved mesh network");
+               return ret;
+       }
+
+       return MESHD_ERROR_NONE;
+}
+
 /* Notifications */
 void mesh_notify_scan_done()
 {
index 43671de..6300540 100644 (file)
@@ -218,7 +218,16 @@ static gboolean _meshd_dbus_handle_scan(NetMesh *object,
 
        ret = mesh_request_scan(info->mesh_interface);
        if (MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to mesh_request_scan");
+               MESH_LOGE("Failed to mesh_request_scan on mesh interface[%s] !",
+                               info->mesh_interface);
+       }
+
+       /* Fall-back */
+       if (MESHD_ERROR_IN_PROGRESS != ret) {
+               ret = mesh_request_scan(info->base_interface);
+               if (MESHD_ERROR_NONE != ret)
+                       MESH_LOGE("Failed to mesh_request_scan on base interface[%s] !",
+                                       info->base_interface);
        }
 
        net_mesh_complete_scan(object, invocation, ret);
@@ -240,7 +249,16 @@ static gboolean _meshd_dbus_handle_specific_scan(NetMesh *object,
 
        ret = mesh_request_specific_scan(info->mesh_interface, mesh_id, channel);
        if (MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to mesh_request_specific_scan");
+               MESH_LOGE("Failed to mesh_request_specific_scan on mesh interface[%s]",
+                               info->mesh_interface);
+       }
+
+       /* Fall-back */
+       if (MESHD_ERROR_IN_PROGRESS != ret) {
+               ret = mesh_request_specific_scan(info->base_interface, mesh_id, channel);
+               if (MESHD_ERROR_NONE != ret)
+                       MESH_LOGE("Failed to mesh_request_specific_scan on base interface[%s]",
+                                       info->base_interface);
        }
 
        net_mesh_complete_specific_scan(object, invocation, ret);
@@ -291,71 +309,50 @@ static gboolean _meshd_dbus_handle_get_found_mesh_networks(NetMesh *object,
 
        MESH_LOGD("Request to get scanned mesh network list");
 
-       /* TODO: Return scan results */
-       /*
-        * struct mesh_found_network_s {
-        * char *mesh_id;
-        * char *bssid;
-        * int channel;
-        * int rssi;
-        * int data_rate;
-        *};
-        */
-
        ret = mesh_request_get_scan_result(info->mesh_interface, &service->scanned_mesh_network);
        if (MESHD_ERROR_NONE != ret) {
                MESH_LOGE("Failed to mesh_request_get_scan_result");
 
-               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}"));
+               /* Fall-back */
+               ret = mesh_request_get_scan_result(info->base_interface,
+                               &service->scanned_mesh_network);
+               if (MESHD_ERROR_NONE != ret) {
+                       MESH_LOGE("Failed to mesh_request_get_scan_result on base interface[%s]",
+                                       info->base_interface);
 
-               /* 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_dbus_method_invocation_return_error(invocation,
+                                       G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
+               }
+       }
 
-               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);
+       g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
 
-               iter = service->scanned_mesh_network;
-               while (iter != NULL) {
-                       scan_item = (mesh_scan_result_s*)iter->data;
+       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);
+               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);
-               }
+               iter = g_list_next(iter);
+       }
 
-               /* Clear scan list */
-               g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
-               service->scanned_mesh_network = NULL;
+       /* 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);
-       }
+       networks = g_variant_builder_end(&builder);
+       net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret);
 
        return TRUE;
 }
@@ -369,20 +366,36 @@ static gboolean _meshd_dbus_handle_enable_mesh(NetMesh *object,
        mesh_interface_s *info = service->interface_info;
 
        /* TODO: Create or join mesh network and create bridge */
-       ret = mesh_request_enable_mesh(info->base_interface,
-                       info->mesh_interface, info->mesh_id, info->mesh_channel);
+       ret = mesh_request_enable_mesh(info->base_interface, info->mesh_interface);
        if (MESHD_ERROR_NONE != ret) {
-               MESH_LOGE("Failed to mesh_request_enable_mesh_gate [%d]", ret);
+               MESH_LOGE("Failed to mesh_request_enable_mesh [%d]", ret);
                goto FINISH;
        }
 
-       ret = mesh_request_create_bridge(info->bridge_interface,
-                       info->mesh_interface, info->external_interface);
+       ret = mesh_request_create_bridge(info->bridge_interface, info->mesh_interface);
        if (MESHD_ERROR_NONE != ret) {
                MESH_LOGE("Failed to mesh_request_create_bridge [%d]", ret);
                goto FINISH;
        }
 
+       ret = mesh_request_join_mesh(info->mesh_interface,
+                       service->saved_mesh_network, &service->joined_network);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to mesh_request_join_mesh [%d]", ret);
+               goto FINISH;
+       }
+
+       /* TODO: Detect external network state (i.e. Ethernet)
+                       and decide to make gate enabled */
+       ret = mesh_request_set_mesh_gate(info->bridge_interface,
+                       info->mesh_interface, info->external_interface);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to mesh_request_set_mesh_gate [%d]", ret);
+       }
+       ret = MESHD_ERROR_NONE;
+
+       /* TODO: Notify bridge status to Connman */
+z
 #if 0
        ret = mesh_request_specific_scan(info->mesh_interface,
                        info->mesh_id, info->mesh_channel);
@@ -407,11 +420,16 @@ static gboolean _meshd_dbus_handle_disable_mesh(NetMesh *object,
                gpointer user_data)
 {
        int ret = MESHD_ERROR_NONE;
+       mesh_service *service = (mesh_service *)user_data;
 
        MESH_LOGD("Not implemented yet !");
-       NOTUSED(user_data);
 
        /* TODO: Destroy bridge and return from mesh to infra mode */
+       if (service->joined_network) {
+               g_free(service->joined_network->mesh_id);
+               g_free(service->joined_network);
+               service->joined_network = NULL;
+       }
 
        net_mesh_complete_disable_mesh(object, invocation, ret);
 
@@ -419,35 +437,46 @@ static gboolean _meshd_dbus_handle_disable_mesh(NetMesh *object,
 }
 
 static gboolean _meshd_dbus_handle_get_joined_mesh_network(NetMesh *object,
-               GDBusMethodInvocation *invocation)
+               GDBusMethodInvocation *invocation,
+               gpointer user_data)
 {
        int ret = MESHD_ERROR_NONE;
+       mesh_service *service = (mesh_service *)user_data;
+       mesh_network_info_s *joined = service->joined_network;
 
-       gchar *meshid = strdup("meshnet");
-    gchar *bssid = strdup("7c:dd:90:d8:2a:64");
-    gint channel = 161;
-    gint max_speed = 866;
-
-       MESH_LOGD("Not implemented yet !");
-       net_mesh_complete_get_joined_mesh_network(object, invocation, meshid, bssid, channel,
-               max_speed, ret);
+       //gchar *meshid = strdup("meshnet");
+       //gchar *bssid = strdup("7c:dd:90:d8:2a:64");
+       //gint channel = 161;
+       //gint max_speed = 866;
 
-       free(meshid);
-       free(bssid);
+       if (joined) {
+               net_mesh_complete_get_joined_mesh_network(object, invocation,
+                       joined->mesh_id, "", joined->channel, 0, ret);
+       } else {
+               net_mesh_complete_get_joined_mesh_network(object, invocation,
+                       "", "", 0, 0, MESHD_ERROR_NO_DATA);
+       }
 
        return TRUE;
 }
 
 static gboolean _meshd_dbus_handle_set_gate(NetMesh *object,
-               GDBusMethodInvocation *invocation, gboolean stp, gint gate_announce)
+               GDBusMethodInvocation *invocation, gboolean stp, gint gate_announce,
+               gpointer user_data)
 {
        int ret = MESHD_ERROR_NONE;
+       mesh_service *service = (mesh_service *)user_data;
+       mesh_interface_s *info = service->interface_info;
 
-       MESH_LOGD("Not implemented yet !");
-       MESH_LOGD("stp = %d", stp);
+       MESH_LOGD("STP = %d", stp);
        MESH_LOGD("gate_announce = %d", gate_announce);
 
-       /* TODO: Set stp and gate_announce */
+       /* Set STP and gate_announce */
+       ret = mesh_request_set_mesh_gate(info->bridge_interface,
+                       info->mesh_interface, info->external_interface);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to mesh_request_set_mesh_gate [%d]", ret);
+       }
 
        net_mesh_complete_set_gate(object, invocation, ret);
 
@@ -455,14 +484,18 @@ static gboolean _meshd_dbus_handle_set_gate(NetMesh *object,
 }
 
 static gboolean _meshd_dbus_handle_unset_gate(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;
 
-       MESH_LOGD("Not implemented yet !");
-
-       /* TODO: Check softAP interface and execute it */
-
+       ret = mesh_request_unset_mesh_gate(info->bridge_interface,
+                       info->mesh_interface, info->external_interface);
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to mesh_request_unset_mesh_gate [%d]", ret);
+       }
        net_mesh_complete_unset_gate(object, invocation, ret);
 
        return TRUE;
@@ -778,7 +811,7 @@ static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name
                        G_CALLBACK(_meshd_dbus_handle_get_joined_mesh_network), service);
        g_signal_connect(meshd_dbus_object, "handle-set-gate",
                        G_CALLBACK(_meshd_dbus_handle_set_gate), service);
-       g_signal_connect(meshd_dbus_object, "handle-unset-mesh",
+       g_signal_connect(meshd_dbus_object, "handle-unset-gate",
                        G_CALLBACK(_meshd_dbus_handle_unset_gate), service);
        g_signal_connect(meshd_dbus_object, "handle-set-softap",
                        G_CALLBACK(_meshd_dbus_handle_set_softap), service);
@@ -876,6 +909,17 @@ static void _meshd_dbus_deinit(mesh_service *service)
        if (info->external_interface)
                g_free(info->external_interface);
 
+       if (service->joined_network) {
+               g_free(service->joined_network->mesh_id);
+               g_free(service->joined_network);
+               service->joined_network = NULL;
+       }
+       mesh_request_clear_saved_mesh_network(&service->saved_mesh_network);
+
+       /* Clear scan list */
+       g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
+       service->scanned_mesh_network = NULL;
+
        g_free(service->interface_info);
        service->interface_info = NULL;
 }