Remove the transaction_thread 94/99794/1
authorSeonah Moon <seonah1.moon@samsung.com>
Wed, 16 Nov 2016 07:33:03 +0000 (16:33 +0900)
committerSeonah Moon <seonah1.moon@samsung.com>
Thu, 24 Nov 2016 06:27:23 +0000 (15:27 +0900)
Change-Id: Ica09a27e7cd7169dd8ad5a10ac8b6e0c80eaced8
Signed-off-by: Seonah Moon <seonah1.moon@samsung.com>
include/http_private.h
packaging/capi-network-http.spec
src/http_session.c
src/http_transaction.c
test/http_test.c

index 078ebec..74572d9 100644 (file)
@@ -138,7 +138,6 @@ typedef struct {
 typedef struct {
        CURLM *multi_handle;
        int session_id;
-       guint timer_event;
        int still_running;
        int active_transaction_count;
        gboolean auto_redirect;
@@ -147,6 +146,7 @@ typedef struct {
 
 typedef struct {
        CURL *easy_handle;
+       guint timer_event;
        gchar *interface_name;
        int timeout;
        int write_event;
@@ -161,6 +161,7 @@ typedef struct {
        bool proxy_auth_type;
        http_auth_scheme_e auth_scheme;
        gchar* realm;
+
        /*Credential Info*/
        gchar* user_name;
        gchar* password;
@@ -186,8 +187,6 @@ typedef struct {
        __http_response_h *response;
        __http_header_h *header;
 
-       GThread *thread;
-       GMainLoop *thread_loop;
 } __http_transaction_h;
 
 typedef struct {
@@ -226,6 +225,12 @@ FILE* _get_upload_file(http_transaction_h http_transaction);
 void _open_upload_file(http_transaction_h http_transaction);
 void _close_upload_file(__http_transaction_h *http_transaction);
 
+void _http_transaction_start_timer(guint msecs, gboolean(*callback) (gpointer), void *user_data);
+void _http_transaction_stop_timer(__http_transaction_h *transaction);
+
+gboolean curl_request_check(gpointer data);
+
+
 #ifdef __cplusplus
 }
 #endif
index 9235e48..42e0bfd 100644 (file)
@@ -1,6 +1,6 @@
 Name:          capi-network-http
 Summary:       Http Framework
-Version:       0.0.14
+Version:       0.0.15
 Release:       0
 Group:         System/Network
 License:       Apache-2.0
index 832b603..01c7d8d 100644 (file)
 
 static int generated_session_id = -1;
 
-void _check_curl_multi_status(gpointer user_data)
+static void _handle_completed_transaction(__http_session_h *user_data)
 {
        __http_transaction_h *transaction = NULL;
-       __http_session_h *session = (__http_session_h *)user_data;
+       __http_session_h *session = user_data;
 
        CURLMsg* message = NULL;
        int count = 0;
@@ -102,173 +102,47 @@ void _check_curl_multi_status(gpointer user_data)
                        }
 
                        if (session->multi_handle != NULL && curl_easy != NULL)
-                               curl_multi_remove_handle(session->multi_handle, curl_easy);
+                               curl_multi_remove_handle(session->multi_handle, transaction->easy_handle);
+
                }
                message = curl_multi_info_read(session->multi_handle, &count);
        }
 }
 
-int _generate_session_id(void)
+gboolean curl_request_check(gpointer data)
 {
-       if (generated_session_id >= INT_MAX)
-               generated_session_id = 0;
-       else
-               generated_session_id++;
-
-       return generated_session_id;
-}
-
-gboolean timer_expired_callback(gpointer user_data)
-{
-       __http_session_h* session = (__http_session_h *)user_data;
-
-       CURLMcode ret;
-
-       if (session == NULL || session->multi_handle == NULL)
-               return FALSE;
-
-       ret = curl_multi_socket_action(session->multi_handle, CURL_SOCKET_TIMEOUT, 0, &(session->still_running));
-       if (ret == CURLM_OK)
-               DBG("CURLM_OK - Called curl_multi_socket_action()\n");
-       else
-               print_curl_multi_errorCode(ret);
-
-       _check_curl_multi_status(session);
-
-       return FALSE;
-}
-
-gboolean _handle_event(int fd, int action, gpointer user_data)
-{
-       __http_session_h *session = (__http_session_h *)user_data;
-
-       int running_handles = -1;
-
-       CURLMcode ret = CURLM_OK;
-
-       ret = curl_multi_socket_action(session->multi_handle, fd, action, &running_handles);
-       if (ret == CURLM_OK)
-               DBG("CURLM_OK: Called curl_multi_socket_action(%d)\n", action);
-       else
-               print_curl_multi_errorCode(ret);
-
-
-       if (running_handles > 0) {
-               _check_curl_multi_status(session);
-               return TRUE;
-       } else {
-               DBG("last transfer done, kill timeout\n");
-               if (session->timer_event) {
-                       g_source_remove(session->timer_event);
-                       session->timer_event = 0;
+       __http_transaction_h *transaction = (__http_transaction_h *)data;
+       __http_session_h *session = transaction->session;
+       int rv = 0;
+
+       if (0 != session->still_running) {
+               rv = curl_multi_perform(session->multi_handle, &session->still_running);
+               if (rv != CURLM_OK) {
+                       DBG("curl multi perform failed %s\n", curl_easy_strerror(rv));
+                       _handle_completed_transaction(session);
+                       _http_transaction_stop_timer(transaction);
+                       return FALSE;
                }
-               _check_curl_multi_status(session);
-               return FALSE;
+               return TRUE;
        }
-}
-
-gboolean __handle_socket_received_event_cb(GIOChannel *channel, GIOCondition condition, gpointer user_data)
-{
-       int fd, action, ret;
-
-       if (condition & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
-               return FALSE;
 
-       fd = g_io_channel_unix_get_fd(channel);
+       DBG("last transfer done");
 
-       /* CURL_CSELECT_IN : 1, CURL_CSELECT_OUT: 2 */
-       action = (condition & G_IO_IN ? CURL_CSELECT_IN : 0) | (condition & G_IO_OUT ? CURL_CSELECT_OUT : 0);
-
-       ret = _handle_event(fd, action, user_data);
-       if (ret)
-               return TRUE;
+       _handle_completed_transaction(session);
+       _http_transaction_stop_timer(transaction);
 
        return FALSE;
 }
 
-/* Clean up the __http_socket_info_h structure */
-static void _remove_socket_info(__http_socket_info_h *sock_info)
-{
-       if (!sock_info)
-               return;
-
-       if (sock_info->event) {
-               g_source_remove(sock_info->event);
-               sock_info->event = 0;
-       }
-       if (sock_info->channel) {
-               g_io_channel_unref(sock_info->channel);
-               sock_info->channel = NULL;
-       }
-       g_free(sock_info);
-       sock_info = NULL;
-}
-
-/* Assign socket information to a __http_socket_info_h structure */
-static void _set_socket_info(__http_socket_info_h *sock_info, curl_socket_t fd, CURL *curl_easy, int action, void *user_data)
-{
-       __http_session_h *session = (__http_session_h *)user_data;
-       GIOCondition condition = (action & CURL_POLL_IN ? G_IO_IN : 0) | (action & CURL_POLL_OUT ? G_IO_OUT : 0);
-
-       sock_info->sockfd = fd;
-       sock_info->action = action;
-       sock_info->easy_handle = curl_easy;
-       if (sock_info->event) {
-               g_source_remove(sock_info->event);
-               sock_info->event = 0;
-       }
-       sock_info->event = g_io_add_watch(sock_info->channel, condition, __handle_socket_received_event_cb, session);
-}
-
-/* Initialize a new Socket Info structure */
-static void _add_socket_info(curl_socket_t fd, CURL *curl_easy, int action, void *user_data)
-{
-       __http_session_h *session = (__http_session_h *)user_data;
-       __http_socket_info_h *sock_info = (__http_socket_info_h *)malloc(sizeof(__http_socket_info_h));
-
-       sock_info->session = session;
-       sock_info->channel = g_io_channel_unix_new(fd);
-       sock_info->event = 0;
-       _set_socket_info(sock_info, fd, curl_easy, action, session);
-       curl_multi_assign(session->multi_handle, fd, sock_info);
-}
-
-int __handle_socket_cb(CURL *curl_easy, curl_socket_t fd, int action, void *user_data, void *socketp)
-{
-       __http_session_h *session = (__http_session_h *)user_data;
-       __http_socket_info_h *sock_info = (__http_socket_info_h*) socketp;
-
-       static const char *actionstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE"};
-
-       DBG("__handle_socket_cb: fd=%d easy_handle=%p action=%s", fd, curl_easy, actionstr[action]);
-       if (action == CURL_POLL_REMOVE) {
-               DBG("CURL_POLL_REMOVE\n");
-               _remove_socket_info(sock_info);
-       } else {
-               if (!sock_info) {
-                       DBG("Adding data: %s%s\n", action & CURL_POLL_IN ? "READ" : "", action & CURL_POLL_OUT ? "WRITE" : "");
-                       _add_socket_info(fd, curl_easy, action, session);
-               } else {
-                       DBG("Changing action from %d to %d\n", sock_info->action, action);
-                       _set_socket_info(sock_info, fd, curl_easy, action, session);
-               }
-       }
-
-       return 0;
-}
 
-int __handle_timer_cb(CURLM *curl_multi, long timeout_ms, void *user_data)
+int _generate_session_id(void)
 {
-       __http_session_h* session = (__http_session_h *)user_data;
-
-       if (session->timer_event) {
-               g_source_remove(session->timer_event);
-               session->timer_event = 0;
-       }
-
-       session->timer_event = g_timeout_add(timeout_ms , timer_expired_callback , session);
+       if (generated_session_id >= INT_MAX)
+               generated_session_id = 0;
+       else
+               generated_session_id++;
 
-       return 0;
+       return generated_session_id;
 }
 
 API int http_session_create(http_session_mode_e mode, http_session_h *http_session)
@@ -291,12 +165,6 @@ API int http_session_create(http_session_mode_e mode, http_session_h *http_sessi
        session->active_transaction_count = 0;
        session->session_mode = mode;
        session->auto_redirect = FALSE;
-       session->timer_event = 0;
-
-       curl_multi_setopt(session->multi_handle, CURLMOPT_SOCKETFUNCTION, __handle_socket_cb);
-       curl_multi_setopt(session->multi_handle, CURLMOPT_SOCKETDATA, session);
-       curl_multi_setopt(session->multi_handle, CURLMOPT_TIMERFUNCTION, __handle_timer_cb);
-       curl_multi_setopt(session->multi_handle, CURLMOPT_TIMERDATA, session);
 
        if (mode == HTTP_SESSION_MODE_PIPELINING)
                curl_multi_setopt(session->multi_handle, CURLMOPT_PIPELINING, 1L);
@@ -325,11 +193,6 @@ API int http_session_destroy(http_session_h http_session)
                session->still_running = 0;
                session->auto_redirect = FALSE;
 
-               if (session->timer_event) {
-                       g_source_remove(session->timer_event);
-                       session->timer_event = 0;
-               }
-
                free(session);
                session = NULL;
        }
index ff61814..51d4ef7 100644 (file)
@@ -212,6 +212,42 @@ int _set_authentication_info(http_transaction_h http_transaction)
 }
 //LCOV_EXCL_STOP
 
+void _http_transaction_start_timer(guint msecs, gboolean(*callback) (gpointer), void *user_data)
+{
+       __http_transaction_h *transaction = (__http_transaction_h *)user_data;
+       guint t_id = 0;
+
+       if (callback == NULL)
+               return;
+
+       if (transaction->timer_event != 0) {
+               ERR("timer is already registered[%ld]", transaction->timer_event);
+               return;
+       }
+
+       t_id = g_timeout_add(msecs, callback, user_data);
+       if (t_id == 0) {
+               ERR("Failed to add timer");
+               return;
+       }
+
+       DBG("g_timeout_add[%ld]", t_id);
+
+       transaction->timer_event = t_id;
+}
+
+void _http_transaction_stop_timer(__http_transaction_h *transaction)
+{
+       if (transaction->timer_event <= 0)
+               return;
+
+       if (transaction->timer_event) {
+          DBG("g_source_remove[%ld]", transaction->timer_event);
+               g_source_remove(transaction->timer_event);
+               transaction->timer_event = 0;
+       }
+}
+
 int _transaction_submit(gpointer user_data)
 {
        __http_transaction_h *transaction = (__http_transaction_h *)user_data;
@@ -351,7 +387,6 @@ int _transaction_submit(gpointer user_data)
 
        _get_request_body_size(transaction, &body_size);
 
-
        /* Setup for POST method */
        if (transaction->write_event) {
                if (content_len > 0 && content_len <= body_size)
@@ -399,9 +434,6 @@ int _transaction_submit(gpointer user_data)
        curl_easy_setopt(transaction->easy_handle, CURLOPT_DEBUGFUNCTION, __http_debug_received);
        curl_easy_setopt(transaction->easy_handle, CURLOPT_ERRORBUFFER, transaction->error);
 
-       curl_easy_setopt(transaction->easy_handle, CURLOPT_OPENSOCKETDATA, &transaction->socket_fd);
-       curl_easy_setopt(transaction->easy_handle, CURLOPT_OPENSOCKETFUNCTION, __handle_opensocket_cb);
-
        curl_easy_setopt(transaction->easy_handle, CURLOPT_PRIVATE, transaction);
 
        ret = curl_multi_add_handle(session->multi_handle, transaction->easy_handle);
@@ -412,22 +444,13 @@ int _transaction_submit(gpointer user_data)
                ERR("Failed to add easy_handle to curl_multi_add_handle()");
        }
 
-       return HTTP_ERROR_NONE;
-}
-
-void* thread_callback(void *user_data)
-{
-       __http_transaction_h *transaction = (__http_transaction_h *)user_data;
-
-       transaction->thread_loop = g_main_loop_new(NULL, FALSE);
-
-       _transaction_submit(transaction);
-
-       g_main_loop_run(transaction->thread_loop);
-
-       DBG("thread exited.\n");
+       ret = curl_multi_perform(session->multi_handle, &session->still_running);
+       if (ret == CURLM_OK)
+               _http_transaction_start_timer(5, curl_request_check, transaction);
+       else
+               print_curl_multi_errorCode(ret);
 
-       return NULL;
+       return ret;
 }
 
 API int http_session_open_transaction(http_session_h http_session, http_method_e method, http_transaction_h *http_transaction)
@@ -444,11 +467,13 @@ API int http_session_open_transaction(http_session_h http_session, http_method_e
        }
 
        transaction->easy_handle = NULL;
+       transaction->timer_event = 0;
        transaction->interface_name = NULL;
        transaction->timeout = 0;
        transaction->verify_peer = 1;
        transaction->ca_path = g_strdup(HTTP_DEFAULT_CA_PATH);
        transaction->error[0] = '\0';
+       transaction->cancel = 0;
 
        transaction->auth_required = FALSE;
        transaction->realm = NULL;
@@ -513,9 +538,6 @@ API int http_session_open_transaction(http_session_h http_session, http_method_e
        transaction->header->header_list = NULL;
        transaction->header->hash_table = NULL;
 
-       transaction->thread = NULL;
-       transaction->thread_loop = NULL;
-
        *http_transaction = (http_transaction_h)transaction;
        _add_transaction_to_list(transaction);
 
@@ -537,9 +559,12 @@ API int http_transaction_submit(http_transaction_h http_transaction)
 
        _retvm_if(transaction->request->host_uri == NULL, HTTP_ERROR_INVALID_OPERATION, "URI isn't set!!");
 
-       transaction->thread = g_thread_new("transaction_thread", thread_callback, transaction);
+       int ret = HTTP_ERROR_NONE;
 
-       return HTTP_ERROR_NONE;
+       if (_transaction_submit(transaction) != CURLM_OK)
+               ret = HTTP_ERROR_OPERATION_FAILED;
+
+       return ret;
 }
 
 API int http_transaction_destroy(http_transaction_h http_transaction)
@@ -565,18 +590,6 @@ API int http_transaction_destroy(http_transaction_h http_transaction)
                session->active_transaction_count--;
 
        if (transaction) {
-               if (transaction->thread_loop != NULL) {
-                       g_main_loop_quit((GMainLoop*)transaction->thread_loop);
-
-                       g_main_loop_unref(transaction->thread_loop);
-                       transaction->thread_loop = NULL;
-               }
-
-               if (transaction->thread != NULL) {
-                       g_thread_join(transaction->thread);
-                       transaction->thread = NULL;
-               }
-
                if (transaction->easy_handle != NULL) {
                        curl_easy_cleanup(transaction->easy_handle);
                        transaction->easy_handle = NULL;
@@ -587,6 +600,11 @@ API int http_transaction_destroy(http_transaction_h http_transaction)
                        transaction->interface_name = NULL;
                }
 
+               if (transaction->timer_event) {
+                       g_source_remove(transaction->timer_event);
+                       transaction->timer_event = 0;
+               }
+
                transaction->timeout = 0;
                transaction->verify_peer = 0;
 
@@ -660,14 +678,11 @@ API int http_transaction_destroy(http_transaction_h http_transaction)
                }
 
                if (response) {
-
                        if (response->status_text != NULL) {
                                free(response->status_text);
                                response->status_text = NULL;
                        }
-
                        free(response);
-
                }
 
                if (header) {
@@ -677,9 +692,7 @@ API int http_transaction_destroy(http_transaction_h http_transaction)
                        }
 
                        if (header->hash_table != NULL) {
-
                                g_hash_table_remove_all(header->hash_table);
-
                                g_hash_table_destroy(header->hash_table);
                                header->hash_table = NULL;
                        }
@@ -1096,6 +1109,7 @@ API int http_transaction_open_authentication(http_transaction_h http_transaction
        }
 
        auth_transaction->easy_handle = NULL;
+       auth_transaction->timer_event = 0;
        auth_transaction->interface_name = NULL;
        auth_transaction->ca_path = NULL;
        auth_transaction->error[0] = '\0';
@@ -1183,8 +1197,6 @@ API int http_transaction_open_authentication(http_transaction_h http_transaction
        auth_transaction->header->header_list = NULL;
        auth_transaction->header->hash_table = NULL;
 
-       auth_transaction->thread = NULL;
-
        *http_auth_transaction = (http_transaction_h)auth_transaction;
        _add_transaction_to_list(auth_transaction);
 
index 2130823..8df660b 100644 (file)
@@ -94,13 +94,6 @@ void __transaction_completed_cb(http_transaction_h transaction, void *user_data)
                _register_callbacks(http_auth_transaction);
                http_transaction_submit(http_auth_transaction);
        }
-
-       http_transaction_header_remove_field(transaction, "Content-Length");
-       ret = http_transaction_destroy(transaction);
-       if (ret == HTTP_ERROR_NONE) DBG("Success to close transaction\n");
-       else DBG("Fail to close transaction\n");
-
-       transaction = NULL;
 }
 
 void __transaction_aborted_cb(http_transaction_h transaction, int reason, void *user_data)
@@ -108,20 +101,40 @@ void __transaction_aborted_cb(http_transaction_h transaction, int reason, void *
        PRG("transaction_aborted_cb", transaction);
        DBG("aborted reason: %d\n", reason);
 
-       int ret = http_transaction_destroy(transaction);
-       if (ret == HTTP_ERROR_NONE) DBG("Success to close transaction\n");
-       else DBG("Fail to close transaction\n");
-
-       transaction = NULL;
+       switch (reason) {
+       case HTTP_ERROR_OPERATION_FAILED:
+               DBG("HTTP_ERROR_OPERATION_FAILED");
+               break;
+       case HTTP_ERROR_COULDNT_RESOLVE_HOST:
+               DBG("HTTP_ERROR_COULDNT_RESOLVE_HOST");
+               break;
+       case HTTP_ERROR_COULDNT_CONNECT:
+               DBG("HTTP_ERROR_COULDNT_CONNECT");
+               break;
+       case HTTP_ERROR_OPERATION_TIMEDOUT:
+               DBG("HTTP_ERROR_OPERATION_TIMEDOUT");
+               break;
+       case HTTP_ERROR_SSL_CONNECT_ERROR:
+               DBG("HTTP_ERROR_SSL_CONNECT_ERROR");
+               break;
+       case HTTP_ERROR_CANCELED:
+               DBG("HTTP_ERROR_CANCELED");
+               break;
+       default:
+               DBG("Unknown error");
+               break;
+       }
        cancel = 0;
+
+       return;
 }
 
 void __transaction_progress_cb(http_transaction_h transaction, double download_total, double download_now, double upload_total, double upload_now, void *user_data)
 {
-       PRG("__transaction_progress_cb", transaction);
-
-       if (cancel)
+       if (cancel) {
+               DBG("Cancel");
                http_transaction_cancel(transaction);
+       }
 }
 
 void _register_callbacks(http_transaction_h transaction)
@@ -139,7 +152,7 @@ void _write_message_body(http_transaction_h transaction, const char *file_path)
        struct stat file_info;
        FILE *fp;
        size_t file_size;
-       size_t chunk_size = 1000;
+       size_t chunk_size = 50;
        char *buf = malloc(chunk_size);
 
        stat(file_path, &file_info);
@@ -230,7 +243,6 @@ int test_simple_get(void)
 
        _register_callbacks(transaction);
        ret = http_transaction_submit(transaction);
-
        if (ret != 0) {
                ERR("Fail to submit transaction", ret);
                return 0;
@@ -275,7 +287,6 @@ int test_simple_post(void)
        int ret;
        http_transaction_h transaction;
        const char* post_msg = "name=tizen&project=capi-network-http";
-       char field_value[15];
 
        ret = http_session_open_transaction(session, HTTP_METHOD_POST, &transaction);
        if (ret != 0) {
@@ -290,9 +301,6 @@ int test_simple_post(void)
        http_transaction_set_ready_to_write(transaction, TRUE);
        http_transaction_request_write_body(transaction, post_msg);
 
-       snprintf(field_value, sizeof(field_value), "%d", (int)strlen(post_msg));
-       http_transaction_header_add_field(transaction, "Content-Length", field_value);
-
        _register_callbacks(transaction);
        http_transaction_submit(transaction);