typedef struct {
CURLM *multi_handle;
int session_id;
- guint timer_event;
int still_running;
int active_transaction_count;
gboolean auto_redirect;
typedef struct {
CURL *easy_handle;
+ guint timer_event;
gchar *interface_name;
int timeout;
int write_event;
bool proxy_auth_type;
http_auth_scheme_e auth_scheme;
gchar* realm;
+
/*Credential Info*/
gchar* user_name;
gchar* password;
__http_response_h *response;
__http_header_h *header;
- GThread *thread;
- GMainLoop *thread_loop;
} __http_transaction_h;
typedef struct {
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
Name: capi-network-http
Summary: Http Framework
-Version: 0.0.14
+Version: 0.0.15
Release: 0
Group: System/Network
License: Apache-2.0
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;
}
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)
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);
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;
}
}
//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;
_get_request_body_size(transaction, &body_size);
-
/* Setup for POST method */
if (transaction->write_event) {
if (content_len > 0 && content_len <= body_size)
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);
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)
}
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;
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);
_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)
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;
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;
}
if (response) {
-
if (response->status_text != NULL) {
free(response->status_text);
response->status_text = NULL;
}
-
free(response);
-
}
if (header) {
}
if (header->hash_table != NULL) {
-
g_hash_table_remove_all(header->hash_table);
-
g_hash_table_destroy(header->hash_table);
header->hash_table = NULL;
}
}
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';
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);
_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)
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)
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);
_register_callbacks(transaction);
ret = http_transaction_submit(transaction);
-
if (ret != 0) {
ERR("Fail to submit transaction", ret);
return 0;
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) {
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);