0fdd56510dafd6348880102d35f1fb50fd8ba05c
[platform/framework/web/download-provider.git] / agent / download-agent-http-mgr.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 #define _GNU_SOURCE
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <time.h>
22 #include <vconf.h>
23
24 #include "download-agent-dl-info.h"
25 #include "download-agent-file.h"
26 #include "download-agent-mime-util.h"
27 #include "download-agent-client-mgr.h"
28 #include "download-agent-http-msg-handler.h"
29 #include "download-agent-plugin-conf.h"
30 #include "download-agent-plugin-drm.h"
31 #include "download-agent-plugin-libcurl.h"
32 #include "download-provider-client-manager.h"
33
34 void __http_update_cb(http_raw_data_t *data, void *user_param);
35 static proxy_info_t *__get_proxy_info();
36
37 #define CONVERT_STR(NAME) (#NAME)
38
39 #define VCONF_KEY_PROXY_EXCEPTION_LIST "db/menu/network/server_network_settings/proxy_exceptional_address"
40 #define PROXY_EXCEPTION_LIST_DELIMITER ";"
41 #define HTTP_PREFIX "http://"
42 #define HTTPS_PREFIX "https://"
43
44 static const char *__get_state_str(http_state_t state)
45 {
46         char *str = NULL;
47         switch (state) {
48         case HTTP_STATE_READY_TO_DOWNLOAD:
49                 str = CONVERT_STR(HTTP_STATE_READY_TO_DOWNLOAD);
50                 break;
51         case HTTP_STATE_REDIRECTED:
52                 str = CONVERT_STR(HTTP_STATE_REDIRECTED);
53                 break;
54         case HTTP_STATE_DOWNLOAD_REQUESTED:
55                 str = CONVERT_STR(HTTP_STATE_DOWNLOAD_REQUESTED);
56                 break;
57         case HTTP_STATE_DOWNLOAD_STARTED:
58                 str = CONVERT_STR(HTTP_STATE_DOWNLOAD_STARTED);
59                 break;
60         case HTTP_STATE_DOWNLOADING:
61                 str = CONVERT_STR(HTTP_STATE_DOWNLOADING);
62                 break;
63         case HTTP_STATE_DOWNLOAD_FINISH:
64                 str = CONVERT_STR(HTTP_STATE_DOWNLOAD_FINISH);
65                 break;
66         case HTTP_STATE_REQUEST_CANCEL:
67                 str = CONVERT_STR(HTTP_STATE_REQUEST_CANCEL);
68                 break;
69         case HTTP_STATE_REQUEST_PAUSE:
70                 str = CONVERT_STR(HTTP_STATE_REQUEST_PAUSE);
71                 break;
72         case HTTP_STATE_REQUEST_RESUME:
73                 str = CONVERT_STR(HTTP_STATE_REQUEST_RESUME);
74                 break;
75         case HTTP_STATE_CANCELED:
76                 str = CONVERT_STR(HTTP_STATE_CANCELED);
77                 break;
78         case HTTP_STATE_FAILED:
79                 str = CONVERT_STR(HTTP_STATE_FAILED);
80                 break;
81         case HTTP_STATE_PAUSED:
82                 str = CONVERT_STR(HTTP_STATE_PAUSED);
83                 break;
84         case HTTP_STATE_RESUMED:
85                 str = CONVERT_STR(HTTP_STATE_RESUMED);
86                 break;
87         case HTTP_STATE_ABORTED:
88                 str = CONVERT_STR(HTTP_STATE_ABORTED);
89                 break;
90         case HTTP_STATE_WAIT_FOR_NET_ERR:
91                 str = CONVERT_STR(HTTP_STATE_WAIT_FOR_NET_ERR);
92                 break;
93         default:
94                 str = "Unknown State";
95                 break;
96         }
97         return str;
98 }
99
100 // 0: not required, 1: required
101 static int __is_proxy_required(char *url)
102 {
103         char *parsed_url = NULL;
104         char *exception_list = vconf_get_str(VCONF_KEY_PROXY_EXCEPTION_LIST);
105         char *ptr = NULL;
106         char *next_ptr = NULL;
107         char *next_ptr2 = NULL;
108
109         if (!exception_list)
110                 return 1;
111
112         DA_LOGI("proxy exception list[%s]", exception_list);
113
114         if (url && strstr(url, HTTP_PREFIX))
115                 parsed_url = url + strlen(HTTP_PREFIX);
116         else if (url && strstr(url, HTTPS_PREFIX))
117                 parsed_url = url + strlen(HTTPS_PREFIX);
118         else
119                 parsed_url = url;
120
121         DA_LOGI("compared url[%s] parsed url[%s]", url, parsed_url);
122
123         ptr = strtok_r(exception_list, PROXY_EXCEPTION_LIST_DELIMITER, &next_ptr);
124         while (ptr) {
125                 // Ignore protocol prefix
126                 if (strstr(ptr, HTTP_PREFIX))
127                         ptr = ptr + strlen(HTTP_PREFIX);
128                 else if (strstr(ptr, HTTPS_PREFIX))
129                         ptr = ptr + strlen(HTTPS_PREFIX);
130
131                 // Remove file path
132                 if (ptr && strstr(ptr, "/"))
133                         ptr = strtok_r(ptr, "/", &next_ptr2);
134
135                 if (ptr && parsed_url && strncmp(parsed_url, ptr, strlen(ptr)) == 0) {
136                         DA_LOGI("[%s/%s] is exist in exception list.", url, ptr);
137                         free(exception_list);
138                         return 0;
139                 }
140
141                 ptr = strtok_r(NULL, PROXY_EXCEPTION_LIST_DELIMITER, &next_ptr);
142         }
143
144         free(exception_list);
145
146         DA_LOGI("There is no matched address in exception list");
147
148         return 1;
149 }
150
151 void __init_http_info(http_info_t *http_info)
152 {
153         DA_LOGV("");
154
155         http_info->update_cb = __http_update_cb;
156         DA_MUTEX_INIT(&(http_info->mutex_state), DA_NULL);
157         DA_MUTEX_INIT(&(http_info->mutex_http), DA_NULL);
158         DA_COND_INIT(&(http_info->cond_http), DA_NULL);
159
160         DA_MUTEX_LOCK(&(http_info->mutex_state));
161         http_info->state = HTTP_STATE_READY_TO_DOWNLOAD;
162         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
163 }
164
165 void __parsing_user_request_header(char *user_request_header,
166                 char **out_field, char **out_value)
167 {
168         int len = 0;
169         char *pos = NULL;
170         char *temp_pos = NULL;
171         char *field = NULL;
172         char *value = NULL;
173
174         DA_LOGV("");
175
176         if (!user_request_header) {
177                 DA_LOGE("NULL CHECK!: user_request_header");
178                 goto ERR;
179         }
180
181         pos = strchr(user_request_header, ':');
182         if (!pos) {
183                 DA_LOGE("Fail to parse");
184                 goto ERR;
185         }
186         temp_pos = (char *)user_request_header;
187         while (*temp_pos) {
188                 if (temp_pos == pos || *temp_pos == ' ') {
189                         len =  temp_pos - user_request_header;
190                         break;
191                 }
192                 temp_pos++;
193         }
194         if (len < 1) {
195                 DA_LOGE("Wrong field name");
196                 goto ERR;
197         }
198         field = (char *)calloc(1, len + 1);
199         if (!field) {
200                 DA_LOGE("Fail to calloc");
201                 goto ERR;
202         }
203         strncpy(field, user_request_header, len);
204         pos++;
205         while (*pos) {
206                 if (*pos != ' ')
207                         break;
208                 pos++;
209         }
210         value = strdup(pos);
211         if (value == NULL) {
212                 DA_LOGE("Fail to copy pos");
213                 goto ERR;
214         }
215         *out_field = field;
216         *out_value = value;
217         DA_SECURE_LOGD("field[%s], value[%s]", field, value);
218
219         return;
220 ERR:
221         if (field) {
222                 free(field);
223                 field = NULL;
224         }
225         return;
226 }
227
228
229 da_ret_t __set_http_request_hdr(req_info_t *req_info, http_info_t *http_info, file_info_t *file_info)
230 {
231         da_ret_t ret = DA_RESULT_OK;
232         http_msg_request_t *http_msg_request = NULL;
233         char *user_agent = NULL;
234         int count = 0;
235
236         DA_LOGV("");
237
238         NULL_CHECK_RET(req_info);
239         NULL_CHECK_RET(http_info);
240         NULL_CHECK_RET(file_info);
241         NULL_CHECK_RET_OPT(req_info->url, DA_ERR_INVALID_URL);
242         count = req_info->req_header_count;
243
244         ret = http_msg_request_create(&http_msg_request);
245         if (ret != DA_RESULT_OK)
246                 goto ERR;
247
248         ret = http_msg_request_set_url(http_msg_request, req_info->url);
249         if (ret != DA_RESULT_OK)
250                 goto ERR;
251
252         ret = get_user_agent_string(&user_agent);
253         if (user_agent && ret == DA_RESULT_OK)
254                 http_msg_request_add_field(http_msg_request,
255                                 HTTP_FIELD_UAGENT, user_agent);
256
257
258         http_msg_request_add_field(http_msg_request,
259                         HTTP_FIELD_ACCEPT_LANGUAGE, "en");
260         http_msg_request_add_field(http_msg_request,
261                         HTTP_FIELD_ACCEPT_CHARSET, "utf-8");
262
263         if (req_info->req_header && count > 0) {
264                 int i = 0;
265                 for (i = 0; i < count; i++) {
266                         char *field = NULL;
267                         char *value = NULL;
268                         __parsing_user_request_header(req_info->req_header[i],
269                                         &field, &value);
270                         if (field && value) {
271                                 http_msg_request_add_field(http_msg_request, field, value);
272                                 if (field) {
273                                         free(field);
274                                         field = NULL;
275                                 }
276                                 if (value) {
277                                         free(value);
278                                         value = NULL;
279                                 }
280                         } else {
281                                 if (field) {
282                                         free(field);
283                                         field = NULL;
284                                 }
285                                 if (value) {
286                                         free(value);
287                                         value = NULL;
288                                 }
289                                 DA_LOGE("Fail to parse user request header");
290                         }
291                 }
292         }
293         if (req_info->etag) {
294                 char buff[64] = {0,};
295                 da_size_t size = 0;
296                 http_msg_request_add_field(http_msg_request,
297                                 HTTP_FIELD_IF_RANGE, req_info->etag);
298                 get_file_size(req_info->temp_file_path, &size);
299 #ifdef _RAF_SUPPORT
300                 file_info->file_size_of_temp_file = size;
301 #endif
302                 snprintf(buff, sizeof(buff)-1, "bytes=%llu-", size);
303                 http_msg_request_add_field(http_msg_request,
304                                 HTTP_FIELD_RANGE, buff);
305         }
306
307         http_info->http_msg_request = http_msg_request;
308         free(user_agent);
309         return ret;
310 ERR:
311         if (http_msg_request)
312                 http_msg_request_destroy(&http_msg_request);
313
314         return ret;
315
316 }
317
318 da_ret_t __create_http_resume_hdr(req_info_t *req_info, http_info_t *http_info,
319                 file_info_t *file_info)
320 {
321         da_ret_t ret = DA_RESULT_OK;
322         da_bool_t b_ret = DA_FALSE;
323         char *value = NULL;
324         char temp_size_str[32] = { 0, };
325         char *etag_from_response = NULL;
326         char *date_from_response = NULL;
327         http_msg_response_t *first_response = NULL;
328         http_msg_request_t *resume_request = NULL;
329         http_msg_request_t *old_request = NULL;
330
331         DA_LOGV("");
332
333         first_response = http_info->http_msg_response;
334         if (first_response) {
335                 b_ret = http_msg_response_get_ETag(first_response, &value);
336                 if (b_ret) {
337                         etag_from_response = value;
338                         value = NULL;
339                         DA_SECURE_LOGD("[ETag][%s]", etag_from_response);
340                 }
341                 b_ret = http_msg_response_get_date(first_response, &value);
342                 if (b_ret) {
343                         date_from_response = value;
344                         value = NULL;
345                         DA_LOGV("[Date][%s]", date_from_response);
346                 }
347                 DA_SECURE_LOGD("downloaded_size[%llu]", file_info->bytes_written_to_file);
348                 snprintf(temp_size_str, sizeof(temp_size_str), "bytes=%llu-",
349                                 file_info->bytes_written_to_file);
350                 DA_SECURE_LOGD("size str[%s]", temp_size_str);
351                 free(first_response);
352                 http_info->http_msg_response = DA_NULL;
353         }
354         old_request = http_info->http_msg_request;
355         free(old_request);
356         http_info->http_msg_request = DA_NULL;
357
358         ret = __set_http_request_hdr(req_info, http_info, file_info);
359         if (ret != DA_RESULT_OK)
360                 goto ERR;
361
362         resume_request = http_info->http_msg_request;
363         if (etag_from_response) {
364                 http_msg_request_add_field(resume_request, HTTP_FIELD_IF_RANGE,
365                                 etag_from_response);
366         } else {
367                 if (date_from_response) {
368                         http_msg_request_add_field(resume_request,
369                                         HTTP_FIELD_IF_RANGE, date_from_response);
370                 }
371         }
372
373         if (strlen(temp_size_str) > 0)
374                 http_msg_request_add_field(resume_request, HTTP_FIELD_RANGE,
375                                 temp_size_str);
376
377 ERR:
378         if (etag_from_response) {
379                 free(etag_from_response);
380                 etag_from_response = NULL;
381         }
382         if (date_from_response) {
383                 free(date_from_response);
384                 date_from_response = NULL;
385         }
386         return ret;
387 }
388
389
390 da_ret_t __start_transaction(da_info_t *da_info)
391 {
392         da_ret_t ret = DA_RESULT_OK;
393         http_info_t *http_info;
394         DA_LOGV("");
395
396         if (!da_info) {
397                 DA_LOGE("NULL CHECK!: da_info");
398                 return DA_ERR_INVALID_ARGUMENT;
399         }
400         http_info = da_info->http_info;
401         if (!http_info) {
402                 DA_LOGE("NULL CHECK!: http_info");
403                 return DA_ERR_INVALID_ARGUMENT;
404         }
405         http_info->http_method = HTTP_METHOD_GET;
406
407         // Check exception list for proxy
408         if (__is_proxy_required(da_info->req_info->url))
409                 http_info->proxy_info = __get_proxy_info();
410         else
411                 http_info->proxy_info = NULL;
412
413         ret = PI_http_start(da_info);
414
415         return ret;
416 }
417
418 da_ret_t __start_resume_transaction(da_info_t *da_info)
419 {
420         da_ret_t ret = DA_RESULT_OK;
421         http_info_t *http_info = DA_NULL;
422         file_info_t *file_info = DA_NULL;
423         req_info_t *req_info = DA_NULL;
424
425         NULL_CHECK_RET(da_info);
426         http_info = da_info->http_info;
427         NULL_CHECK_RET(http_info);
428         file_info = da_info->file_info;
429         NULL_CHECK_RET(file_info);
430         req_info = da_info->req_info;
431         NULL_CHECK_RET(req_info);
432
433         ret = __create_http_resume_hdr(req_info, http_info,
434                         file_info);
435         if (ret != DA_RESULT_OK)
436                 return ret;
437
438         reset_http_info_for_resume(http_info);
439         if (file_info->file_path) {
440                 req_info->temp_file_path = strdup(file_info->file_path);
441         } else {
442                 DA_LOGE("file_path cannot be NULL in resume case");
443                 return DA_ERR_INVALID_ARGUMENT;
444         }
445         ret = __start_transaction(da_info);
446         return ret;
447 }
448
449
450 da_ret_t __start_new_transaction(da_info_t *da_info)
451 {
452         da_ret_t ret = DA_RESULT_OK;
453
454         if (!da_info) {
455                 DA_LOGE("NULL CHECK!: da_info");
456                 return DA_ERR_INVALID_ARGUMENT;
457         }
458
459         ret = __set_http_request_hdr(da_info->req_info, da_info->http_info, da_info->file_info);
460         if (ret != DA_RESULT_OK)
461                 return ret;
462
463         ret = __start_transaction(da_info);
464         return ret;
465 }
466
467 int __check_wait_for_auto_retry(http_info_t *http_info)
468 {
469         da_ret_t ret = DA_RESULT_OK;
470         struct timespec ts;
471         struct timeval tp;
472         NULL_CHECK_RET_OPT(http_info, 0);
473         gettimeofday(&tp, NULL);
474         ts.tv_sec = tp.tv_sec + DA_MAX_TIME_OUT;
475         ts.tv_nsec = tp.tv_usec * 1000;
476         DA_LOGI("Network Fail case, wait for a while");
477
478         DA_MUTEX_LOCK(&(http_info->mutex_state));
479         http_info->state = HTTP_STATE_WAIT_FOR_NET_ERR;
480         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
481         DA_MUTEX_LOCK(&(http_info->mutex_http));
482         ret = pthread_cond_timedwait(&(http_info->cond_http),
483                         &(http_info->mutex_http), &ts);
484         DA_MUTEX_UNLOCK(&(http_info->mutex_http));
485         if (ret == ETIMEDOUT) {
486                 DA_LOGI("Waiting is done by timeout");
487         } else if (ret != 0) {
488                 DA_LOGE("fail to pthread_cond_waittime[%d]", ret);
489         } else {
490                 DA_LOGI("Waiting is done by control");
491                 DA_MUTEX_LOCK(&(http_info->mutex_state));
492                 DA_LOGI("http_state[%s]", __get_state_str(http_info->state));
493                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
494                 return 1;
495         }
496
497         return 0;
498 }
499
500 // In download thread
501 da_ret_t request_http_download(da_info_t *da_info)
502 {
503         da_ret_t ret = DA_RESULT_OK;
504         req_info_t *req_info = DA_NULL;
505         http_info_t *http_info = DA_NULL;
506         http_state_t http_state = HTTP_STATE_READY_TO_DOWNLOAD;
507         da_bool_t need_wait = DA_TRUE;
508
509         DA_LOGV("");
510
511         NULL_CHECK_RET(da_info);
512         req_info = da_info->req_info;
513         NULL_CHECK_RET(req_info);
514         http_info = da_info->http_info;
515         NULL_CHECK_RET(http_info);
516         __init_http_info(http_info);
517
518         do {
519                 DA_MUTEX_LOCK(&(http_info->mutex_state));
520                 http_state = http_info->state;
521                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
522                 DA_LOGD("http_state[%s][%d]", __get_state_str(http_info->state), da_info->da_id);
523                 switch (http_state) {
524                 case HTTP_STATE_READY_TO_DOWNLOAD:
525                         DA_MUTEX_LOCK(&(http_info->mutex_state));
526                         http_info->state = HTTP_STATE_DOWNLOAD_REQUESTED;
527                         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
528                         ret = __start_new_transaction(da_info);
529                         DA_MUTEX_LOCK(&(http_info->mutex_state));
530                         http_state = http_info->state;
531                         DA_LOGD("http_state[%s][%d]", __get_state_str(http_info->state), da_info->da_id);
532                         http_info->error_code = ret;
533                         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
534                         if (ret == DA_ERR_NETWORK_FAIL && http_state != HTTP_STATE_PAUSED) {
535                                 DA_LOGE("Network failed");
536                                 if (__check_wait_for_auto_retry(http_info) == 1)
537                                         need_wait = DA_TRUE;
538                                 else
539                                         need_wait = DA_FALSE;
540                         }
541                         break;
542                 case HTTP_STATE_REDIRECTED:
543                 case HTTP_STATE_DOWNLOAD_REQUESTED:
544                 case HTTP_STATE_DOWNLOAD_STARTED:
545                 case HTTP_STATE_DOWNLOADING:
546                 case HTTP_STATE_REQUEST_PAUSE:
547                         DA_LOGE("Cannot enter here:[%s][%d]",
548                                         __get_state_str(http_info->state), da_info->da_id);
549                         break;
550                 case HTTP_STATE_REQUEST_CANCEL:
551                         break;
552                 case HTTP_STATE_REQUEST_RESUME:
553                         DA_MUTEX_LOCK(&(http_info->mutex_state));
554                         http_info->state = HTTP_STATE_READY_TO_DOWNLOAD;
555                         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
556                         need_wait = DA_TRUE;
557                         break;
558                 case HTTP_STATE_CANCELED:
559                         need_wait = DA_FALSE;
560                         ret = DA_RESULT_USER_CANCELED;
561                         break;
562                 case HTTP_STATE_PAUSED:
563                         DA_LOGD("error_code[%d]", http_info->error_code);
564                         send_client_paused_info(da_info);
565                         DA_LOGD("Waiting thread for paused state");
566                         DA_MUTEX_LOCK(&(http_info->mutex_http));
567                         pthread_cond_wait(&(http_info->cond_http), &(http_info->mutex_http));
568                         DA_MUTEX_UNLOCK(&(http_info->mutex_http));
569                         DA_LOGD("Wake up thread due to resume");
570                         break;
571                 case HTTP_STATE_RESUMED:
572                         DA_MUTEX_LOCK(&(http_info->mutex_state));
573                         http_info->state = HTTP_STATE_DOWNLOAD_REQUESTED;
574                         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
575                         ret = __start_resume_transaction(da_info);
576                         DA_MUTEX_LOCK(&(http_info->mutex_state));
577                         http_state = http_info->state;
578                         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
579                         if (ret == DA_ERR_NETWORK_FAIL && http_state != HTTP_STATE_PAUSED) {
580                                 DA_LOGE("Network failed");
581                                 if (__check_wait_for_auto_retry(http_info) == 1)
582                                         need_wait = DA_TRUE;
583                                 else
584                                         need_wait = DA_FALSE;
585                         }
586                         break;
587                 case HTTP_STATE_DOWNLOAD_FINISH:
588                         need_wait = DA_FALSE;
589                         if (ret == DA_RESULT_OK)
590                                 ret = check_drm_convert(da_info->file_info);
591                         break;
592                 case HTTP_STATE_FAILED:
593                         if (ret == DA_ERR_NETWORK_FAIL) {
594                                 if (__check_wait_for_auto_retry(http_info) == 1)
595                                         need_wait = DA_TRUE;
596                                 else
597                                         need_wait = DA_FALSE;
598                         } else {
599                                 need_wait = DA_FALSE;
600                         }
601                         break;
602                 case HTTP_STATE_ABORTED:
603                         need_wait = DA_FALSE;
604                         break;
605                 default:
606                         break;
607                 }
608         } while (need_wait == DA_TRUE);
609         DA_LOGD("Final http_state[%s][%d] err[%d]", __get_state_str(http_info->state), da_info->da_id, ret);
610         if (http_info->state != HTTP_STATE_PAUSED)
611                 send_client_finished_info(da_info, ret);
612         DA_LOGI("=== Exiting http_download ret[%d] ===", ret);
613         return ret;
614 }
615
616 da_ret_t __disconnect_transaction(http_info_t *http_info)
617 {
618         da_ret_t ret = DA_RESULT_OK;
619         DA_LOGD("");
620         ret = PI_http_disconnect(http_info);
621         return ret;
622 }
623
624 da_ret_t __handle_event_abort(http_info_t *http_info)
625 {
626         da_ret_t ret = DA_RESULT_OK;
627         http_state_t state = 0;
628
629         DA_LOGD("");
630
631         DA_MUTEX_LOCK(&(http_info->mutex_state));
632         state = http_info->state;
633         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
634         DA_LOGV("http_state[%s]", __get_state_str(state));
635
636         switch (state) {
637         case HTTP_STATE_READY_TO_DOWNLOAD:
638         case HTTP_STATE_REDIRECTED:
639         case HTTP_STATE_DOWNLOAD_REQUESTED:
640         case HTTP_STATE_DOWNLOAD_STARTED:
641         case HTTP_STATE_DOWNLOADING:
642         case HTTP_STATE_REQUEST_CANCEL:
643         case HTTP_STATE_REQUEST_PAUSE:
644         case HTTP_STATE_REQUEST_RESUME:
645         case HTTP_STATE_CANCELED:
646         case HTTP_STATE_PAUSED:
647         case HTTP_STATE_RESUMED:
648         case HTTP_STATE_ABORTED:
649         case HTTP_STATE_WAIT_FOR_NET_ERR:
650                 /* IF the network session is terminated due to some error,
651                  * the state can be aborted.(data aborted case) */
652                 DA_MUTEX_LOCK(&(http_info->mutex_state));
653                 http_info->state = HTTP_STATE_ABORTED;
654                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
655                 __disconnect_transaction(http_info);
656                 break;
657         case HTTP_STATE_DOWNLOAD_FINISH:
658                 break;
659         default:
660                 DA_LOGE("Cannot enter here");
661                 break;
662         }
663         return ret;
664 }
665
666 da_ret_t __check_enough_memory(http_info_t *http_info, req_info_t *req_info)
667 {
668         da_ret_t ret = DA_RESULT_OK;
669         da_size_t cont_len = 0;
670         dp_client_slots_fmt *slot = DA_NULL;
671         const char *dir_path = DA_NULL;
672         const char *user_install_path = DA_NULL;
673
674         DA_LOGV("");
675         NULL_CHECK_RET(http_info);
676         cont_len = http_info->content_len_from_header;
677         NULL_CHECK_RET(req_info);
678         user_install_path = (const char*)req_info->install_path;
679         slot = req_info->user_client_data;
680         NULL_CHECK_RET(slot);
681         if (cont_len > 0) {
682                 if (user_install_path) {
683                         dir_path = user_install_path;
684                 } else {
685                         tzplatform_set_user(slot->credential.uid);
686                         dir_path = DA_DEFAULT_INSTALL_PATH_FOR_PHONE;
687                         tzplatform_reset_user();
688                 }
689                 ret = get_available_memory(dir_path, cont_len);
690         }
691         return ret;
692 }
693
694 da_ret_t request_to_abort_http_download(da_info_t *da_info)
695 {
696         da_ret_t ret = DA_RESULT_OK;
697         ret = __handle_event_abort(da_info->http_info);
698         return ret;
699 }
700
701 da_ret_t request_to_cancel_http_download(da_info_t *da_info)
702 {
703         da_ret_t ret = DA_RESULT_OK;
704         http_info_t *http_info = DA_NULL;
705         http_state_t http_state = 0;
706         int mutex_ret = 0;
707
708         DA_LOGV("");
709
710         NULL_CHECK_RET(da_info);
711         http_info = da_info->http_info;
712         NULL_CHECK_RET(http_info);
713
714         DA_MUTEX_LOCK(&(http_info->mutex_state));
715         http_state = http_info->state;
716         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
717         DA_LOGD("http_state[%s]", __get_state_str(http_state));
718         switch (http_state) {
719         case HTTP_STATE_READY_TO_DOWNLOAD:
720                 ret = PI_http_cancel(http_info);
721                 DA_MUTEX_LOCK(&(http_info->mutex_state));
722                 http_info->state = HTTP_STATE_CANCELED;
723                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
724                 break;
725         case HTTP_STATE_WAIT_FOR_NET_ERR:
726                 DA_MUTEX_LOCK(&(http_info->mutex_state));
727                 http_info->state = HTTP_STATE_CANCELED;
728                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
729                 DA_MUTEX_LOCK(&(http_info->mutex_http));
730                 DA_COND_SIGNAL(&(http_info->cond_http));
731                 DA_MUTEX_UNLOCK(&(http_info->mutex_http));
732                 break;
733         case HTTP_STATE_PAUSED:
734                 DA_MUTEX_LOCK(&(http_info->mutex_state));
735                 http_info->state = HTTP_STATE_CANCELED;
736                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
737                 break;
738         case HTTP_STATE_DOWNLOAD_REQUESTED:
739         case HTTP_STATE_DOWNLOAD_STARTED:
740         case HTTP_STATE_DOWNLOADING:
741         case HTTP_STATE_REQUEST_RESUME:
742         case HTTP_STATE_RESUMED:
743                 DA_LOGI("Change http_info->state to HTTP_STATE_REQUEST_CANCEL");
744                 mutex_ret = pthread_mutex_lock(&(http_info->mutex_state));
745                 if (mutex_ret == 0) {
746                         http_info->state = HTTP_STATE_REQUEST_CANCEL;
747                         mutex_ret = pthread_mutex_unlock(&(http_info->mutex_state));
748                         if (mutex_ret != 0)
749                                 DA_LOGE("pthread_mutex_unlock FAIL with [%d]", mutex_ret);
750                 } else {
751                         DA_LOGE("pthread_mutex_lock FAIL with [%d]", mutex_ret);
752                 }
753                 ret = PI_http_cancel(http_info);
754                 break;
755         case HTTP_STATE_DOWNLOAD_FINISH:
756                 ret = DA_ERR_INVALID_STATE;
757                 break;
758         case HTTP_STATE_REQUEST_CANCEL:
759                 DA_LOGV("cancel is already in progress... ");
760                 ret = DA_ERR_INVALID_STATE;
761                 break;
762         default:
763                 ret = DA_ERR_INVALID_STATE;
764                 DA_LOGE("Cannot enter here");
765                 break;
766         }
767         return ret;
768 }
769
770 da_ret_t request_to_suspend_http_download(da_info_t *da_info)
771 {
772
773         da_ret_t ret = DA_RESULT_OK;
774         http_info_t *http_info = DA_NULL;
775         http_state_t http_state = 0;
776
777         DA_LOGV("");
778
779         NULL_CHECK_RET(da_info);
780         http_info = da_info->http_info;
781         NULL_CHECK_RET(http_info);
782
783         DA_MUTEX_LOCK(&(http_info->mutex_state));
784         http_state = http_info->state;
785         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
786         DA_LOGD("http_state[%s]", __get_state_str(http_state));
787
788         switch (http_state) {
789         case HTTP_STATE_PAUSED:
790         case HTTP_STATE_REQUEST_PAUSE:
791                 DA_LOGI("Already paused. http_state[%s]", __get_state_str(http_state));
792                 ret = DA_ERR_ALREADY_SUSPENDED;
793                 break;
794         case HTTP_STATE_READY_TO_DOWNLOAD:
795                 DA_LOGE("Download has not been started yet");
796                 ret = DA_ERR_INVALID_STATE;
797                 break;
798         case HTTP_STATE_WAIT_FOR_NET_ERR:
799                 DA_LOGD("error_code[%d]", http_info->error_code);
800                 DA_MUTEX_LOCK(&(http_info->mutex_state));
801                 http_info->state = HTTP_STATE_PAUSED;
802                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
803                 DA_MUTEX_LOCK(&(http_info->mutex_http));
804                 DA_COND_SIGNAL(&(http_info->cond_http));
805                 DA_MUTEX_UNLOCK(&(http_info->mutex_http));
806                 break;
807         default:
808                 DA_MUTEX_LOCK(&(http_info->mutex_state));
809                 http_info->state = HTTP_STATE_REQUEST_PAUSE;
810                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
811                 DA_LOGD("error_code[%d]", http_info->error_code);
812                 if (http_info->error_code != DA_ERR_NETWORK_FAIL)
813                         ret = PI_http_pause(http_info);
814                 DA_MUTEX_LOCK(&(http_info->mutex_state));
815                 http_info->state = HTTP_STATE_PAUSED;
816                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
817
818                 break;
819         }
820         return ret;
821 }
822
823 da_ret_t request_to_resume_http_download(da_info_t *da_info)
824 {
825         da_ret_t ret = DA_RESULT_OK;
826         http_info_t *http_info = DA_NULL;
827         http_state_t http_state = 0;
828         int retry_count = 0;
829
830         DA_LOGV("");
831
832         NULL_CHECK_RET(da_info);
833         http_info = da_info->http_info;
834         NULL_CHECK_RET(http_info);
835
836         DA_MUTEX_LOCK(&(http_info->mutex_state));
837         http_state = http_info->state;
838         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
839         DA_LOGD("http_state[%s]", __get_state_str(http_state));
840
841         switch (http_state) {
842         case HTTP_STATE_PAUSED:
843                 DA_MUTEX_LOCK(&(http_info->mutex_state));
844                 http_info->state = HTTP_STATE_RESUMED;
845                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
846                 DA_LOGD("Wake up thread for paused state");
847                 DA_MUTEX_LOCK(&(http_info->mutex_http));
848                 DA_COND_SIGNAL(&(http_info->cond_http));
849                 DA_MUTEX_UNLOCK(&(http_info->mutex_http));
850                 DA_LOGD("error_code[%d]", http_info->error_code);
851                 if (http_info->error_code != DA_ERR_NETWORK_FAIL) {
852                         ret = PI_http_unpause(http_info);
853                         if (ret != DA_RESULT_OK)
854                                 PI_http_cancel(http_info);
855                         DA_LOGD("Change state to HTTP_STATE_DOWNLOADING");
856                         DA_MUTEX_LOCK(&(http_info->mutex_state));
857                         http_info->state = HTTP_STATE_DOWNLOADING;
858                         DA_LOGD("Changed state[%s]", __get_state_str(http_info->state));
859                         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
860                         DA_LOGD("Complete to change state");
861                 } else {
862                         DA_LOGD("Can't resume[%d]", http_info->error_code);
863                 }
864                 break;
865         case HTTP_STATE_REQUEST_PAUSE:
866                 DA_LOGD("Waiting to handle pause request");
867                 do {
868                         DA_MUTEX_LOCK(&(http_info->mutex_state));
869                         http_state = http_info->state;
870                         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
871                         if (http_state == HTTP_STATE_PAUSED) {
872                                 DA_LOGD("Change to paused state");
873                                 ret = PI_http_unpause(http_info);
874                                 break;
875                         }
876                         retry_count++;
877                 } while (retry_count < 10000);
878                 if (ret != DA_RESULT_OK || retry_count >= 10000)
879                         PI_http_cancel(http_info);
880                 break;
881         case HTTP_STATE_RESUMED:
882                 ret = DA_ERR_ALREADY_RESUMED;
883                 break;
884         default:
885                 DA_LOGE("Fail to resume. Invalid state check. http_state[%s]",
886                                 __get_state_str(http_state));
887                 ret = DA_ERR_INVALID_STATE;
888                 // If resume is failed due to invalid state, the previous pause should be canceled.
889                 PI_http_cancel(http_info);
890                 break;
891         }
892         return ret;
893 }
894
895 da_ret_t __check_resume_download_is_available(
896                 req_info_t *req_info, http_info_t *http_info, file_info_t *file_info)
897 {
898         da_ret_t ret = DA_RESULT_OK;
899         da_bool_t b_ret = DA_FALSE;
900         char *origin_ETag = NULL;
901         char *new_ETag = NULL;
902         da_size_t remained_content_len = 0;
903         char *value = NULL;
904         da_size_t size = 0;
905         char *temp_file_path = DA_NULL;
906         const char *dir_path = DA_NULL;
907         dp_client_slots_fmt *slot = DA_NULL;
908
909         DA_LOGV("");
910         NULL_CHECK_RET(req_info);
911         slot  =  req_info->user_client_data;
912         NULL_CHECK_RET(slot);
913
914         origin_ETag = req_info->etag;
915
916         b_ret = http_msg_response_get_content_length(http_info->http_msg_response,
917                         &size);
918         if (b_ret) {
919                 remained_content_len = size;
920                 size = 0;
921                 DA_SECURE_LOGD("remained_content_len[%llu]", remained_content_len);
922         }
923
924         b_ret = http_msg_response_get_ETag(http_info->http_msg_response, &value);
925         if (b_ret) {
926                 new_ETag = value;
927                 value = NULL;
928                 DA_SECURE_LOGD("new ETag[%s]", new_ETag);
929         } else {
930                 goto ERR;
931         }
932
933         if (origin_ETag && new_ETag && strcmp(origin_ETag, new_ETag)) {
934                 DA_LOGE("ETag is not identical! revoke!");
935                 /* FIXME Later : Need to detail error exception handling */
936                 ret = DA_ERR_NETWORK_FAIL;
937                 /*ret = DA_ERR_MISMATCH_HTTP_HEADER; */
938                 goto ERR;
939         }
940
941         if (remained_content_len > 0) {
942                 if (req_info->install_path)
943                         dir_path = (const char *)req_info->install_path;
944                 else {
945                         tzplatform_set_user(slot->credential.uid);
946                         dir_path = DA_DEFAULT_INSTALL_PATH_FOR_PHONE;
947                         tzplatform_reset_user();
948                 }
949                 ret = get_available_memory(dir_path, remained_content_len);
950                 if (ret != DA_RESULT_OK)
951                         goto ERR;
952         }
953
954         if (!http_info->content_type_from_header) {
955                 b_ret = http_msg_response_get_content_type(http_info->http_msg_response,
956                                 &value);
957                 if (b_ret) {
958                         http_info->content_type_from_header = value;
959                         value = NULL;
960                         DA_SECURE_LOGD("Content-Type[%s]",
961                                 http_info->content_type_from_header);
962                 }
963         }
964         temp_file_path = req_info->temp_file_path;
965         if (!temp_file_path) {
966                 DA_LOGE("Temporary file path cannot be NULL");
967                 ret = DA_ERR_INVALID_ARGUMENT;
968                 goto ERR;
969         }
970         get_file_size(temp_file_path, &size);
971         http_info->content_len_from_header = remained_content_len + size;
972         DA_SECURE_LOGD("Content-Length[%llu]", http_info->content_len_from_header);
973 ERR:
974         if (new_ETag) {
975                 free(new_ETag);
976                 new_ETag = DA_NULL;
977         }
978         return ret;
979 }
980
981
982 da_ret_t __check_content_type_is_matched(http_info_t *http_info)
983 {
984         da_ret_t ret = DA_RESULT_OK;
985         char *content_type_from_server = DA_NULL;
986
987         DA_LOGV("");
988
989         content_type_from_server = http_info->content_type_from_header;
990         if (content_type_from_server == DA_NULL) {
991                 DA_LOGV("http header has no Content-Type field, no need to compare");
992                 return DA_RESULT_OK;
993         }
994         return ret;
995 }
996
997 da_ret_t __handle_http_status_code(http_info_t *http_info,
998                 file_info_t *file_info, req_info_t *req_info)
999 {
1000         da_ret_t ret = DA_RESULT_OK;
1001         http_state_t http_state = 0;
1002         http_msg_response_t *http_msg_response = DA_NULL;
1003         char *location = DA_NULL;
1004         char *if_range_str = DA_NULL;
1005         char *range_str = DA_NULL;
1006         int http_status = 0;
1007
1008         NULL_CHECK_RET(http_info);
1009         NULL_CHECK_RET(file_info);
1010         NULL_CHECK_RET(req_info);
1011         DA_MUTEX_LOCK(&(http_info->mutex_state));
1012         http_state = http_info->state;
1013         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1014         DA_LOGD("http_state[%s]", __get_state_str(http_state));
1015         http_msg_response = http_info->http_msg_response;
1016         NULL_CHECK_RET(http_msg_response);
1017         http_status = http_msg_response->status_code;
1018         switch (http_status) {
1019         case 200:
1020         case 201:
1021         case 202:
1022         case 203:
1023 // Although expecting 206, 200 response is received. Remove temporary file and reset file info
1024                 if (http_info->http_msg_request &&
1025                                 http_msg_request_get_if_range(http_info->http_msg_request, &if_range_str) == DA_TRUE &&
1026                                 http_msg_request_get_range(http_info->http_msg_request, &range_str) == DA_TRUE) {
1027                         DA_LOGI("Server do not support if-range option");
1028                         clean_paused_file(file_info);
1029                 }
1030                 free(if_range_str);
1031                 free(range_str);
1032                 if (http_state == HTTP_STATE_REQUEST_RESUME)
1033                         clean_paused_file(file_info);
1034                 ret = __check_content_type_is_matched(http_info);
1035                 if (ret != DA_RESULT_OK)
1036                         goto ERR;
1037                 ret = __check_enough_memory(http_info, req_info);
1038                 if (ret != DA_RESULT_OK)
1039                         goto ERR;
1040                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1041                 http_info->state =  HTTP_STATE_DOWNLOAD_STARTED;
1042                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1043                 break;
1044
1045         case 206:
1046                 DA_LOGV("HTTP Status is %d - Partial download for resume!", http_status);
1047                 /* The resume can be started with start API.
1048                  * So the state should be not HTTP_STATE_RESUME_REQUESTED but HTTP_STATE_DOWNLOAD_REQUESTED*/
1049                 if (http_state == HTTP_STATE_DOWNLOAD_REQUESTED) {
1050                         ret = __check_resume_download_is_available(req_info, http_info, file_info);
1051                         if (ret != DA_RESULT_OK)
1052                                 goto ERR;
1053                         DA_MUTEX_LOCK(&(http_info->mutex_state));
1054                         http_info->state = HTTP_STATE_DOWNLOAD_STARTED;
1055                         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1056
1057                 } else if (http_state == HTTP_STATE_REQUEST_RESUME) {
1058                         ///FIXME later : how get previous response header
1059                         ///ret = __check_this_partial_download_is_available(http_info,
1060                                 ///     previous_ http_msg_response);
1061                         //if (ret != DA_RESULT_OK)
1062                                 //goto ERR;
1063                         DA_MUTEX_LOCK(&(http_info->mutex_state));
1064                         http_info->state = HTTP_STATE_RESUMED;
1065                         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1066                 } else {
1067                         DA_LOGE("This download is not resumed, revoke");
1068                         ret = DA_ERR_INVALID_STATE;
1069                         goto ERR;
1070                 }
1071                 break;
1072
1073         case 300:
1074         case 301:
1075         case 302:
1076         case 303:
1077         case 305:
1078         case 306:
1079         case 307:
1080                 DA_LOGV("HTTP Status is %d - redirection!", http_status);
1081                 if (http_msg_response_get_location(http_msg_response, &location)) {
1082                         DA_SECURE_LOGD("location  = %s\n", location);
1083                         http_info->location_url = location;
1084                         DA_LOGI("[TEST] location_url[%p]", http_info->location_url);
1085                 }
1086                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1087                 http_info->state = HTTP_STATE_REDIRECTED;
1088                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1089                 http_msg_response_destroy(&http_msg_response);
1090                 http_info->http_msg_response = DA_NULL;
1091                 break;
1092
1093         case 100:
1094         case 101:
1095         case 102:
1096         case 204:
1097         case 304:
1098                 DA_LOGV("HTTP Status is %d - 204 server got the request, \
1099                                 but no content to reply back, \
1100                                 304 means not modified!", http_status);
1101                 if (!req_info->cache)
1102                         ret = DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT;
1103                 break;
1104
1105         case 416: // Requested range not satisfiable
1106         case 503:
1107         case 504:
1108         default:
1109                 ret = DA_ERR_UNREACHABLE_SERVER;
1110                 DA_LOGI("set internal error code : DA_ERR_UNREACHABLE_SERVER");
1111                 break;
1112         }
1113
1114 ERR:
1115         return ret;
1116 }
1117
1118 da_ret_t __check_before_downloading(da_info_t *da_info, http_state_t state)
1119 {
1120         da_ret_t ret = DA_RESULT_OK;
1121         http_info_t *http_info = DA_NULL;
1122         req_info_t *req_info = DA_NULL;
1123         file_info_t *file_info = DA_NULL;
1124         NULL_CHECK_RET(da_info);
1125         http_info = da_info->http_info;
1126         NULL_CHECK_RET(http_info);
1127         req_info = da_info->req_info;
1128         NULL_CHECK_RET(req_info);
1129         file_info = da_info->file_info;
1130         NULL_CHECK_RET(file_info);
1131         DA_LOGD("state:%s", __get_state_str(state));
1132         // resume case
1133         if (req_info->temp_file_path && file_info->bytes_written_to_file > 0) {
1134                 ret = start_file_append(file_info);
1135         } else if (state == HTTP_STATE_DOWNLOAD_STARTED) {
1136                 ret = start_file_writing(da_info);
1137         } else {
1138                 DA_LOGE("Cannot enter here!");
1139                 ret = DA_ERR_INVALID_ARGUMENT;
1140                 goto ERR;
1141         }
1142         if (DA_RESULT_OK != ret)
1143                 goto ERR;
1144
1145         DA_MUTEX_LOCK(&(http_info->mutex_state));
1146         http_info->state = HTTP_STATE_DOWNLOADING;
1147         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1148
1149         ret = send_client_update_dl_info(da_info);
1150 ERR:
1151         return ret;
1152 }
1153
1154 static void __handle_empty_file(da_info_t *da_info)
1155 {
1156         char *transfer_encoding = DA_NULL;
1157         http_msg_response_t *http_msg_response = DA_NULL;
1158
1159         NULL_CHECK(da_info);
1160         NULL_CHECK(da_info->http_info);
1161
1162         http_msg_response = da_info->http_info->http_msg_response;
1163         NULL_CHECK(http_msg_response);
1164
1165         if (http_msg_response->status_code == 200
1166                         && http_msg_response_get_transfer_encoding(http_msg_response,
1167                                 &transfer_encoding) == DA_FALSE) {
1168                 start_file_writing(da_info);
1169                 DA_LOGD("Empty file");
1170         }
1171
1172         if (transfer_encoding)
1173                 free(transfer_encoding);
1174 }
1175
1176 static proxy_info_t *__get_proxy_info()
1177 {
1178         proxy_info_t *proxy_info = DA_NULL;
1179         char scheme[DA_MAX_SCHEME_LEN] = {0, };
1180         char user_name[DA_MAX_USER_NAME_LEN] = {0, };
1181         char password[DA_MAX_PASSWORD_LEN] = {0, };
1182         char host[DA_MAX_PROXY_ADDR_LEN] = {0, }; // ip:port
1183         char *proxy_uri = get_proxy_address(); // scheme://userinfo@ip:port
1184         int ret = 0;
1185
1186         if (proxy_uri && !strstr(proxy_uri, "0.0.0.0")) {
1187                 proxy_info = (proxy_info_t *)calloc(1, sizeof(proxy_info_t));
1188                 if (!proxy_info) {
1189                         DA_LOGE("Failed to calloc");
1190                         free(proxy_uri);
1191                         return DA_NULL;
1192                 }
1193
1194                 char *found = strrchr(proxy_uri, '@');
1195                 if (found) {
1196                         size_t userinfo_len = strlen(proxy_uri) - strlen(found);
1197                         char *userinfo = strndup(proxy_uri, userinfo_len);
1198                         if (!userinfo) {
1199                                 DA_LOGE("Failed to copy proxy_uri to userinfo");
1200                                 free(proxy_info);
1201                                 free(proxy_uri);
1202                                 return DA_NULL;
1203                         }
1204
1205                         if (strstr(userinfo, SCHEME_DELIMETER))
1206                                 sscanf(userinfo, "%7[^:/]://%255[^:]:%255s", scheme, user_name, password);
1207                         else
1208                                 sscanf(userinfo, "%255[^:]:%255s", user_name, password);
1209
1210                         free(userinfo);
1211
1212                         sscanf(found + 1, "%63s", host);
1213                         if (strlen(host) == 0) {
1214                                 DA_LOGE("Invalid proxy address");
1215                                 free(proxy_info);
1216                                 free(proxy_uri);
1217                                 return DA_NULL;
1218                         }
1219
1220                         if (strlen(scheme) == 0)
1221                                 strncpy(scheme, DEFAULT_SCHEME, DA_MAX_SCHEME_LEN - 1);
1222
1223                         ret = asprintf(&proxy_info->addr, "%s://%s", scheme, host);
1224                         if (ret == -1 || proxy_info->addr == NULL) {
1225                                 DA_LOGE("Failed to set proxy_info->addr");
1226                                 free(proxy_info);
1227                                 free(proxy_uri);
1228                                 return DA_NULL;
1229                         }
1230                 } else {
1231                         proxy_info->addr = strdup(proxy_uri);
1232                         DA_LOGI("proxy_info->addr[%s] will be used.", proxy_info->addr);
1233                 }
1234                 proxy_info->user_name = strlen(user_name) > 0 ? strdup(user_name) : DA_NULL;
1235                 proxy_info->password = strlen(password) > 0 ? strdup(password) : DA_NULL;
1236         }
1237
1238         if (proxy_uri)
1239                 free(proxy_uri);
1240
1241         DA_LOGI("host[%s] user_name[%s] password[***]", host, user_name);
1242
1243         return proxy_info;
1244 }
1245
1246 da_ret_t __handle_event_http_header(http_raw_data_t *raw_data, da_info_t *da_info)
1247 {
1248         da_ret_t ret = DA_RESULT_OK;
1249         http_state_t http_state = 0;
1250         http_info_t *http_info = DA_NULL;
1251         file_info_t *file_info = DA_NULL;
1252         req_info_t *req_info = DA_NULL;
1253         http_msg_response_t *http_msg_response = DA_NULL;
1254         http_msg_t *http_msg = DA_NULL;
1255         da_size_t size = 0;
1256         char *mime_type = DA_NULL;
1257         char *etag = DA_NULL;
1258         char *cache_control = DA_NULL;
1259         char *last_modified = DA_NULL;
1260         char *file_name = DA_NULL;
1261
1262         NULL_CHECK_RET(da_info);
1263         http_info = da_info->http_info;
1264         NULL_CHECK_RET(http_info);
1265         file_info = da_info->file_info;
1266         NULL_CHECK_RET(file_info);
1267         req_info = da_info->req_info;
1268         NULL_CHECK_RET(req_info);
1269         NULL_CHECK_RET(raw_data);
1270
1271         http_msg = http_info->http_msg;
1272         NULL_CHECK_RET(http_msg);
1273
1274         DA_MUTEX_LOCK(&(http_info->mutex_state));
1275         http_state = http_info->state;
1276         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1277         DA_LOGD("http_state[%s]", __get_state_str(http_state));
1278         http_msg_response = http_info->http_msg_response;
1279         switch (http_state) {
1280         case HTTP_STATE_DOWNLOAD_REQUESTED:
1281         case HTTP_STATE_REQUEST_PAUSE:
1282         case HTTP_STATE_REQUEST_RESUME:
1283         case HTTP_STATE_REDIRECTED:
1284                 http_msg_response_get_content_length(http_msg_response, &size);
1285                 if (size == 0)
1286                         __handle_empty_file(da_info);
1287                 http_info->content_len_from_header = size;
1288                 http_msg_response_get_content_type(http_msg_response, &mime_type);
1289                 http_info->content_type_from_header = mime_type;
1290                 if (mime_type)
1291                         file_info->mime_type = strdup(mime_type);
1292                 http_msg_response_get_ETag(http_msg_response, &etag);
1293                 http_info->etag_from_header = etag;
1294
1295                 http_msg_response_get_cache_control(http_msg_response, &cache_control);
1296                 http_info->cache_control_from_header = cache_control;
1297                 http_msg_response_get_last_modified(http_msg_response, &last_modified);
1298                 http_info->last_modified_from_header = last_modified;
1299
1300                 http_msg_response_get_content_disposition(
1301                                 http_msg_response, http_msg, DA_NULL, &file_name);
1302                 http_info->file_name_from_header = file_name;
1303                 ret = __handle_http_status_code(http_info, file_info, req_info);
1304                 if (ret != DA_RESULT_OK) {
1305                         DA_LOGE("Fail to handle http status code");
1306                         goto ERR;
1307                 }
1308 #ifdef _RAF_SUPPORT
1309                 char *val = NULL;
1310                 http_msg_response_get_RAF_mode(http_msg_response, &val);
1311                 if (!val) {
1312                         DA_LOGE("Fail to raf mode value from response header");
1313                 } else {
1314                         DA_LOGI("[RAF] val[%s:%s]", HTTP_FIELD_RAF_MODE, val);
1315                         if (strcmp(val, "yes") == 0) {
1316                                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1317                                 http_info->state = HTTP_STATE_DOWNLOAD_STARTED;
1318                                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1319                                 ret = __check_before_downloading(da_info, http_info->state);
1320                                 if (ret != DA_RESULT_OK) {
1321                                         free(val);
1322                                         goto ERR;
1323                                 }
1324                                 http_info->is_raf_mode_confirmed = DA_TRUE;
1325                                 ret = PI_http_set_file_name_to_curl(http_info->http_msg, file_info->file_path);
1326                                 if (ret != DA_RESULT_OK) {
1327                                         DA_LOGE("Fail to set file name to curl");
1328                                         free(val);
1329                                         goto ERR;
1330                                 }
1331                         }
1332                         free(val);
1333                 }
1334 #endif
1335                 break;
1336         case HTTP_STATE_REQUEST_CANCEL:
1337                 DA_LOGV("Cancel is in progress.. http_state[%s]",
1338                                 __get_state_str(http_state));
1339                 break;
1340
1341         default:
1342                 DA_LOGE("http_state[%s]", __get_state_str(http_state));
1343                 goto ERR;
1344         }
1345
1346 ERR:
1347         if (ret != DA_RESULT_OK) {
1348                 DA_LOGE("Request to cancel due to error[%d]", ret);
1349                 PI_http_cancel(http_info);
1350                 http_info->error_code = ret;
1351                 discard_download(file_info);
1352                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1353                 http_info->state = HTTP_STATE_FAILED;
1354                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1355         }
1356         free(raw_data);
1357         return ret;
1358 }
1359
1360 da_ret_t __handle_event_http_packet(http_raw_data_t *raw_data, da_info_t *da_info)
1361 {
1362         da_ret_t ret = DA_RESULT_OK;
1363         http_state_t http_state = 0;
1364         http_info_t *http_info = DA_NULL;
1365         file_info_t *file_info = DA_NULL;
1366         time_t t;
1367         struct tm lc_time;
1368         DA_LOGV("");
1369
1370         NULL_CHECK_RET(da_info);
1371         http_info = da_info->http_info;
1372         NULL_CHECK_RET(http_info);
1373         file_info = da_info->file_info;
1374         NULL_CHECK_RET(file_info);
1375         NULL_CHECK_RET(raw_data);
1376
1377         DA_MUTEX_LOCK(&(http_info->mutex_state));
1378         http_state = http_info->state;
1379         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1380
1381         switch (http_state) {
1382         case HTTP_STATE_DOWNLOAD_STARTED:
1383 #ifdef _RAF_SUPPORT
1384                 if (http_info->is_raf_mode_confirmed == DA_FALSE) {
1385 #endif
1386                 ret = __check_before_downloading(da_info, http_state);
1387                 if (ret != DA_RESULT_OK)
1388                         goto ERR;
1389                 ret = file_write_ongoing(file_info,
1390                                 raw_data->body, raw_data->body_len);
1391                 if (ret != DA_RESULT_OK)
1392                         goto ERR;
1393 #ifdef _RAF_SUPPORT
1394                 } else {
1395                         file_info->bytes_written_to_file =
1396                                         raw_data->received_len + file_info->file_size_of_temp_file;
1397                         file_info->is_updated = DA_TRUE;
1398                 }
1399 #endif
1400                 ret = send_client_update_progress_info(da_info);
1401                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1402                 http_state = HTTP_STATE_DOWNLOADING;
1403                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1404                 break;
1405         case HTTP_STATE_RESUMED:
1406                 DA_LOGD("http_state[%s]", __get_state_str(http_state));
1407 #ifdef _RAF_SUPPORT
1408                 if (http_info->is_raf_mode_confirmed == DA_FALSE) {
1409 #endif
1410                 if (__check_before_downloading(da_info, http_state) == DA_RESULT_OK) {
1411                         ret = file_write_ongoing(file_info,
1412                                 raw_data->body, raw_data->body_len);
1413                         if (ret != DA_RESULT_OK)
1414                                 goto ERR;
1415 #ifdef _RAF_SUPPORT
1416                 } else {
1417                         file_info->bytes_written_to_file =
1418                                         raw_data->received_len + file_info->file_size_of_temp_file;
1419                         file_info->is_updated = DA_TRUE;
1420                 }
1421 #endif
1422                         ret = send_client_update_progress_info(da_info);
1423                 } else {
1424                         DA_LOGD("Do nothing! Wait for changing state properly");
1425                 }
1426                 break;
1427         case HTTP_STATE_REDIRECTED:
1428                 DA_LOGV("http_state[%s]", __get_state_str(http_state));
1429                 break;
1430         case HTTP_STATE_DOWNLOADING:
1431 #ifdef _RAF_SUPPORT
1432                 if (http_info->is_raf_mode_confirmed == DA_FALSE) {
1433 #endif
1434                 /* Should this function before updating download info
1435                  * Because it extract mime type at once only if first download updating at client */
1436                 ret = file_write_ongoing(file_info,
1437                                 raw_data->body, raw_data->body_len);
1438                 if (ret != DA_RESULT_OK)
1439                         goto ERR;
1440 #ifdef _RAF_SUPPORT
1441                 } else {
1442                         file_info->bytes_written_to_file =
1443                                         raw_data->received_len + file_info->file_size_of_temp_file;
1444                         file_info->is_updated = DA_TRUE;
1445                 }
1446 #endif
1447                 // send event every 1 second.
1448                 if ((t = time(DA_NULL)) > 0) {
1449                         if ((localtime_r(&t, &lc_time)) != DA_NULL) {
1450                                 if (da_info->update_time != lc_time.tm_sec) {
1451                                         da_info->update_time = lc_time.tm_sec;
1452                                         ret = send_client_update_progress_info(da_info);
1453                                 }
1454                         } else {
1455                                 DA_LOGE("Fail to call localtime");
1456                                 ret = send_client_update_progress_info(da_info);
1457                         }
1458                 } else {
1459                         DA_LOGE("Fail to call time");
1460                         ret = send_client_update_progress_info(da_info);
1461                 }
1462                 break;
1463         case HTTP_STATE_REQUEST_PAUSE:
1464 #ifdef _RAF_SUPPORT
1465                 if (http_info->is_raf_mode_confirmed == DA_FALSE) {
1466 #endif
1467                 DA_LOGV("http_state[%s]", __get_state_str(http_state));
1468                 ret = file_write_ongoing(file_info,
1469                                 raw_data->body, raw_data->body_len);
1470                 if (ret != DA_RESULT_OK)
1471                         goto ERR;
1472 #ifdef _RAF_SUPPORT
1473                 } else {
1474                         file_info->bytes_written_to_file =
1475                                         raw_data->received_len + file_info->file_size_of_temp_file;
1476                         file_info->is_updated = DA_TRUE;
1477                 }
1478 #endif
1479
1480                 break;
1481         default:
1482                 DA_LOGE("Do nothing! http_state is in case[%s]",
1483                                 __get_state_str(http_state));
1484                 goto ERR;
1485         }
1486 ERR:
1487         if (ret != DA_RESULT_OK) {
1488                 DA_LOGE("Request to cancel due to error[%d]", ret);
1489                 PI_http_cancel(http_info);
1490                 http_info->error_code = ret;
1491                 discard_download(da_info->file_info);
1492                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1493                 http_info->state = HTTP_STATE_FAILED;
1494                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1495         }
1496         if (raw_data->body)
1497                 free(raw_data->body);
1498         free(raw_data);
1499         return ret;
1500 }
1501
1502 da_ret_t __check_file_size_with_header_content_size(file_info_t *file_info)
1503 {
1504         da_ret_t ret = DA_RESULT_OK;
1505         unsigned long long tmp_file_size = 0;
1506
1507         DA_LOGV("");
1508
1509         if (file_info->file_size > 0) {
1510
1511 #ifdef _ENABLE_OMA_DRM
1512                 if (is_content_drm_dm(file_info->mime_type)) {
1513                         /* FIXME Later : How can get the file size of DRM file. */
1514                         return ret;
1515                 }
1516 #endif
1517
1518                 get_file_size(file_info->file_path, &tmp_file_size);
1519
1520                 if (tmp_file_size != file_info->file_size) {
1521                         DA_SECURE_LOGE("Real file size[%llu], MISMATCH CONTENT SIZE",
1522                                         tmp_file_size);
1523                         ret = DA_ERR_MISMATCH_CONTENT_SIZE;
1524                 }
1525         }
1526         return ret;
1527 }
1528
1529 da_ret_t __handle_event_http_final(http_raw_data_t *raw_data, da_info_t *da_info)
1530 {
1531         da_ret_t ret = DA_RESULT_OK;
1532         http_state_t http_state = 0;
1533         http_info_t *http_info = DA_NULL;
1534         file_info_t *file_info = DA_NULL;
1535
1536         DA_LOGV("");
1537
1538         NULL_CHECK_RET(da_info);
1539         http_info = da_info->http_info;
1540         NULL_CHECK_RET(http_info);
1541         file_info = da_info->file_info;
1542         NULL_CHECK_RET(file_info);
1543         NULL_CHECK_RET(raw_data);
1544
1545         DA_MUTEX_LOCK(&(http_info->mutex_state));
1546         http_state = http_info->state;
1547         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1548         DA_LOGD("http_state[%s]", __get_state_str(http_state));
1549
1550         switch (http_state) {
1551         case HTTP_STATE_REDIRECTED:
1552                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1553                 http_info->state = HTTP_STATE_READY_TO_DOWNLOAD;
1554                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1555                 break;
1556         case HTTP_STATE_DOWNLOAD_REQUESTED:
1557                 DA_LOGV("case HTTP_STATE_DOWNLOAD_REQUESTED");
1558                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1559                 http_info->state = HTTP_STATE_DOWNLOAD_FINISH;
1560                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1561                 break;
1562         case HTTP_STATE_DOWNLOAD_STARTED:
1563         case HTTP_STATE_DOWNLOADING:
1564                 DA_LOGD("case HTTP_STATE_DOWNLOAD_STARTED or HTTP_STATE_DOWNLOADING");
1565 #ifdef _RAF_SUPPORT
1566                 if (http_info->is_raf_mode_confirmed == DA_TRUE)
1567                         ret = file_write_complete_for_raf(file_info);
1568                 else
1569                         ret = file_write_complete(file_info);
1570 #else
1571                 ret = file_write_complete(file_info);
1572 #endif
1573                 if (ret != DA_RESULT_OK) {
1574                         discard_download(file_info);
1575                         goto ERR;
1576                 }
1577                 ret = __check_file_size_with_header_content_size(file_info);
1578                 if (ret != DA_RESULT_OK) {
1579                         discard_download(file_info) ;
1580                         goto ERR;
1581                 }
1582                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1583                 http_info->state = HTTP_STATE_DOWNLOAD_FINISH;
1584                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1585                 ret = send_client_update_progress_info(da_info);
1586                 break;
1587         case HTTP_STATE_REQUEST_PAUSE:
1588 #ifdef _RAF_SUPPORT
1589                 if (http_info->is_raf_mode_confirmed == DA_TRUE) {
1590                         if (file_info->file_handle)
1591                                 ret = file_write_complete_for_raf(file_info);
1592                 } else {
1593                         ret = file_write_complete(file_info);
1594                 }
1595 #else
1596                 if (file_info->file_handle) {
1597                         ret = file_write_complete(file_info);
1598 //                      send_client_update_progress_info(da_info);
1599                 }
1600 #endif
1601                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1602                 http_info->state = HTTP_STATE_PAUSED;
1603                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1604                 break;
1605         case HTTP_STATE_ABORTED:
1606         case HTTP_STATE_CANCELED:
1607                 discard_download(file_info);
1608                 break;
1609         case HTTP_STATE_REQUEST_CANCEL:
1610 #ifdef _RAF_SUPPORT
1611                 if (http_info->is_raf_mode_confirmed == DA_TRUE)
1612                         ret = file_write_complete_for_raf(file_info);
1613                 else
1614                         ret = file_write_complete(file_info);
1615 #else
1616                 ret = file_write_complete(file_info);
1617 #endif
1618                 if (ret != DA_RESULT_OK)
1619                         goto ERR;
1620                 discard_download(file_info);
1621                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1622                 http_info->state = HTTP_STATE_CANCELED;
1623                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1624                 break;
1625         case HTTP_STATE_PAUSED:
1626                 DA_LOGD("Remain paused stated");
1627                 break;
1628         default:
1629 #ifdef _RAF_SUPPORT
1630                 if (http_info->is_raf_mode_confirmed == DA_TRUE)
1631                         ret = file_write_complete_for_raf(file_info);
1632                 else
1633                         ret = file_write_complete(file_info);
1634 #else
1635                 ret = file_write_complete(file_info);
1636 #endif
1637                 if (ret != DA_RESULT_OK)
1638                         goto ERR;
1639                 discard_download(file_info);
1640                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1641                 http_info->state = HTTP_STATE_FAILED;
1642                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1643                 break;
1644         }
1645
1646 ERR:
1647         /* When file complete is failed */
1648         if (DA_RESULT_OK != ret) {
1649                 DA_MUTEX_LOCK(&(http_info->mutex_state));
1650                 http_info->state = HTTP_STATE_DOWNLOAD_FINISH;
1651                 DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1652         }
1653         if (raw_data->body)
1654                 free(raw_data->body);
1655         free(raw_data);
1656         return ret;
1657 }
1658
1659 void __http_update_cb(http_raw_data_t *data, void *user_param)
1660 {
1661         http_raw_data_t *raw_data = DA_NULL;
1662         da_info_t *da_info = DA_NULL;
1663         if (!data || !user_param) {
1664                 DA_LOGE("NULL CHECK!: data, user_param");
1665                 return;
1666         }
1667         DA_LOGV("");
1668         raw_data = data;
1669         da_info = (da_info_t *)user_param;
1670
1671         switch (data->type) {
1672         case HTTP_EVENT_GOT_HEADER:
1673                 __handle_event_http_header(raw_data, da_info);
1674                 break;
1675         case HTTP_EVENT_GOT_PACKET:
1676                 __handle_event_http_packet(raw_data, da_info);
1677                 break;
1678         case HTTP_EVENT_FINAL:
1679                 __handle_event_http_final(raw_data, da_info);
1680                 break;
1681 /*
1682         case HTTP_EVENT_ABORT:
1683                 ret = __handle_event_http_abort(raw_data, da_info);
1684                 break;
1685 */
1686         }
1687 }
1688
1689 da_bool_t is_stopped_state(da_info_t *da_info)
1690 {
1691         http_info_t *http_info = DA_NULL;
1692         http_state_t http_state;
1693         NULL_CHECK_RET_OPT(da_info, DA_FALSE);
1694         http_info = da_info->http_info;
1695         NULL_CHECK_RET_OPT(http_info, DA_FALSE);
1696         DA_MUTEX_LOCK(&(http_info->mutex_state));
1697         http_state = http_info->state;
1698         DA_MUTEX_UNLOCK(&(http_info->mutex_state));
1699         switch (http_state) {
1700         case HTTP_STATE_REQUEST_CANCEL:
1701         case HTTP_STATE_CANCELED:
1702         case HTTP_STATE_FAILED:
1703         case HTTP_STATE_ABORTED:
1704         //case HTTP_STATE_REQUEST_PAUSE:
1705         //case HTTP_STATE_REQUEST_RESUME:
1706         //case HTTP_STATE_WAIT_FOR_NET_ERR:
1707                 return DA_TRUE;
1708         default:
1709                 return DA_FALSE;
1710         }
1711         return DA_FALSE;
1712 }