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