2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "download-agent-utils.h"
18 #include "download-agent-debug.h"
19 #include "download-agent-client-mgr.h"
20 #include "download-agent-http-mgr.h"
21 #include "download-agent-http-misc.h"
22 #include "download-agent-http-msg-handler.h"
23 #include "download-agent-file.h"
24 #include "download-agent-plugin-conf.h"
25 #include "download-agent-plugin-http-interface.h"
27 da_result_t make_default_http_request_hdr(const char *url,
28 char **user_request_header,
29 int user_request_heaer_count,
30 http_msg_request_t **out_http_msg_request,
31 char *user_request_etag,
32 char *user_request_temp_file_path);
33 da_result_t create_resume_http_request_hdr(stage_info *stage,
34 http_msg_request_t **out_resume_request);
36 da_result_t start_new_transaction(stage_info *stage);
37 da_result_t set_http_request_hdr(stage_info *stage);
38 da_result_t make_transaction_info_and_start_transaction(stage_info *stage);
40 da_result_t pause_for_flow_control(stage_info *stage);
41 da_result_t unpause_for_flow_control(stage_info *stage);
43 da_result_t handle_any_input(stage_info *stage);
44 da_result_t handle_event_control(stage_info *stage, q_event_t *event);
45 da_result_t handle_event_http(stage_info *stage, q_event_t *event);
46 da_result_t handle_event_http_packet(stage_info *stage, q_event_t *event);
47 da_result_t handle_event_http_final(stage_info *stage, q_event_t *event);
48 da_result_t handle_event_http_abort(stage_info *stage, q_event_t *event);
50 da_result_t exchange_url_from_header_for_redirection(stage_info *stage,
51 http_msg_response_t *http_msg_response);
53 da_result_t handle_event_abort(stage_info *stage);
54 da_result_t handle_event_cancel(stage_info *stage);
55 da_result_t handle_event_suspend(stage_info *stage);
56 da_result_t handle_event_resume(stage_info *stage);
57 da_result_t handle_http_hdr(stage_info *stage,
58 http_msg_response_t *http_msg_response, int http_status);
59 da_result_t handle_http_status_code(stage_info *stage,
60 http_msg_response_t *http_msg_response, int http_status);
61 da_result_t handle_http_body(stage_info *stage, char *body, int body_len);
63 da_result_t set_hdr_fields_on_download_info(stage_info *stage);
65 da_result_t _check_content_type_is_matched(stage_info *stage);
66 da_result_t _check_enough_memory_for_this_download(stage_info *stage);
67 da_result_t _check_downloaded_file_size_is_same_with_header_content_size(
70 da_result_t _check_resume_download_is_available(stage_info *stage,
71 http_msg_response_t *new_http_msg_response);
72 da_result_t _check_this_partial_download_is_available(stage_info *stage,
73 http_msg_response_t *new_http_msg_response);
75 da_result_t _cancel_transaction(stage_info *stage);
76 da_result_t _disconnect_transaction(stage_info *stage);
78 void __parsing_user_request_header(char *user_request_header,
79 char **out_field, char **out_value);
83 da_result_t init_http_mgr(void)
85 da_result_t ret = DA_RESULT_OK;
87 DA_LOG_FUNC_START(HTTPManager);
89 if (http_mgr.is_http_init == DA_FALSE) {
90 http_mgr.is_http_init = DA_TRUE;
98 da_result_t request_to_abort_http_download(stage_info *stage)
100 da_result_t ret = DA_RESULT_OK;
101 q_event_t *q_event = DA_NULL;
103 DA_LOG_FUNC_START(HTTPManager);
105 DA_LOG_ERR(HTTPManager, "Stage is NULL. download info is already destroyed");
106 return DA_ERR_INVALID_ARGUMENT;
109 DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_ABORT");
110 ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_ABORT, &q_event);
111 if (ret != DA_RESULT_OK) {
112 DA_LOG_ERR(HTTPManager, "fail to make q_control_event");
115 DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage)));
116 Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), q_event);
123 void deinit_http_mgr(void)
125 DA_LOG_FUNC_START(HTTPManager);
127 if (http_mgr.is_http_init == DA_TRUE) {
128 http_mgr.is_http_init = DA_FALSE;
135 da_result_t request_http_download(stage_info *stage)
137 da_result_t ret = DA_RESULT_OK;
139 int slot_id = DA_INVALID_ID;
140 http_state_t http_state = 0;
141 da_bool_t need_wait = DA_TRUE;
143 queue_t *queue = DA_NULL;
144 req_dl_info *req_info = DA_NULL;
146 DA_LOG_FUNC_START(HTTPManager);
148 slot_id = GET_STAGE_DL_ID(stage);
149 queue = GET_DL_QUEUE(slot_id);
150 req_info = GET_STAGE_TRANSACTION_INFO(stage);
152 DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(slot_id));
154 CHANGE_HTTP_STATE(HTTP_STATE_READY_TO_DOWNLOAD, stage);
157 ret = handle_any_input(stage);
158 if (ret != DA_RESULT_OK) {
159 if (DA_RESULT_OK == GET_REQUEST_HTTP_RESULT(req_info)) {
160 GET_REQUEST_HTTP_RESULT(req_info) = ret;
161 DA_LOG_CRITICAL(HTTPManager, "setting internal error [%d]", ret);
163 _cancel_transaction(stage);
165 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
166 http_state = GET_HTTP_STATE_ON_STAGE(stage);
167 DA_LOG_VERBOSE(HTTPManager, "http_state = %d", http_state);
168 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
170 switch (http_state) {
171 case HTTP_STATE_READY_TO_DOWNLOAD:
172 ret = start_new_transaction(stage);
173 if (ret != DA_RESULT_OK) {
174 if (DA_RESULT_OK == GET_REQUEST_HTTP_RESULT(req_info)) {
175 GET_REQUEST_HTTP_RESULT(req_info) = ret;
176 DA_LOG_CRITICAL(HTTPManager, "setting internal error [%d]", ret);
178 DA_LOG(HTTPManager, "exiting with error...");
179 need_wait = DA_FALSE;
183 CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_REQUESTED, stage);
186 case HTTP_STATE_CANCELED:
187 case HTTP_STATE_DOWNLOAD_FINISH:
188 case HTTP_STATE_ABORTED:
190 case HTTP_STATE_PAUSED:
192 DA_LOG(HTTPManager, "exiting...");
193 need_wait = DA_FALSE;
200 if (need_wait == DA_TRUE) {
201 _da_thread_mutex_lock(&(queue->mutex_queue));
202 if (DA_FALSE == GET_IS_Q_HAVING_DATA(queue)) {
203 unpause_for_flow_control(stage);
205 // DA_LOG(HTTPManager, "Waiting for input");
207 // DA_LOG(HTTPManager, "Woke up to receive new packet or control event");
209 _da_thread_mutex_unlock (&(queue->mutex_queue));
213 } while (need_wait == DA_TRUE);
215 ret = GET_REQUEST_HTTP_RESULT(req_info);
216 DA_LOG(HTTPManager, "--------------Exiting request_http_download! ret = %d", ret);
220 da_result_t request_to_cancel_http_download(stage_info *stage)
222 da_result_t ret = DA_RESULT_OK;
223 q_event_t *q_event = DA_NULL;
225 DA_LOG_FUNC_START(HTTPManager);
227 DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_CANCEL");
228 ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_CANCEL, &q_event);
229 if (ret != DA_RESULT_OK) {
230 DA_LOG_ERR(HTTPManager, "fail to make q_control_event");
233 DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage)));
234 Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), q_event);
241 da_result_t request_to_suspend_http_download(stage_info *stage)
243 da_result_t ret = DA_RESULT_OK;
244 http_state_t http_state = 0;
245 q_event_t *q_event = DA_NULL;
247 DA_LOG_FUNC_START(HTTPManager);
249 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
250 http_state = GET_HTTP_STATE_ON_STAGE(stage);
251 DA_LOG(HTTPManager, "http_state = %d", http_state);
252 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
254 switch (http_state) {
255 case HTTP_STATE_PAUSED:
256 case HTTP_STATE_REQUEST_PAUSE:
257 DA_LOG_CRITICAL(HTTPManager, "Already paused. http_state = %d", http_state);
258 ret = DA_ERR_ALREADY_SUSPENDED;
262 DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_SUSPEND");
263 ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_SUSPEND,
265 if (ret != DA_RESULT_OK) {
266 DA_LOG_ERR(HTTPManager, "fail to make q_control_event");
269 DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage)));
270 Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)),
281 da_result_t request_to_resume_http_download(stage_info *stage)
283 da_result_t ret = DA_RESULT_OK;
284 http_state_t http_state = 0;
285 q_event_t *q_event = DA_NULL;
287 DA_LOG_FUNC_START(HTTPManager);
289 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
290 http_state = GET_HTTP_STATE_ON_STAGE(stage);
291 DA_LOG(HTTPManager, "[%d] http_state = %d", GET_STAGE_DL_ID(stage), http_state);
292 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
294 switch (http_state) {
295 case HTTP_STATE_PAUSED:
296 DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_RESUME");
297 ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_RESUME,
299 if (ret != DA_RESULT_OK) {
300 DA_LOG_ERR(HTTPManager, "fail to make q_control_event");
303 DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage)));
304 Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)),
310 case HTTP_STATE_REQUEST_PAUSE:
311 DA_LOG_ERR(HTTPManager, "[%d] Fail to resume. Previous pause is not finished. http_state = %d", GET_STAGE_DL_ID(stage), http_state);
312 ret = DA_ERR_INVALID_STATE;
316 case HTTP_STATE_RESUMED:
317 ret = DA_ERR_ALREADY_RESUMED;
322 DA_LOG_ERR(HTTPManager, "[%d] Fail to resume. This is not a paused ID. http_state = %d", GET_STAGE_DL_ID(stage), http_state);
323 ret = DA_ERR_INVALID_STATE;
332 da_result_t start_new_transaction(stage_info *stage)
334 da_result_t ret = DA_RESULT_OK;
336 ret = set_http_request_hdr(stage);
337 if (ret != DA_RESULT_OK)
340 ret = make_transaction_info_and_start_transaction(stage);
344 da_result_t make_default_http_request_hdr(const char *url,
345 char **user_request_header,
346 int user_request_header_count,
347 http_msg_request_t **out_http_msg_request,
348 char *user_request_etag,
349 char *user_request_temp_file_path)
351 da_result_t ret = DA_RESULT_OK;
353 http_msg_request_t *http_msg_request = NULL;
354 char *user_agent = NULL;
356 DA_LOG_FUNC_START(HTTPManager);
359 DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL");
360 ret = DA_ERR_INVALID_URL;
364 ret = http_msg_request_create(&http_msg_request);
365 if (ret != DA_RESULT_OK)
368 ret = http_msg_request_set_url(http_msg_request, url);
369 if (ret != DA_RESULT_OK)
372 user_agent = get_user_agent();
374 http_msg_request_add_field(http_msg_request, HTTP_FIELD_UAGENT,
377 http_msg_request_add_field(http_msg_request, HTTP_FIELD_ACCEPT_LANGUAGE, "en");
378 http_msg_request_add_field(http_msg_request, HTTP_FIELD_ACCEPT_CHARSET, "utf-8");
380 if (user_request_header && user_request_header_count > 0) {
382 for (i = 0; i < user_request_header_count; i++)
386 __parsing_user_request_header(user_request_header[i],
388 if (field && value) {
389 http_msg_request_add_field(http_msg_request, field, value);
407 DA_LOG_ERR(HTTPManager, "Fail to parse user request header");
411 DA_LOG(HTTPManager, "no user reqeust header inserted");
413 if (user_request_etag) {
414 char buff[64] = {0,};
415 unsigned long long size = 0;
416 http_msg_request_add_field(http_msg_request,
417 HTTP_FIELD_IF_RANGE, user_request_etag);
418 get_file_size(user_request_temp_file_path, &size);
419 snprintf(buff, sizeof(buff)-1, "bytes=%llu-", size);
420 http_msg_request_add_field(http_msg_request,
421 HTTP_FIELD_RANGE, buff);
424 *out_http_msg_request = http_msg_request;
427 if (ret != DA_RESULT_OK)
428 http_msg_request_destroy(&http_msg_request);
434 da_result_t set_http_request_hdr(stage_info *stage)
436 da_result_t ret = DA_RESULT_OK;
437 req_dl_info *request_info = DA_NULL;
440 char **user_request_header = DA_NULL;
441 int user_request_header_count = 0;
442 char *user_request_etag = DA_NULL;
443 char *user_request_temp_file_path = DA_NULL;
444 http_msg_request_t* http_msg_request = NULL;
446 DA_LOG_FUNC_START(HTTPManager);
448 request_info = GET_STAGE_TRANSACTION_INFO(stage);
451 (url = GET_REQUEST_HTTP_REQ_URL(request_info))) {
452 DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL");
453 ret = DA_ERR_INVALID_URL;
457 user_request_header = GET_REQUEST_HTTP_USER_REQUEST_HEADER(
459 user_request_header_count = GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT(
461 user_request_etag = GET_REQUEST_HTTP_USER_REQUEST_ETAG(
463 user_request_temp_file_path = GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(
465 if (user_request_etag) {
466 DA_LOG(HTTPManager, "user_request_etag[%s]",user_request_etag);
468 DA_LOG_ERR(HTTPManager, "user_request_etag is NULL");
470 ret = make_default_http_request_hdr(url, user_request_header,
471 user_request_header_count, &http_msg_request,
472 user_request_etag, user_request_temp_file_path);
473 if (ret == DA_RESULT_OK)
474 request_info->http_info.http_msg_request = http_msg_request;
481 da_result_t make_transaction_info_and_start_transaction(stage_info *stage)
483 da_result_t ret = DA_RESULT_OK;
485 int slot_id = DA_INVALID_ID;
486 req_dl_info *request_info = DA_NULL;
488 input_for_tranx_t *input_for_tranx = DA_NULL;
490 DA_LOG_FUNC_START(HTTPManager);
492 slot_id = GET_STAGE_DL_ID(stage);
494 request_info = GET_STAGE_TRANSACTION_INFO(stage);
496 if (GET_REQUEST_HTTP_REQ_URL(request_info) == DA_NULL) {
497 DA_LOG_ERR(HTTPManager, "url is NULL");
498 ret = DA_ERR_INVALID_URL;
502 input_for_tranx = (input_for_tranx_t*) calloc(1,
503 sizeof(input_for_tranx_t));
504 if (input_for_tranx == DA_NULL) {
505 ret = DA_ERR_FAIL_TO_MEMALLOC;
508 input_for_tranx->proxy_addr = get_proxy_address();
509 input_for_tranx->queue = GET_DL_QUEUE(slot_id);
511 input_for_tranx->http_method = PI_HTTP_METHOD_GET;
512 input_for_tranx->http_msg_request
513 = request_info->http_info.http_msg_request;
516 ret = PI_http_start_transaction(input_for_tranx,
517 &(GET_REQUEST_HTTP_TRANS_ID(request_info)));
518 if (ret != DA_RESULT_OK)
522 if (input_for_tranx) {
523 free(input_for_tranx);
524 input_for_tranx = DA_NULL;
530 da_result_t make_req_dl_info_http(stage_info *stage, req_dl_info *out_info)
533 char **user_request_header = DA_NULL;
534 int user_request_header_count = 0;
535 char *user_request_etag = DA_NULL;
536 char *user_request_temp_file_path = DA_NULL;
538 source_info_t *source_info = DA_NULL;
540 DA_LOG_FUNC_START(HTTPManager);
543 DA_LOG_ERR(HTTPManager, "stage is NULL");
544 return DA_ERR_INVALID_ARGUMENT;
547 source_info = GET_STAGE_SOURCE_INFO(stage);
549 url = source_info->source_info_type.source_info_basic->url;
550 user_request_header =
551 source_info->source_info_type.source_info_basic->user_request_header;
552 user_request_header_count =
553 source_info->source_info_type.source_info_basic->user_request_header_count;
554 dl_id = source_info->source_info_type.source_info_basic->dl_id;
555 user_request_etag = GET_DL_USER_ETAG(GET_STAGE_DL_ID(stage));
556 user_request_temp_file_path = GET_DL_USER_TEMP_FILE_PATH(GET_STAGE_DL_ID(stage));
558 DA_LOG(HTTPManager, "url [%s]", url);
561 GET_REQUEST_HTTP_REQ_URL(out_info) = url;
562 GET_REQUEST_HTTP_USER_REQUEST_HEADER(out_info) = user_request_header;
563 GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT(out_info) =
564 user_request_header_count;
565 GET_REQUEST_HTTP_USER_REQUEST_ETAG(out_info) =
567 GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(out_info) =
568 user_request_temp_file_path;
570 DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL");
571 return DA_ERR_INVALID_URL;
574 _da_thread_mutex_init(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)), NULL);
579 da_result_t pause_for_flow_control(stage_info *stage)
584 da_result_t unpause_for_flow_control(stage_info *stage)
586 da_result_t ret = DA_RESULT_OK;
588 // DA_LOG_FUNC_START(HTTPManager);
590 PI_http_unpause_transaction(
591 GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)));
594 da_result_t handle_event_abort(stage_info *stage)
596 da_result_t ret = DA_RESULT_OK;
597 http_state_t state = 0;
599 DA_LOG_FUNC_START(HTTPManager);
601 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
602 state = GET_HTTP_STATE_ON_STAGE(stage);
603 DA_LOG(HTTPManager, "http_state = %d", state);
604 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
606 case HTTP_STATE_READY_TO_DOWNLOAD:
607 case HTTP_STATE_REDIRECTED:
608 case HTTP_STATE_DOWNLOAD_REQUESTED:
609 case HTTP_STATE_DOWNLOAD_STARTED:
610 case HTTP_STATE_DOWNLOADING:
611 case HTTP_STATE_REQUEST_CANCEL:
612 case HTTP_STATE_REQUEST_PAUSE:
613 case HTTP_STATE_REQUEST_RESUME:
614 case HTTP_STATE_CANCELED:
615 case HTTP_STATE_PAUSED:
616 case HTTP_STATE_RESUMED:
617 case HTTP_STATE_ABORTED:
618 /* IF the network session is terminated due to some error,
619 * the state can be aborted.(data aborted case) */
620 CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage);
621 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_ABORTED, stage);
622 _disconnect_transaction(stage);
624 case HTTP_STATE_DOWNLOAD_FINISH:
627 DA_LOG_ERR(HTTPManager, "have to check the flow for this case");
633 da_result_t handle_event_cancel(stage_info *stage)
635 da_result_t ret = DA_RESULT_OK;
636 http_state_t state = 0;
638 DA_LOG_FUNC_START(HTTPManager);
640 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
641 state = GET_HTTP_STATE_ON_STAGE(stage);
642 DA_LOG(HTTPManager, "http_state = %d", state);
643 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
645 case HTTP_STATE_READY_TO_DOWNLOAD:
646 CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage);
647 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage);
650 case HTTP_STATE_PAUSED:
651 discard_download(stage);
652 CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage);
653 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage);
656 case HTTP_STATE_DOWNLOAD_REQUESTED:
657 case HTTP_STATE_DOWNLOAD_STARTED:
658 case HTTP_STATE_DOWNLOADING:
659 case HTTP_STATE_REQUEST_RESUME:
660 case HTTP_STATE_RESUMED:
661 _cancel_transaction(stage);
662 CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_CANCEL, stage);
665 case HTTP_STATE_DOWNLOAD_FINISH:
668 case HTTP_STATE_REQUEST_CANCEL:
669 DA_LOG(HTTPManager, "HTTP_STATE_REQUEST_CANCEL : cancel is already in progress... ");
673 DA_LOG_ERR(HTTPManager, "have to check the flow for this case");
680 da_result_t handle_event_suspend(stage_info *stage)
682 da_result_t ret = DA_RESULT_OK;
683 http_state_t http_state = 0;
685 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
686 http_state = GET_HTTP_STATE_ON_STAGE(stage);
687 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
689 switch (http_state) {
690 case HTTP_STATE_REQUEST_PAUSE:
691 DA_LOG(HTTPManager, "already requested to pause! do nothing");
694 case HTTP_STATE_READY_TO_DOWNLOAD:
695 CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage);
696 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage);
697 send_client_paused_info(GET_STAGE_DL_ID(stage));
701 //send_client_paused_info(GET_STAGE_DL_ID(stage));
702 _cancel_transaction(stage);
703 GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) = DA_RESULT_OK;
704 DA_LOG_CRITICAL(HTTPManager, "[%d] cleanup internal error", GET_STAGE_DL_ID(stage));
705 CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_PAUSE,stage);
712 da_result_t handle_event_resume(stage_info *stage)
714 da_result_t ret = DA_RESULT_OK;
715 http_msg_request_t *resume_request = NULL;
717 http_state_t http_state = 0;
719 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
720 http_state = GET_HTTP_STATE_ON_STAGE(stage);
721 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
723 if (http_state != HTTP_STATE_PAUSED) {
724 DA_LOG_ERR(HTTPManager, "Not HTTP_STATE_PAUSED! http_state = %d", http_state);
725 ret = DA_ERR_INVALID_STATE;
729 GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) = DA_RESULT_OK;
730 DA_LOG_CRITICAL(HTTPManager, "[%d] cleanup internal error", GET_STAGE_DL_ID(stage));
732 CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_RESUME,stage);
733 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage);
735 ret = create_resume_http_request_hdr(stage, &resume_request);
736 if (ret != DA_RESULT_OK)
739 if (GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request)
740 free(GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request);
742 GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request
745 make_transaction_info_and_start_transaction(stage);
752 da_result_t create_resume_http_request_hdr(stage_info *stage,
753 http_msg_request_t **out_resume_request)
755 da_result_t ret = DA_RESULT_OK;
756 da_bool_t b_ret = DA_FALSE;
758 req_dl_info *request_info = NULL;
760 http_msg_response_t *first_response = NULL;
761 http_msg_request_t *resume_request = NULL;
765 unsigned int downloaded_data_size = 0;
766 char downloaded_data_size_to_str[32] = { 0, };
768 char *etag_from_response = NULL;
769 char *date_from_response = NULL;
771 DA_LOG_FUNC_START(HTTPManager);
773 request_info = GET_STAGE_TRANSACTION_INFO(stage);
775 if (!(url = GET_REQUEST_HTTP_REQ_URL(GET_STAGE_TRANSACTION_INFO(stage)))) {
776 DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL");
777 ret = DA_ERR_INVALID_URL;
781 first_response = request_info->http_info.http_msg_response;
782 if (first_response) {
783 b_ret = http_msg_response_get_ETag(first_response, &value);
785 etag_from_response = value;
787 DA_LOG(HTTPManager, "[ETag][%s]", etag_from_response);
790 b_ret = http_msg_response_get_date(first_response, &value);
792 date_from_response = value;
794 DA_LOG(HTTPManager, "[Date][%s]", date_from_response);
798 = GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage));
799 DA_LOG(HTTPManager, "downloaded_data_size = %u", downloaded_data_size);
800 snprintf(downloaded_data_size_to_str, sizeof(downloaded_data_size_to_str), "bytes=%u-",
801 downloaded_data_size);
802 DA_LOG(HTTPManager, "downloaded_data_size_to_str = %s", downloaded_data_size_to_str);
805 ret = make_default_http_request_hdr(url, NULL, 0, &resume_request, NULL, NULL);
806 if (ret != DA_RESULT_OK)
809 if (etag_from_response) {
810 http_msg_request_add_field(resume_request, HTTP_FIELD_IF_RANGE,
813 if (date_from_response) {
814 http_msg_request_add_field(resume_request,
815 HTTP_FIELD_IF_RANGE, date_from_response);
819 if (strlen(downloaded_data_size_to_str) > 0)
820 http_msg_request_add_field(resume_request, HTTP_FIELD_RANGE,
821 downloaded_data_size_to_str);
823 *out_resume_request = resume_request;
826 if (etag_from_response) {
827 free(etag_from_response);
828 etag_from_response = NULL;
831 if (date_from_response) {
832 free(date_from_response);
833 date_from_response = NULL;
839 da_result_t handle_any_input(stage_info *stage)
841 da_result_t ret = DA_RESULT_OK;
843 int slot_id = GET_STAGE_DL_ID(stage);
845 queue_t *queue = DA_NULL;
846 q_event_t *event = DA_NULL;
848 // DA_LOG_FUNC_START(HTTPManager);
850 queue = GET_DL_QUEUE(slot_id);
852 Q_pop_event(queue, &event);
853 if (event == DA_NULL) {
854 DA_LOG(HTTPManager, "There is no data on the queue!");
858 switch (event->event_type) {
859 case Q_EVENT_TYPE_CONTROL:
860 ret = handle_event_control(stage, event);
863 case Q_EVENT_TYPE_DATA_HTTP:
864 ret = handle_event_http(stage, event);
867 case Q_EVENT_TYPE_DATA_DRM:
873 Q_destroy_q_event(&event);
878 da_result_t handle_event_control(stage_info *stage, q_event_t *event)
880 da_result_t ret = DA_RESULT_OK;
882 DA_LOG_FUNC_START(HTTPManager);
884 if (event->event_type == Q_EVENT_TYPE_CONTROL) {
885 switch (event->type.q_event_control.control_type) {
886 case Q_EVENT_TYPE_CONTROL_CANCEL:
887 DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_CANCEL");
888 ret = handle_event_cancel(stage);
891 case Q_EVENT_TYPE_CONTROL_SUSPEND:
892 DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_SUSPEND");
893 ret = handle_event_suspend(stage);
896 case Q_EVENT_TYPE_CONTROL_RESUME:
897 DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_RESUME");
898 ret = handle_event_resume(stage);
900 case Q_EVENT_TYPE_CONTROL_ABORT:
901 DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_ABORT");
902 ret = handle_event_abort(stage);
904 /* Fixme: need to think how we use this type. For now, this type is not used. */
905 case Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED:
906 DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED");
914 da_result_t handle_event_http(stage_info *stage, q_event_t *event)
916 da_result_t ret = DA_RESULT_OK;
917 q_event_data_http_t *q_event_data_http = DA_NULL;
919 // DA_LOG_FUNC_START(HTTPManager);
921 if (event->event_type == Q_EVENT_TYPE_DATA_HTTP) {
922 q_event_data_http = &(event->type.q_event_data_http);
923 switch (q_event_data_http->data_type) {
924 case Q_EVENT_TYPE_DATA_PACKET:
925 ret = handle_event_http_packet(stage, event);
929 case Q_EVENT_TYPE_DATA_FINAL:
930 DA_LOG(HTTPManager, "Q_EVENT_TYPE_DATA_FINAL");
931 ret = handle_event_http_final(stage, event);
935 case Q_EVENT_TYPE_DATA_ABORT:
936 DA_LOG(HTTPManager, "Q_EVENT_TYPE_DATA_ABORT");
937 ret = handle_event_http_abort(stage, event);
945 da_result_t handle_event_http_packet(stage_info *stage, q_event_t *event)
947 da_result_t ret = DA_RESULT_OK;
948 da_bool_t is_handle_hdr_success = DA_TRUE;
949 q_event_data_http_t *received_data = DA_NULL;
951 // DA_LOG_FUNC_START(HTTPManager);
953 received_data = &(event->type.q_event_data_http);
955 if (received_data->http_response_msg) {
956 ret = handle_http_hdr(stage, received_data->http_response_msg,
957 received_data->http_response_msg->status_code);
958 if (DA_RESULT_OK != ret) {
959 is_handle_hdr_success = DA_FALSE;
962 received_data->http_response_msg = NULL;
965 if (received_data->body_len > 0) {
966 if (is_handle_hdr_success == DA_TRUE) {
967 ret = handle_http_body(stage, received_data->body_data,
968 received_data->body_len);
970 /*For all cases body_data should be deleted*/
971 free(received_data->body_data);
972 received_data->body_data = DA_NULL;
977 da_result_t handle_event_http_final(stage_info *stage, q_event_t *event)
979 da_result_t ret = DA_RESULT_OK;
981 http_state_t http_state = 0;
982 int slot_id = DA_INVALID_ID;
984 DA_LOG_FUNC_START(HTTPManager);
986 slot_id = GET_STAGE_DL_ID(stage);
987 _disconnect_transaction(stage);
989 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
990 http_state = GET_HTTP_STATE_ON_STAGE(stage);
991 DA_LOG(HTTPManager, "http_state = %d", http_state);
992 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
994 switch (http_state) {
995 case HTTP_STATE_REDIRECTED:
996 CHANGE_HTTP_STATE(HTTP_STATE_READY_TO_DOWNLOAD,stage);
999 case HTTP_STATE_DOWNLOAD_REQUESTED:
1000 DA_LOG(HTTPManager, "case HTTP_STATE_DOWNLOAD_REQUESTED");
1001 CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage);
1004 case HTTP_STATE_DOWNLOADING:
1005 DA_LOG(HTTPManager, "case HTTP_STATE_DOWNLOADING");
1006 ret = file_write_complete(stage);
1007 if (ret != DA_RESULT_OK) {
1008 discard_download(stage);
1011 /* ret = _check_downloaded_file_size_is_same_with_header_content_size(stage);
1012 if(ret != DA_RESULT_OK)
1014 discard_download(stage) ;
1018 CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage);
1019 send_client_update_progress_info(
1022 GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage))
1026 case HTTP_STATE_REQUEST_PAUSE:
1027 if (GET_CONTENT_STORE_FILE_HANDLE(GET_STAGE_CONTENT_STORE_INFO(stage))) {
1028 ret = file_write_complete(stage);
1029 send_client_update_progress_info(
1032 GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage))
1035 IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage))
1038 CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage);
1039 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage);
1040 send_client_paused_info(GET_STAGE_DL_ID(stage));
1041 DA_LOG(HTTPManager, "Server Notification code is set to NULL");
1044 case HTTP_STATE_ABORTED:
1045 case HTTP_STATE_CANCELED:
1046 discard_download(stage);
1049 case HTTP_STATE_REQUEST_CANCEL:
1050 ret = file_write_complete(stage);
1051 if (ret != DA_RESULT_OK)
1053 discard_download(stage);
1054 CHANGE_HTTP_STATE(HTTP_STATE_CANCELED, stage);
1055 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage);
1059 ret = file_write_complete(stage);
1060 if (ret != DA_RESULT_OK)
1062 discard_download(stage);
1063 CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage);
1068 /* When file complete is failed */
1069 if (DA_RESULT_OK != ret) {
1070 CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage);
1075 da_result_t handle_event_http_abort(stage_info *stage, q_event_t *event)
1077 da_result_t ret = DA_RESULT_OK;
1078 http_state_t http_state = 0;
1079 DA_LOG_FUNC_START(HTTPManager);
1081 GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))
1082 = event->type.q_event_data_http.error_type;
1083 DA_LOG_CRITICAL(HTTPManager, "set internal error code : [%d]", GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)));
1084 _disconnect_transaction(stage);
1086 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1087 http_state = GET_HTTP_STATE_ON_STAGE(stage);
1088 DA_LOG(HTTPManager, "http_state = %d", http_state);
1089 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1091 switch (http_state) {
1092 case HTTP_STATE_REQUEST_PAUSE:
1093 CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage);
1094 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage);
1095 send_client_paused_info(GET_STAGE_DL_ID(stage));
1096 ret = file_write_complete(stage);
1097 if (ret != DA_RESULT_OK)
1101 case HTTP_STATE_REQUEST_CANCEL:
1102 CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage);
1103 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage);
1104 ret = file_write_complete(stage);
1105 if (ret != DA_RESULT_OK)
1107 discard_download(stage);
1111 CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage);
1112 ret = file_write_complete(stage);
1113 if (ret != DA_RESULT_OK)
1115 discard_download(stage);
1122 da_result_t handle_http_hdr(stage_info *stage,
1123 http_msg_response_t *http_msg_response, int http_status)
1125 da_result_t ret = DA_RESULT_OK;
1126 int slot_id = DA_INVALID_ID;
1127 http_state_t http_state = 0;
1129 DA_LOG_FUNC_START(HTTPManager);
1131 slot_id = GET_STAGE_DL_ID(stage);
1133 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1134 http_state = GET_HTTP_STATE_ON_STAGE(stage);
1135 DA_LOG(HTTPManager, "http_state = %d", http_state);
1136 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1138 switch (http_state) {
1139 case HTTP_STATE_DOWNLOAD_REQUESTED:
1140 case HTTP_STATE_REQUEST_PAUSE:
1141 case HTTP_STATE_REQUEST_RESUME:
1142 case HTTP_STATE_REDIRECTED:
1143 ret = handle_http_status_code(stage, http_msg_response,
1145 if (ret != DA_RESULT_OK)
1149 case HTTP_STATE_REQUEST_CANCEL:
1150 DA_LOG(HTTPManager, "Cancel is in progress.. http_state = %d", http_state);
1154 DA_LOG_ERR(HTTPManager, "http_state = %d", http_state);
1162 da_result_t handle_http_status_code(stage_info *stage,
1163 http_msg_response_t *http_msg_response, int http_status)
1165 da_result_t ret = DA_RESULT_OK;
1167 int slot_id = DA_INVALID_ID;
1168 req_dl_info *request_info = DA_NULL;
1169 http_state_t http_state = 0;
1171 DA_LOG_FUNC_START(HTTPManager);
1173 slot_id = GET_STAGE_DL_ID(stage);
1174 request_info = GET_STAGE_TRANSACTION_INFO(stage);
1176 GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_response
1177 = http_msg_response;
1179 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1180 http_state = GET_HTTP_STATE_ON_STAGE(stage);
1181 DA_LOG(HTTPManager, "http_state = %d", http_state);
1182 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1184 store_http_status(slot_id, http_status);
1186 switch (http_status) {
1191 if (http_state == HTTP_STATE_REQUEST_RESUME)
1192 clean_paused_file(stage);
1193 ret = set_hdr_fields_on_download_info(stage);
1194 if (ret != DA_RESULT_OK)
1196 ret = _check_content_type_is_matched(stage);
1197 if (ret != DA_RESULT_OK)
1199 ret = _check_enough_memory_for_this_download(stage);
1200 if (ret != DA_RESULT_OK)
1202 CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_STARTED,stage);
1203 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); // ?
1207 DA_LOG(HTTPManager, "HTTP Status is %d - Partial download for resume!",http_status);
1208 /* The resume can be started with start API.
1209 * So the state should be not HTTP_STATE_RESUME_REQUESTED but HTTP_STATE_DOWNLOAD_REQUESTED*/
1210 if (http_state == HTTP_STATE_DOWNLOAD_REQUESTED) {
1211 ret = _check_resume_download_is_available(stage,
1213 if (ret != DA_RESULT_OK)
1215 CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_STARTED,stage);
1217 } else if (http_state == HTTP_STATE_REQUEST_RESUME) {
1218 ret = _check_this_partial_download_is_available(stage,
1220 if (ret != DA_RESULT_OK)
1222 CHANGE_HTTP_STATE(HTTP_STATE_RESUMED,stage);
1224 DA_LOG_ERR(HTTPManager, "This download is not resumed, revoke");
1225 ret = DA_ERR_INVALID_STATE;
1228 CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage);
1238 DA_LOG(HTTPManager, "HTTP Status is %d - redirection!",http_status);
1239 ret = exchange_url_from_header_for_redirection(stage, http_msg_response);
1240 if (ret != DA_RESULT_OK)
1242 CHANGE_HTTP_STATE(HTTP_STATE_REDIRECTED,stage);
1243 http_msg_response_destroy(&http_msg_response);
1251 DA_LOG(HTTPManager, "HTTP Status is %d - 204 means server got the request, but no content to reply back, 304 means not modified!",http_status);
1252 ret = DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT;
1255 case 416: // Requested range not satisfiable
1259 GET_REQUEST_HTTP_RESULT(request_info)
1260 = DA_ERR_UNREACHABLE_SERVER;
1261 DA_LOG_CRITICAL(HTTPManager, "set internal error code : DA_ERR_UNREACHABLE_SERVER [%d]", DA_ERR_UNREACHABLE_SERVER);
1269 da_result_t exchange_url_from_header_for_redirection(stage_info *stage,
1270 http_msg_response_t *http_msg_response)
1272 da_result_t ret = DA_RESULT_OK;
1273 char *location = DA_NULL;
1275 DA_LOG_FUNC_START(HTTPManager);
1277 if (http_msg_response_get_location(http_msg_response, &location)) {
1278 DA_LOG(HTTPManager, "location = %s\n", location);
1279 GET_REQUEST_HTTP_REQ_LOCATION(GET_STAGE_TRANSACTION_INFO(stage)) = location;
1285 da_result_t handle_http_body(stage_info *stage, char *body, int body_len)
1287 da_result_t ret = DA_RESULT_OK;
1288 http_state_t http_state = 0;
1289 int slot_id = DA_INVALID_ID;
1291 // DA_LOG_FUNC_START(HTTPManager);
1293 slot_id = GET_STAGE_DL_ID(stage);
1296 != GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))) {
1297 DA_LOG_CRITICAL(HTTPManager, "ignore because internal error code is set with [%d]",
1298 GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)));
1302 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1303 http_state = GET_HTTP_STATE_ON_STAGE(stage);
1304 // DA_LOG(HTTPManager, "http_state = %d", http_state);
1305 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1307 if (http_state == HTTP_STATE_DOWNLOAD_STARTED) {
1309 if (GET_REQUEST_HTTP_USER_REQUEST_ETAG(GET_STAGE_TRANSACTION_INFO(stage)))
1310 ret = start_file_writing_append_with_new_download(stage);
1312 ret = start_file_writing(stage);
1313 if (DA_RESULT_OK != ret)
1316 CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOADING, stage);
1317 send_client_update_dl_info(
1320 GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)),
1321 GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)),
1322 GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)),
1323 GET_CONTENT_STORE_PURE_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)),
1324 GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage)),
1325 GET_CONTENT_STORE_EXTENSION(GET_STAGE_CONTENT_STORE_INFO(stage))
1327 } else if (http_state == HTTP_STATE_RESUMED) {
1328 ret = start_file_writing_append(stage);
1329 if (DA_RESULT_OK != ret)
1332 CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOADING,stage);
1333 send_client_update_dl_info(
1336 GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)),
1337 GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)),
1338 GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)),
1339 GET_CONTENT_STORE_PURE_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)),
1340 GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage)),
1341 GET_CONTENT_STORE_EXTENSION(GET_STAGE_CONTENT_STORE_INFO(stage))
1345 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1346 http_state = GET_HTTP_STATE_ON_STAGE(stage);
1347 // DA_LOG(HTTPManager, "http_state = %d", http_state);
1348 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1350 switch (http_state) {
1351 case HTTP_STATE_REDIRECTED:
1352 DA_LOG(HTTPManager, "Just ignore http body, because this body is not for redirection one.");
1355 case HTTP_STATE_DOWNLOADING:
1356 /* Should this function before updating download info
1357 * Because it extract mime type at once only if first download updating at client */
1358 ret = file_write_ongoing(stage, body, body_len);
1359 if (ret != DA_RESULT_OK)
1362 IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)))) {
1363 send_client_update_progress_info(
1366 GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage))
1369 IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage))
1374 case HTTP_STATE_REQUEST_PAUSE:
1375 ret = file_write_ongoing(stage, body, body_len);
1376 if (ret != DA_RESULT_OK)
1381 DA_LOG(HTTPManager, "Do nothing! http_state is in case %d", http_state);
1390 /* Function should be renamed , as it is actually not setting the header fields in download info */
1391 da_result_t set_hdr_fields_on_download_info(stage_info *stage)
1393 da_result_t ret = DA_RESULT_OK;
1394 da_bool_t b_ret = DA_FALSE;
1396 req_dl_info *request_info = DA_NULL;
1397 http_msg_response_t *http_msg_response = NULL;
1400 unsigned long long size = 0;
1402 DA_LOG_FUNC_START(HTTPManager);
1404 request_info = GET_STAGE_TRANSACTION_INFO(stage);
1407 = request_info->http_info.http_msg_response;
1408 if (!http_msg_response) {
1409 DA_LOG_ERR(HTTPManager, "There is no header data!!");
1410 ret = DA_ERR_INVALID_ARGUMENT;
1414 b_ret = http_msg_response_get_content_type(http_msg_response, &value);
1416 GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info) = value;
1418 DA_LOG_VERBOSE(HTTPManager, "[Content-Type][%s] - stored", GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info));
1421 b_ret = http_msg_response_get_content_length(http_msg_response,
1424 GET_REQUEST_HTTP_HDR_CONT_LEN(request_info) = size;
1426 DA_LOG_VERBOSE(HTTPManager, "[Content-Length][%d] - stored", GET_REQUEST_HTTP_HDR_CONT_LEN(request_info));
1429 b_ret = http_msg_response_get_ETag(http_msg_response, &value);
1431 GET_REQUEST_HTTP_HDR_ETAG(request_info) = value;
1433 DA_LOG_VERBOSE(HTTPManager, "[ETag][%s] - stored ", GET_REQUEST_HTTP_HDR_ETAG(request_info));
1440 da_result_t _check_content_type_is_matched(stage_info *stage)
1442 da_result_t ret = DA_RESULT_OK;
1443 req_dl_info *request_info = DA_NULL;
1444 source_info_t *source_info = DA_NULL;
1445 char *content_type_from_server = DA_NULL;
1447 DA_LOG_FUNC_START(HTTPManager);
1449 request_info = GET_STAGE_TRANSACTION_INFO(stage);
1450 source_info = GET_STAGE_SOURCE_INFO(stage);
1452 content_type_from_server = GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info);
1453 if (content_type_from_server == DA_NULL) {
1454 DA_LOG(HTTPManager, "http header has no Content-Type field, no need to compare");
1455 return DA_RESULT_OK;
1461 da_result_t _check_enough_memory_for_this_download(stage_info *stage)
1463 da_result_t ret = DA_RESULT_OK;
1465 req_dl_info *request_info = DA_NULL;
1467 long long cont_len = 0;
1468 da_storage_size_t memory;
1470 DA_LOG_FUNC_START(HTTPManager);
1472 memset(&memory, 0x00, sizeof(da_storage_size_t));
1473 request_info = GET_STAGE_TRANSACTION_INFO(stage);
1475 cont_len = (long long) GET_REQUEST_HTTP_HDR_CONT_LEN(request_info);
1477 ret = get_available_memory(DA_STORAGE_PHONE, &memory);
1478 if (DA_RESULT_OK == ret) {
1479 DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %llu",memory.b_available,memory.b_size, cont_len);
1480 if (memory.b_available < ((cont_len
1481 + SAVE_FILE_BUFFERING_SIZE_50KB)
1482 / memory.b_size)) /* 50KB buffering */
1484 ret = DA_ERR_DISK_FULL;
1494 da_result_t _check_this_partial_download_is_available(stage_info *stage,
1495 http_msg_response_t *new_http_msg_response)
1497 da_result_t ret = DA_RESULT_OK;
1498 da_bool_t b_ret = DA_FALSE;
1499 char *origin_ETag = NULL;
1500 char *new_ETag = NULL;
1501 unsigned long long remained_content_len = 0;
1502 da_storage_size_t memory;
1504 unsigned long long size = 0;
1506 DA_LOG_FUNC_START(HTTPManager);
1509 = GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage));
1511 b_ret = http_msg_response_get_content_length(new_http_msg_response,
1514 remained_content_len = size;
1516 DA_LOG(HTTPManager, "[remained_content_len][%lu]", remained_content_len);
1519 b_ret = http_msg_response_get_ETag(new_http_msg_response, &value);
1523 DA_LOG(HTTPManager, "[new ETag][%s]", new_ETag);
1528 if (origin_ETag && new_ETag &&
1529 0 != strncmp(origin_ETag, new_ETag, strlen(new_ETag))) {
1530 DA_LOG_ERR(HTTPManager, "ETag is not identical! revoke!");
1531 /* FIXME Later : Need to detail error exception handling */
1532 ret = DA_ERR_NETWORK_FAIL;
1533 /*ret = DA_ERR_MISMATCH_HTTP_HEADER; */
1537 if (remained_content_len) {
1538 ret = get_available_memory(DA_STORAGE_PHONE, &memory);
1539 if (DA_RESULT_OK == ret) {
1540 DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %llu",
1541 memory.b_available,memory.b_size, remained_content_len);
1542 if (memory.b_available < ((remained_content_len
1543 + SAVE_FILE_BUFFERING_SIZE_50KB)
1544 / memory.b_size)) /* 50KB buffering */
1546 ret = DA_ERR_DISK_FULL;
1561 da_result_t _check_resume_download_is_available(stage_info *stage,
1562 http_msg_response_t *new_http_msg_response)
1564 da_result_t ret = DA_RESULT_OK;
1565 da_bool_t b_ret = DA_FALSE;
1566 char *origin_ETag = NULL;
1567 char *new_ETag = NULL;
1568 unsigned long long remained_content_len = 0;
1569 da_storage_size_t memory;
1571 unsigned long long size = 0;
1572 char *temp_file_path = DA_NULL;
1573 req_dl_info *request_info = DA_NULL;
1575 DA_LOG_FUNC_START(HTTPManager);
1577 request_info = GET_STAGE_TRANSACTION_INFO(stage);
1579 = GET_REQUEST_HTTP_USER_REQUEST_ETAG(request_info);
1581 b_ret = http_msg_response_get_content_length(new_http_msg_response,
1584 remained_content_len = size;
1586 DA_LOG(HTTPManager, "[remained_content_len][%lu]", remained_content_len);
1589 b_ret = http_msg_response_get_ETag(new_http_msg_response, &value);
1593 DA_LOG(HTTPManager, "[new ETag][%s]", new_ETag);
1598 if (origin_ETag && new_ETag &&
1599 0 != strncmp(origin_ETag, new_ETag, strlen(new_ETag))) {
1600 DA_LOG_ERR(HTTPManager, "ETag is not identical! revoke!");
1601 /* FIXME Later : Need to detail error exception handling */
1602 ret = DA_ERR_NETWORK_FAIL;
1603 /*ret = DA_ERR_MISMATCH_HTTP_HEADER; */
1607 if (remained_content_len) {
1608 ret = get_available_memory(DA_STORAGE_PHONE, &memory);
1609 if (DA_RESULT_OK == ret) {
1610 DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %llu",
1611 memory.b_available,memory.b_size, remained_content_len);
1612 if (memory.b_available < ((remained_content_len
1613 + SAVE_FILE_BUFFERING_SIZE_50KB)
1614 / memory.b_size)) /* 50KB buffering */
1616 ret = DA_ERR_DISK_FULL;
1621 b_ret = http_msg_response_get_content_type(new_http_msg_response, &value);
1623 GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info) = value;
1625 DA_LOG(HTTPManager, "[Content-Type][%s]",
1626 GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info));
1628 temp_file_path = GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(request_info);
1629 get_file_size(temp_file_path, &size);
1630 GET_REQUEST_HTTP_HDR_CONT_LEN(request_info) = remained_content_len + size;
1631 DA_LOG(HTTPManager, "[Content-Length][%d]",
1632 GET_REQUEST_HTTP_HDR_CONT_LEN(request_info));
1645 da_result_t _check_downloaded_file_size_is_same_with_header_content_size(
1648 da_result_t ret = DA_RESULT_OK;
1650 req_dl_info *request_info = DA_NULL;
1651 file_info *file_info_data = DA_NULL;
1653 char *real_file_path = DA_NULL;
1654 unsigned long long content_size_from_real_file = 0;
1655 unsigned long long content_size_from_http_header = 0;
1657 DA_LOG_FUNC_START(HTTPManager);
1659 request_info = GET_STAGE_TRANSACTION_INFO(stage);
1660 file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage);
1662 content_size_from_http_header
1663 = GET_CONTENT_STORE_FILE_SIZE(file_info_data);
1665 if (content_size_from_http_header > 0) {
1667 = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data);
1669 get_file_size(real_file_path,
1670 &content_size_from_real_file);
1672 if (content_size_from_real_file
1673 != content_size_from_http_header) {
1674 DA_LOG_ERR(HTTPManager, "size from header = %llu, real size = %llu, DA_ERR_MISMATCH_CONTENT_SIZE",
1675 content_size_from_http_header, content_size_from_real_file);
1676 ret = DA_ERR_MISMATCH_CONTENT_SIZE;
1683 da_result_t _disconnect_transaction(stage_info *stage)
1685 da_result_t ret = DA_RESULT_OK;
1686 int transaction_id = DA_INVALID_ID;
1688 DA_LOG_FUNC_START(HTTPManager);
1691 = GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage));
1693 DA_LOG(HTTPManager, "transaction_id = %d slot_id = %d", transaction_id, GET_STAGE_DL_ID(stage));
1695 if (transaction_id != DA_INVALID_ID) {
1696 ret = PI_http_disconnect_transaction(transaction_id);
1697 GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage))
1704 da_result_t _cancel_transaction(stage_info *stage)
1706 da_result_t ret = DA_RESULT_OK;
1707 int transaction_id = DA_INVALID_ID;
1709 DA_LOG_FUNC_START(HTTPManager);
1712 = GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage));
1714 DA_LOG(HTTPManager, "transaction_id = %d", transaction_id);
1716 if (transaction_id != DA_INVALID_ID) {
1717 http_state_t state = 0;
1718 _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1719 state = GET_HTTP_STATE_ON_STAGE(stage);
1720 if (state <= HTTP_STATE_DOWNLOAD_REQUESTED)
1721 ret = PI_http_cancel_transaction(transaction_id, DA_TRUE);
1723 ret = PI_http_cancel_transaction(transaction_id, DA_FALSE);
1724 _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)));
1730 void __parsing_user_request_header(char *user_request_header,
1731 char **out_field, char **out_value)
1735 char *temp_pos = NULL;
1739 DA_LOG_FUNC_START(HTTPManager);
1741 if (!user_request_header) {
1742 DA_LOG_ERR(HTTPManager, "user_request_header is NULL");
1746 pos = strchr(user_request_header, ':');
1748 DA_LOG_ERR(HTTPManager, "Fail to parse");
1751 temp_pos = (char *)user_request_header;
1754 if (temp_pos == pos || *temp_pos == ' ') {
1755 len = temp_pos - user_request_header;
1761 DA_LOG_ERR(HTTPManager, "Wrong field name");
1764 field = (char *)calloc(1, len + 1);
1766 DA_LOG_ERR(HTTPManager, "Fail to calloc");
1769 strncpy(field, user_request_header, len);
1777 len = strlen(pos) + 1;
1778 value = (char *)calloc(1, len + 1);
1780 DA_LOG_ERR(HTTPManager, "Fail to calloc");
1783 strncpy(value, pos, len);
1786 DA_LOG(HTTPManager, "field[%s], value[%s]", field, value);