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.
19 #include <curl/curl.h>
20 #include <openssl/crypto.h>
22 #include "download-agent-dl-info.h"
23 #include "download-agent-http-mgr.h"
24 #include "download-agent-http-msg-handler.h"
26 static pthread_mutex_t mutex_da_info_list = PTHREAD_MUTEX_INITIALIZER;
27 static pthread_mutex_t *g_openssl_locks_list;
28 da_info_t *da_info_list[DA_MAX_ID];
30 /* locking mechnism for safe use of openssl context */
31 static void openssl_lock_callback(int mode, int type, char *file, int line)
33 DA_LOGV("type [%d], mode [%d]", type, mode);
37 if (mode & CRYPTO_LOCK)
38 pthread_mutex_lock(&(g_openssl_locks_list[type]));
40 pthread_mutex_unlock(&(g_openssl_locks_list[type]));
43 static unsigned long thread_id(void)
45 unsigned long ret = (unsigned long)pthread_self();
49 da_ret_t init_openssl_locks(void)
53 int crypto_num_locks = CRYPTO_num_locks();
54 DA_LOGD("crypto_num_locks [%d]", crypto_num_locks);
55 g_openssl_locks_list = (pthread_mutex_t *)OPENSSL_malloc(crypto_num_locks * sizeof(pthread_mutex_t));
56 if (g_openssl_locks_list == DA_NULL) {
57 DA_LOGE("Failed to OPENSSL_malloc");
58 return DA_ERR_FAIL_TO_MEMALLOC;
60 for (index = 0; index < crypto_num_locks; index++)
61 pthread_mutex_init(&(g_openssl_locks_list[index]), NULL);
63 CRYPTO_set_id_callback((unsigned long (*)())thread_id);
64 CRYPTO_set_locking_callback((void (*)())openssl_lock_callback);
68 da_ret_t deinit_openssl_locks(void)
72 int crypto_num_locks = CRYPTO_num_locks();
73 for (index = 0; index < crypto_num_locks; index++)
74 pthread_mutex_destroy(&(g_openssl_locks_list[index]));
76 CRYPTO_set_id_callback(NULL);
77 CRYPTO_set_locking_callback(NULL);
78 OPENSSL_free(g_openssl_locks_list);
79 g_openssl_locks_list = NULL;
84 static void __init_da_info(int id)
86 da_info_t *da_info = DA_NULL;
87 file_info_t *file_info = DA_NULL;
88 http_info_t *http_info = DA_NULL;
89 req_info_t *req_info = DA_NULL;
91 da_info = (da_info_t *)calloc(1, sizeof(da_info_t));
93 DA_LOGE("Fail to calloc. id[%d]", id);
94 da_info_list[id] = DA_NULL;
97 file_info = (file_info_t *)calloc(1, sizeof(file_info_t));
99 DA_LOGE("Fail to calloc. id[%d]", id);
101 da_info_list[id] = DA_NULL;
104 http_info = (http_info_t *)calloc(1, sizeof(http_info_t));
106 DA_LOGE("Fail to calloc. id[%d]", id);
109 da_info_list[id] = DA_NULL;
112 req_info = (req_info_t *)calloc(1, sizeof(req_info_t));
114 DA_LOGE("Fail to calloc. id[%d]", id);
118 da_info_list[id] = DA_NULL;
122 da_info->da_id = DA_INVALID_ID;
123 da_info->tid = DA_INVALID_ID;
124 memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t));
125 da_info->is_cb_update = DA_FALSE;
126 da_info->http_info = http_info;
127 da_info->file_info = file_info;
128 da_info->req_info = req_info;
129 da_info->update_time = 0;
130 da_info_list[id] = da_info;
133 da_ret_t init_http_msg_t(http_msg_t **http_msg)
135 da_ret_t ret = DA_RESULT_OK;
136 http_msg_t *temp = DA_NULL;
137 temp = (http_msg_t *)calloc(1, sizeof(http_msg_t));
139 DA_LOGE("Fail to calloc. id");
140 return DA_ERR_FAIL_TO_MEMALLOC;
146 void destroy_http_msg_t(http_msg_t *http_msg)
154 da_ret_t get_available_da_id(int *available_id)
156 da_ret_t ret = DA_ERR_ALREADY_MAX_DOWNLOAD;
159 DA_MUTEX_LOCK(&mutex_da_info_list);
160 for (i = 0; i < DA_MAX_ID; i++) {
161 if (da_info_list[i] == DA_NULL) {
163 DA_LOGV("available download id[%d]", *available_id);
169 DA_MUTEX_UNLOCK(&mutex_da_info_list);
174 da_ret_t get_da_info_with_da_id(int id, da_info_t **out_info)
176 da_ret_t ret = DA_ERR_INVALID_ARGUMENT;
179 DA_MUTEX_LOCK(&mutex_da_info_list);
180 for (i = 0; i < DA_MAX_ID; i++) {
181 if (DA_NULL != da_info_list[i] && da_info_list[i]->da_id == id) {
182 *out_info = da_info_list[i];
187 DA_MUTEX_UNLOCK(&mutex_da_info_list);
192 da_ret_t __is_supporting_protocol(const char *url)
194 da_ret_t ret = DA_RESULT_OK;
195 int wanted_str_len = 0;
196 char *protocol = NULL;
197 char *wanted_str_start = NULL;
198 char *wanted_str_end = NULL;
200 if (DA_NULL == url || strlen(url) < 1)
201 return DA_ERR_INVALID_URL;
203 wanted_str_start = (char*)url;
204 wanted_str_end = strstr(url, "://");
205 if (!wanted_str_end) {
206 DA_LOGE("No protocol on this url");
207 return DA_ERR_INVALID_URL;
210 wanted_str_len = wanted_str_end - wanted_str_start;
211 protocol = (char*)calloc(1, wanted_str_len + 1);
213 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
214 return DA_ERR_FAIL_TO_MEMALLOC;
216 strncpy(protocol, wanted_str_start, wanted_str_len);
218 if (strlen(protocol) < 1)
219 ret = DA_ERR_UNSUPPORTED_PROTOCAL;
220 else if (strcasecmp(protocol, "http") != 0 &&
221 strcasecmp(protocol, "https") != 0)
222 ret = DA_ERR_UNSUPPORTED_PROTOCAL;
228 da_ret_t copy_user_input_data(da_info_t *da_info, const char *url,
229 req_data_t *ext_data, da_cb_t *da_cb_data)
231 da_ret_t ret = DA_RESULT_OK;
233 if (!url || !da_info) {
234 DA_LOGE("Invalid Param");
235 return DA_ERR_INVALID_ARGUMENT;
238 ret = __is_supporting_protocol(url);
239 if (ret != DA_RESULT_OK) {
240 DA_SECURE_LOGE("url[%s]", url);
245 req_info_t *req_info = da_info->req_info;
247 if (ext_data->request_header_count > 0) {
249 int count = ext_data->request_header_count;
250 req_info->req_header = (char **)calloc(count, sizeof(char *));
251 if (DA_NULL == req_info->req_header) {
252 DA_LOGE("Fail to calloc");
254 da_info->req_info = DA_NULL;
255 return DA_ERR_FAIL_TO_MEMALLOC;
257 for (i = 0; i < count; i++) {
258 if (ext_data->request_header[i])
259 req_info->req_header[i] =
260 strdup(ext_data->request_header[i]);
262 req_info->req_header_count = count;
266 req_info->url = strdup(url);
267 if (ext_data->install_path)
268 req_info->install_path = strdup(ext_data->install_path);
269 if (ext_data->file_name)
270 req_info->file_name = strdup(ext_data->file_name);
272 req_info->etag = strdup(ext_data->etag);
273 if (ext_data->temp_file_path)
274 req_info->temp_file_path = strdup(ext_data->temp_file_path);
275 if (ext_data->pkg_name)
276 req_info->pkg_name = strdup(ext_data->pkg_name);
277 req_info->network_bonding = ext_data->network_bonding;
278 if (ext_data->user_req_data)
279 req_info->user_req_data = ext_data->user_req_data;
280 if (ext_data->user_client_data)
281 req_info->user_client_data = ext_data->user_client_data;
282 da_info->req_info = req_info;
285 da_info->is_cb_update = DA_TRUE;
286 memcpy(&(da_info->cb_info), da_cb_data, sizeof(da_cb_t));
291 static void __destroy_http_msg(http_msg_t *msg)
297 static void __destroy_http_msg_request(http_msg_request_t *msg)
300 http_msg_request_destroy(&msg);
305 static void __destroy_http_msg_response(http_msg_response_t *msg)
308 http_msg_response_destroy(&msg);
313 static void __destroy_req_info(req_info_t *req_info)
316 NULL_CHECK_AND_FREE(req_info->url);
317 if (req_info->req_header && req_info->req_header_count > 0) {
319 int count = req_info->req_header_count;
320 for (i = 0; i < count; i++) {
321 NULL_CHECK_AND_FREE(req_info->req_header[i]);
322 req_info->req_header[i] = DA_NULL;
324 NULL_CHECK_AND_FREE(req_info->req_header);
325 req_info->req_header = DA_NULL;
326 req_info->req_header_count = 0;
328 NULL_CHECK_AND_FREE(req_info->install_path);
329 NULL_CHECK_AND_FREE(req_info->file_name);
330 NULL_CHECK_AND_FREE(req_info->etag);
331 NULL_CHECK_AND_FREE(req_info->temp_file_path);
332 NULL_CHECK_AND_FREE(req_info->pkg_name);
333 req_info->user_req_data = DA_NULL;
334 req_info->user_client_data = DA_NULL;
335 NULL_CHECK_AND_FREE(req_info);
339 void destroy_http_info(http_info_t *http_info)
342 NULL_CHECK_AND_FREE(http_info->location_url);
343 NULL_CHECK_AND_FREE(http_info->proxy_addr);
344 NULL_CHECK_AND_FREE(http_info->content_type_from_header);
345 NULL_CHECK_AND_FREE(http_info->etag_from_header);
346 NULL_CHECK_AND_FREE(http_info->file_name_from_header);
347 if (http_info->http_msg_request) {
348 __destroy_http_msg_request(http_info->http_msg_request);
349 http_info->http_msg_request = DA_NULL;
351 if (http_info->http_msg_response) {
352 __destroy_http_msg_response(http_info->http_msg_response);
353 http_info->http_msg_response = DA_NULL;
355 if (http_info->http_msg) {
356 __destroy_http_msg(http_info->http_msg);
357 http_info->http_msg = DA_NULL;
359 DA_MUTEX_DESTROY(&(http_info->mutex_state));
360 DA_MUTEX_DESTROY(&(http_info->mutex_http));
361 DA_COND_DESTROY(&(http_info->cond_http));
362 http_info->state = HTTP_STATE_READY_TO_DOWNLOAD;
363 http_info->http_method = HTTP_METHOD_GET;
364 http_info->content_len_from_header = 0;
365 http_info->total_size = 0;
366 http_info->error_code = 0;
367 NULL_CHECK_AND_FREE(http_info);
371 void destroy_file_info(file_info_t *file_info)
374 file_info->file_handle = DA_NULL;
375 NULL_CHECK_AND_FREE(file_info->pure_file_name);
376 NULL_CHECK_AND_FREE(file_info->extension);
377 NULL_CHECK_AND_FREE(file_info->file_path);
378 NULL_CHECK_AND_FREE(file_info->mime_type);
379 NULL_CHECK_AND_FREE(file_info->buffer);
380 file_info->buffer_len = 0;
381 file_info->file_size = 0;
383 file_info->file_size_of_temp_file = 0;
385 file_info->bytes_written_to_file = 0;
386 file_info->is_updated = DA_FALSE;
387 NULL_CHECK_AND_FREE(file_info);
391 // For pause and resume case
392 void reset_http_info_for_resume(http_info_t *http_info)
395 DA_LOGI("[TEST] location_url[%p]", http_info->location_url);
396 NULL_CHECK_AND_FREE(http_info->location_url);
397 http_info->location_url = DA_NULL;
398 NULL_CHECK_AND_FREE(http_info->proxy_addr);
399 http_info->proxy_addr = DA_NULL;
400 NULL_CHECK_AND_FREE(http_info->content_type_from_header);
401 http_info->content_type_from_header = DA_NULL;
402 if (http_info->http_msg_response) {
403 __destroy_http_msg_response(http_info->http_msg_response);
404 http_info->http_msg_response = DA_NULL;
406 if (http_info->http_msg) {
407 __destroy_http_msg(http_info->http_msg);
408 http_info->http_msg = DA_NULL;
410 http_info->http_method = HTTP_METHOD_GET;
411 http_info->content_len_from_header = 0;
412 http_info->total_size = 0;
416 void reset_http_info(http_info_t *http_info)
419 DA_LOGI("[TEST] location_url[%p]", http_info->location_url);
420 free(http_info->location_url);
421 http_info->location_url = DA_NULL;
422 free(http_info->proxy_addr);
423 http_info->proxy_addr = DA_NULL;
424 free(http_info->content_type_from_header);
425 http_info->content_type_from_header = DA_NULL;
426 if (http_info->http_msg_request) {
427 __destroy_http_msg_request(http_info->http_msg_request);
428 http_info->http_msg_request = DA_NULL;
430 if (http_info->http_msg_response) {
431 __destroy_http_msg_response(http_info->http_msg_response);
432 http_info->http_msg_response = DA_NULL;
434 if (http_info->http_msg) {
435 __destroy_http_msg(http_info->http_msg);
436 http_info->http_msg = DA_NULL;
438 http_info->http_method = HTTP_METHOD_GET;
439 http_info->content_len_from_header = 0;
440 http_info->total_size = 0;
444 da_bool_t is_valid_download_id(int download_id)
446 da_ret_t ret = DA_RESULT_OK;
449 DA_MUTEX_LOCK(&mutex_da_info_list);
450 if (DA_NULL == da_info_list[download_id]) {
451 DA_MUTEX_UNLOCK(&mutex_da_info_list);
454 if (is_stopped_state(da_info_list[download_id])) {
455 DA_MUTEX_UNLOCK(&mutex_da_info_list);
458 if (da_info_list[download_id]->da_id != DA_INVALID_ID) {
459 DA_MUTEX_UNLOCK(&mutex_da_info_list);
462 DA_MUTEX_UNLOCK(&mutex_da_info_list);
465 DA_MUTEX_UNLOCK(&mutex_da_info_list);
469 void destroy_da_info_list()
472 DA_MUTEX_LOCK(&mutex_da_info_list);
473 for (i = 0; i < DA_MAX_ID; i++) {
474 if (DA_NULL != da_info_list[i]) {
475 if (da_info_list[i]->req_info) {
476 __destroy_req_info(da_info_list[i]->req_info);
477 da_info_list[i]->req_info = DA_NULL;
479 if (da_info_list[i]->http_info) {
480 destroy_http_info(da_info_list[i]->http_info);
481 da_info_list[i]->http_info = DA_NULL;
483 if (da_info_list[i]->file_info) {
484 destroy_file_info(da_info_list[i]->file_info);
485 da_info_list[i]->file_info = DA_NULL;
487 free(da_info_list[i]);
488 da_info_list[i] = DA_NULL;
491 DA_MUTEX_UNLOCK(&mutex_da_info_list);
494 void destroy_da_info(int id)
496 da_info_t *da_info = DA_NULL;
497 DA_MUTEX_LOCK(&mutex_da_info_list);
498 da_info = da_info_list[id];
500 if (da_info->req_info) {
501 __destroy_req_info(da_info->req_info);
502 da_info->req_info = DA_NULL;
504 if (da_info->http_info) {
505 destroy_http_info(da_info->http_info);
506 da_info->http_info = DA_NULL;
508 if (da_info->file_info) {
509 destroy_file_info(da_info->file_info);
510 da_info->file_info = DA_NULL;
512 da_info->da_id = DA_INVALID_ID;
513 da_info->tid = DA_INVALID_ID;
514 memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t));
516 da_info_list[id] = DA_NULL;
518 DA_MUTEX_UNLOCK(&mutex_da_info_list);