2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <linux/version.h>
20 #include "http_private.h"
22 static __thread GList *transaction_list = NULL;
25 void _add_transaction_to_list(http_transaction_h http_transaction)
27 transaction_list = g_list_append(transaction_list, http_transaction);
30 void _remove_transaction_from_list(http_transaction_h http_transaction)
32 transaction_list = g_list_remove(transaction_list, http_transaction);
35 void _remove_transaction_list(void)
37 g_list_free_full(transaction_list, g_free);
38 transaction_list = NULL;
41 void _destroy_transactions(int session_id)
44 GList *list = transaction_list;
47 __http_transaction_h *transaction = (__http_transaction_h *)list->data;
48 if (session_id == transaction->session->session_id) {
49 DBG("PREV[%p] NEXT[%p]", list->prev, list->next);
55 ret = http_transaction_destroy((http_transaction_h) transaction);
56 if (ret != HTTP_ERROR_NONE)
57 ERR("Fail to destroy transaction!!");
66 curl_socket_t __handle_opensocket_cb(void *client_fd, curlsocktype purpose, struct curl_sockaddr *address)
68 int fd = socket(address->family, address->socktype, address->protocol);
69 DBG("socket opened:%d\n", fd);
74 size_t __handle_header_cb(gchar *buffer, size_t size, size_t nmemb, gpointer user_data)
76 __http_transaction_h *transaction = (__http_transaction_h *)user_data;
77 __http_header_h *header = transaction->header;
80 size_t written = size * nmemb;
81 size_t new_len = header->rsp_header_len + written;
83 tmp = (gchar *)realloc(header->rsp_header, new_len + 1);
85 ERR("realloc() failed\n");
88 header->rsp_header = tmp;
91 memcpy(header->rsp_header + header->rsp_header_len, buffer, written);
92 header->rsp_header[new_len] = '\0';
93 header->rsp_header_len = new_len;
95 __parse_response_header(buffer, written, user_data);
100 size_t __handle_body_cb(gchar *ptr, size_t size, size_t nmemb, gpointer user_data)
102 __http_transaction_h *transaction = (__http_transaction_h *)user_data;
103 __http_header_h *header = transaction->header;
104 size_t written = size * nmemb;
106 if (!transaction->header_event) {
107 transaction->header_event = TRUE;
108 if (transaction->header_cb)
109 transaction->header_cb(transaction, header->rsp_header, header->rsp_header_len, transaction->header_user_data);
112 if (transaction->body_cb)
113 transaction->body_cb(transaction, ptr, size, nmemb, transaction->body_user_data);
119 size_t __handle_write_cb(gchar *ptr, size_t size, size_t nmemb, gpointer user_data)
121 __http_transaction_h *transaction = (__http_transaction_h *)user_data;
122 __http_request_h *request = transaction->request;
123 size_t body_size = 0;
124 size_t max_size = size * nmemb;
127 data = (char *)g_queue_pop_head(request->body_queue);
129 body_size = strlen(data);
130 memcpy(ptr, data, (max_size > body_size) ? body_size : max_size);
132 DBG("Sent the last chunk.\n");
136 if (transaction->write_cb)
137 transaction->write_cb(transaction, body_size, transaction->write_user_data);
142 size_t __handle_upload_cb(gchar *ptr, size_t size, size_t nmemb, gpointer user_data)
144 __http_transaction_h *transaction = (__http_transaction_h *)user_data;
145 size_t recommended_size;
147 FILE *fp = _get_upload_file(transaction);
149 recommended_size = fread(ptr, size, nmemb, fp);
150 nread = (curl_off_t)recommended_size;
151 DBG("Read %" CURL_FORMAT_CURL_OFF_T " bytes from file", nread);
153 if (transaction->write_cb)
154 transaction->write_cb(transaction, recommended_size, transaction->write_user_data);
156 return recommended_size;
160 size_t __http_debug_received(CURL *easy_handle, curl_infotype type, gchar *byte, size_t size, void *user_data)
162 char log_buffer[_HTTP_DEFAULT_HEADER_SIZE];
165 if (_HTTP_DEFAULT_HEADER_SIZE > size)
168 log_size = _HTTP_DEFAULT_HEADER_SIZE - 1;
170 if (type == CURLINFO_TEXT) {
171 strncpy(log_buffer, byte, log_size);
172 log_buffer[log_size] = '\0';
173 DBG("[DEBUG] %s", log_buffer);
174 } else if (type == CURLINFO_HEADER_IN || type == CURLINFO_HEADER_OUT) {
175 /* Ignore the body message. */
176 if (size >= 2 && byte[0] == 0x0D && byte[1] == 0x0A) {
179 strncpy(log_buffer, byte, log_size);
180 log_buffer[log_size] = '\0';
181 DBG("[DEBUG] %s", log_buffer);
188 int __progress_cb(void *user_data, double dltotal, double dlnow, double ultotal, double ulnow)
190 __http_transaction_h *transaction = (__http_transaction_h *)user_data;
192 double total_download = dltotal;
193 double current_download = dlnow;
194 double total_upload = ultotal;
195 double current_upload = ulnow;
197 if (transaction->progress_cb)
198 transaction->progress_cb(transaction, total_download, current_download,
199 total_upload, current_upload, transaction->progress_user_data);
201 return transaction->cancel;
205 int _set_authentication_info(http_transaction_h http_transaction)
207 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
208 "parameter(http_transaction) is NULL\n");
210 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
212 http_auth_scheme_e auth_scheme = HTTP_AUTH_NONE;
214 http_transaction_get_http_auth_scheme(transaction, &auth_scheme);
216 switch (auth_scheme) {
217 case HTTP_AUTH_PROXY_BASIC:
218 case HTTP_AUTH_PROXY_MD5:
219 case HTTP_AUTH_PROXY_NTLM:
220 http_transaction_header_get_field_value(transaction, _HTTP_PROXY_AUTHENTICATE_HEADER_NAME, &transaction->realm);
222 transaction->proxy_auth_type = TRUE;
225 case HTTP_AUTH_WWW_BASIC:
226 case HTTP_AUTH_WWW_MD5:
227 case HTTP_AUTH_WWW_NEGOTIATE:
228 case HTTP_AUTH_WWW_NTLM:
229 http_transaction_header_get_field_value(transaction, _HTTP_WWW_AUTHENTICATE_HEADER_NAME, &transaction->realm);
231 transaction->proxy_auth_type = FALSE;
238 return HTTP_ERROR_NONE;
242 void _http_transaction_start_timer(guint msecs, gboolean(*callback) (gpointer), void *user_data)
244 __http_transaction_h *transaction = (__http_transaction_h *)user_data;
247 if (callback == NULL)
250 if (transaction->timer_event != 0) {
251 ERR("timer is already registered[%u]", transaction->timer_event);
255 t_id = g_timeout_add(msecs, callback, user_data);
257 ERR("Failed to add timer");
261 DBG("g_timeout_add[%u]", t_id);
263 transaction->timer_event = t_id;
266 void _http_transaction_stop_timer(__http_transaction_h *transaction)
268 if (transaction->timer_event <= 0)
271 if (transaction->timer_event) {
272 DBG("g_source_remove[%u]", transaction->timer_event);
273 g_source_remove(transaction->timer_event);
274 transaction->timer_event = 0;
278 int _transaction_submit(gpointer user_data)
280 __http_transaction_h *transaction = (__http_transaction_h *)user_data;
281 __http_session_h *session = transaction->session;
282 __http_request_h *request = transaction->request;
284 int ret = HTTP_ERROR_NONE;
285 gchar *proxy_addr = NULL;
286 struct curl_slist* header_list = NULL;
287 gchar *field_value = NULL;
288 gboolean write_event = FALSE;
290 gint content_len = 0;
291 http_auth_scheme_e auth_scheme = HTTP_AUTH_NONE;
293 if (!transaction->easy_handle)
294 transaction->easy_handle = curl_easy_init();
296 if (request->http_version == HTTP_VERSION_1_0)
297 curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
299 curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
301 if (request->host_uri)
302 curl_easy_setopt(transaction->easy_handle, CURLOPT_URL, request->host_uri);
304 proxy_addr = _get_proxy();
306 DBG("Proxy address:%s\n", proxy_addr);
307 curl_easy_setopt(transaction->easy_handle, CURLOPT_PROXY, proxy_addr);
312 curl_easy_setopt(transaction->easy_handle, CURLOPT_CUSTOMREQUEST, request->method);
314 if (transaction->interface_name)
315 curl_easy_setopt(transaction->easy_handle, CURLOPT_INTERFACE, transaction->interface_name);
317 header_list = _get_header_list(transaction);
319 curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTPHEADER, header_list);
321 if (request->encoding)
322 curl_easy_setopt(transaction->easy_handle, CURLOPT_ACCEPT_ENCODING, request->encoding);
325 curl_easy_setopt(transaction->easy_handle, CURLOPT_COOKIE, request->cookie);
327 /* The connection timeout is 30s. (default) */
328 curl_easy_setopt(transaction->easy_handle, CURLOPT_CONNECTTIMEOUT, _HTTP_DEFAULT_CONNECTION_TIMEOUT);
330 if (transaction->timeout > 0) {
331 curl_easy_setopt(transaction->easy_handle, CURLOPT_TIMEOUT, transaction->timeout);
332 } else if (transaction->timeout == 0) {
333 /* Set the transaction timeout. The timeout includes connection timeout. */
334 curl_easy_setopt(transaction->easy_handle, CURLOPT_LOW_SPEED_LIMIT, 1L);
335 curl_easy_setopt(transaction->easy_handle, CURLOPT_LOW_SPEED_TIME, 30L);
338 if (!transaction->verify_peer) {
339 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYPEER, 0);
340 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYHOST, 0);
343 curl_easy_setopt(transaction->easy_handle, CURLOPT_CAPATH, transaction->ca_path);
344 DBG("CA path is (%s)", transaction->ca_path);
345 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYPEER, 1L);
346 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYHOST, 2L);
347 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_CIPHER_LIST, "HIGH");
350 if (session->auto_redirect) {
351 curl_easy_setopt(transaction->easy_handle, CURLOPT_FOLLOWLOCATION, 1L);
352 curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
353 DBG("Enabled Auto-Redirection\n");
355 curl_easy_setopt(transaction->easy_handle, CURLOPT_FOLLOWLOCATION, 0L);
356 DBG("Disabled Auto-Redirection\n");
361 if (transaction->auth_required) {
363 curl_http_auth_scheme_e curl_auth_scheme;
364 gchar *user_name = NULL;
365 gchar *password = NULL;
366 gchar *credentials = NULL;
367 int credentials_len = 0;
369 ret = http_transaction_get_credentials(transaction, &user_name, &password);
370 if (ret != HTTP_ERROR_NONE)
373 credentials_len = sizeof(gchar) * (strlen(user_name) + 1 + strlen(password) + 1);
374 credentials = (gchar *)malloc(credentials_len);
376 snprintf(credentials, credentials_len, "%s:%s", (gchar*)user_name, (gchar*)password);
378 http_transaction_get_http_auth_scheme(transaction, &auth_scheme);
380 curl_auth_scheme = _get_http_curl_auth_scheme(auth_scheme);
382 if (transaction->proxy_auth_type) {
383 curl_easy_setopt(transaction->easy_handle, CURLOPT_PROXYAUTH, curl_auth_scheme);
384 curl_easy_setopt(transaction->easy_handle, CURLOPT_PROXYUSERPWD, credentials);
387 curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTPAUTH, curl_auth_scheme);
388 curl_easy_setopt(transaction->easy_handle, CURLOPT_USERPWD, credentials);
397 if (transaction->tcp_fastopen)
398 curl_easy_setopt(transaction->easy_handle, CURLOPT_TCP_FASTOPEN, 1L);
400 curl_easy_setopt(transaction->easy_handle, CURLOPT_HEADERFUNCTION, __handle_header_cb);
401 curl_easy_setopt(transaction->easy_handle, CURLOPT_HEADERDATA, transaction);
403 curl_easy_setopt(transaction->easy_handle, CURLOPT_WRITEFUNCTION, __handle_body_cb);
404 curl_easy_setopt(transaction->easy_handle, CURLOPT_WRITEDATA, transaction);
406 if (http_transaction_header_get_field_value(transaction, "Content-Length", &field_value) == HTTP_ERROR_NONE) {
407 content_len = atoi(field_value);
408 if (content_len > 0) {
409 curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)(content_len));
410 DBG("Set the Content-Length(%d).", content_len);
411 } else if (content_len == 0) {
412 curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)(content_len));
413 curl_easy_setopt(transaction->easy_handle, CURLOPT_COPYPOSTFIELDS, NULL);
414 DBG("Set the Content-Length(%d).", content_len);
418 DBG("The Content-Length is not set.\n");
421 _get_request_body_size(transaction, &body_size);
423 /* Setup for POST method */
424 if (transaction->write_event)
427 DBG("The write_event[%d/%d] formpost[%d] upload_event[%d]\n",
428 transaction->write_event,
429 write_event, (request->formpost) ? 1 : 0,
430 transaction->upload_event);
432 if ((_get_method(request->method) == HTTP_METHOD_POST) && !write_event && !request->formpost) {
435 ret = _read_request_body(transaction, &body);
436 if (ret != HTTP_ERROR_NONE) {
442 curl_easy_setopt(transaction->easy_handle, CURLOPT_COPYPOSTFIELDS, body);
448 curl_easy_setopt(transaction->easy_handle, CURLOPT_POST, 1);
449 curl_easy_setopt(transaction->easy_handle, CURLOPT_READFUNCTION, __handle_write_cb);
450 curl_easy_setopt(transaction->easy_handle, CURLOPT_READDATA, transaction);
454 if (request->formpost)
455 curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTPPOST, request->formpost);
457 /* Setup for PUT method */
458 if (transaction->upload_event) {
459 if (_open_upload_file(transaction) != HTTP_ERROR_NONE)
460 return CURLM_INTERNAL_ERROR;
462 curl_easy_setopt(transaction->easy_handle, CURLOPT_UPLOAD, 1L);
463 curl_easy_setopt(transaction->easy_handle, CURLOPT_READFUNCTION, __handle_upload_cb);
464 curl_easy_setopt(transaction->easy_handle, CURLOPT_READDATA, transaction);
465 curl_easy_setopt(transaction->easy_handle, CURLOPT_INFILESIZE_LARGE, _get_upload_file_size(transaction));
468 curl_easy_setopt(transaction->easy_handle, CURLOPT_NOPROGRESS, FALSE);
469 curl_easy_setopt(transaction->easy_handle, CURLOPT_PROGRESSFUNCTION, __progress_cb);
470 curl_easy_setopt(transaction->easy_handle, CURLOPT_PROGRESSDATA, transaction);
472 curl_easy_setopt(transaction->easy_handle, CURLOPT_VERBOSE, 1L);
473 curl_easy_setopt(transaction->easy_handle, CURLOPT_DEBUGFUNCTION, __http_debug_received);
474 curl_easy_setopt(transaction->easy_handle, CURLOPT_ERRORBUFFER, transaction->error);
476 curl_easy_setopt(transaction->easy_handle, CURLOPT_PRIVATE, transaction);
478 ret = curl_multi_add_handle(session->multi_handle, transaction->easy_handle);
479 if (ret == CURLM_OK) {
480 DBG("CURLM_OK: Called curl_multi_add_handle().");
482 print_curl_multi_errorCode(ret);
483 ERR("Failed to add easy_handle to curl_multi_add_handle()");
486 ret = curl_multi_perform(session->multi_handle, &session->still_running);
487 if (ret == CURLM_OK) {
488 _http_transaction_start_timer(5, curl_request_check, transaction);
490 print_curl_multi_errorCode(ret);
491 ret = HTTP_ERROR_OPERATION_FAILED;
497 API int http_session_open_transaction(http_session_h http_session, http_method_e method, http_transaction_h *http_transaction)
499 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION, "http isn't initialized");
500 _retvm_if(http_session == NULL, HTTP_ERROR_INVALID_PARAMETER, "parameter(http_session) is NULL\n");
502 __http_transaction_h *transaction = NULL;
504 transaction = (__http_transaction_h *)malloc(sizeof(__http_transaction_h));
505 if (transaction == NULL) {
506 ERR("Fail to allocate transaction memory!!");
507 return HTTP_ERROR_OUT_OF_MEMORY;
510 transaction->request = (__http_request_h *)malloc(sizeof(__http_request_h));
511 if (transaction->request == NULL) {
512 ERR("Fail to allocate request memory!!");
514 return HTTP_ERROR_OUT_OF_MEMORY;
517 transaction->response = (__http_response_h *)malloc(sizeof(__http_response_h));
518 if (transaction->response == NULL) {
519 ERR("Fail to allocate response memory!!");
520 free(transaction->request);
522 return HTTP_ERROR_OUT_OF_MEMORY;
525 transaction->header = (__http_header_h *)malloc(sizeof(__http_header_h));
526 if (transaction->header == NULL) {
527 ERR("Fail to allocate header memory!!");
528 free(transaction->response);
529 free(transaction->request);
531 return HTTP_ERROR_OUT_OF_MEMORY;
534 transaction->easy_handle = NULL;
535 transaction->timer_event = 0;
536 transaction->interface_name = NULL;
537 transaction->timeout = 0;
538 transaction->write_event = 0;
539 transaction->upload_event = FALSE;
540 transaction->verify_peer = TRUE;
541 transaction->ca_path = g_strdup(HTTP_DEFAULT_CA_PATH);
542 transaction->tcp_fastopen = 0;
543 transaction->error[0] = '\0';
544 transaction->cancel = 0;
546 transaction->auth_required = FALSE;
547 transaction->realm = NULL;
548 transaction->user_name = NULL;
549 transaction->password = NULL;
550 transaction->proxy_auth_type = FALSE;
551 transaction->auth_scheme = HTTP_AUTH_NONE;
553 transaction->header_cb = NULL;
554 transaction->body_cb = NULL;
555 transaction->write_cb = NULL;
556 transaction->completed_cb = NULL;
557 transaction->aborted_cb = NULL;
558 transaction->progress_cb = NULL;
560 transaction->session = http_session;
561 transaction->session->active_transaction_count++;
564 transaction->header->rsp_header_len = 0;
565 transaction->header->rsp_header = malloc(transaction->header->rsp_header_len + 1);
566 if (transaction->header->rsp_header)
567 transaction->header->rsp_header[0] = '\0';
568 transaction->header->header_list = NULL;
569 transaction->header->hash_table = NULL;
570 transaction->header_event = FALSE;
573 transaction->request->host_uri = NULL;
574 transaction->request->method = _get_http_method(method);
575 if (method == HTTP_METHOD_PUT)
576 transaction->upload_event = TRUE;
578 transaction->upload_event = FALSE;
580 transaction->request->encoding = NULL;
581 transaction->request->cookie = NULL;
582 transaction->request->http_version = HTTP_VERSION_1_1;
583 transaction->request->body_queue = g_queue_new();
584 transaction->request->tot_size = 0;
585 transaction->request->upload_size = 0;
586 transaction->request->upload_file = NULL;
587 transaction->request->fp = NULL;
588 transaction->request->formpost = NULL;
589 transaction->request->lastptr = NULL;
592 transaction->response->status_text = NULL;
594 *http_transaction = (http_transaction_h)transaction;
595 _add_transaction_to_list(transaction);
597 return HTTP_ERROR_NONE;
600 API int http_transaction_submit(http_transaction_h http_transaction)
602 _retvm_if(_http_check_permission(HTTP_PRIVILEGE_INTERNET) == false,
603 HTTP_ERROR_PERMISSION_DENIED, "Permission denied");
604 _retvm_if(_http_check_permission(HTTP_PRIVILEGE_NETWORK_GET) == false,
605 HTTP_ERROR_PERMISSION_DENIED, "Permission denied");
606 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
607 "http isn't initialized");
608 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
609 "parameter(http_transaction) is NULL");
611 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
613 _retvm_if(transaction->request->host_uri == NULL, HTTP_ERROR_INVALID_OPERATION, "URI isn't set!!");
615 int ret = HTTP_ERROR_NONE;
617 if (_transaction_submit(transaction) != CURLM_OK)
618 ret = HTTP_ERROR_OPERATION_FAILED;
623 API int http_transaction_destroy(http_transaction_h http_transaction)
625 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
626 "http isn't initialized");
627 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
628 "parameter(http_transaction) is NULL\n");
630 __http_transaction_h *transaction = NULL;
631 __http_session_h *session = NULL;
632 __http_header_h *header = NULL;
633 __http_request_h *request = NULL;
634 __http_response_h *response = NULL;
636 transaction = (__http_transaction_h *)http_transaction;
637 session = transaction->session;
638 request = transaction->request;
639 response = transaction->response;
640 header = transaction->header;
643 session->active_transaction_count--;
646 if (transaction->easy_handle != NULL) {
647 curl_easy_cleanup(transaction->easy_handle);
648 transaction->easy_handle = NULL;
651 if (transaction->interface_name != NULL) {
652 free(transaction->interface_name);
653 transaction->interface_name = NULL;
656 if (transaction->timer_event) {
657 g_source_remove(transaction->timer_event);
658 transaction->timer_event = 0;
661 transaction->timeout = 0;
662 transaction->verify_peer = 0;
663 transaction->tcp_fastopen = 0;
665 if (transaction->ca_path) {
666 free(transaction->ca_path);
667 transaction->ca_path = NULL;
669 transaction->error[0] = '\0';
671 if (transaction->user_name) {
672 free(transaction->user_name);
673 transaction->user_name = NULL;
676 if (transaction->password) {
677 free(transaction->password);
678 transaction->password = NULL;
681 if (transaction->realm) {
682 free(transaction->realm);
683 transaction->realm = NULL;
686 transaction->auth_required = FALSE;
687 transaction->proxy_auth_type = FALSE;
688 transaction->auth_scheme = HTTP_AUTH_NONE;
690 transaction->progress_cb = NULL;
691 transaction->header_cb = NULL;
692 transaction->body_cb = NULL;
693 transaction->write_cb = NULL;
694 transaction->completed_cb = NULL;
695 transaction->aborted_cb = NULL;
697 transaction->progress_user_data = NULL;
698 transaction->header_user_data = NULL;
699 transaction->body_user_data = NULL;
700 transaction->write_user_data = NULL;
701 transaction->completed_user_data = NULL;
702 transaction->aborted_user_data = NULL;
705 if (request->host_uri != NULL) {
706 free(request->host_uri);
707 request->host_uri = NULL;
710 if (request->method != NULL) {
711 free(request->method);
712 request->method = NULL;
715 if (request->encoding != NULL) {
716 free(request->encoding);
717 request->encoding = NULL;
720 if (request->cookie != NULL) {
721 free(request->cookie);
722 request->cookie = NULL;
725 if (request->body_queue != NULL)
726 g_queue_free(request->body_queue);
728 if (request->formpost) {
729 curl_formfree(request->formpost);
730 request->formpost = NULL;
733 if (request->upload_file != NULL) {
734 free(request->upload_file);
735 request->upload_file = NULL;
742 if (response->status_text != NULL) {
743 free(response->status_text);
744 response->status_text = NULL;
750 if (header->header_list != NULL) {
751 curl_slist_free_all(header->header_list);
752 header->header_list = NULL;
755 if (header->hash_table != NULL) {
756 g_hash_table_remove_all(header->hash_table);
757 g_hash_table_destroy(header->hash_table);
758 header->hash_table = NULL;
761 if (header->rsp_header != NULL) {
762 free(header->rsp_header);
763 header->rsp_header = NULL;
764 header->rsp_header_len = 0;
769 _remove_transaction_from_list(transaction);
771 transaction->session = NULL;
772 transaction->request = NULL;
773 transaction->response = NULL;
774 transaction->header = NULL;
780 return HTTP_ERROR_NONE;
784 API int http_transaction_pause(http_transaction_h http_transaction, http_pause_type_e pause_type)
786 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
787 "http isn't initialized");
788 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
789 "parameter(http_transaction) is NULL\n");
790 _retvm_if(pause_type < HTTP_PAUSE_RECV || pause_type > HTTP_PAUSE_ALL, HTTP_ERROR_INVALID_PARAMETER,
791 "Wrong pause state \n");
793 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
796 ret = curl_easy_pause(transaction->easy_handle, pause_type);
798 ERR("Fail to pause!(%d)", ret);
799 return HTTP_ERROR_OPERATION_FAILED;
802 return HTTP_ERROR_NONE;
805 API int http_transaction_resume(http_transaction_h http_transaction)
807 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
808 "http isn't initialized");
809 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
810 "parameter(http_transaction) is NULL\n");
812 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
815 ret = curl_easy_pause(transaction->easy_handle, CURLPAUSE_CONT);
817 ERR("Fail to resume!(%d)", ret);
818 return HTTP_ERROR_OPERATION_FAILED;
821 return HTTP_ERROR_NONE;
825 API int http_transaction_cancel(http_transaction_h http_transaction)
827 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
828 "http isn't initialized");
829 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
830 "parameter(http_transaction) is NULL\n");
832 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
834 transaction->cancel = true;
836 return HTTP_ERROR_NONE;
839 API int http_transaction_set_progress_cb(http_transaction_h http_transaction, http_transaction_progress_cb progress_cb, void* user_data)
841 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
842 "http isn't initialized");
843 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
844 "parameter(http_transaction) is NULL\n");
845 _retvm_if(progress_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
846 "parameter(progress_cb) is NULL\n");
848 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
850 transaction->progress_cb = progress_cb;
851 transaction->progress_user_data = user_data;
853 return HTTP_ERROR_NONE;
856 API int http_transaction_set_received_header_cb(http_transaction_h http_transaction, http_transaction_header_cb header_cb, void* user_data)
858 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
859 "http isn't initialized");
860 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
861 "parameter(http_transaction) is NULL\n");
862 _retvm_if(header_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
863 "parameter(header_cb) is NULL\n");
865 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
867 transaction->header_cb = header_cb;
868 transaction->header_user_data = user_data;
870 return HTTP_ERROR_NONE;
873 API int http_transaction_set_received_body_cb(http_transaction_h http_transaction, http_transaction_body_cb body_cb, void* user_data)
875 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
876 "http isn't initialized");
877 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
878 "parameter(http_transaction) is NULL\n");
879 _retvm_if(body_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
880 "parameter(body_cb) is NULL\n");
882 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
884 transaction->body_cb = body_cb;
885 transaction->body_user_data = user_data;
887 return HTTP_ERROR_NONE;
890 API int http_transaction_set_uploaded_cb(http_transaction_h http_transaction, http_transaction_write_cb write_cb, void* user_data)
892 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
893 "http isn't initialized");
894 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
895 "parameter(http_transaction) is NULL\n");
896 _retvm_if(write_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
897 "parameter(write_cb) is NULL\n");
899 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
901 transaction->write_cb = write_cb;
902 transaction->write_user_data = user_data;
904 return HTTP_ERROR_NONE;
907 API int http_transaction_set_completed_cb(http_transaction_h http_transaction, http_transaction_completed_cb completed_cb, void* user_data)
909 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
910 "http isn't initialized");
911 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
912 "parameter(http_transaction) is NULL\n");
913 _retvm_if(completed_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
914 "parameter(completed_cb) is NULL\n");
916 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
918 transaction->completed_cb = completed_cb;
919 transaction->completed_user_data = user_data;
921 return HTTP_ERROR_NONE;
924 API int http_transaction_set_aborted_cb(http_transaction_h http_transaction, http_transaction_aborted_cb aborted_cb, void* user_data)
926 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
927 "http isn't initialized");
928 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
929 "parameter(http_transaction) is NULL\n");
930 _retvm_if(aborted_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
931 "parameter(aborted_cb) is NULL\n");
933 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
935 transaction->aborted_cb = aborted_cb;
936 transaction->aborted_user_data = user_data;
938 return HTTP_ERROR_NONE;
941 API int http_transaction_set_timeout(http_transaction_h http_transaction, int timeout)
943 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
944 "http isn't initialized");
945 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
946 "parameter(http_transaction) is NULL\n");
948 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
950 transaction->timeout = timeout;
952 return HTTP_ERROR_NONE;
955 API int http_transaction_get_timeout(http_transaction_h http_transaction, int *timeout)
957 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
958 "http isn't initialized");
959 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
960 "parameter(http_transaction) is NULL\n");
961 _retvm_if(timeout == NULL, HTTP_ERROR_INVALID_PARAMETER,
962 "parameter(timeout) is NULL\n");
964 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
966 *timeout = transaction->timeout;
968 return HTTP_ERROR_NONE;
971 API int http_transaction_set_interface_name(http_transaction_h http_transaction, const char *interface_name)
973 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
974 "http isn't initialized");
975 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
976 "parameter(http_transaction) is NULL\n");
977 _retvm_if(interface_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
978 "parameter(interface_name) is NULL\n");
980 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
982 transaction->interface_name = g_strdup(interface_name);
984 return HTTP_ERROR_NONE;
987 API int http_transaction_get_interface_name(http_transaction_h http_transaction, char **interface_name)
989 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
990 "http isn't initialized");
991 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
992 "parameter(http_transaction) is NULL\n");
993 _retvm_if(interface_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
994 "parameter(interface_name) is NULL\n");
996 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
998 *interface_name = g_strdup(transaction->interface_name);
999 if (*interface_name == NULL) {
1000 ERR("strdup is failed\n");
1001 return HTTP_ERROR_OUT_OF_MEMORY;
1004 return HTTP_ERROR_NONE;
1007 API int http_transaction_set_ready_to_write(http_transaction_h http_transaction, bool read_to_write)
1009 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
1010 "http isn't initialized");
1011 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1012 "parameter(http_transaction) is NULL\n");
1014 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1016 transaction->write_event = read_to_write;
1018 return HTTP_ERROR_NONE;
1021 API int http_transaction_get_server_certificate_verification(http_transaction_h http_transaction, bool* verify)
1023 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
1024 "http isn't initialized");
1025 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1026 "parameter(http_transaction) is NULL\n");
1028 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1030 *verify = transaction->verify_peer;
1032 return HTTP_ERROR_NONE;
1035 API int http_transaction_set_server_certificate_verification(http_transaction_h http_transaction, bool verify)
1037 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
1038 "http isn't initialized");
1039 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1040 "parameter(http_transaction) is NULL\n");
1042 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1044 transaction->verify_peer = verify;
1046 return HTTP_ERROR_NONE;
1049 API int http_transaction_get_tcp_fastopen(http_transaction_h http_transaction, bool *enable)
1051 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
1052 "http isn't initialized");
1053 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1054 "parameter(http_transaction) is NULL\n");
1056 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
1057 return HTTP_ERROR_NOT_SUPPORTED;
1059 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1060 *enable = transaction->tcp_fastopen;
1061 return HTTP_ERROR_NONE;
1065 API int http_transaction_set_tcp_fastopen(http_transaction_h http_transaction, bool enable)
1067 _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
1068 "http isn't initialized");
1069 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1070 "parameter(http_transaction) is NULL\n");
1072 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
1073 return HTTP_ERROR_NOT_SUPPORTED;
1075 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1076 transaction->tcp_fastopen = enable;
1077 return HTTP_ERROR_NONE;
1082 API int http_transaction_set_http_auth_scheme(http_transaction_h http_transaction, http_auth_scheme_e auth_scheme)
1084 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1085 "parameter(http_transaction) is NULL\n");
1087 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1089 transaction->auth_scheme = auth_scheme;
1091 return HTTP_ERROR_NONE;
1094 API int http_transaction_get_http_auth_scheme(http_transaction_h http_transaction, http_auth_scheme_e *auth_scheme)
1096 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1097 "parameter(http_transaction) is NULL\n");
1098 _retvm_if(auth_scheme == NULL, HTTP_ERROR_INVALID_PARAMETER,
1099 "parameter(auth_scheme) is NULL\n");
1101 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1103 *auth_scheme = transaction->auth_scheme;
1105 return HTTP_ERROR_NONE;
1108 API int http_transaction_get_realm(http_transaction_h http_transaction, char **realm)
1110 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1111 "parameter(http_transaction) is NULL\n");
1112 _retvm_if(realm == NULL, HTTP_ERROR_INVALID_PARAMETER,
1113 "parameter(realm) is NULL\n");
1115 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1117 if (transaction->realm == NULL)
1118 return HTTP_ERROR_INVALID_OPERATION;
1120 *realm = g_strdup(transaction->realm);
1121 if (*realm == NULL) {
1122 ERR("strdup is failed\n");
1123 return HTTP_ERROR_OUT_OF_MEMORY;
1126 return HTTP_ERROR_NONE;
1129 API int http_transaction_set_credentials(http_transaction_h http_transaction, const char *user_name, const char *password)
1131 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1132 "parameter(http_transaction) is NULL\n");
1133 _retvm_if(user_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
1134 "parameter(user_name) is NULL\n");
1135 _retvm_if(password == NULL, HTTP_ERROR_INVALID_PARAMETER,
1136 "parameter(password) is NULL\n");
1138 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1140 transaction->user_name = g_strdup(user_name);
1141 transaction->password = g_strdup(password);
1143 return HTTP_ERROR_NONE;
1146 API int http_transaction_get_credentials(http_transaction_h http_transaction, char **user_name, char **password)
1148 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1149 "parameter(http_transaction) is NULL\n");
1150 _retvm_if(user_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
1151 "parameter(user_name) is NULL\n");
1152 _retvm_if(password == NULL, HTTP_ERROR_INVALID_PARAMETER,
1153 "parameter(password) is NULL\n");
1155 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1157 *user_name = g_strdup(transaction->user_name);
1158 if (*user_name == NULL) {
1159 ERR("strdup is failed\n");
1160 return HTTP_ERROR_OUT_OF_MEMORY;
1163 *password = g_strdup(transaction->password);
1164 if (*password == NULL) {
1165 ERR("strdup is failed\n");
1168 return HTTP_ERROR_OUT_OF_MEMORY;
1170 return HTTP_ERROR_NONE;
1173 API int http_transaction_open_authentication(http_transaction_h http_transaction, http_transaction_h *http_auth_transaction)
1175 _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1176 "parameter(http_transaction) is NULL\n");
1178 __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1179 __http_transaction_h *auth_transaction = NULL;
1181 auth_transaction = (__http_transaction_h *)malloc(sizeof(__http_transaction_h));
1182 if (auth_transaction == NULL) {
1183 ERR("Fail to allocate transaction memory!!");
1184 return HTTP_ERROR_OUT_OF_MEMORY;
1187 auth_transaction->easy_handle = NULL;
1188 auth_transaction->timer_event = 0;
1189 auth_transaction->interface_name = NULL;
1190 auth_transaction->ca_path = NULL;
1191 auth_transaction->error[0] = '\0';
1193 if (transaction->interface_name)
1194 auth_transaction->interface_name = g_strdup(transaction->interface_name);
1195 auth_transaction->timeout = 0;
1196 auth_transaction->verify_peer = transaction->verify_peer;
1197 if (transaction->ca_path)
1198 auth_transaction->ca_path = g_strdup(transaction->ca_path);
1200 auth_transaction->auth_required = transaction->auth_required;
1201 auth_transaction->user_name = NULL;
1202 auth_transaction->password = NULL;
1203 auth_transaction->proxy_auth_type = FALSE;
1204 auth_transaction->auth_scheme = transaction->auth_scheme;
1205 if (transaction->realm)
1206 auth_transaction->realm = g_strdup(transaction->realm);
1208 auth_transaction->write_event = FALSE;
1209 auth_transaction->upload_event = FALSE;
1211 auth_transaction->header_cb = NULL;
1212 auth_transaction->header_user_data = NULL;
1213 auth_transaction->body_cb = NULL;
1214 auth_transaction->body_user_data = NULL;
1215 auth_transaction->write_cb = NULL;
1216 auth_transaction->write_user_data = NULL;
1217 auth_transaction->completed_cb = NULL;
1218 auth_transaction->completed_user_data = NULL;
1219 auth_transaction->aborted_cb = NULL;
1220 auth_transaction->progress_cb = NULL;
1221 auth_transaction->progress_user_data = NULL;
1223 auth_transaction->session = transaction->session;
1224 auth_transaction->session->active_transaction_count = transaction->session->active_transaction_count;
1226 auth_transaction->request = (__http_request_h *)malloc(sizeof(__http_request_h));
1227 if (auth_transaction->request == NULL) {
1228 g_free(auth_transaction->interface_name);
1229 g_free(auth_transaction->ca_path);
1230 g_free(auth_transaction->realm);
1231 free(auth_transaction);
1232 ERR("Fail to allocate request memory!!");
1233 return HTTP_ERROR_OUT_OF_MEMORY;
1236 auth_transaction->request->host_uri = NULL;
1237 auth_transaction->request->method = NULL;
1239 auth_transaction->response = (__http_response_h *)malloc(sizeof(__http_response_h));
1240 if (auth_transaction->response == NULL) {
1241 g_free(auth_transaction->interface_name);
1242 g_free(auth_transaction->ca_path);
1243 g_free(auth_transaction->realm);
1244 free(auth_transaction->request);
1245 free(auth_transaction);
1246 ERR("Fail to allocate response memory!!");
1247 return HTTP_ERROR_OUT_OF_MEMORY;
1250 auth_transaction->header = (__http_header_h *)malloc(sizeof(__http_header_h));
1251 if (auth_transaction->header == NULL) {
1252 g_free(auth_transaction->interface_name);
1253 g_free(auth_transaction->ca_path);
1254 g_free(auth_transaction->realm);
1255 free(auth_transaction->request);
1256 free(auth_transaction->response);
1257 free(auth_transaction);
1258 ERR("Fail to allocate header memory!!");
1259 return HTTP_ERROR_OUT_OF_MEMORY;
1262 auth_transaction->header->rsp_header_len = 0;
1263 auth_transaction->header->rsp_header = malloc(auth_transaction->header->rsp_header_len + 1);
1264 if (auth_transaction->header->rsp_header)
1265 auth_transaction->header->rsp_header[0] = '\0';
1266 auth_transaction->header_event = FALSE;
1268 if (transaction->request->host_uri)
1269 auth_transaction->request->host_uri = g_strdup(transaction->request->host_uri);
1270 if (transaction->request->method)
1271 auth_transaction->request->method = g_strdup(transaction->request->method);
1272 auth_transaction->request->encoding = NULL;
1273 auth_transaction->request->cookie = NULL;
1274 auth_transaction->request->http_version = HTTP_VERSION_1_1;
1275 auth_transaction->request->body_queue = g_queue_new();
1276 auth_transaction->request->tot_size = 0;
1278 auth_transaction->header->header_list = NULL;
1279 auth_transaction->header->hash_table = NULL;
1281 *http_auth_transaction = (http_transaction_h)auth_transaction;
1282 _add_transaction_to_list(auth_transaction);
1284 return HTTP_ERROR_NONE;