4d76a2c760efb600d109c6210a3cf38b6a587cdb
[platform/framework/web/download-provider.git] / agent / download-agent-plugin-libcurl.c
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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 <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
20
21 #include "glib.h"
22
23 #include <tpkp_curl.h>
24
25 #include "download-agent-dl-info.h"
26 #include "download-agent-http-msg-handler.h"
27 #include "download-agent-plugin-libcurl.h"
28
29 da_bool_t using_content_sniffing = DA_FALSE;
30
31 int __translate_error_code(int curl_error)
32 {
33         switch (curl_error) {
34         case CURLE_OPERATION_TIMEDOUT:
35                 return DA_ERR_HTTP_TIMEOUT;
36         case CURLE_SSL_CONNECT_ERROR:
37         case CURLE_SSL_ENGINE_NOTFOUND:
38         case CURLE_SSL_ENGINE_SETFAILED:
39         case CURLE_SSL_CERTPROBLEM:
40         case CURLE_SSL_CIPHER:
41         case CURLE_SSL_CACERT:
42         case CURLE_SSL_ENGINE_INITFAILED:
43         case CURLE_SSL_CACERT_BADFILE:
44         case CURLE_SSH:
45         case CURLE_SSL_SHUTDOWN_FAILED:
46         case CURLE_SSL_CRL_BADFILE:
47         case CURLE_SSL_ISSUER_ERROR:
48                 return DA_ERR_SSL_FAIL;
49         case CURLE_TOO_MANY_REDIRECTS:
50                 return DA_ERR_TOO_MANY_REDIRECTS;
51         case CURLE_OUT_OF_MEMORY:
52                 return DA_ERR_FAIL_TO_MEMALLOC;
53         case CURLE_UNSUPPORTED_PROTOCOL:
54         case CURLE_URL_MALFORMAT:
55         case CURLE_COULDNT_RESOLVE_PROXY:
56         case CURLE_COULDNT_RESOLVE_HOST:
57         case CURLE_COULDNT_CONNECT:
58         case CURLE_REMOTE_ACCESS_DENIED:
59         case CURLE_HTTP_POST_ERROR:
60         case CURLE_BAD_DOWNLOAD_RESUME:
61                 return DA_ERR_CONNECTION_FAIL;
62         case CURLE_ABORTED_BY_CALLBACK:
63                 return DA_RESULT_USER_CANCELED;
64         default:
65                 return DA_ERR_NETWORK_FAIL;
66         }
67 }
68
69 int my_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *user)
70 {
71         switch(type) {
72         case CURLINFO_TEXT:
73                 if (data)
74                         DA_SECURE_LOGI("[curl] Info:%s", data);
75                 break;
76         case CURLINFO_HEADER_OUT:
77                 DA_LOGD("[curl] Send header");
78                 if (data)
79                         DA_SECURE_LOGI("[curl] %s", data);
80                 break;
81         case CURLINFO_DATA_OUT:
82                 DA_LOGD("[curl] Send data");
83                 if (data)
84                         DA_SECURE_LOGI("[curl] %s", data);
85                 break;
86         case CURLINFO_SSL_DATA_OUT:
87                 DA_LOGD("[curl] Send SSL data");
88                 break;
89         case CURLINFO_HEADER_IN:
90                 DA_LOGD("[curl] Recv header");
91                 if (data)
92                         DA_SECURE_LOGI("[curl] %s", data);
93                 break;
94 #if 0
95         case CURLINFO_DATA_IN:
96                 DA_LOGD("[curl] Recv data");
97                 if (data)
98                         DA_SECURE_LOGI("[curl] %d", strlen(data));
99                 break;
100 #endif
101         case CURLINFO_SSL_DATA_IN:
102                 DA_SECURE_LOGI("[curl] Recv SSL data");
103                 break;
104         default:
105                 return 0;
106         }
107         return 0;
108 }
109
110 void __parse_raw_header(const char *raw_data, http_info_t *http_info)
111 {
112         char *ptr = DA_NULL;
113         char *ptr2 = DA_NULL;
114         int len = 0;
115         char *field = DA_NULL;
116         char *value = DA_NULL;
117         http_msg_response_t *http_msg_response = NULL;
118
119         if (!raw_data || !http_info) {
120                 DA_LOGE("NULL Check!: raw_data or http_info");
121                 return;
122         }
123
124         if (!http_info->http_msg_response) {
125                 http_info->http_msg_response = (http_msg_response_t *)calloc(1,
126                                 sizeof(http_msg_response_t));
127                 if (!http_info->http_msg_response) {
128                         DA_LOGE("Fail to calloc");
129                         return;
130                 }
131                 http_info->http_msg_response->head = DA_NULL;
132         }
133         http_msg_response = http_info->http_msg_response;
134
135         ptr = strchr(raw_data, ':');
136         if (!ptr)
137                 return;
138         len = ptr - (char *)raw_data;
139         field = (char *)calloc(len + 1, sizeof(char));
140         if (!field) {
141                 DA_LOGE("Fail to calloc");
142                 return;
143         }
144         memcpy(field, raw_data, len);
145         field[len] = '\0';
146                 ptr++;
147         while(ptr) {
148                 if (*ptr == ' ')
149                         ptr++;
150                 else
151                         break;
152         }
153         ptr2 = strchr(raw_data, '\n');
154         if (ptr2) {
155                 len = ptr2 - ptr -1;
156         } else {
157                 len = strlen(ptr);
158         }
159         value = (char *)calloc(len + 1, sizeof(char));
160         if (!value) {
161                 DA_LOGE("Fail to calloc");
162                 free(field);
163                 return;
164         }
165         memcpy(value, ptr, len);
166         value[len] = '\0';
167         http_msg_response_add_field(http_msg_response, field, value);
168         free(field);
169         free(value);
170 }
171
172 void __store_header(void *msg, da_info_t *da_info, size_t header_size,
173                 const char *sniffed_type)
174 {
175         http_info_t *http_info = DA_NULL;
176
177         if (!da_info || !msg) {
178                 DA_LOGE("NULL Check!: da_info or msg");
179                 return;
180         }
181         http_info = da_info->http_info;
182         if (!http_info) {
183                 DA_LOGE("NULL Check!: http_info");
184                 return;
185         }
186
187         // FIXME later : check status code and redirection case check.
188
189         if (strncmp(msg, HTTP_FIELD_END_OF_FIELD,
190                         strlen(HTTP_FIELD_END_OF_FIELD)) == 0) {
191                 long status = 0;
192                 CURLcode res;
193                 CURL *curl;
194                 http_raw_data_t *raw_data = DA_NULL;
195                 curl = http_info->http_msg->curl;
196                 res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
197                 if (res != CURLE_OK) {
198                         DA_LOGE("Fail to get response status code");
199                         return;
200                 }
201                 DA_LOGV("status code[%d]", (int)status);
202                 if (http_info->http_msg_response) {
203                         http_info->http_msg_response->status_code = (int)status;
204                 }
205                 raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t));
206                 if (!raw_data) {
207                         DA_LOGE("Fail to calloc");
208                         return;
209                 }
210
211                 raw_data->status_code = (int)status;
212                 raw_data->type = HTTP_EVENT_GOT_HEADER;
213
214                 if (http_info->update_cb) {
215                         http_info->update_cb(raw_data, da_info);
216                 } else {
217                         free(raw_data);
218                 }
219                 return;
220         }
221         DA_LOGI("%s",(char *)msg);
222         __parse_raw_header((const char *)msg, http_info);
223 }
224
225 size_t __http_gotheaders_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
226 {
227         da_info_t *da_info = DA_NULL;
228         if (!ptr || !userdata) {
229                 DA_LOGE("Check NULL!: ptr, userdata");
230                 return 0;
231         }
232         da_info = (da_info_t *)userdata;
233         if (da_info->http_info && da_info->http_info->http_msg
234                         && da_info->http_info->http_msg->is_cancel_reqeusted) {
235                 DA_LOGI("Cancel requested");
236                 return -1;
237         }
238         if (!using_content_sniffing)
239                 __store_header(ptr, da_info, (size * nmemb), DA_NULL);
240         else
241                 DA_LOGV("ignore because content sniffing is turned on");
242 /*
243 #ifdef _RAF_SUPPORT
244         DA_LOGI("[RAF] __http_gotheaders_cb done");
245 #endif
246 */
247         return (size * nmemb);
248 }
249
250 #ifdef _RAF_SUPPORT
251 da_ret_t PI_http_set_file_name_to_curl(http_msg_t *http_msg, char *file_path)
252 {
253         NULL_CHECK_RET(http_msg);
254         NULL_CHECK_RET(file_path);
255         DA_LOGI("[RAF]set file_path[%s]", file_path);
256         curl_easy_setopt(http_msg->curl, CURLOPT_BOOSTER_RAF_FILE, file_path);
257         return DA_RESULT_OK;
258 }
259 #endif
260
261 size_t __http_gotchunk_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
262 {
263         http_info_t *http_info = DA_NULL;
264         da_info_t *da_info = DA_NULL;
265         http_raw_data_t *raw_data = DA_NULL;
266         if (!ptr || !userdata) {
267                 DA_LOGE("Check NULL!: ptr, stream");
268                 return 0;
269         }
270         da_info = (da_info_t *)userdata;
271         NULL_CHECK_RET_OPT(da_info, 0);
272         http_info = da_info->http_info;
273         NULL_CHECK_RET_OPT(http_info, 0);
274         NULL_CHECK_RET_OPT(http_info->http_msg, 0);
275         if (da_info->http_info->http_msg->is_cancel_reqeusted) {
276                 DA_LOGI("Cancel requested");
277                 return -1;
278         }
279         //DA_LOGV("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr));
280 #ifdef _RAF_SUPPORT
281         //DA_LOGI("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr));
282         if (http_info->is_raf_mode_confirmed) {
283                 DA_LOGI("[RAF] return chunked callback");
284                 return (size * nmemb);
285         }
286 #endif
287
288         if (ptr && size * nmemb > 0) {
289                 if (http_info->update_cb) {
290                         raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t));
291                         if (!raw_data) {
292                                 DA_LOGE("Fail to calloc");
293                                 return 0;
294                         }
295                         raw_data->body = (char *)calloc(size, nmemb);
296                         if (!(raw_data->body)) {
297                                 DA_LOGE("Fail to calloc");
298                                 free(raw_data);
299                                 return 0;
300                         }
301                         memcpy(raw_data->body, ptr, size * nmemb);
302                         raw_data->body_len = size*nmemb;
303                         raw_data->type = HTTP_EVENT_GOT_PACKET;
304                         http_info->update_cb(raw_data, da_info);
305                 }
306         }
307         return (size * nmemb);
308 }
309
310 long __http_finished_cb(void *ptr)
311 {
312         if (!ptr) {
313                 DA_LOGE("Check NULL!: ptr");
314                 return CURL_CHUNK_END_FUNC_FAIL;
315         }
316         DA_LOGI("");
317         return CURL_CHUNK_END_FUNC_OK;
318 }
319
320
321 da_ret_t __set_proxy_on_soup_session(char *proxy_addr, CURL *curl)
322 {
323         da_ret_t ret = DA_RESULT_OK;
324
325         if (proxy_addr && strlen(proxy_addr) > 0) {
326                 DA_SECURE_LOGI("received proxy[%s]", proxy_addr);
327                 if (!strstr(proxy_addr, "0.0.0.0")) {
328                         if (strstr((const char *)proxy_addr, "http") == DA_NULL) {
329                                 char *tmp_str = DA_NULL;
330                                 int needed_len = 0;
331
332                                 needed_len = strlen(proxy_addr) + strlen(
333                                                 SCHEME_HTTP) + 1;
334                                 tmp_str = (char *) calloc(1, needed_len);
335                                 if (!tmp_str) {
336                                         DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
337                                         ret = DA_ERR_FAIL_TO_MEMALLOC;
338                                         goto ERR;
339                                 }
340                                 snprintf(tmp_str, needed_len, "%s%s",
341                                                 SCHEME_HTTP, proxy_addr);
342
343                                 curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr);
344
345                                 free(tmp_str);
346                         } else {
347                                 DA_LOGV("There is \"http\" on uri, so, push this address to soup directly.");
348                                 curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr);
349                         }
350                 }
351         }
352 ERR:
353         return ret;
354 }
355
356 struct curl_slist *__fill_soup_msg_header(CURL *curl, http_info_t *info)
357 {
358         http_msg_request_t *input_http_msg_request;
359         struct curl_slist *headers = DA_NULL;
360
361         if (!curl) {
362                 DA_LOGE("NULL Check!: curl");
363                 return DA_NULL;
364         }
365         input_http_msg_request = info->http_msg_request;
366
367         if (input_http_msg_request) {
368                 char *field = DA_NULL;
369                 char *value = DA_NULL;
370                 char *buff = DA_NULL;
371                 int len = 0;
372                 http_header_t *cur = DA_NULL;
373                 cur = input_http_msg_request->head;
374                 while (cur) {
375                         field = cur->field;
376                         value = cur->value;
377                         if (field && value) {
378                                 len = strlen(field) + strlen(value) + 1;
379                                 buff = (char *)calloc(len + 1, sizeof(char));
380                                 if (!buff) {
381                                         DA_LOGE("Fail to memalloc");
382                                         break;
383                                 }
384 //                              DA_SECURE_LOGI("[%s] %s", field, value);
385                                 snprintf(buff, len + 1, "%s:%s", field, value);
386                                 headers = curl_slist_append(headers, (const char *)buff);
387                                 free(buff);
388                                 buff = DA_NULL;
389                         }
390                         cur = cur->next;
391                 }
392         } else {
393                 DA_LOGE("NULL Check!: input_http_msg_request");
394                 return DA_NULL;
395         }
396         if (input_http_msg_request->http_body) {
397                 char buff[256] = {0,};
398                 int body_len = strlen(input_http_msg_request->http_body);
399                 snprintf(buff, sizeof(buff), "%s:%d", HTTP_FIELD_CONTENT_LENGTH,
400                                 body_len);
401                 headers = curl_slist_append(headers, buff);
402                 memset(buff, 0x00, 256);
403                 snprintf(buff, sizeof(buff), "%s:text/plain", HTTP_FIELD_CONTENT_TYPE);
404                 headers = curl_slist_append(headers, buff);
405                 headers = curl_slist_append(headers, input_http_msg_request->http_body);
406         }
407         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
408         return headers;
409 }
410
411 #ifdef _RAF_SUPPORT
412 int __http_progress_cb(void *clientp, double dltotal, double dlnow,
413                 double ultotal, double ulnow)
414 {
415         da_info_t *da_info = DA_NULL;
416         http_info_t *http_info = DA_NULL;
417         http_raw_data_t *raw_data = DA_NULL;
418 /*
419         if (dlnow > 0 || ulnow > 0)
420                 DA_LOGI("[RAF]dlnow/ulnow[%llu/%llu][%llu,%llu]", (da_size_t)dlnow, (da_size_t)ulnow, (da_size_t)dltotal, (da_size_t)ultotal);
421 */
422
423 /*
424         if (dlnow == 0) {
425                 DA_LOGI("[RAF]dlnow is zero. Why is this callback called although there is zero size?");
426         }
427 */
428         NULL_CHECK_RET_OPT(clientp, -1);
429         da_info = (da_info_t *)clientp;
430         http_info = da_info->http_info;
431         NULL_CHECK_RET_OPT(http_info, -1);
432         NULL_CHECK_RET_OPT(http_info->http_msg, -1);
433
434         if (http_info->http_msg->is_cancel_reqeusted) {
435                 DA_LOGI("Cancel requested");
436                 return -1;
437         }
438
439         if (dlnow > 0) {
440                 if (http_info->update_cb) {
441                         raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t));
442                         if (!raw_data) {
443                                 DA_LOGE("Fail to calloc");
444                                 return 0;
445                         }
446                         raw_data->received_len = (da_size_t)dlnow;
447                         raw_data->type = HTTP_EVENT_GOT_PACKET;
448                         http_info->update_cb(raw_data, da_info);
449                 }
450         }
451         return CURLE_OK;
452 }
453 #endif
454
455 da_ret_t PI_http_start(da_info_t *da_info)
456 {
457         da_ret_t ret = DA_RESULT_OK;
458         http_method_t http_method;
459         CURL *curl = DA_NULL;
460         CURLcode res;
461         http_msg_t *http_msg = DA_NULL;
462         char *url = DA_NULL;
463         http_info_t *http_info = DA_NULL;
464         long http_status = 0;
465         struct curl_httppost* post = NULL;
466         struct curl_slist *headers = DA_NULL;
467         char err_buffer[CURL_ERROR_SIZE] = {0,};
468
469         DA_LOGV("");
470 #ifdef _RAF_SUPPORT
471         // test code
472         get_smart_bonding_vconf();
473 #endif
474         NULL_CHECK_GOTO(da_info);
475         NULL_CHECK_GOTO(da_info->req_info);
476         url = da_info->req_info->url;
477         NULL_CHECK_GOTO(url);
478         http_info = da_info->http_info;
479         NULL_CHECK_GOTO(http_info);
480
481         http_method = http_info->http_method;
482         ret = init_http_msg_t(&http_msg);
483         if (ret != DA_RESULT_OK)
484                 goto ERR;
485         http_info->http_msg = http_msg;
486
487         curl_global_init(CURL_GLOBAL_ALL);
488         curl = curl_easy_init();
489
490         if (!curl) {
491                 DA_LOGE("Fail to create curl");
492                 return DA_ERR_FAIL_TO_MEMALLOC;
493         }
494         DA_LOGI("curl[%p]", curl);
495
496         curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, MAX_SESSION_COUNT);
497         curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, MAX_TIMEOUT);
498
499         __set_proxy_on_soup_session(http_info->proxy_addr, curl);
500
501         curl_easy_setopt(curl, CURLOPT_URL, url);
502         switch (http_method) {
503         case HTTP_METHOD_GET:
504                 curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
505                 break;
506         case HTTP_METHOD_POST:
507                 // FIXME later : If the post method is supprot, the post data should be set with curl_fromadd
508                 curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
509                 DA_LOGI("Need more information for post filed");
510                 break;
511         case HTTP_METHOD_HEAD:
512                 DA_LOGI("Donnot implement yet");
513                 break;
514         default:
515                 DA_LOGE("Cannot enter here");
516                 break;
517         }
518
519         if (using_content_sniffing) {
520                 /* FIXME later*/
521         } else {
522                 /* FIXME later*/
523         }
524         headers = __fill_soup_msg_header(curl, http_info);
525
526         curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, __http_gotheaders_cb); // can replace to started_cb
527         curl_easy_setopt(curl, CURLOPT_HEADERDATA, da_info); // param .. same with CURLOPT_WRITEHEADER
528         curl_easy_setopt(curl, CURLOPT_HEADER, 0L); // does not include header to body
529         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, __http_gotchunk_cb); // can replace to progress_
530         curl_easy_setopt(curl, CURLOPT_WRITEDATA, da_info); // param .. same with CURLOPT_WRITEHEADERcb
531         curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, __http_finished_cb);
532         curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, da_info);
533 #if _ENABLE_LIBCURL_LOG_VERBOSE
534         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
535 #else
536         curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
537 #endif
538 //      curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
539         curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, err_buffer);
540         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
541         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
542 #ifdef _RAF_SUPPORT
543         curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, __http_progress_cb);
544         curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, da_info);
545         curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
546 #endif
547
548         if (da_info->req_info->network_bonding) {
549 #ifdef _DOWNLOAD_BOOSTER_SUPPORT
550                 DA_LOGI("network bonding enable");
551                 curl_easy_setopt(curl, CURLOPT_MULTIRAT_NEEDED, 1L);
552 #endif
553 #ifdef _RAF_SUPPORT
554                 curl_easy_setopt(curl, CURLOPT_BOOSTER_RAF_MODE, 1L);
555 #endif
556         }
557         http_msg->curl = curl;
558         curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, tpkp_curl_ssl_ctx_callback);
559         res = curl_easy_perform(curl);
560         DA_LOGD("perform done! res[%d]",res);
561         if (res != CURLE_OK) {
562                 //DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res));
563                 DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res));
564                 if (strlen(err_buffer) > 1)
565                         DA_LOGE("Fail to error buffer[%s]", err_buffer);
566         } else {
567                 res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
568                 if (res != CURLE_OK) {
569                         //DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res));
570                         DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res));
571                         ret = DA_ERR_FAIL_TO_MEMALLOC;;
572                         goto ERR;
573                 } else {
574                         DA_LOGD("Response Http Status code[%d]", (int)http_status);
575                 }
576         }
577         if (http_info->update_cb) {
578                 http_raw_data_t *raw_data = DA_NULL;
579                 raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t));
580                 if (!raw_data) {
581                         DA_LOGE("Fail to calloc");
582                         ret = DA_ERR_FAIL_TO_MEMALLOC;
583                         goto ERR;
584                 }
585                 if (http_msg->is_cancel_reqeusted ||
586                                 res == CURLE_ABORTED_BY_CALLBACK) {
587                         DA_LOGI("canceled exit. Err[%d]", http_info->error_code);
588                         if (http_info->error_code < 0)
589                                 ret = http_info->error_code;
590                         else
591                                 ret = DA_RESULT_USER_CANCELED;
592                 } else  if ((http_status > 0 && http_status < 100)) {
593                         raw_data->error = __translate_error_code(res);
594                         ret = DA_ERR_NETWORK_FAIL;
595                 } else if (res != CURLE_OK) {
596                         raw_data->error = __translate_error_code(res);
597                         ret = DA_ERR_NETWORK_FAIL;
598                 } else {
599                         raw_data->status_code = (int)http_status;
600                 }
601                 raw_data->type = HTTP_EVENT_FINAL;
602                 http_info->update_cb(raw_data, da_info);
603         }
604         if (DA_NULL != headers)
605                 curl_slist_free_all(headers);
606         curl_easy_cleanup(curl);
607         tpkp_curl_cleanup();
608         http_msg->curl = DA_NULL;
609         DA_MUTEX_INIT(&(http_msg->mutex), DA_NULL);
610 ERR:
611         DA_LOGD("Done");
612         return ret;
613
614 }
615
616 da_ret_t PI_http_disconnect(http_info_t *info)
617 {
618         da_ret_t ret = DA_RESULT_OK;
619         http_msg_t *http_msg = DA_NULL;
620
621         DA_LOGD("");
622         NULL_CHECK_RET(info);
623         http_msg = info->http_msg;
624         NULL_CHECK_RET(http_msg);
625         DA_LOGV("session [%p]", http_msg->curl);
626         DA_MUTEX_LOCK(&(http_msg->mutex));
627         if (http_msg->is_paused)
628                 PI_http_unpause(info);
629          if (http_msg->curl)
630                  curl_easy_cleanup(http_msg->curl);
631
632         http_msg->curl = DA_NULL;
633         http_msg->is_paused = DA_FALSE;
634         http_msg->is_cancel_reqeusted = DA_FALSE;
635         DA_MUTEX_UNLOCK(&(http_msg->mutex));
636         DA_MUTEX_DESTROY(&(http_msg->mutex));
637         destroy_http_msg_t(http_msg);
638         info->http_msg = DA_NULL;
639         return ret;
640 }
641
642 da_ret_t PI_http_cancel(http_info_t *info)
643 {
644         da_ret_t ret = DA_RESULT_OK;
645         http_msg_t *http_msg = DA_NULL;
646
647         DA_LOGV("");
648
649         NULL_CHECK_RET(info);
650         http_msg = info->http_msg;
651         NULL_CHECK_RET(http_msg);
652         NULL_CHECK_RET(http_msg->curl);
653         DA_MUTEX_LOCK(&(http_msg->mutex));
654         DA_LOGI("curl[%p]", http_msg->curl);
655         http_msg->is_cancel_reqeusted = DA_TRUE;
656         DA_MUTEX_UNLOCK(&(http_msg->mutex));
657         DA_LOGD("Done - soup cancel");
658         return ret;
659 }
660
661 da_ret_t PI_http_pause(http_info_t *info)
662 {
663         da_ret_t ret = DA_RESULT_OK;
664         http_msg_t *http_msg = DA_NULL;
665         CURLcode res = CURLE_OK;
666         DA_LOGV("");
667
668         NULL_CHECK_RET(info);
669         http_msg = info->http_msg;
670         NULL_CHECK_RET(http_msg);
671         DA_LOGD("curl [%p]", http_msg->curl);
672         NULL_CHECK_RET(http_msg->curl);
673         DA_MUTEX_LOCK(&(http_msg->mutex));
674         DA_LOGE("curl_easy_pause call");
675         res = curl_easy_pause(http_msg->curl, CURLPAUSE_ALL);
676         DA_LOGE("curl_easy_pause:%d", res);
677         if (res == CURLE_OK) {
678                 http_msg->is_paused = DA_TRUE;
679         } else {
680                 ret = DA_ERR_CANNOT_SUSPEND;
681         }
682         DA_MUTEX_UNLOCK(&(http_msg->mutex));
683         return ret;
684 }
685
686 da_ret_t PI_http_unpause(http_info_t *info)
687 {
688         da_ret_t ret = DA_RESULT_OK;
689         http_msg_t *http_msg = DA_NULL;
690         CURLcode res = CURLE_OK;
691         DA_LOGV("");
692
693         NULL_CHECK_RET(info);
694         http_msg = info->http_msg;
695         DA_LOGV("curl [%p]", http_msg->curl);
696         NULL_CHECK_RET(http_msg->curl);
697         DA_MUTEX_LOCK(&(http_msg->mutex));
698         res = curl_easy_pause(http_msg->curl, CURLPAUSE_CONT);
699         if (res == CURLE_OK)
700                 http_msg->is_paused = DA_FALSE;
701         else
702                 ret = DA_ERR_CANNOT_RESUME;
703         DA_MUTEX_UNLOCK(&(http_msg->mutex));
704         return ret;
705 }