From: Seonah Moon Date: Thu, 17 Mar 2016 06:17:16 +0000 (+0900) Subject: Add APIs for request/response X-Git-Tag: submit/tizen/20160511.063207~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F45%2F61045%2F4;p=platform%2Fcore%2Fapi%2Fhttp.git Add APIs for request/response - get/set request cookie - get/set verify flag - get status code/text - get HTTP version - pause/resume transaction Change-Id: I5c82918b0779e28d2c9eac7459081a0d5247cc33 Signed-off-by: Seonah Moon --- diff --git a/include/http.h b/include/http.h index 1cdd038..c3bd308 100644 --- a/include/http.h +++ b/include/http.h @@ -81,6 +81,17 @@ typedef enum { HTTP_VERSION_1_1 /**< %Http version 1.1 */ } http_version_e; +/** + * @internal + * @brief Enumeration for transfer pause state + * @since_tizen 3.0 + */ +typedef enum { + HTTP_PAUSE_RECV = 1 << 0, /**< Pause receiving data */ + HTTP_PAUSE_SEND = 1 << 2, /**< Pause sending data */ + HTTP_PAUSE_ALL = HTTP_PAUSE_RECV | HTTP_PAUSE_SEND /**< %Pause both directions */ +} http_pause_state_e; + /** * @internal * @brief Enumeration for the http error code. @@ -156,7 +167,7 @@ typedef enum { * @param[in] header header information of Http Transaction * @param[in] header_len length of the Http Transaction header */ -typedef void (*http_transaction_header_cb)(char *header, size_t header_len); +typedef void (*http_transaction_header_cb)(http_transaction_h transaction, char *header, size_t header_len, void *user_data); /** * @internal @@ -167,7 +178,7 @@ typedef void (*http_transaction_header_cb)(char *header, size_t header_len); * @param[in] size Size in bytes of each element to be written * @param[in] count Number of elements, each one with a size of size bytes */ -typedef void (*http_transaction_body_cb)(char *body, size_t size, size_t count); +typedef void (*http_transaction_body_cb)(http_transaction_h transaction, char *body, size_t size, size_t count, void *user_data); /** * @internal @@ -176,7 +187,7 @@ typedef void (*http_transaction_body_cb)(char *body, size_t size, size_t count); * @details Called when the http ready to write event is received. * @param[in] recommended_chunk_size recommended chunk length of the Http transaction */ -typedef void (*http_transaction_write_cb)(int recommended_chunk_size); +typedef void (*http_transaction_write_cb)(http_transaction_h transaction, int recommended_chunk_size, void *user_data); /** * @internal @@ -184,7 +195,7 @@ typedef void (*http_transaction_write_cb)(int recommended_chunk_size); * @since_tizen 3.0 * @details Called when the http transaction is completed. */ -typedef void (*http_transaction_completed_cb)(void); +typedef void (*http_transaction_completed_cb)(http_transaction_h transaction, void *user_data); /** * @internal @@ -193,7 +204,7 @@ typedef void (*http_transaction_completed_cb)(void); * @details Called when the http transaction is aborted. * @param[in] reason aborted reason code */ -typedef void (*http_transaction_aborted_cb)(int reason); +typedef void (*http_transaction_aborted_cb)(http_transaction_h transaction, int reason); /** * @internal @@ -371,9 +382,7 @@ int http_session_get_max_transaction_count(http_session_h http_session, int *tra * @retval #HTTP_ERROR_NONE Successful * @retval #HTTP_ERROR_INVALID_PARAMETER Invalid parameter */ -int http_open_transaction(http_session_h http_session, http_method_e method, http_transaction_header_cb transaction_header_callback, - http_transaction_body_cb transaction_body_callback, http_transaction_write_cb transaction_write_callback, - http_transaction_completed_cb transaction_completed_cb, http_transaction_aborted_cb transaction_aborted_cb, http_transaction_h *http_transaction); +int http_open_transaction(http_session_h http_session, http_method_e method, http_transaction_h *http_transaction); /** * @internal @@ -403,6 +412,17 @@ int http_transaction_submit(http_transaction_h http_transaction); */ int http_transaction_close(http_transaction_h http_transaction); +int http_transaction_set_received_header_cb(http_transaction_h transaction, http_transaction_header_cb header_cb, void* user_data); + +int http_transaction_set_received_body_cb(http_transaction_h transaction, http_transaction_body_cb body_cb, void* user_data); + +int http_transaction_set_uploaded_cb(http_transaction_h transaction, http_transaction_write_cb write_cb, void* user_data); + +int http_transaction_set_completed_cb(http_transaction_h transaction, http_transaction_completed_cb completed_cb, void* user_data); + +int http_transaction_close_all(http_session_h session); + + /** * @internal * @brief Sets the progress callbacks. @@ -507,7 +527,7 @@ int http_transaction_resume(http_transaction_h http_transaction); * @retval #HTTP_ERROR_NONE Successful * @retval #HTTP_ERROR_INVALID_PARAMETER Invalid parameter */ -int http_transaction_pause(http_transaction_h http_transaction); +int http_transaction_pause(http_transaction_h http_transaction, http_pause_state_e pause_state); /** * @internal @@ -554,6 +574,36 @@ int http_transaction_set_interface_name(http_transaction_h http_transaction, con */ int http_transaction_get_interface_name(http_transaction_h http_transaction, char **interface_name); +/** + * @internal + * @brief Sets the flag to verify a server certificate. + * @since_tizen 3.0 + * @privlevel platform + * @privilege http://tizen.org/privilege/http.admin + * @details Get the interface name. + * @param[in] http_transaction The http transaction handle + * @param[in] verify flag to verify a server certificate. + * @return 0 on success, otherwise negative error value + * @retval #HTTP_ERROR_NONE Successful + * @retval #HTTP_ERROR_INVALID_PARAMETER Invalid parameter + */ +int http_transaction_set_server_certificate_verification(http_transaction_h http_transaction, bool verify); + +/** + * @internal + * @brief Gets the flag to verify a server certificate. + * @since_tizen 3.0 + * @privlevel platform + * @privilege http://tizen.org/privilege/http.admin + * @details Get the interface name. + * @param[in] http_transaction The http transaction handle + * @param[out] verify flag to verify a server certificate. + * @return 0 on success, otherwise negative error value + * @retval #HTTP_ERROR_NONE Successful + * @retval #HTTP_ERROR_INVALID_PARAMETER Invalid parameter + */ +int http_transaction_get_server_certificate_verification(http_transaction_h http_transaction, bool* verify); + /** * @internal * @brief Adds a named field, which is a <@c fieldName, @c fieldValue> pair, to the current instance of Http Transaction. diff --git a/include/http_private.h b/include/http_private.h index fa53f26..b0e4803 100644 --- a/include/http_private.h +++ b/include/http_private.h @@ -77,6 +77,13 @@ extern "C" { } \ } while (0) +#define HTTP_PREFIX_SIZE 5 +#define HTTP_VERSION_SIZE 3 +#define HTTP_STATUS_CODE_SIZE 3 +#define HTTP_REASON_PHRASE_SIZE 1024 + +#define HTTP_DEFAULT_CA_PATH "/etc/ssl/certs" + static const int _HTTP_DEFAULT_CONNECTION_TIMEOUT = 30; static const int _HTTP_DEFAULT_HEADER_SIZE = 1024; static const int _MAX_HTTP_TRANSACTIONS_PER_SESSION_NORMAL = 1; @@ -91,6 +98,7 @@ typedef struct { gchar *host_uri; gchar *method; gchar *encoding; + gchar *cookie; GQueue* body_queue; gint tot_size; http_version_e http_version; @@ -99,10 +107,12 @@ typedef struct { typedef struct { gchar *status_text; http_status_code_e status_code; + http_version_e version; } __http_response_h; typedef struct { CURLM *multi_handle; + int session_id; guint timer_event; int still_running; int active_transaction_count; @@ -112,18 +122,27 @@ typedef struct { typedef struct { CURL *easy_handle; + int session_id; + int transaction_id; gchar *interface_name; int timeout; int write_event; + bool verify_peer; + gchar *ca_path; gchar error[CURL_ERROR_SIZE]; int socket_fd; - /*Transaction Callbacks */ + /*Transaction Callbacks and User data*/ http_transaction_header_cb header_cb; + void *header_user_data; http_transaction_body_cb body_cb; + void *body_user_data; http_transaction_write_cb write_cb; + void *write_user_data; http_transaction_completed_cb completed_cb; + void *completed_user_data; http_transaction_aborted_cb aborted_cb; + /*Progress Callbacks */ http_transaction_upload_progress_cb upload_progress_cb; http_transaction_download_progress_cb download_progress_cb; @@ -156,6 +175,12 @@ struct curl_slist* _get_header_list(http_transaction_h http_transaction); int _get_request_body_size(http_transaction_h http_transaction, int *body_size); int _read_request_body(http_transaction_h http_transaction, char **body); +void __parse_response_header(char *buffer, size_t written, gpointer user_data); +int _generate_session_id(void); +int _generate_transaction_id(void); +void _add_transaction_to_list(http_transaction_h http_transaction); +void _remove_transaction_from_list(http_transaction_h http_transaction); +void _remove_transaction_list(void); #ifdef __cplusplus } diff --git a/packaging/capi-network-http.spec b/packaging/capi-network-http.spec index 250a093..af02a13 100644 --- a/packaging/capi-network-http.spec +++ b/packaging/capi-network-http.spec @@ -1,6 +1,6 @@ Name: capi-network-http Summary: Http Framework -Version: 0.0.2 +Version: 0.0.3 Release: 0 Group: System/Network License: Apache-2.0 diff --git a/src/http_common.c b/src/http_common.c index bb5613e..35d45fd 100644 --- a/src/http_common.c +++ b/src/http_common.c @@ -146,3 +146,18 @@ CATCH: return proxy_addr; } + +API int http_init() +{ + if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { + DBG("curl_global_init failed, so returning!\n"); + return HTTP_ERROR_OPERATION_FAILED; + } + + return HTTP_ERROR_NONE; +} + +API void http_deinit() +{ + curl_global_cleanup(); +} diff --git a/src/http_header.c b/src/http_header.c index 5ca3c33..8bf7501 100644 --- a/src/http_header.c +++ b/src/http_header.c @@ -33,8 +33,8 @@ struct curl_slist* _get_header_list(http_transaction_h http_transaction) g_hash_table_iter_init(&iter, header->hash_table); - while(g_hash_table_iter_next (&iter, &key, &value)) { - header_str = (gchar *)malloc(sizeof(gchar) * (strlen(key) + 1 + 1 + strlen(value) + 1) ); + while (g_hash_table_iter_next(&iter, &key, &value)) { + header_str = (gchar *)malloc(sizeof(gchar) * (strlen(key) + 1 + 1 + strlen(value) + 1)); sprintf(header_str, "%s: %s", (gchar*)key, (gchar*)value); DBG("Header Field: %s\n", header_str); header->header_list = curl_slist_append(header->header_list, header_str); diff --git a/src/http_request.c b/src/http_request.c index a61cc21..c5c5e76 100644 --- a/src/http_request.c +++ b/src/http_request.c @@ -108,6 +108,7 @@ API int http_request_get_uri(http_transaction_h http_transaction, char **host_ur ERR("strdup is failed\n"); return HTTP_ERROR_OUT_OF_MEMORY; } + DBG("-"); return HTTP_ERROR_NONE; } @@ -146,6 +147,40 @@ API int http_request_get_accept_encoding(http_transaction_h http_transaction, ch return HTTP_ERROR_NONE; } +API int http_request_set_cookie(http_transaction_h http_transaction, const char* cookie) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(cookie == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(cookie) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + __http_request_h *request = transaction->request; + + request->cookie = g_strdup(cookie); + + return HTTP_ERROR_NONE; +} + +API int http_request_get_cookie(http_transaction_h http_transaction, const char** cookie) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(cookie == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(cookie) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + __http_request_h *request = transaction->request; + + *cookie = g_strdup(request->cookie); + if (*cookie == NULL) { + ERR("strdup is failed\n"); + return HTTP_ERROR_OUT_OF_MEMORY; + } + + return HTTP_ERROR_NONE; +} + API int http_request_write_body(http_transaction_h http_transaction, const char *body) { _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, diff --git a/src/http_response.c b/src/http_response.c index c01bbb6..3b27bd4 100644 --- a/src/http_response.c +++ b/src/http_response.c @@ -14,6 +14,98 @@ * limitations under the License. */ +#include + #include "http.h" #include "http_private.h" +static int __convert_status_code(char* status_code) +{ + int i = 0; + int converted_digit = 0; + int converted_status_code = 0; + + for (i = HTTP_STATUS_CODE_SIZE - 1; i >= 0; i--) { + converted_digit = g_ascii_digit_value(status_code[i]); + converted_status_code += converted_digit * pow(10, HTTP_STATUS_CODE_SIZE - i - 1); + } + + return converted_status_code; +} + +void __parse_response_header(char* buffer, size_t written, gpointer user_data) +{ + __http_transaction_h* transaction = (__http_transaction_h *)user_data; + __http_response_h*response = (__http_response_h *)transaction->response; + + char status_code[HTTP_STATUS_CODE_SIZE] = {0, }; + //char reason_phrase[HTTP_REASON_PHRASE_SIZE] = {0, }; + char* start = NULL; + char* end = NULL; + + if (strncmp(buffer, "HTTP/", HTTP_PREFIX_SIZE) == 0) { + if (strncmp(buffer + HTTP_PREFIX_SIZE, "1.0", HTTP_VERSION_SIZE) == 0) + response->version = HTTP_VERSION_1_0; + else if (strncmp(buffer + HTTP_PREFIX_SIZE, "1.1", HTTP_VERSION_SIZE) == 0) + response->version = HTTP_VERSION_1_1; + + start = buffer + HTTP_PREFIX_SIZE + HTTP_VERSION_SIZE + 1; + strncpy(status_code, start, HTTP_STATUS_CODE_SIZE); + + start += HTTP_STATUS_CODE_SIZE + 1; + end = start + strcspn(start, "\n"); + + while (end > start && (end[-1] == '\r' || end[-1] == ' ' || end[-1] == '\t')) + end--; + + response->status_code = __convert_status_code(status_code); + response->status_text = g_strndup(start, end - start); + + DBG("[Seonah] reason_pharse: %s", response->status_text); + } +} + +API int http_response_get_status_code(http_transaction_h http_transaction, http_status_code_e* status_code) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(status_code == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(status_code) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + __http_response_h* response = (__http_response_h *)transaction->response; + + *status_code = response->status_code; + + return HTTP_ERROR_NONE; +} + +API int http_response_get_status_text(http_transaction_h http_transaction, char** status_text) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(status_text == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(status_text) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + __http_response_h* response = (__http_response_h *)transaction->response; + + *status_text = g_strdup(response->status_text); + + return HTTP_ERROR_NONE; +} + +API int http_response_get_version(http_transaction_h http_transaction, http_version_e* version) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(version == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(version) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + __http_response_h* response = (__http_response_h *)transaction->response; + + *version = response->version; + + return HTTP_ERROR_NONE; +} diff --git a/src/http_session.c b/src/http_session.c index 9e9bb11..2876a16 100644 --- a/src/http_session.c +++ b/src/http_session.c @@ -40,7 +40,7 @@ void _check_curl_multi_status(gpointer user_data) DBG("Completed -%s: result(%d)\n", url, curl_code); if (curl_code == CURLE_OK) { - transaction->completed_cb(); + transaction->completed_cb(transaction, transaction->completed_user_data); } else { } @@ -52,6 +52,13 @@ void _check_curl_multi_status(gpointer user_data) } } +int _generate_session_id(void) +{ + int session_id = 0; + + return session_id; +} + gboolean timer_expired_callback(gpointer user_data) { __http_session_h* session = (__http_session_h *)user_data; @@ -81,8 +88,7 @@ gboolean _handle_event(int fd, int action, gpointer user_data) 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 { + } else { print_curl_multi_errorCode(ret); } @@ -142,7 +148,7 @@ static void _remove_socket_info(__http_socket_info_h *sock_info) 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); + 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; @@ -172,7 +178,7 @@ int __handle_socket_cb(CURL *curl_easy, curl_socket_t fd, int action, void *user __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"}; + 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) { @@ -180,10 +186,9 @@ int __handle_socket_cb(CURL *curl_easy, curl_socket_t fd, int action, void *user _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":"" ); + 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 { + } else { DBG("Changing action from %d to %d\n", sock_info->action, action); _set_socket_info(sock_info, fd, curl_easy, action, session); } @@ -201,21 +206,6 @@ int __handle_timer_cb(CURLM *curl_multi, long timeout_ms, void *user_data) return 0; } -API int http_init() -{ - if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { - DBG("curl_global_init failed, so returning!\n"); - return HTTP_ERROR_OPERATION_FAILED; - } - - return HTTP_ERROR_NONE; -} - -API void http_deinit() -{ - curl_global_cleanup(); -} - API int http_create_session(http_session_h *http_session, http_session_mode_e mode) { _retvm_if(http_session == NULL, HTTP_ERROR_INVALID_PARAMETER, @@ -226,6 +216,7 @@ API int http_create_session(http_session_h *http_session, http_session_mode_e mo session = (__http_session_h *)malloc(sizeof(__http_session_h)); session->multi_handle = curl_multi_init(); + session->session_id = _generate_session_id(); session->active_transaction_count = 0; session->session_mode = mode; session->auto_redirect = FALSE; diff --git a/src/http_transaction.c b/src/http_transaction.c index da25482..4660729 100644 --- a/src/http_transaction.c +++ b/src/http_transaction.c @@ -17,6 +17,32 @@ #include "http.h" #include "http_private.h" +static __thread GSList *transaction_list = NULL; + +void _add_transaction_to_list(http_transaction_h http_transaction) +{ + transaction_list = g_slist_append(transaction_list, http_transaction); +} + +void _remove_transaction_from_list(http_transaction_h http_transaction) +{ + transaction_list = g_slist_remove(transaction_list, http_transaction); + //g_free(http_transaction); +} + +void _remove_transaction_list(void) +{ + g_slist_free_full(transaction_list, g_free); + transaction_list = NULL; +} + +int _generate_transaction_id(void) +{ + int transaction_id = 0; + + return transaction_id; +} + curl_socket_t __handle_opensocket_cb(void *client_fd, curlsocktype purpose, struct curl_sockaddr *address) { int fd = socket(address->family, address->socktype, address->protocol); @@ -30,7 +56,8 @@ size_t __handle_header_cb(char *buffer, size_t size, size_t nmemb, gpointer user __http_transaction_h *transaction = (__http_transaction_h *)user_data; size_t written = size * nmemb; - transaction->header_cb(buffer, written); + __parse_response_header(buffer, written, user_data); + transaction->header_cb(transaction, buffer, written, transaction->header_user_data); return written; } @@ -40,7 +67,7 @@ size_t __handle_body_cb(char *ptr, size_t size, size_t nmemb, gpointer user_data __http_transaction_h *transaction = (__http_transaction_h *)user_data; size_t written = size * nmemb; - transaction->body_cb(ptr, size, nmemb); + transaction->body_cb(transaction, ptr, size, nmemb, transaction->body_user_data); return written; } @@ -52,7 +79,7 @@ size_t __handle_write_cb(char *ptr, size_t size, size_t nmemb, gpointer user_dat size_t recommended_size = size * nmemb; size_t body_size = 0; - transaction->write_cb(recommended_size); + transaction->write_cb(transaction, recommended_size, transaction->write_user_data); ptr = (gchar*)g_queue_pop_head(request->body_queue); if (ptr == NULL) { @@ -69,24 +96,20 @@ size_t __http_debug_received(CURL* easy_handle, curl_infotype type, char* byte, char log_buffer[_HTTP_DEFAULT_HEADER_SIZE]; int log_size = 0; - if (_HTTP_DEFAULT_HEADER_SIZE > size) { + if (_HTTP_DEFAULT_HEADER_SIZE > size) log_size = size; - } - else { + else log_size = _HTTP_DEFAULT_HEADER_SIZE - 1; - } if (type == CURLINFO_TEXT) { strncpy(log_buffer, byte, log_size); log_buffer[log_size] = '\0'; DBG("[DEBUG] %s", log_buffer); - } - else if (type == CURLINFO_HEADER_IN || type == CURLINFO_HEADER_OUT) { - //Ignore the body message. + } else if (type == CURLINFO_HEADER_IN || type == CURLINFO_HEADER_OUT) { + /* Ignore the body message. */ if (size >= 2 && byte[0] == 0x0D && byte[1] == 0x0A) { return 0; - } - else { + } else { strncpy(log_buffer, byte, log_size); log_buffer[log_size] = '\0'; DBG("[DEBUG] %s", log_buffer); @@ -112,11 +135,10 @@ int _transaction_submit(gpointer user_data) transaction->easy_handle = curl_easy_init(); - if (request->http_version == HTTP_VERSION_1_0) { + if (request->http_version == HTTP_VERSION_1_0) curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - } else { + else curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - } if (request->host_uri) curl_easy_setopt(transaction->easy_handle, CURLOPT_URL, request->host_uri); @@ -141,6 +163,9 @@ int _transaction_submit(gpointer user_data) if (request->encoding) curl_easy_setopt(transaction->easy_handle, CURLOPT_ENCODING, request->encoding); + if (request->cookie) + curl_easy_setopt(transaction->easy_handle, CURLOPT_COOKIE, request->cookie); + //The connection timeout is 30s. (default) curl_easy_setopt(transaction->easy_handle, CURLOPT_CONNECTTIMEOUT, _HTTP_DEFAULT_CONNECTION_TIMEOUT); @@ -152,6 +177,19 @@ int _transaction_submit(gpointer user_data) curl_easy_setopt(transaction->easy_handle, CURLOPT_LOW_SPEED_TIME, 30L); } + if (!transaction->verify_peer) { + curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYHOST, 0); + + } else { + curl_easy_setopt(transaction->easy_handle, CURLOPT_CAPATH, transaction->ca_path); + DBG("CA path is (%s)", transaction->ca_path); + + curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYHOST, 2); + curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_CIPHER_LIST, "HIGH"); + } + if (session->auto_redirect) { curl_easy_setopt(transaction->easy_handle, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); @@ -174,8 +212,7 @@ int _transaction_submit(gpointer user_data) if (content_len > 0) { curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)(content_len)); DBG("Set the Content-Length(%d).", content_len); - } - else if (content_len == 0) { + } else if (content_len == 0) { curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)(content_len)); curl_easy_setopt(transaction->easy_handle, CURLOPT_COPYPOSTFIELDS, NULL); DBG("Set the Content-Length(%d).", content_len); @@ -187,12 +224,10 @@ int _transaction_submit(gpointer user_data) _get_request_body_size(transaction, &body_size); if (transaction->write_event) { - if (content_len >= 0 && content_len <= body_size) { + if (content_len >= 0 && content_len <= body_size) write_event = FALSE; - } - else { + else write_event = TRUE; - } DBG("The write_event is %d.\n", write_event); } @@ -248,55 +283,45 @@ void* thread_callback(void *user_data) return NULL; } -API int http_open_transaction(http_session_h http_session, http_method_e method, http_transaction_header_cb transaction_header_callback, - http_transaction_body_cb transaction_body_callback, http_transaction_write_cb transaction_write_callback, - http_transaction_completed_cb transaction_completed_cb, http_transaction_aborted_cb transaction_aborted_cb, http_transaction_h *http_transaction) +API int http_open_transaction(http_session_h http_session, http_method_e method, http_transaction_h *http_transaction) { _retvm_if(http_session == NULL, HTTP_ERROR_INVALID_PARAMETER, "parameter(http_session) is NULL\n"); - _retvm_if(transaction_header_callback == NULL, HTTP_ERROR_INVALID_PARAMETER, - "parameter(transaction_header_callback) is NULL\n"); - _retvm_if(transaction_body_callback == NULL, HTTP_ERROR_INVALID_PARAMETER, - "parameter(transaction_body_callback) is NULL\n"); - _retvm_if(transaction_write_callback == NULL, HTTP_ERROR_INVALID_PARAMETER, - "parameter(transaction_write_callback) is NULL\n"); - _retvm_if(transaction_completed_cb == NULL, HTTP_ERROR_INVALID_PARAMETER, - "parameter(transaction_completed_cb) is NULL\n"); - _retvm_if(transaction_aborted_cb == NULL, HTTP_ERROR_INVALID_PARAMETER, - "parameter(transaction_aborted_cb) is NULL\n"); __http_transaction_h *transaction = NULL; - transaction = (__http_transaction_h *)malloc(sizeof(__http_transaction_h)); + DBG("[Seonah] + "); + transaction = (__http_transaction_h *)malloc(sizeof(__http_transaction_h)); transaction->easy_handle = NULL; 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->header_cb = transaction_header_callback; - transaction->body_cb = transaction_body_callback; - transaction->write_cb = transaction_write_callback; - transaction->completed_cb = transaction_completed_cb; - transaction->aborted_cb = transaction_aborted_cb; + transaction->header_cb = NULL; + transaction->body_cb = NULL; + transaction->write_cb = NULL; + transaction->completed_cb = NULL; + transaction->aborted_cb = NULL; transaction->upload_progress_cb = NULL; transaction->download_progress_cb = NULL; transaction->session = http_session; transaction->session->active_transaction_count++; + transaction->session_id = 0; transaction->request = (__http_request_h *)malloc(sizeof(__http_request_h)); transaction->response = (__http_response_h *)malloc(sizeof(__http_response_h)); transaction->header = (__http_header_h *)malloc(sizeof(__http_header_h)); transaction->request->host_uri = NULL; - transaction->request->method = _get_http_method(method); - transaction->request->encoding = NULL; + transaction->request->cookie = NULL; transaction->request->http_version = HTTP_VERSION_1_1; - transaction->request->body_queue = g_queue_new(); transaction->header->header_list = NULL; @@ -305,7 +330,9 @@ API int http_open_transaction(http_session_h http_session, http_method_e method, transaction->thread = NULL; *http_transaction = (http_transaction_h)transaction; + _add_transaction_to_list(transaction); + DBG("[Seonah] - "); return HTTP_ERROR_NONE; } @@ -338,12 +365,10 @@ API int http_transaction_close(http_transaction_h http_transaction) response = transaction->response; header = transaction->header; - if (session) { + if (session) session->active_transaction_count--; - } if (transaction) { - g_thread_join(transaction->thread); transaction->thread = NULL; @@ -358,6 +383,8 @@ API int http_transaction_close(http_transaction_h http_transaction) } transaction->timeout = 0; + transaction->verify_peer = 0; + transaction->ca_path = '\0'; transaction->error[0] = '\0'; transaction->header_cb = NULL; @@ -385,10 +412,14 @@ API int http_transaction_close(http_transaction_h http_transaction) request->encoding = NULL; } - if (request->body_queue != NULL) { - g_queue_free(request->body_queue); + if (request->cookie != NULL) { + free(request->cookie); + request->cookie = NULL; } + if (request->body_queue != NULL) + g_queue_free(request->body_queue); + free(request); } free(response); @@ -414,6 +445,33 @@ API int http_transaction_close(http_transaction_h http_transaction) return HTTP_ERROR_NONE; } +API int http_transaction_pause(http_transaction_h http_transaction, http_pause_state_e pause_state) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(pause_state < HTTP_PAUSE_RECV || pause_state > HTTP_PAUSE_ALL, HTTP_ERROR_INVALID_PARAMETER, + "Wrong pause state \n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + curl_easy_pause(transaction->easy_handle, pause_state); + + return HTTP_ERROR_NONE; +} + +API int http_transaction_resume(http_transaction_h http_transaction) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + curl_easy_pause(transaction->easy_handle, CURLPAUSE_CONT); + + return HTTP_ERROR_NONE; +} + + API int http_transaction_set_progress_cb(http_transaction_h http_transaction, http_transaction_upload_progress_cb upload_progress_cb, http_transaction_download_progress_cb download_progress_cb) { @@ -432,6 +490,80 @@ API int http_transaction_set_progress_cb(http_transaction_h http_transaction, ht return HTTP_ERROR_NONE; } +API int http_transaction_set_received_header_cb(http_transaction_h http_transaction, http_transaction_header_cb header_cb, void* user_data) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(header_cb == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(header_cb) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + transaction->header_cb = header_cb; + transaction->header_user_data = user_data; + + return HTTP_ERROR_NONE; +} + +API int http_transaction_set_received_body_cb(http_transaction_h http_transaction, http_transaction_body_cb body_cb, void* user_data) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(body_cb == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(body_cb) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + transaction->body_cb = body_cb; + transaction->body_user_data = user_data; + + return HTTP_ERROR_NONE; +} + +API int http_transaction_set_uploaded_cb(http_transaction_h http_transaction, http_transaction_write_cb write_cb, void* user_data) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(write_cb == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(write_cb) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + transaction->write_cb = write_cb; + transaction->write_user_data = user_data; + + return HTTP_ERROR_NONE; +} + +API int http_transaction_set_completed_cb(http_transaction_h http_transaction, http_transaction_completed_cb completed_cb, void* user_data) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(completed_cb == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(completed_cb) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + transaction->completed_cb = completed_cb; + transaction->completed_user_data = user_data; + + return HTTP_ERROR_NONE; +} + + +API int http_transaction_unset_progress_cb(http_transaction_h http_transaction) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + transaction->upload_progress_cb = NULL; + transaction->download_progress_cb = NULL; + + return HTTP_ERROR_NONE; +} + API int http_transaction_set_timeout(http_transaction_h http_transaction, int timeout) { _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, @@ -501,3 +633,50 @@ API int http_transaction_set_ready_to_write(http_transaction_h http_transaction, return HTTP_ERROR_NONE; } + +API int http_transaction_get_server_certificate_verification(http_transaction_h http_transaction, bool* verify) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + *verify = transaction->verify_peer; + + return HTTP_ERROR_NONE; +} + +API int http_transaction_set_server_certificate_verification(http_transaction_h http_transaction, bool verify) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + transaction->verify_peer = verify; + + return HTTP_ERROR_NONE; +} + +API int http_transaction_close_all(http_session_h http_session) +{ + _retvm_if(http_session == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_session) is NULL\n"); + + GSList *list = NULL; + __http_session_h *session = (__http_session_h *)http_session; + + for (list = transaction_list; list; list = list->next) { + __http_transaction_h *transaction = (__http_transaction_h *)list->data; + if (session->session_id == transaction->session_id) { + DBG("[Seonah]Close.. (%p)", list->data); + _remove_transaction_from_list(list->data); + DBG("[Seonah]Close..1"); + http_transaction_close((http_transaction_h) transaction); + DBG("[Seonah]Close..11"); + } + } + + return HTTP_ERROR_NONE; +} + diff --git a/test/http_test.c b/test/http_test.c index 49b7feb..72bd458 100644 --- a/test/http_test.c +++ b/test/http_test.c @@ -28,128 +28,108 @@ static GMainLoop *mainloop = NULL; FILE* fp1 = NULL; FILE* fp2 = NULL; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////Request 1 Callbacks//////////////////////////////////////////////////////////////////////////// -void transaction_header_cb(char *header, size_t header_len) -{ - DBG("########################## 1:transaction_header_cb#########################################\n"); - - if (!fp1) - fp1 = fopen ("./google.html", "w+"); +http_session_h session_handle = NULL; +http_transaction_h transaction_handle1 = NULL; +http_transaction_h transaction_handle2 = NULL; +int count = 0; -} +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void transaction_body_cb(char *body, size_t size, size_t nmemb) +int add_http_header(http_transaction_h transaction_handle) { - DBG("########################## 1:transaction_body_cb#########################################\n"); - //DBG("Body:%s\n", body); - int written = size * nmemb; + http_header_add_field(transaction_handle, "Connection", "close"); + //http_header_add_field(transaction_handle, "Accept-Charset", "ISO-8859-1,UTF-8;q=0.7,*;q=0.7"); + //http_header_add_field(transaction_handle, "Cache-Control", "no-cache"); + //http_header_add_field(transaction_handle, "Accept-Language", "en-us;q=0.3"); - if (written) { - fwrite(body, size, nmemb, fp1); - } + return 0; } -void transaction_write_cb(int recommended_chunk_size) +int remove_http_header(http_transaction_h transaction_handle) { - DBG("########################## 1:transaction_write_cb#########################################\n"); + http_header_remove_field(transaction_handle, "Connection"); + //http_header_remove_field(transaction_handle, "Accept-Charset"); + //http_header_remove_field(transaction_handle, "Cache-Control"); + //http_header_remove_field(transaction_handle, "Accept-Language"); - DBG("recommended_chunk_size:%d\n", recommended_chunk_size); + return 0; } -void transaction_completed_cb(void) +void print_response_header(http_transaction_h transaction_handle) { - DBG("########################## 1:transaction_completed_cb#########################################\n"); + char* uri = NULL; + char* status_text = NULL; + http_status_code_e status_code; + http_version_e version; - fclose(fp1); + DBG("########################## Result #########################################\n"); - //g_main_loop_quit((GMainLoop*)mainloop); -} - -void transaction_aborted_cb(int reason) -{ - DBG("########################## 1:transaction_aborted_cb#########################################\n"); + http_request_get_uri(transaction_handle, &uri); + http_response_get_version(transaction_handle, &version); + http_response_get_status_code(transaction_handle, &status_code); + http_response_get_status_text(transaction_handle, &status_text); + DBG("URI(%s) HTTP version (%d) Status Code (%d) Status message (%s)\n", uri, version, status_code, status_text); } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////Request 2 Callbacks//////////////////////////////////////////////////////////////////////////// -void transaction_header_callback(char *header, size_t header_len) +/////////////////Callbacks//////////////////////////////////////////////////////////////////////////// +void transaction_header_cb(http_transaction_h transaction_handle, char *header, size_t header_len, void *user_data) { - DBG("########################## 2: transaction_header_callback#########################################\n"); - - if (!fp2) - fp2 = fopen ("./ibnlive.html", "w+"); + DBG("########################## transaction_header_cb#########################################\n"); } -void transaction_body_callback(char *body, size_t size, size_t nmemb) +void transaction_body_cb(http_transaction_h transaction_handle, char *body, size_t size, size_t nmemb, void *user_data) { - DBG("########################## 2: transaction_body_callback#########################################\n"); - //DBG("Body:%s\n", body); + DBG("########################## transaction_body_cb#########################################\n"); int written = size * nmemb; - - if (written) { - fwrite(body, size, nmemb, fp2); - } + DBG("Received: %d\n", written); + //if (written) { + //fwrite(body, size, nmemb, fp1); + //} } -void transaction_write_callback(int recommended_chunk_size) +void transaction_write_cb(http_transaction_h transaction_handle, int recommended_chunk_size, void *user_data) { - DBG("########################## 2:transaction_write_callback#########################################\n"); + DBG("########################## transaction_write_cb#########################################\n"); DBG("recommended_chunk_size:%d\n", recommended_chunk_size); } -void transaction_completed_callback(void) -{ - DBG("########################## 2:transaction_completed_callback #########################################\n"); - - fclose(fp2); - - g_main_loop_quit((GMainLoop*)mainloop); -} - -void transaction_aborted_callback(int reason) +void transaction_completed_cb(http_transaction_h transaction_handle, void *user_data) { - DBG("########################## 2:transaction_aborted_callback#########################################\n"); + DBG("########################## transaction_completed_cb#########################################\n"); -} -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + char *uri = NULL; -int add_http_header(http_transaction_h transaction_handle) -{ - http_header_add_field(transaction_handle, "Connection", "close"); - http_header_add_field(transaction_handle, "Accept-Charset", "ISO-8859-1,UTF-8;q=0.7,*;q=0.7"); - http_header_add_field(transaction_handle, "Cache-Control", "no-cache"); - http_header_add_field(transaction_handle, "Accept-Language", "en-us;q=0.3"); + http_request_get_uri(transaction_handle, &uri); + DBG("Completed uri: %s\n", uri); + print_response_header(transaction_handle); + count--; - return 0; + if (count == 0) + g_main_loop_quit((GMainLoop*)mainloop); } -int remove_http_header(http_transaction_h transaction_handle) +void transaction_aborted_cb(int reason) { - http_header_remove_field(transaction_handle, "Connection"); - http_header_remove_field(transaction_handle, "Accept-Charset"); - http_header_remove_field(transaction_handle, "Cache-Control"); - http_header_remove_field(transaction_handle, "Accept-Language"); + DBG("########################## transaction_aborted_cb#########################################\n"); - return 0; } -http_transaction_h create_http_request(http_session_h session_handle, gchar* host_url, http_transaction_header_cb header_cb, http_transaction_body_cb body_cb, http_transaction_write_cb write_cb, - http_transaction_completed_cb completed_cb, http_transaction_aborted_cb aborted_cb) +http_transaction_h create_http_request(http_session_h session_handle, gchar* host_url) { http_transaction_h transaction_handle = NULL; - http_session_set_auto_redirection(session_handle, TRUE); + //http_session_set_auto_redirection(session_handle, TRUE); - http_open_transaction(session_handle, HTTP_METHOD_GET, (http_transaction_header_cb)header_cb, - (http_transaction_body_cb)body_cb, (http_transaction_write_cb)write_cb, (http_transaction_completed_cb)completed_cb, - (http_transaction_aborted_cb)aborted_cb, &transaction_handle); + http_open_transaction(session_handle, HTTP_METHOD_GET, &transaction_handle); http_request_set_uri(transaction_handle, host_url); add_http_header(transaction_handle); + count++; return transaction_handle; } @@ -163,10 +143,6 @@ int submit_http_request(http_transaction_h transaction_handle) int main() { - http_session_h session_handle = NULL; - http_transaction_h transaction_handle1 = NULL; - http_transaction_h transaction_handle2 = NULL; - DBG("########################## main:Enter#########################################\n"); mainloop = g_main_loop_new(NULL, FALSE); @@ -175,23 +151,39 @@ int main() http_create_session(&session_handle, HTTP_SESSION_MODE_NORMAL); - transaction_handle1 = create_http_request(session_handle, "http://www.google.com", transaction_header_cb, transaction_body_cb, - transaction_write_cb, transaction_completed_cb, transaction_aborted_cb); - transaction_handle2 = create_http_request(session_handle, "http://www.ibnlive.com", transaction_header_callback, transaction_body_callback, - transaction_write_callback, transaction_completed_callback, transaction_aborted_callback); + transaction_handle1 = create_http_request(session_handle, "https://www.google.com"); + transaction_handle2 = create_http_request(session_handle, "http://www.naver.com"); + + http_transaction_set_server_certificate_verification(transaction_handle1, 0); + http_transaction_set_received_header_cb(transaction_handle1, transaction_header_cb, NULL); + http_transaction_set_received_body_cb(transaction_handle1, transaction_body_cb, NULL); + http_transaction_set_uploaded_cb(transaction_handle1, transaction_write_cb, NULL); + http_transaction_set_completed_cb(transaction_handle1, transaction_completed_cb, NULL); + http_transaction_set_received_header_cb(transaction_handle2, transaction_header_cb, NULL); + http_transaction_set_received_body_cb(transaction_handle2, transaction_body_cb, NULL); + http_transaction_set_uploaded_cb(transaction_handle2, transaction_write_cb, NULL); + http_transaction_set_completed_cb(transaction_handle2, transaction_completed_cb, NULL); + + DBG("transaction1(%p), transaction2(%p)\n", transaction_handle1, transaction_handle2); submit_http_request(transaction_handle1); submit_http_request(transaction_handle2); g_main_loop_run(mainloop); remove_http_header(transaction_handle1); + //http_transaction_close(transaction_handle1); + remove_http_header(transaction_handle2); + //http_transaction_close(transaction_handle2); + http_transaction_close_all(session_handle); + + if (transaction_handle1) DBG("transaction_handle1 remained(%p)\n", transaction_handle1); + if (transaction_handle2) DBG("transaction_handle2 remained(%p)\n", transaction_handle2); - http_transaction_close(transaction_handle1); - transaction_handle1 = NULL; - http_transaction_close(transaction_handle2); transaction_handle1 = NULL; + transaction_handle2 = NULL; + http_delete_session(session_handle); session_handle = NULL; http_deinit();