Fixed doxygen comments
[platform/core/api/http.git] / src / http_transaction.c
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "http.h"
18 #include "http_private.h"
19
20 static __thread GSList *transaction_list = NULL;
21
22 void _add_transaction_to_list(http_transaction_h http_transaction)
23 {
24         transaction_list = g_slist_append(transaction_list, http_transaction);
25 }
26
27 void _remove_transaction_from_list(http_transaction_h http_transaction)
28 {
29         transaction_list = g_slist_remove(transaction_list, http_transaction);
30 }
31
32 void _remove_transaction_list(void)
33 {
34         g_slist_free_full(transaction_list, g_free);
35         transaction_list = NULL;
36 }
37
38 int _generate_transaction_id(void)
39 {
40         int transaction_id = 0;
41
42         return transaction_id;
43 }
44
45 curl_socket_t __handle_opensocket_cb(void *client_fd, curlsocktype purpose, struct curl_sockaddr *address)
46 {
47         int fd = socket(address->family, address->socktype, address->protocol);
48         DBG("socket opened:%d\n", fd);
49
50         return fd;
51 }
52
53 size_t __handle_header_cb(gchar *buffer, size_t size, size_t nmemb, gpointer user_data)
54 {
55         __http_transaction_h *transaction = (__http_transaction_h *)user_data;
56         __http_header_h *header = transaction->header;
57
58         gchar *temp_header = NULL;
59         size_t written = size * nmemb;
60         size_t new_len = header->rsp_header_len + written;
61
62         temp_header = header->rsp_header;
63         header->rsp_header = realloc(header->rsp_header, new_len + 1);
64         if (header->rsp_header == NULL) {
65                 free(temp_header);
66                 ERR("realloc() failed\n");
67                 return -1;
68         }
69
70         memcpy(header->rsp_header + header->rsp_header_len, buffer, written);
71         header->rsp_header[new_len] = '\0';
72         header->rsp_header_len = new_len;
73
74         __parse_response_header(buffer, written, user_data);
75
76         return written;
77 }
78
79 size_t __handle_body_cb(gchar *ptr, size_t size, size_t nmemb, gpointer user_data)
80 {
81         __http_transaction_h *transaction = (__http_transaction_h *)user_data;
82         __http_header_h *header = transaction->header;
83         size_t written = size * nmemb;
84
85         if (!transaction->header_event) {
86                 transaction->header_event = TRUE;
87                 transaction->header_cb(transaction, header->rsp_header, header->rsp_header_len, transaction->header_user_data);
88         }
89
90         transaction->body_cb(transaction, ptr, size, nmemb, transaction->body_user_data);
91
92         return written;
93 }
94
95 size_t __handle_write_cb(gchar *ptr, size_t size, size_t nmemb, gpointer user_data)
96 {
97         __http_transaction_h *transaction = (__http_transaction_h *)user_data;
98         __http_request_h *request = transaction->request;
99         size_t recommended_size = size * nmemb;
100         size_t body_size = 0;
101
102         transaction->write_cb(transaction, recommended_size, transaction->write_user_data);
103
104         ptr = (gchar*)g_queue_pop_head(request->body_queue);
105         if (ptr == NULL) {
106                 DBG("Sent the last chunk.\n");
107                 return 0;
108         }
109         body_size = strlen(ptr);
110
111         return body_size;
112 }
113
114 size_t __http_debug_received(CURL* easy_handle, curl_infotype type, gchar* byte, size_t size, void *user_data)
115 {
116         char log_buffer[_HTTP_DEFAULT_HEADER_SIZE];
117         int log_size = 0;
118
119         if (_HTTP_DEFAULT_HEADER_SIZE > size)
120                 log_size = size;
121         else
122                 log_size = _HTTP_DEFAULT_HEADER_SIZE - 1;
123
124         if (type == CURLINFO_TEXT) {
125                 strncpy(log_buffer, byte, log_size);
126                 log_buffer[log_size] = '\0';
127                 DBG("[DEBUG] %s", log_buffer);
128         } else if (type == CURLINFO_HEADER_IN || type == CURLINFO_HEADER_OUT) {
129                 /* Ignore the body message. */
130                 if (size >= 2 && byte[0] == 0x0D && byte[1] == 0x0A) {
131                         return 0;
132                 } else {
133                         strncpy(log_buffer, byte, log_size);
134                         log_buffer[log_size] = '\0';
135                         DBG("[DEBUG] %s", log_buffer);
136                 }
137         }
138
139         return 0;
140 }
141
142 int http_transaction_set_authentication_info(http_transaction_h http_transaction)
143 {
144         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
145                         "parameter(http_transaction) is NULL\n");
146
147         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
148
149         http_auth_scheme_e auth_scheme = HTTP_AUTH_NONE;
150
151         http_transaction_get_http_auth_scheme(transaction, &auth_scheme);
152
153         switch (auth_scheme) {
154         case HTTP_AUTH_PROXY_BASIC:
155         case HTTP_AUTH_PROXY_MD5:
156         case HTTP_AUTH_PROXY_NTLM:
157                 http_transaction_header_get_field_value(transaction, _HTTP_PROXY_AUTHENTICATE_HEADER_NAME, &transaction->realm);
158
159                 transaction->proxy_auth_type = TRUE;
160                 break;
161
162         case HTTP_AUTH_WWW_BASIC:
163         case HTTP_AUTH_WWW_MD5:
164         case HTTP_AUTH_WWW_NEGOTIATE:
165         case HTTP_AUTH_WWW_NTLM:
166                 http_transaction_header_get_field_value(transaction, _HTTP_WWW_AUTHENTICATE_HEADER_NAME, &transaction->realm);
167
168                 transaction->proxy_auth_type = FALSE;
169                 break;
170
171         default:
172                 break;
173         }
174
175         return HTTP_ERROR_NONE;
176 }
177
178 int _transaction_submit(gpointer user_data)
179 {
180         __http_transaction_h *transaction = (__http_transaction_h *)user_data;
181         __http_session_h *session = transaction->session;
182         __http_request_h *request = transaction->request;
183
184         CURLMcode ret = CURLM_OK;
185         gchar *proxy_addr = NULL;
186         struct curl_slist* header_list = NULL;
187         gchar *field_value = NULL;
188         gboolean write_event = FALSE;
189         gint body_size = 0;
190         gint content_len = 0;
191         http_auth_scheme_e auth_scheme = HTTP_AUTH_NONE;
192
193         if (!transaction->easy_handle)
194                 transaction->easy_handle = curl_easy_init();
195
196         if (request->http_version == HTTP_VERSION_1_0)
197                 curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
198         else
199                 curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
200
201         if (request->host_uri)
202                 curl_easy_setopt(transaction->easy_handle, CURLOPT_URL, request->host_uri);
203
204         proxy_addr = _get_proxy();
205         if (proxy_addr) {
206                 DBG("Proxy address:%s\n", proxy_addr);
207                 curl_easy_setopt(transaction->easy_handle, CURLOPT_PROXY, proxy_addr);
208                 free(proxy_addr);
209         }
210
211         if (request->method)
212                 curl_easy_setopt(transaction->easy_handle, CURLOPT_CUSTOMREQUEST, request->method);
213
214         if (transaction->interface_name)
215                 curl_easy_setopt(transaction->easy_handle, CURLOPT_INTERFACE, transaction->interface_name);
216
217         header_list = _get_header_list(transaction);
218         if (header_list)
219                 curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTPHEADER, header_list);
220
221         if (request->encoding)
222                 curl_easy_setopt(transaction->easy_handle, CURLOPT_ACCEPT_ENCODING, request->encoding);
223
224         if (request->cookie)
225                 curl_easy_setopt(transaction->easy_handle, CURLOPT_COOKIE, request->cookie);
226
227         /* The connection timeout is 30s. (default) */
228         curl_easy_setopt(transaction->easy_handle, CURLOPT_CONNECTTIMEOUT, _HTTP_DEFAULT_CONNECTION_TIMEOUT);
229
230         if (transaction->timeout > 0) {
231                 curl_easy_setopt(transaction->easy_handle, CURLOPT_TIMEOUT, transaction->timeout);
232         } else if (transaction->timeout == 0) {
233                 /* Set the transaction timeout. The timeout includes connection timeout. */
234                 curl_easy_setopt(transaction->easy_handle, CURLOPT_LOW_SPEED_LIMIT, 1L);
235                 curl_easy_setopt(transaction->easy_handle, CURLOPT_LOW_SPEED_TIME, 30L);
236         }
237
238         if (!transaction->verify_peer) {
239                 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYPEER, 0);
240                 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYHOST, 0);
241
242         } else {
243                         curl_easy_setopt(transaction->easy_handle, CURLOPT_CAPATH, transaction->ca_path);
244                         DBG("CA path is (%s)", transaction->ca_path);
245
246                 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYPEER, 0);
247                 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_VERIFYHOST, 2);
248                 curl_easy_setopt(transaction->easy_handle, CURLOPT_SSL_CIPHER_LIST, "HIGH");
249         }
250
251         if (session->auto_redirect) {
252                 curl_easy_setopt(transaction->easy_handle, CURLOPT_FOLLOWLOCATION, 1L);
253                 curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
254                 DBG("Enabled Auto-Redirection\n");
255         } else {
256                 curl_easy_setopt(transaction->easy_handle, CURLOPT_FOLLOWLOCATION, 0L);
257                 DBG("Disabled Auto-Redirection\n");
258         }
259
260         /* Authentication */
261         if (transaction->auth_required) {
262
263                 curl_http_auth_scheme_e curl_auth_scheme;
264                 gchar *user_name = NULL;
265                 gchar *password = NULL;
266                 gchar *credentials = NULL;
267
268                 http_transaction_get_credentials(transaction, &user_name, &password);
269                 credentials = (gchar *)malloc(sizeof(gchar) * (strlen(user_name) + 1 + strlen(password) + 1));
270                 sprintf(credentials, "%s:%s", (gchar*)user_name, (gchar*)password);
271                 free(user_name);
272                 free(password);
273
274                 http_transaction_get_http_auth_scheme(transaction, &auth_scheme);
275
276                 curl_auth_scheme = _get_http_curl_auth_scheme(auth_scheme);
277
278                 if (transaction->proxy_auth_type) {
279
280                         curl_easy_setopt(transaction->easy_handle, CURLOPT_PROXYAUTH, curl_auth_scheme);
281                         curl_easy_setopt(transaction->easy_handle, CURLOPT_PROXYUSERPWD, credentials);
282
283                 } else {
284                         curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTPAUTH, curl_auth_scheme);
285                         curl_easy_setopt(transaction->easy_handle, CURLOPT_USERPWD, credentials);
286                 }
287                 free(credentials);
288         }
289
290         curl_easy_setopt(transaction->easy_handle, CURLOPT_HEADERFUNCTION, __handle_header_cb);
291         curl_easy_setopt(transaction->easy_handle, CURLOPT_HEADERDATA, transaction);
292
293         curl_easy_setopt(transaction->easy_handle, CURLOPT_WRITEFUNCTION, __handle_body_cb);
294         curl_easy_setopt(transaction->easy_handle, CURLOPT_WRITEDATA, transaction);
295
296         if (http_transaction_header_get_field_value(transaction, "Content-Length", &field_value) == HTTP_ERROR_NONE) {
297                 content_len = atoi(field_value);
298                 if (content_len > 0) {
299                         curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)(content_len));
300                         DBG("Set the Content-Length(%d).", content_len);
301                 } else if (content_len == 0) {
302                         curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)(content_len));
303                         curl_easy_setopt(transaction->easy_handle, CURLOPT_COPYPOSTFIELDS, NULL);
304                         DBG("Set the Content-Length(%d).", content_len);
305                 }
306         } else {
307                 DBG("The Content-Length is not set.\n");
308         }
309
310         _get_request_body_size(transaction, &body_size);
311
312         if (transaction->write_event) {
313                 if (content_len >= 0 && content_len <= body_size)
314                         write_event = FALSE;
315                 else
316                         write_event = TRUE;
317                 DBG("The write_event is %d.\n", write_event);
318         }
319
320         if ((_get_method(request->method) == HTTP_METHOD_POST) && !write_event) {
321                 gchar *body = NULL;
322
323                 _read_request_body(transaction, &body);
324
325                 if (body) {
326                         curl_easy_setopt(transaction->easy_handle, CURLOPT_COPYPOSTFIELDS, body);
327                         free(body);
328                 }
329         }
330
331         if (write_event) {
332                 curl_easy_setopt(transaction->easy_handle, CURLOPT_POST, 1);
333                 curl_easy_setopt(transaction->easy_handle, CURLOPT_READFUNCTION, __handle_write_cb);
334                 curl_easy_setopt(transaction->easy_handle, CURLOPT_READDATA, transaction);
335         }
336
337         curl_easy_setopt(transaction->easy_handle, CURLOPT_VERBOSE, 1L);
338         curl_easy_setopt(transaction->easy_handle, CURLOPT_DEBUGFUNCTION, __http_debug_received);
339         curl_easy_setopt(transaction->easy_handle, CURLOPT_ERRORBUFFER, transaction->error);
340
341         curl_easy_setopt(transaction->easy_handle, CURLOPT_OPENSOCKETDATA, &transaction->socket_fd);
342         curl_easy_setopt(transaction->easy_handle, CURLOPT_OPENSOCKETFUNCTION, __handle_opensocket_cb);
343
344         curl_easy_setopt(transaction->easy_handle, CURLOPT_PRIVATE, transaction);
345
346         ret = curl_multi_add_handle(session->multi_handle, transaction->easy_handle);
347         if (ret == CURLM_OK) {
348                 DBG("CURLM_OK: Called curl_multi_add_handle().");
349         } else {
350                 print_curl_multi_errorCode(ret);
351                 ERR("Failed to add easy_handle to curl_multi_add_handle()");
352         }
353
354         return HTTP_ERROR_NONE;
355 }
356
357 void* thread_callback(void *user_data)
358 {
359         __http_transaction_h *transaction = (__http_transaction_h *)user_data;
360
361         transaction->thread_loop = g_main_loop_new(NULL, FALSE);
362
363         _transaction_submit(transaction);
364
365         g_main_loop_run(transaction->thread_loop);
366
367         DBG("thread exited.\n");
368
369         return NULL;
370 }
371
372 API int http_session_open_transaction(http_session_h http_session, http_method_e method, http_transaction_h *http_transaction)
373 {
374         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION, "http isn't initialized");
375         _retvm_if(http_session == NULL, HTTP_ERROR_INVALID_PARAMETER, "parameter(http_session) is NULL\n");
376
377         __http_transaction_h *transaction = NULL;
378
379         transaction = (__http_transaction_h *)malloc(sizeof(__http_transaction_h));
380         if (transaction == NULL) {
381                 ERR("Fail to allocate transaction memory!!");
382                 return HTTP_ERROR_OUT_OF_MEMORY;
383         }
384
385         transaction->easy_handle = NULL;
386         transaction->interface_name = NULL;
387         transaction->timeout = 0;
388         transaction->verify_peer = 1;
389         transaction->ca_path = g_strdup(HTTP_DEFAULT_CA_PATH);
390         transaction->error[0] = '\0';
391
392         transaction->auth_required = FALSE;
393         transaction->realm = NULL;
394         transaction->user_name = NULL;
395         transaction->password = NULL;
396         transaction->proxy_auth_type = FALSE;
397         transaction->auth_scheme = HTTP_AUTH_NONE;
398
399         transaction->header_cb = NULL;
400         transaction->body_cb = NULL;
401         transaction->write_cb = NULL;
402         transaction->completed_cb = NULL;
403         transaction->aborted_cb = NULL;
404         transaction->progress_cb = NULL;
405
406         transaction->session = http_session;
407         transaction->session->active_transaction_count++;
408         transaction->session_id = 0;
409
410         transaction->request = (__http_request_h *)malloc(sizeof(__http_request_h));
411         if (transaction->request == NULL) {
412                 ERR("Fail to allocate request memory!!");
413                 return HTTP_ERROR_OUT_OF_MEMORY;
414         }
415
416         transaction->response = (__http_response_h *)malloc(sizeof(__http_response_h));
417         if (transaction->response == NULL) {
418                 ERR("Fail to allocate response memory!!");
419                 return HTTP_ERROR_OUT_OF_MEMORY;
420         }
421
422         transaction->header = (__http_header_h *)malloc(sizeof(__http_header_h));
423         if (transaction->header == NULL) {
424                 ERR("Fail to allocate header memory!!");
425                 return HTTP_ERROR_OUT_OF_MEMORY;
426         }
427
428         transaction->header->rsp_header_len = 0;
429         transaction->header->rsp_header = malloc(transaction->header->rsp_header_len + 1);
430         transaction->header->rsp_header[0] = '\0';
431         transaction->header_event = FALSE;
432
433         transaction->request->host_uri = NULL;
434         transaction->request->method = _get_http_method(method);
435         transaction->request->encoding = NULL;
436         transaction->request->cookie = NULL;
437         transaction->request->http_version = HTTP_VERSION_1_1;
438         transaction->request->body_queue = g_queue_new();
439         transaction->request->tot_size = 0;
440
441         transaction->response->status_text = NULL;
442
443         transaction->header->header_list = NULL;
444         transaction->header->hash_table = NULL;
445
446         transaction->thread = NULL;
447         transaction->thread_loop = NULL;
448
449         *http_transaction = (http_transaction_h)transaction;
450         _add_transaction_to_list(transaction);
451
452         return HTTP_ERROR_NONE;
453 }
454
455 API int http_transaction_submit(http_transaction_h http_transaction)
456 {
457         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
458                         "http isn't initialized");
459         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
460                         "parameter(http_transaction) is NULL");
461
462         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
463
464         _retvm_if(transaction->request->host_uri == NULL, HTTP_ERROR_INVALID_OPERATION, "URI isn't set!!");
465
466         transaction->thread = g_thread_new("transaction_thread", thread_callback, transaction);
467
468         return HTTP_ERROR_NONE;
469 }
470
471 API int http_transaction_destroy(http_transaction_h http_transaction)
472 {
473         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
474                         "http isn't initialized");
475         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
476                         "parameter(http_transaction) is NULL\n");
477
478         __http_transaction_h *transaction = NULL;
479         __http_session_h *session = NULL;
480         __http_header_h *header = NULL;
481         __http_request_h *request = NULL;
482         __http_response_h *response = NULL;
483
484         transaction = (__http_transaction_h *)http_transaction;
485         session = transaction->session;
486         request = transaction->request;
487         response = transaction->response;
488         header = transaction->header;
489
490         if (session)
491                 session->active_transaction_count--;
492
493         if (transaction) {
494                 if (transaction->easy_handle != NULL) {
495                         curl_easy_cleanup(transaction->easy_handle);
496                         transaction->easy_handle = NULL;
497                 }
498
499                 if (transaction->interface_name != NULL) {
500                         free(transaction->interface_name);
501                         transaction->interface_name = NULL;
502                 }
503
504                 transaction->timeout = 0;
505                 transaction->verify_peer = 0;
506
507                 if (transaction->ca_path) {
508                         free(transaction->ca_path);
509                         transaction->ca_path = NULL;
510                 }
511                 transaction->error[0] = '\0';
512
513                 if (transaction->user_name) {
514                         free(transaction->user_name);
515                         transaction->user_name = NULL;
516                 }
517
518                 if (transaction->password) {
519                         free(transaction->password);
520                         transaction->password = NULL;
521                 }
522
523                 if (transaction->realm) {
524                         free(transaction->realm);
525                         transaction->realm = NULL;
526                 }
527
528                 transaction->auth_required = FALSE;
529                 transaction->proxy_auth_type = FALSE;
530                 transaction->auth_scheme = HTTP_AUTH_NONE;
531
532                 transaction->header_cb = NULL;
533                 transaction->body_cb = NULL;
534                 transaction->write_cb = NULL;
535                 transaction->completed_cb = NULL;
536                 transaction->aborted_cb = NULL;
537                 transaction->progress_cb = NULL;
538
539                 if (request) {
540                         if (request->host_uri != NULL) {
541                                 free(request->host_uri);
542                                 request->host_uri = NULL;
543                         }
544
545                         if (request->method != NULL) {
546                                 free(request->method);
547                                 request->method = NULL;
548                         }
549
550                         if (request->encoding != NULL) {
551                                 free(request->encoding);
552                                 request->encoding = NULL;
553                         }
554
555                         if (request->cookie != NULL) {
556                                 free(request->cookie);
557                                 request->cookie = NULL;
558                         }
559
560                         if (request->body_queue != NULL)
561                                 g_queue_free(request->body_queue);
562
563                         free(request);
564                 }
565
566                 if (response) {
567
568                         if (response->status_text != NULL) {
569                                 free(response->status_text);
570                                 response->status_text = NULL;
571                         }
572
573                         free(response);
574
575                 }
576
577                 if (header) {
578                         if (header->header_list != NULL) {
579                                 curl_slist_free_all(header->header_list);
580                                 header->header_list = NULL;
581                         }
582
583                         if (header->hash_table != NULL) {
584
585                                 g_hash_table_remove_all(header->hash_table);
586
587                                 g_hash_table_destroy(header->hash_table);
588                                 header->hash_table = NULL;
589                         }
590
591                         if (header->rsp_header != NULL) {
592                                 free(header->rsp_header);
593                                 header->rsp_header = NULL;
594                                 header->rsp_header_len = 0;
595                         }
596                         free(header);
597                 }
598
599                 _remove_transaction_from_list(transaction);
600
601                 if (transaction->thread_loop != NULL) {
602                         g_main_loop_quit((GMainLoop*)transaction->thread_loop);
603
604                         g_main_loop_unref(transaction->thread_loop);
605                         transaction->thread_loop = NULL;
606                 }
607
608                 if (transaction->thread != NULL) {
609                         g_thread_join(transaction->thread);
610                         transaction->thread = NULL;
611                 }
612
613                 free(transaction);
614                 transaction = NULL;
615         }
616
617         return HTTP_ERROR_NONE;
618 }
619
620 API int http_transaction_pause(http_transaction_h http_transaction, http_pause_type_e pause_type)
621 {
622         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
623                         "http isn't initialized");
624         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
625                         "parameter(http_transaction) is NULL\n");
626         _retvm_if(pause_type < HTTP_PAUSE_RECV || pause_type > HTTP_PAUSE_ALL, HTTP_ERROR_INVALID_PARAMETER,
627                         "Wrong pause state \n");
628
629         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
630         int ret = 0;
631
632         ret = curl_easy_pause(transaction->easy_handle, pause_type);
633         if (ret != 0) {
634                 ERR("Fail to pause!(%d)", ret);
635                 return HTTP_ERROR_OPERATION_FAILED;
636         }
637
638         return HTTP_ERROR_NONE;
639 }
640
641 API int http_transaction_resume(http_transaction_h http_transaction)
642 {
643         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
644                         "http isn't initialized");
645         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
646                         "parameter(http_transaction) is NULL\n");
647
648         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
649         int ret = 0;
650
651         ret = curl_easy_pause(transaction->easy_handle, CURLPAUSE_CONT);
652         if (ret != 0) {
653                 ERR("Fail to resume!(%d)", ret);
654                 return HTTP_ERROR_OPERATION_FAILED;
655         }
656
657         return HTTP_ERROR_NONE;
658 }
659
660
661 API int http_transaction_set_progress_cb(http_transaction_h http_transaction, http_transaction_progress_cb progress_cb, void* user_data)
662 {
663         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
664                         "http isn't initialized");
665         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
666                         "parameter(http_transaction) is NULL\n");
667         _retvm_if(progress_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
668                         "parameter(progress_cb) is NULL\n");
669
670         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
671
672         transaction->progress_cb = progress_cb;
673         transaction->progress_user_data = user_data;
674
675         return HTTP_ERROR_NONE;
676 }
677
678 API int http_transaction_set_received_header_cb(http_transaction_h http_transaction, http_transaction_header_cb header_cb, void* user_data)
679 {
680         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
681                         "http isn't initialized");
682         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
683                         "parameter(http_transaction) is NULL\n");
684         _retvm_if(header_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
685                         "parameter(header_cb) is NULL\n");
686
687         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
688
689         transaction->header_cb = header_cb;
690         transaction->header_user_data = user_data;
691
692         return HTTP_ERROR_NONE;
693 }
694
695 API int http_transaction_set_received_body_cb(http_transaction_h http_transaction, http_transaction_body_cb body_cb, void* user_data)
696 {
697         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
698                         "http isn't initialized");
699         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
700                         "parameter(http_transaction) is NULL\n");
701         _retvm_if(body_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
702                         "parameter(body_cb) is NULL\n");
703
704         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
705
706         transaction->body_cb = body_cb;
707         transaction->body_user_data = user_data;
708
709         return HTTP_ERROR_NONE;
710 }
711
712 API int http_transaction_set_uploaded_cb(http_transaction_h http_transaction, http_transaction_write_cb write_cb, void* user_data)
713 {
714         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
715                         "http isn't initialized");
716         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
717                         "parameter(http_transaction) is NULL\n");
718         _retvm_if(write_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
719                         "parameter(write_cb) is NULL\n");
720
721         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
722
723         transaction->write_cb = write_cb;
724         transaction->write_user_data = user_data;
725
726         return HTTP_ERROR_NONE;
727 }
728
729 API int http_transaction_set_completed_cb(http_transaction_h http_transaction, http_transaction_completed_cb completed_cb, void* user_data)
730 {
731         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
732                         "http isn't initialized");
733         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
734                         "parameter(http_transaction) is NULL\n");
735         _retvm_if(completed_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
736                         "parameter(completed_cb) is NULL\n");
737
738         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
739
740         transaction->completed_cb = completed_cb;
741         transaction->completed_user_data = user_data;
742
743         return HTTP_ERROR_NONE;
744 }
745
746 API int http_transaction_set_aborted_cb(http_transaction_h http_transaction, http_transaction_aborted_cb aborted_cb,  void* user_data)
747 {
748         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
749                         "http isn't initialized");
750         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
751                          "parameter(http_transaction) is NULL\n");
752         _retvm_if(aborted_cb == NULL, HTTP_ERROR_INVALID_PARAMETER,
753                         "parameter(aborted_cb) is NULL\n");
754
755         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
756
757         transaction->aborted_cb = aborted_cb;
758
759         return HTTP_ERROR_NONE;
760 }
761
762 API int http_transaction_unset_progress_cb(http_transaction_h http_transaction)
763 {
764         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
765                         "http isn't initialized");
766         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
767                         "parameter(http_transaction) is NULL\n");
768
769         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
770         transaction->progress_cb = NULL;
771
772         return HTTP_ERROR_NONE;
773 }
774
775 API int http_transaction_set_timeout(http_transaction_h http_transaction, int timeout)
776 {
777         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
778                         "http isn't initialized");
779         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
780                         "parameter(http_transaction) is NULL\n");
781
782         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
783
784         transaction->timeout = timeout;
785
786         return HTTP_ERROR_NONE;
787 }
788
789 API int http_transaction_get_timeout(http_transaction_h http_transaction, int *timeout)
790 {
791         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
792                         "http isn't initialized");
793         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
794                         "parameter(http_transaction) is NULL\n");
795         _retvm_if(timeout == NULL, HTTP_ERROR_INVALID_PARAMETER,
796                         "parameter(timeout) is NULL\n");
797
798         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
799
800         *timeout =  transaction->timeout;
801
802         return HTTP_ERROR_NONE;
803 }
804
805 API int http_transaction_set_interface_name(http_transaction_h http_transaction, const char *interface_name)
806 {
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");
811         _retvm_if(interface_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
812                         "parameter(interface_name) is NULL\n");
813
814         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
815
816         transaction->interface_name = g_strdup(interface_name);
817
818         return HTTP_ERROR_NONE;
819 }
820
821 API int http_transaction_get_interface_name(http_transaction_h http_transaction, char **interface_name)
822 {
823         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
824                         "http isn't initialized");
825         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
826                         "parameter(http_transaction) is NULL\n");
827         _retvm_if(interface_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
828                         "parameter(interface_name) is NULL\n");
829
830         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
831
832         *interface_name = g_strdup(transaction->interface_name);
833         if (*interface_name == NULL) {
834                 ERR("strdup is failed\n");
835                 return HTTP_ERROR_OUT_OF_MEMORY;
836         }
837
838         return HTTP_ERROR_NONE;
839 }
840
841 API int http_transaction_set_ready_to_write(http_transaction_h http_transaction, bool read_to_write)
842 {
843         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
844                         "http isn't initialized");
845         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
846                         "parameter(http_transaction) is NULL\n");
847
848         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
849
850         transaction->write_event = read_to_write;
851
852         return HTTP_ERROR_NONE;
853 }
854
855 API int http_transaction_get_server_certificate_verification(http_transaction_h http_transaction, bool* verify)
856 {
857         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
858                         "http isn't initialized");
859         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
860                         "parameter(http_transaction) is NULL\n");
861
862         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
863
864         *verify = transaction->verify_peer;
865
866         return HTTP_ERROR_NONE;
867 }
868
869 API int http_transaction_set_server_certificate_verification(http_transaction_h http_transaction, bool verify)
870 {
871         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
872                         "http isn't initialized");
873         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
874                         "parameter(http_transaction) is NULL\n");
875
876         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
877
878         transaction->verify_peer = verify;
879
880         return HTTP_ERROR_NONE;
881 }
882
883 API int http_session_destroy_all_transactions(http_session_h http_session)
884 {
885         _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
886                         "http isn't initialized");
887         _retvm_if(http_session == NULL, HTTP_ERROR_INVALID_PARAMETER,
888                         "parameter(http_session) is NULL\n");
889
890         int ret = 0;
891         GSList *list = NULL;
892         __http_session_h *session = (__http_session_h *)http_session;
893
894         for (list = transaction_list; list; list = list->next) {
895                 __http_transaction_h *transaction = (__http_transaction_h *)list->data;
896                 if (session->session_id == transaction->session_id) {
897                         _remove_transaction_from_list(list->data);
898                         ret = http_transaction_destroy((http_transaction_h) transaction);
899                         if (ret != HTTP_ERROR_NONE) {
900                                 ERR("Fail to destroy transaction!!");
901                                 return HTTP_ERROR_OPERATION_FAILED;
902                         }
903                 }
904         }
905
906         return HTTP_ERROR_NONE;
907 }
908
909 API int http_transaction_set_http_auth_scheme(http_transaction_h http_transaction, http_auth_scheme_e auth_scheme)
910 {
911         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
912                         "parameter(http_transaction) is NULL\n");
913
914         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
915
916         transaction->auth_scheme = auth_scheme;
917
918         return HTTP_ERROR_NONE;
919 }
920
921 API int http_transaction_get_http_auth_scheme(http_transaction_h http_transaction, http_auth_scheme_e *auth_scheme)
922 {
923         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
924                         "parameter(http_transaction) is NULL\n");
925         _retvm_if(auth_scheme == NULL, HTTP_ERROR_INVALID_PARAMETER,
926                         "parameter(auth_scheme) is NULL\n");
927
928         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
929
930         *auth_scheme =  transaction->auth_scheme;
931
932         return HTTP_ERROR_NONE;
933 }
934
935 API int http_transaction_get_realm(http_transaction_h http_transaction, char **realm)
936 {
937         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
938                         "parameter(http_transaction) is NULL\n");
939         _retvm_if(realm == NULL, HTTP_ERROR_INVALID_PARAMETER,
940                         "parameter(realm) is NULL\n");
941
942         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
943
944         if (transaction->realm == NULL)
945                 return HTTP_ERROR_INVALID_OPERATION;
946
947         *realm = g_strdup(transaction->realm);
948         if (*realm == NULL) {
949                 ERR("strdup is failed\n");
950                 return HTTP_ERROR_OUT_OF_MEMORY;
951         }
952
953         return HTTP_ERROR_NONE;
954 }
955
956 API int http_transaction_set_credentials(http_transaction_h http_transaction, const char *user_name, const char *password)
957 {
958         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
959                         "parameter(http_transaction) is NULL\n");
960         _retvm_if(user_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
961                         "parameter(user_name) is NULL\n");
962         _retvm_if(password == NULL, HTTP_ERROR_INVALID_PARAMETER,
963                         "parameter(password) is NULL\n");
964
965         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
966
967         transaction->user_name = g_strdup(user_name);
968         transaction->password = g_strdup(password);
969
970         return HTTP_ERROR_NONE;
971 }
972
973 API int http_transaction_get_credentials(http_transaction_h http_transaction, char **user_name, char **password)
974 {
975         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
976                         "parameter(http_transaction) is NULL\n");
977         _retvm_if(user_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
978                         "parameter(user_name) is NULL\n");
979         _retvm_if(password == NULL, HTTP_ERROR_INVALID_PARAMETER,
980                         "parameter(password) is NULL\n");
981
982         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
983
984         *user_name = g_strdup(transaction->user_name);
985         if (*user_name == NULL) {
986                 ERR("strdup is failed\n");
987                 return HTTP_ERROR_OUT_OF_MEMORY;
988         }
989
990         *password = g_strdup(transaction->password);
991         if (*password == NULL) {
992                 ERR("strdup is failed\n");
993                 return HTTP_ERROR_OUT_OF_MEMORY;
994         }
995         return HTTP_ERROR_NONE;
996 }
997
998 API int http_transaction_open_authentication(http_transaction_h http_transaction, http_transaction_h *http_auth_transaction)
999 {
1000         _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
1001                         "parameter(http_transaction) is NULL\n");
1002
1003         __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
1004         __http_transaction_h *auth_transaction = NULL;
1005
1006         auth_transaction = (__http_transaction_h *)malloc(sizeof(__http_transaction_h));
1007         if (auth_transaction == NULL) {
1008                 ERR("Fail to allocate transaction memory!!");
1009                 return HTTP_ERROR_OUT_OF_MEMORY;
1010         }
1011
1012         auth_transaction->easy_handle = NULL;
1013         auth_transaction->interface_name = NULL;
1014         auth_transaction->ca_path = NULL;
1015         auth_transaction->error[0] = '\0';
1016
1017         if (transaction->interface_name)
1018                 auth_transaction->interface_name = g_strdup(transaction->interface_name);
1019         auth_transaction->timeout = 0;
1020         auth_transaction->verify_peer = transaction->verify_peer;
1021         if (transaction->ca_path)
1022                 auth_transaction->ca_path = g_strdup(transaction->ca_path);
1023
1024         auth_transaction->auth_required = transaction->auth_required;
1025         auth_transaction->realm = NULL;
1026         auth_transaction->user_name = NULL;
1027         auth_transaction->password = NULL;
1028         auth_transaction->proxy_auth_type = FALSE;
1029         auth_transaction->auth_scheme = transaction->auth_scheme;
1030         auth_transaction->write_event = FALSE;
1031
1032         auth_transaction->header_cb = NULL;
1033         auth_transaction->header_user_data = NULL;
1034         auth_transaction->body_cb = NULL;
1035         auth_transaction->body_user_data = NULL;
1036         auth_transaction->write_cb = NULL;
1037         auth_transaction->write_user_data = NULL;
1038         auth_transaction->completed_cb = NULL;
1039         auth_transaction->completed_user_data = NULL;
1040         auth_transaction->aborted_cb = NULL;
1041         auth_transaction->progress_cb = NULL;
1042         auth_transaction->progress_user_data = NULL;
1043
1044         auth_transaction->session = transaction->session;
1045         auth_transaction->session->active_transaction_count = transaction->session->active_transaction_count;
1046         auth_transaction->session_id = transaction->session_id;
1047
1048         auth_transaction->request = (__http_request_h *)malloc(sizeof(__http_request_h));
1049         if (auth_transaction->request == NULL) {
1050                 free(auth_transaction->interface_name);
1051                 free(auth_transaction->ca_path);
1052                 free(auth_transaction);
1053                 ERR("Fail to allocate request memory!!");
1054                 return HTTP_ERROR_OUT_OF_MEMORY;
1055         }
1056
1057         auth_transaction->request->host_uri = NULL;
1058         auth_transaction->request->method = NULL;
1059
1060         auth_transaction->response = (__http_response_h *)malloc(sizeof(__http_response_h));
1061         if (auth_transaction->response == NULL) {
1062                 free(auth_transaction->interface_name);
1063                 free(auth_transaction->ca_path);
1064                 free(auth_transaction->request);
1065                 free(auth_transaction);
1066                 ERR("Fail to allocate response memory!!");
1067                 return HTTP_ERROR_OUT_OF_MEMORY;
1068         }
1069
1070         auth_transaction->header = (__http_header_h *)malloc(sizeof(__http_header_h));
1071         if (auth_transaction->header == NULL) {
1072                 free(auth_transaction->interface_name);
1073                 free(auth_transaction->ca_path);
1074                 free(auth_transaction->request);
1075                 free(auth_transaction->response);
1076                 free(auth_transaction);
1077                 ERR("Fail to allocate header memory!!");
1078                 return HTTP_ERROR_OUT_OF_MEMORY;
1079         }
1080
1081         auth_transaction->header->rsp_header_len = 0;
1082         auth_transaction->header->rsp_header = malloc(auth_transaction->header->rsp_header_len + 1);
1083         auth_transaction->header->rsp_header[0] = '\0';
1084         auth_transaction->header_event = FALSE;
1085
1086         if (transaction->request->host_uri)
1087                 auth_transaction->request->host_uri = g_strdup(transaction->request->host_uri);
1088         if (transaction->request->method)
1089                 auth_transaction->request->method = g_strdup(transaction->request->method);
1090         auth_transaction->request->encoding = NULL;
1091         auth_transaction->request->cookie = NULL;
1092         auth_transaction->request->http_version = HTTP_VERSION_1_1;
1093         auth_transaction->request->body_queue = g_queue_new();
1094         auth_transaction->request->tot_size = 0;
1095
1096         auth_transaction->header->header_list = NULL;
1097         auth_transaction->header->hash_table = NULL;
1098
1099         auth_transaction->thread = NULL;
1100
1101         *http_auth_transaction = (http_transaction_h)auth_transaction;
1102         _add_transaction_to_list(auth_transaction);
1103
1104         http_transaction_set_authentication_info((http_transaction_h)auth_transaction);
1105
1106         return HTTP_ERROR_NONE;
1107 }