Add DHCP terminate logic
authorJiwan Kim <ji-wan.kim@samsung.com>
Tue, 14 Mar 2017 08:21:54 +0000 (17:21 +0900)
committersaerome.kim <saerome.kim@samsung.com>
Mon, 17 Jul 2017 02:35:36 +0000 (11:35 +0900)
include/mesh-dhcp.h
include/mesh-request.h
src/mesh-dhcp.c
src/mesh-request.c
src/mesh-service-interface.c

index 08c10b0..fb23d8c 100644 (file)
@@ -23,5 +23,6 @@ typedef void (*dhcp_finished_cb)(const char* interface, const char* ip_address,
                void *user_data);
 int mesh_dhcp_request(const char* interface,
                dhcp_finished_cb callback, void *user_data);
+int mesh_dhcp_stop_request();
 
 #endif /* __MESH_DHCP_H__ */
index 031310f..3d4c37f 100644 (file)
@@ -20,6 +20,7 @@
 #define __MESH_REQUEST_H__
 
 int mesh_request_dhcp(const char* interface);
+int mesh_request_stop_dhcp();
 
 int mesh_request_enable_mesh(const char* base_interface,
                const char* mesh_interface);
index d0b4078..d12ccfc 100644 (file)
@@ -46,6 +46,8 @@ typedef struct {
        void *user_data;
 } spawn_info_s;
 
+static spawn_info_s *dhcp_info = NULL;
+
 static char* __get_obtained_ip_address(const char *str)
 {
        char *token = NULL;
@@ -73,21 +75,22 @@ static char* __get_obtained_ip_address(const char *str)
 static gboolean _child_logger(GIOChannel *source, GIOCondition condition,
                gpointer data)
 {
-       spawn_info_s *info = (spawn_info_s *)data;
        gchar *buf = NULL;
        gchar *address = NULL;
        GError *error = NULL;
        GIOStatus status = G_IO_STATUS_NORMAL;
 
        NOTUSED(condition);
+       NOTUSED(data);
 
-       while(G_IO_STATUS_NORMAL == status || G_IO_STATUS_AGAIN == status) {
+       while(G_IO_STATUS_NORMAL == status) {
                status = g_io_channel_read_line(source, &buf, NULL, NULL, &error);
                if (G_IO_STATUS_ERROR == status) {
                        MESH_LOGE("Failed to read i/o [%s]", error->message);
                        g_free(buf);
                        g_error_free(error);
                } else if (G_IO_STATUS_EOF != status) {
+                       if (NULL == buf) continue;
                        MESH_LOGD("[CHILD] %s", buf);
 
                        /* Check if IP obtained */
@@ -97,8 +100,8 @@ static gboolean _child_logger(GIOChannel *source, GIOCondition condition,
                                        address = g_strdup("0.0.0.0");
 
                                MESH_LOGD("[Found] %s", address);
-                               if (info)
-                                       info->ip_address = address;
+                               if (dhcp_info)
+                                       dhcp_info->ip_address = address;
                        }
                }
        }
@@ -109,22 +112,25 @@ static gboolean _child_logger(GIOChannel *source, GIOCondition condition,
 
 static void _child_process_watcher(GPid pid, gint status, gpointer user_data)
 {
-       spawn_info_s *info = (spawn_info_s *)user_data;
+       NOTUSED(user_data);
 
        g_spawn_close_pid(pid);
-       if (info) {
-               info->callback(info->interface, info->ip_address, info->user_data);
-
-               g_source_remove(info->error_source);
-               g_source_remove(info->output_source);
-               g_source_remove(info->child_source);
-               g_free(info->ip_address);
-               g_free(info);
+       if (dhcp_info) {
+               dhcp_info->callback(dhcp_info->interface,
+                               dhcp_info->ip_address, dhcp_info->user_data);
+
+               g_source_remove(dhcp_info->error_source);
+               g_source_remove(dhcp_info->output_source);
+               g_source_remove(dhcp_info->child_source);
+               g_free(dhcp_info->ip_address);
+
+               g_free(dhcp_info);
+               dhcp_info = NULL;
        }
        MESH_LOGD("[CHILD] terminated with [%d]", status);
 }
 
-static int _internal_request_dhcp(const char *interface_name, spawn_info_s *info)
+static int _internal_request_dhcp(const char *interface_name)
 {
        gboolean result = FALSE;
 
@@ -145,35 +151,44 @@ static int _internal_request_dhcp(const char *interface_name, spawn_info_s *info
                NULL
        };
 
+       if (NULL == dhcp_info) {
+               MESH_LOGE("Unexpected parameter failure");
+               return MESHD_ERROR_OPERATION_FAILED;
+       }
+
        result = g_spawn_async_with_pipes(NULL,
                request_dhcp,
                NULL,
                (G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD),
                NULL,
                NULL,
-               &(info->child_pid),
+               &(dhcp_info->child_pid),
                NULL,
                &standard_output,
                &standard_error,
                &error);
        if (result == FALSE) {
                MESH_LOGE("Failed to request DHCP! : [%s]", error->message);
-               g_free(info);
                g_error_free(error);
+               g_free(dhcp_info);
+               dhcp_info = NULL;
+
                return MESHD_ERROR_OPERATION_FAILED;
        }
 
        output_channel = g_io_channel_unix_new(standard_output);
        error_channel = g_io_channel_unix_new(standard_error);
-       info->output_source = g_io_add_watch(output_channel,
-                       (G_IO_IN | G_IO_ERR), _child_logger, info);
-       info->error_source = g_io_add_watch(error_channel,
-                       (G_IO_IN | G_IO_ERR), _child_logger, info);
+       g_io_channel_set_flags(output_channel, G_IO_FLAG_NONBLOCK, NULL);
+       g_io_channel_set_flags(error_channel, G_IO_FLAG_NONBLOCK, NULL);
+       dhcp_info->output_source = g_io_add_watch(output_channel,
+                       (G_IO_IN | G_IO_ERR), _child_logger, NULL);
+       dhcp_info->error_source = g_io_add_watch(error_channel,
+                       (G_IO_IN | G_IO_ERR), _child_logger, NULL);
        g_io_channel_unref(output_channel);
        g_io_channel_unref(error_channel);
 
-       info->child_source = g_child_watch_add(info->child_pid,
-                       _child_process_watcher, info);
+       dhcp_info->child_source = g_child_watch_add(dhcp_info->child_pid,
+                       _child_process_watcher, NULL);
 
        MESH_LOGD("DHCP requested");
        return MESHD_ERROR_NONE;
@@ -183,18 +198,48 @@ int mesh_dhcp_request(const char* interface,
                dhcp_finished_cb callback, void *user_data)
 {
        int ret = MESHD_ERROR_NONE;
-       spawn_info_s *info = NULL;
 
-       info = g_new0(spawn_info_s, 1);
-       if (NULL == info) {
+       if (NULL != dhcp_info) {
+               MESH_LOGE("DHCP is requested already");
+               return MESHD_ERROR_IN_PROGRESS;
+       }
+
+       dhcp_info = g_new0(spawn_info_s, 1);
+       if (NULL == dhcp_info) {
                MESH_LOGE("Falied to allocate information");
                return MESHD_ERROR_OUT_OF_MEMORY;
        }
 
-       info->interface = interface;
-       info->callback = callback;
-       info->user_data = user_data;
-       ret = _internal_request_dhcp(interface, info);
+       dhcp_info->interface = interface;
+       dhcp_info->callback = callback;
+       dhcp_info->user_data = user_data;
+       ret = _internal_request_dhcp(interface);
 
        return ret;
 }
+
+int mesh_dhcp_stop_request()
+{
+       gboolean result;
+       GError *error = NULL;
+
+       if (NULL == dhcp_info) {
+               MESH_LOGE("DHCP is not requested or terminated already !");
+               return MESHD_ERROR_NONE;
+       }
+
+       result = g_spawn_command_line_async("/usr/bin/killall dhcp", &error);
+       if (FALSE == result) {
+               MESH_LOGE("Failed to terminate DHCP : [%s]", error->message);
+               g_error_free(error);
+               return MESHD_ERROR_OPERATION_FAILED;
+       }
+
+       g_source_remove(dhcp_info->output_source);
+       g_source_remove(dhcp_info->error_source);
+
+       g_free(dhcp_info);
+       dhcp_info = NULL;
+
+       return MESHD_ERROR_NONE;
+}
index 2c760e4..47bd1a2 100644 (file)
@@ -65,6 +65,16 @@ int mesh_request_dhcp(const char* interface)
        return ret;
 }
 
+int mesh_request_stop_dhcp()
+{
+       int ret = MESHD_ERROR_NONE;
+
+       /* Terminate DHCP */
+       ret = mesh_dhcp_stop_request();
+
+       return ret;
+}
+
 int mesh_request_scan(const char* interface)
 {
        int ret = MESHD_ERROR_NONE;
index 0a6e80d..6684c8f 100644 (file)
@@ -468,6 +468,12 @@ static gboolean _meshd_dbus_handle_disable_mesh(NetMesh *object,
                return TRUE;
        }
 
+       /* If DHCP is on progress, stop it */
+       ret = mesh_request_stop_dhcp();
+       if (MESHD_ERROR_NONE != ret) {
+               MESH_LOGE("Failed to stop DHCP request !");
+       }
+
        ret = mesh_request_disable_mesh(info->mesh_interface);
        if (MESHD_ERROR_NONE != ret) {
                MESH_LOGE("Failed to mesh_request_disable_mesh_gate");