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