Add APIs for request/response 45/61045/4
authorSeonah Moon <seonah1.moon@samsung.com>
Thu, 17 Mar 2016 06:17:16 +0000 (15:17 +0900)
committerSeonah Moon <seonah1.moon@samsung.com>
Thu, 17 Mar 2016 06:17:20 +0000 (15:17 +0900)
- 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 <seonah1.moon@samsung.com>
include/http.h
include/http_private.h
packaging/capi-network-http.spec
src/http_common.c
src/http_header.c
src/http_request.c
src/http_response.c
src/http_session.c
src/http_transaction.c
test/http_test.c

index 1cdd038..c3bd308 100644 (file)
@@ -83,6 +83,17 @@ typedef enum {
 
 /**
  * @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.
  * @since_tizen 3.0
  */
@@ -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
@@ -556,6 +576,36 @@ int http_transaction_get_interface_name(http_transaction_h http_transaction, cha
 
 /**
  * @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.
  * @since_tizen 3.0
  * @privlevel platform
index fa53f26..b0e4803 100644 (file)
@@ -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
  }
index 250a093..af02a13 100644 (file)
@@ -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
index bb5613e..35d45fd 100644 (file)
@@ -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();
+}
index 5ca3c33..8bf7501 100644 (file)
@@ -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);
index a61cc21..c5c5e76 100644 (file)
@@ -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,
index c01bbb6..3b27bd4 100644 (file)
  * limitations under the License.
  */
 
+#include <math.h>
+
 #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;
+}
index 9e9bb11..2876a16 100644 (file)
@@ -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;
index da25482..4660729 100644 (file)
 #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;
+}
+
index 49b7feb..72bd458 100644 (file)
@@ -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();