4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
20 * @file download-agent-dl-info-util.c
21 * @brief create and destroy functions for download_info
22 * @author Keunsoon Lee(keunsoon.lee@samsung.com)
23 * @author Jungki Kwak(jungki.kwak@samsung.com)
28 #include "download-agent-client-mgr.h"
29 #include "download-agent-dl-info-util.h"
30 #include "download-agent-debug.h"
31 #include "download-agent-utils.h"
32 #include "download-agent-file.h"
33 #include "download-agent-http-mgr.h"
34 #include "download-agent-plugin-conf.h"
36 pthread_mutex_t mutex_download_state[DA_MAX_DOWNLOAD_ID];
37 static pthread_mutex_t mutex_download_mgr = PTHREAD_MUTEX_INITIALIZER;
38 download_mgr_t download_mgr;
40 void init_state_watcher(state_watcher_t *state_watcher);
41 void cleanup_state_watcher(state_watcher_t *state_watcher);
43 da_result_t set_default_header_info(void);
45 void cleanup_source_info_basic_download(source_info_basic_t *source_info_basic);
46 void cleanup_req_dl_info_http(req_dl_info *http_download);
47 void destroy_file_info(file_info *file);
49 da_result_t init_download_mgr() {
50 da_result_t ret = DA_RESULT_OK;
53 DA_LOG_FUNC_START(Default);
55 if (is_client_app_mgr_init() == DA_FALSE) {
56 DA_LOG_ERR(Default, "client app manager is not initiated!");
57 return DA_ERR_INVALID_CLIENT;
60 _da_thread_mutex_lock(&mutex_download_mgr);
62 if (download_mgr.is_init == DA_FALSE) {
63 download_mgr.is_init = DA_TRUE;
65 for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) {
66 _da_thread_mutex_init(&mutex_download_state[i], DA_NULL);
67 init_download_info(i);
70 init_state_watcher(&(download_mgr.state_watcher));
71 init_dl_req_id_history(&(download_mgr.dl_req_id_history));
73 download_mgr.default_hdr_info = (default_http_hdr_info_t *) calloc(1,
74 sizeof(default_http_hdr_info_t));
75 if (download_mgr.default_hdr_info) {
76 /* Don't check return value,
77 * because UA and UAprof is not mandatory field at HTTP request header */
78 set_default_header_info();
80 DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC");
81 ret = DA_ERR_FAIL_TO_MEMALLOC;
85 _da_thread_mutex_unlock(&mutex_download_mgr);
90 da_result_t deinit_download_mgr(void) {
91 da_result_t ret = DA_RESULT_OK;
93 DA_LOG_FUNC_START(Default);
95 _da_thread_mutex_lock(&mutex_download_mgr);
96 if (download_mgr.is_init == DA_TRUE) {
98 download_info_t *dl_info = DA_NULL;
99 void *t_return = NULL;
100 for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) {
101 dl_info = &(download_mgr.download_info[i]);
102 if (dl_info && dl_info->is_using) {
103 request_to_abort_http_download(GET_DL_CURRENT_STAGE(i));
104 DA_LOG_CRITICAL(Thread, "===download id[%d] thread id[%lu] join===",i, GET_DL_THREAD_ID(i));
105 /* Because the download daemon can call the deinit function, the resources of pthread are not freed
106 FIXME later : It is needed to change the termination flow again.
107 if (pthread_join(GET_DL_THREAD_ID(i), &t_return) < 0) {
108 DA_LOG_ERR(Thread, "join client thread is failed!!!");
111 DA_LOG_CRITICAL(Thread, "===download id[%d] thread join return[%d]===",i, (char*)t_return);
114 download_mgr.is_init = DA_FALSE;
115 cleanup_state_watcher(&(download_mgr.state_watcher));
116 if (NULL != download_mgr.default_hdr_info) {
117 if (NULL != download_mgr.default_hdr_info->user_agent_string)
118 free(download_mgr.default_hdr_info->user_agent_string);
120 download_mgr.default_hdr_info->user_agent_string = NULL;
122 free(download_mgr.default_hdr_info);
123 download_mgr.default_hdr_info = NULL;
125 deinit_dl_req_id_history(&(download_mgr.dl_req_id_history));
127 _da_thread_mutex_unlock(&mutex_download_mgr);
131 da_result_t set_default_header_info(void)
133 da_result_t ret = DA_RESULT_OK;
135 ret = get_user_agent_string(
136 &download_mgr.default_hdr_info->user_agent_string);
138 if (DA_RESULT_OK != ret)
141 DA_LOG(Default, "download_mgr.default_hdr_info->user_agent_string = %s ",
142 download_mgr.default_hdr_info->user_agent_string);
147 void init_download_info(int download_id)
149 download_info_t *dl_info = DA_NULL;
151 // DA_LOG_FUNC_START(Default);
153 _da_thread_mutex_lock(&mutex_download_state[download_id]);
154 DA_LOG(Default, "Init download_id [%d] Info", download_id);
155 dl_info = &(download_mgr.download_info[download_id]);
157 dl_info->is_using = DA_FALSE;
158 dl_info->state = DOWNLOAD_STATE_IDLE;
159 dl_info->download_stage_data = DA_NULL;
160 dl_info->dl_req_id = DA_NULL;
161 dl_info->user_install_path = DA_NULL;
162 dl_info->user_data = DA_NULL;
164 Q_init_queue(&(dl_info->queue));
166 DA_LOG(Default, "Init download_id [%d] Info END", download_id);
167 _da_thread_mutex_unlock(&mutex_download_state[download_id]);
172 void destroy_download_info(int download_id)
174 download_info_t *dl_info = DA_NULL;
176 DA_LOG_FUNC_START(Default);
178 DA_LOG(Default, "Destroying download_id [%d] Info", download_id);
180 if (download_id == DA_INVALID_ID) {
181 DA_LOG_ERR(Default, "invalid download_id");
185 dl_info = &(download_mgr.download_info[download_id]);
186 if (DA_FALSE == dl_info->is_using) {
187 /* DA_LOG_ERR(Default, "invalid download_id"); */
191 _da_thread_mutex_lock (&mutex_download_state[download_id]);
192 dl_info->state = DOWNLOAD_STATE_IDLE;
193 DA_LOG(Default, "Changed download_state to - [%d] ", dl_info->state);
195 dl_info->active_dl_thread_id = 0;
197 if (dl_info->download_stage_data != DA_NULL) {
198 remove_download_stage(download_id, dl_info->download_stage_data);
199 dl_info->download_stage_data = DA_NULL;
201 dl_info->dl_req_id = DA_NULL;
202 if (dl_info->user_install_path) {
203 free(dl_info->user_install_path);
204 dl_info->user_install_path = DA_NULL;
206 dl_info->user_data = DA_NULL;
207 dl_info->cur_da_state = DA_STATE_WAITING;
209 Q_destroy_queue(&(dl_info->queue));
211 dl_info->is_using = DA_FALSE;
213 DA_LOG(Default, "Destroying download_id [%d] Info END", download_id);
214 _da_thread_mutex_unlock (&mutex_download_state[download_id]);
218 void *Add_new_download_stage(int download_id)
220 stage_info *download_stage_data = NULL;
221 stage_info *new_download_stage_data = NULL;
223 DA_LOG_FUNC_START(Default);
225 new_download_stage_data = (stage_info*)calloc(1, sizeof(stage_info));
226 if (!new_download_stage_data)
229 new_download_stage_data->dl_id = download_id;
230 download_stage_data = GET_DL_CURRENT_STAGE(download_id);
231 if (download_stage_data) {
232 while (download_stage_data->next_stage_info) {
234 = download_stage_data->next_stage_info;
236 download_stage_data->next_stage_info = new_download_stage_data;
238 GET_DL_CURRENT_STAGE(download_id) = new_download_stage_data;
240 DA_LOG(Default, "NEW STAGE ADDED FOR DOWNLOAD ID[%d] new_stage[%p]", download_id,new_download_stage_data);
243 return new_download_stage_data;
246 void remove_download_stage(int download_id, stage_info *in_stage)
248 stage_info *stage = DA_NULL;
250 DA_LOG_FUNC_START(Default);
252 stage = GET_DL_CURRENT_STAGE(download_id);
253 if (DA_NULL == stage) {
254 DA_LOG_VERBOSE(Default, "There is no stage field on download_id = %d", download_id);
258 if (DA_NULL == in_stage) {
259 DA_LOG_VERBOSE(Default, "There is no in_stage to remove.");
263 if (in_stage == stage) {
264 DA_LOG_VERBOSE(Default, "Base stage will be removed. in_stage[%p]",in_stage);
265 DA_LOG_VERBOSE(Default, "next stage[%p]",stage->next_stage_info);
266 GET_DL_CURRENT_STAGE(download_id) = stage->next_stage_info;
267 empty_stage_info(in_stage);
271 while (in_stage != stage->next_stage_info) {
272 stage = stage->next_stage_info;
274 if (in_stage == stage->next_stage_info) {
275 stage->next_stage_info
276 = stage->next_stage_info->next_stage_info;
277 DA_LOG_VERBOSE(Default, "Stage will be removed. in_stage[%p]",in_stage);
278 DA_LOG_VERBOSE(Default, "next stage[%p]",stage->next_stage_info);
279 empty_stage_info(in_stage);
289 void empty_stage_info(stage_info *in_stage)
291 source_info_t *source_information = NULL;
292 req_dl_info *request_download_info = NULL;
293 file_info *file_information = NULL;
295 DA_LOG_FUNC_START(Default);
297 DA_LOG(Default, "Stage to Remove:[%p]", in_stage);
298 source_information = GET_STAGE_SOURCE_INFO(in_stage);
300 cleanup_source_info_basic_download(
301 GET_SOURCE_BASIC(source_information));
303 request_download_info = GET_STAGE_TRANSACTION_INFO(in_stage);
305 cleanup_req_dl_info_http(request_download_info);
307 file_information = GET_STAGE_CONTENT_STORE_INFO(in_stage);
308 destroy_file_info(file_information);
311 void cleanup_source_info_basic_download(source_info_basic_t *source_info_basic)
313 if (NULL == source_info_basic)
316 DA_LOG_FUNC_START(Default);
318 if (NULL != source_info_basic->url) {
319 free(source_info_basic->url);
320 source_info_basic->url = DA_NULL;
328 void cleanup_req_dl_info_http(req_dl_info *http_download)
330 DA_LOG_FUNC_START(Default);
332 if (http_download->http_info.http_msg_request) {
333 http_msg_request_destroy(
334 &(http_download->http_info.http_msg_request));
337 if (http_download->http_info.http_msg_response) {
338 http_msg_response_destroy(
339 &(http_download->http_info.http_msg_response));
342 if (DA_NULL != http_download->location_url) {
343 free(http_download->location_url);
344 http_download->location_url = DA_NULL;
346 if (DA_NULL != http_download->content_type_from_header) {
347 free(http_download->content_type_from_header);
348 http_download->content_type_from_header = DA_NULL;
351 if (DA_NULL != http_download->etag_from_header) {
352 free(http_download->etag_from_header);
353 http_download->etag_from_header = DA_NULL;
356 http_download->invloved_transaction_id = DA_INVALID_ID;
357 http_download->content_len_from_header = 0;
358 http_download->downloaded_data_size = 0;
360 _da_thread_mutex_destroy(&(http_download->mutex_http_state));
365 void destroy_file_info(file_info *file_information)
367 // DA_LOG_FUNC_START(Default);
369 if (!file_information)
372 if (file_information->file_name_tmp) {
373 free(file_information->file_name_tmp);
374 file_information->file_name_tmp = NULL;
377 if (file_information->file_name_final) {
378 free(file_information->file_name_final);
379 file_information->file_name_final = NULL;
382 if (file_information->content_type) {
383 free(file_information->content_type);
384 file_information->content_type = NULL;
387 if (file_information->pure_file_name) {
388 free(file_information->pure_file_name);
389 file_information->pure_file_name = NULL;
392 if (file_information->extension) {
393 free(file_information->extension);
394 file_information->extension = NULL;
399 void clean_up_client_input_info(client_input_t *client_input)
401 DA_LOG_FUNC_START(Default);
404 client_input->user_data = NULL;
406 if (client_input->install_path) {
407 free(client_input->install_path);
408 client_input->install_path = DA_NULL;
411 if (client_input->file_name) {
412 free(client_input->file_name);
413 client_input->file_name = DA_NULL;
416 client_input_basic_t *client_input_basic =
417 &(client_input->client_input_basic);
419 if (client_input_basic && client_input_basic->req_url) {
420 free(client_input_basic->req_url);
421 client_input_basic->req_url = DA_NULL;
424 if (client_input_basic && client_input_basic->user_request_header) {
426 int count = client_input_basic->user_request_header_count;
427 for (i = 0; i < count; i++)
429 if (client_input_basic->user_request_header[i]) {
430 free(client_input_basic->user_request_header[i]);
431 client_input_basic->user_request_header[i] = DA_NULL;
435 free(client_input_basic->user_request_header);
436 client_input_basic->user_request_header = DA_NULL;
437 client_input_basic->user_request_header_count = 0;
440 DA_LOG_ERR(Default, "client_input is NULL.");
446 da_result_t get_download_id_for_dl_req_id(
447 da_handle_t dl_req_id,
448 da_handle_t* download_id)
450 da_result_t ret = DA_ERR_INVALID_DL_REQ_ID;
454 DA_LOG_ERR(Default, "dl_req_id is less than 0 - %d", dl_req_id);
455 return DA_ERR_INVALID_DL_REQ_ID;
458 _da_thread_mutex_lock(&mutex_download_mgr);
459 for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) {
460 if (download_mgr.download_info[iter].is_using == DA_TRUE) {
461 if (download_mgr.download_info[iter].dl_req_id ==
469 _da_thread_mutex_unlock(&mutex_download_mgr);
475 da_result_t get_available_download_id(da_handle_t *available_id)
477 da_result_t ret = DA_ERR_ALREADY_MAX_DOWNLOAD;
480 _da_thread_mutex_lock(&mutex_download_mgr);
481 for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) {
482 if (download_mgr.download_info[i].is_using == DA_FALSE) {
483 init_download_info(i);
485 download_mgr.download_info[i].is_using = DA_TRUE;
487 download_mgr.download_info[i].dl_req_id
488 = get_available_dl_req_id(&(download_mgr.dl_req_id_history));
491 DA_LOG_CRITICAL(Default, "available download id = %d", *available_id);
497 _da_thread_mutex_unlock(&mutex_download_mgr);
502 da_bool_t is_valid_dl_ID( download_id)
504 da_bool_t ret = DA_FALSE;
506 if (download_id >= 0 && download_id < DA_MAX_DOWNLOAD_ID) {
507 if (download_mgr.download_info[download_id].is_using == DA_TRUE)
514 void init_state_watcher(state_watcher_t *state_watcher)
516 DA_LOG_FUNC_START(Default);
518 _da_thread_mutex_init(&(state_watcher->mutex), DA_NULL);
520 _da_thread_mutex_lock(&(state_watcher->mutex));
521 state_watcher->type = STATE_WATCHER_TYPE_NONE;
522 state_watcher->state_watching_bitmap = 0;
523 state_watcher->is_progressing_to_all = DA_FALSE;
524 _da_thread_mutex_unlock(&(state_watcher->mutex));
527 void cleanup_state_watcher(state_watcher_t *state_watcher)
529 DA_LOG_FUNC_START(Default);
531 _da_thread_mutex_lock(&(state_watcher->mutex));
532 state_watcher->type = STATE_WATCHER_TYPE_NONE;
533 state_watcher->state_watching_bitmap = 0;
534 state_watcher->is_progressing_to_all = DA_FALSE;
535 _da_thread_mutex_unlock(&(state_watcher->mutex));
537 _da_thread_mutex_destroy(&(state_watcher->mutex));
540 void state_watcher_flag_ON_for_download_id(
541 state_watcher_t *state_watcher,
544 unsigned short mask = 0;
546 _da_thread_mutex_lock(&(state_watcher->mutex));
548 mask = 1 << download_id;
550 state_watcher->state_watching_bitmap |= mask;
552 DA_LOG(Default, "state_watcher [%d], download_id [%d]", state_watcher->state_watching_bitmap, download_id);
554 _da_thread_mutex_unlock(&(state_watcher->mutex));
557 void state_watcher_flag_OFF_for_download_id(
558 state_watcher_t *state_watcher,
561 unsigned short mask = 0;
563 _da_thread_mutex_lock(&(state_watcher->mutex));
565 mask = ~(1 << download_id);
567 state_watcher->state_watching_bitmap &= mask;
569 DA_LOG(Default, "state_watcher [%d], download_id [%d]", state_watcher->state_watching_bitmap, download_id);
571 _da_thread_mutex_unlock(&(state_watcher->mutex));
574 da_bool_t state_watcher_is_flag_on_for_download_id_Q(
575 state_watcher_t *state_watcher,
578 da_bool_t b_ret = DA_FALSE;
579 unsigned short mask = 0;
580 unsigned short result = 0;
582 _da_thread_mutex_lock(&(state_watcher->mutex));
584 mask = 1 << download_id;
586 result = state_watcher->state_watching_bitmap & mask;
588 /* DA_LOG(Default, "state_watcher after [%d]", state_watcher->state_watching_bitmap); */
590 _da_thread_mutex_unlock(&(state_watcher->mutex));
600 da_bool_t state_watcher_need_redirect_Q(int download_id)
602 da_bool_t b_ret = DA_FALSE;
603 state_watcher_t *state_watcher = DA_NULL;
605 state_watcher = &(download_mgr.state_watcher);
607 b_ret = state_watcher_is_flag_on_for_download_id_Q(state_watcher,
610 DA_LOG(Default, "state_watcher - need to redirect? [%d]", b_ret);
615 void state_watcher_redirect_state(int download_id, da_state state, int err)
617 state_watcher_t *state_watcher = DA_NULL;
619 DA_LOG_FUNC_START(Default);
621 DA_LOG(Default, "download_id = [%d], receiving state = [%d]", download_id, state);
623 state_watcher = &(download_mgr.state_watcher);
626 case DA_STATE_FAILED:
627 case DA_STATE_FINISHED:
628 state_watcher_flag_OFF_for_download_id(state_watcher,
630 send_client_da_state(download_id, state, err);
634 case DA_STATE_CANCELED:
635 state_watcher_flag_OFF_for_download_id(state_watcher,
638 if (state_watcher->type == STATE_WATCHER_TYPE_CANCEL) {
639 if (!(state_watcher->state_watching_bitmap) &&
640 (state_watcher->is_progressing_to_all
642 send_client_da_state(download_id,
643 DA_STATE_CANCELED_ALL,
647 send_client_da_state(download_id, state, err);
652 case DA_STATE_SUSPENDED:
653 state_watcher_flag_OFF_for_download_id(state_watcher,
656 if (state_watcher->type == STATE_WATCHER_TYPE_SUSPEND) {
657 if (!(state_watcher->state_watching_bitmap) &&
658 (state_watcher->is_progressing_to_all
660 send_client_da_state(download_id,
661 DA_STATE_SUSPENDED_ALL,
668 case DA_STATE_RESUMED:
669 state_watcher_flag_OFF_for_download_id(state_watcher,
672 if (state_watcher->type == STATE_WATCHER_TYPE_RESUME) {
673 if (!(state_watcher->state_watching_bitmap) &&
674 (state_watcher->is_progressing_to_all
676 send_client_da_state(download_id,
677 DA_STATE_RESUMED_ALL,
685 DA_LOG(Default, "blocked...");