Fix BAD_CHECK_OF_WAIT_COND in cache agent
[platform/framework/web/download-provider.git] / agent / download-agent-dl-info.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 <string.h>
18 #include <stdlib.h>
19 #include <curl/curl.h>
20 #include <pthread.h>
21
22 #include "download-agent-dl-info.h"
23 #include "download-agent-http-mgr.h"
24 #include "download-agent-http-msg-handler.h"
25
26 static pthread_mutex_t mutex_da_info_list = PTHREAD_MUTEX_INITIALIZER;
27 da_info_t *da_info_list[DA_MAX_ID];
28
29 static void __init_da_info(int id)
30 {
31         da_info_t *da_info = DA_NULL;
32         file_info_t *file_info = DA_NULL;
33         http_info_t *http_info = DA_NULL;
34         req_info_t *req_info = DA_NULL;
35
36         da_info = (da_info_t *)calloc(1, sizeof(da_info_t));
37         if (!da_info) {
38                 DA_LOGE("Fail to calloc. id[%d]", id);
39                 da_info_list[id] = DA_NULL;
40                 return;
41         }
42         file_info = (file_info_t *)calloc(1, sizeof(file_info_t));
43         if (!file_info) {
44                 DA_LOGE("Fail to calloc. id[%d]", id);
45                 free(da_info);
46                 da_info_list[id] = DA_NULL;
47                 return;
48         }
49         http_info = (http_info_t *)calloc(1, sizeof(http_info_t));
50         if (!http_info) {
51                 DA_LOGE("Fail to calloc. id[%d]", id);
52                 free(da_info);
53                 free(file_info);
54                 da_info_list[id] = DA_NULL;
55                 return;
56         }
57         req_info = (req_info_t *)calloc(1, sizeof(req_info_t));
58         if (!req_info) {
59                 DA_LOGE("Fail to calloc. id[%d]", id);
60                 free(da_info);
61                 free(file_info);
62                 free(http_info);
63                 da_info_list[id] = DA_NULL;
64                 return;
65         }
66
67         da_info->da_id = DA_INVALID_ID;
68         da_info->thread_id = 0;
69         memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t));
70         da_info->is_cb_update = DA_FALSE;
71         da_info->http_info = http_info;
72         da_info->file_info = file_info;
73         da_info->req_info = req_info;
74         da_info->update_time = 0;
75         da_info_list[id] = da_info;
76 }
77
78 da_ret_t init_http_msg_t(http_msg_t **http_msg)
79 {
80         da_ret_t ret = DA_RESULT_OK;
81         http_msg_t *temp = DA_NULL;
82         temp = (http_msg_t *)calloc(1, sizeof(http_msg_t));
83         if (!temp) {
84                 DA_LOGE("Fail to calloc. id");
85                 return DA_ERR_FAIL_TO_MEMALLOC;
86         }
87         *http_msg = temp;
88         return ret;
89 }
90
91 void destroy_http_msg_t(http_msg_t *http_msg)
92 {
93         if (http_msg)
94                 free(http_msg);
95         http_msg = DA_NULL;
96         return;
97 }
98
99 da_ret_t get_available_da_id(int *available_id)
100 {
101         da_ret_t ret = DA_ERR_ALREADY_MAX_DOWNLOAD;
102         int i = 0;
103
104         DA_MUTEX_LOCK(&mutex_da_info_list);
105         for (i = 0; i < DA_MAX_ID; i++) {
106                 if (da_info_list[i] == DA_NULL) {
107                         *available_id = i;
108                         DA_LOGV("available download id[%d]", *available_id);
109                         __init_da_info(i);
110                         ret = DA_RESULT_OK;
111                         break;
112                 }
113         }
114         DA_MUTEX_UNLOCK(&mutex_da_info_list);
115
116         return ret;
117 }
118
119 da_ret_t get_da_info_with_da_id(int id, da_info_t **out_info)
120 {
121         da_ret_t ret = DA_ERR_INVALID_ARGUMENT;
122         int i = 0;
123
124         DA_MUTEX_LOCK(&mutex_da_info_list);
125         for (i = 0; i < DA_MAX_ID; i++) {
126                 if (DA_NULL != da_info_list[i] && da_info_list[i]->da_id == id) {
127                         *out_info = da_info_list[i];
128                         ret = DA_RESULT_OK;
129                         break;
130                 }
131         }
132         DA_MUTEX_UNLOCK(&mutex_da_info_list);
133
134         return ret;
135 }
136
137 da_ret_t __is_supporting_protocol(const char *url)
138 {
139         da_ret_t ret = DA_RESULT_OK;
140         int wanted_str_len = 0;
141         char *protocol = NULL;
142         char *wanted_str_start = NULL;
143         char *wanted_str_end = NULL;
144
145         if (DA_NULL == url || strlen(url) < 1)
146                 return DA_ERR_INVALID_URL;
147
148         wanted_str_start = (char*)url;
149         wanted_str_end = strstr(url, "://");
150         if (!wanted_str_end) {
151                 DA_LOGE("No protocol on this url");
152                 return DA_ERR_INVALID_URL;
153         }
154
155         wanted_str_len = wanted_str_end - wanted_str_start;
156         protocol = (char*)calloc(1, wanted_str_len + 1);
157         if (!protocol) {
158                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
159                 return DA_ERR_FAIL_TO_MEMALLOC;
160         }
161         strncpy(protocol, wanted_str_start, wanted_str_len);
162
163         if (strlen(protocol) < 1)
164                 ret = DA_ERR_UNSUPPORTED_PROTOCAL;
165         else if (strcasecmp(protocol, "http") != 0 &&
166                         strcasecmp(protocol, "https") != 0)
167                 ret = DA_ERR_UNSUPPORTED_PROTOCAL;
168
169         free(protocol);
170         return ret;
171 }
172
173 da_ret_t copy_user_input_data(da_info_t *da_info, const char *url,
174                 req_data_t *ext_data, da_cb_t *da_cb_data)
175 {
176         da_ret_t ret = DA_RESULT_OK;
177
178         if (!url || !da_info) {
179                 DA_LOGE("Invalid Param");
180                 return DA_ERR_INVALID_ARGUMENT;
181         }
182
183         ret = __is_supporting_protocol(url);
184         if (ret != DA_RESULT_OK) {
185                 DA_SECURE_LOGE("url[%s]", url);
186                 return ret;
187         }
188
189         if (ext_data) {
190                 req_info_t *req_info = da_info->req_info;
191
192                 if (ext_data->request_header_count > 0) {
193                         int i = 0;
194                         int count = ext_data->request_header_count;
195                         req_info->req_header = (char **)calloc(count, sizeof(char *));
196                         if (DA_NULL == req_info->req_header) {
197                                 DA_LOGE("Fail to calloc");
198                                 free(req_info);
199                                 da_info->req_info = DA_NULL;
200                                 return DA_ERR_FAIL_TO_MEMALLOC;
201                         }
202                         for (i = 0; i < count; i++) {
203                                 if (ext_data->request_header[i])
204                                         req_info->req_header[i] =
205                                                         strdup(ext_data->request_header[i]);
206                         }
207                         req_info->req_header_count = count;
208                 }
209
210                 if (url)
211                         req_info->url = strdup(url);
212                 if (ext_data->proxy)
213                         req_info->proxy = strdup(ext_data->proxy);
214                 if (ext_data->install_path)
215                         req_info->install_path = strdup(ext_data->install_path);
216                 if (ext_data->file_name)
217                         req_info->file_name = strdup(ext_data->file_name);
218                 if (ext_data->etag)
219                         req_info->etag = strdup(ext_data->etag);
220                 if (ext_data->temp_file_path)
221                         req_info->temp_file_path = strdup(ext_data->temp_file_path);
222                 if (ext_data->pkg_name)
223                         req_info->pkg_name = strdup(ext_data->pkg_name);
224                 if (ext_data->user_req_data)
225                         req_info->user_req_data = ext_data->user_req_data;
226                 if (ext_data->user_client_data)
227                         req_info->user_client_data = ext_data->user_client_data;
228
229                 req_info->network_bonding = ext_data->network_bonding;
230                 req_info->disable_verify_host = ext_data->disable_verify_host;
231                 req_info->cache = ext_data->cache;
232
233                 da_info->req_info = req_info;
234         }
235         if (da_cb_data) {
236                 da_info->is_cb_update = DA_TRUE;
237                 memcpy(&(da_info->cb_info), da_cb_data, sizeof(da_cb_t));
238         }
239         return ret;
240 }
241
242 static void __destroy_http_msg(http_msg_t *msg)
243 {
244         msg->curl = DA_NULL;
245         free(msg);
246 }
247
248 static void __destroy_http_msg_request(http_msg_request_t *msg)
249 {
250         if (msg) {
251                 http_msg_request_destroy(&msg);
252                 free(msg);
253         }
254 }
255
256 static void __destroy_http_msg_response(http_msg_response_t *msg)
257 {
258         if (msg) {
259                 http_msg_response_destroy(&msg);
260                 free(msg);
261         }
262 }
263
264 static void __destroy_req_info(req_info_t *req_info)
265 {
266         if (req_info) {
267                 NULL_CHECK_AND_FREE(req_info->url);
268                 if (req_info->req_header && req_info->req_header_count > 0) {
269                         int i = 0;
270                         int count = req_info->req_header_count;
271                         for (i = 0; i < count; i++)     {
272                                 NULL_CHECK_AND_FREE(req_info->req_header[i]);
273                                 req_info->req_header[i] = DA_NULL;
274                         }
275                         NULL_CHECK_AND_FREE(req_info->req_header);
276                         req_info->req_header = DA_NULL;
277                         req_info->req_header_count = 0;
278                 }
279                 NULL_CHECK_AND_FREE(req_info->proxy);
280                 NULL_CHECK_AND_FREE(req_info->install_path);
281                 NULL_CHECK_AND_FREE(req_info->file_name);
282                 NULL_CHECK_AND_FREE(req_info->etag);
283                 NULL_CHECK_AND_FREE(req_info->temp_file_path);
284                 NULL_CHECK_AND_FREE(req_info->pkg_name);
285                 req_info->user_req_data = DA_NULL;
286                 req_info->user_client_data = DA_NULL;
287                 NULL_CHECK_AND_FREE(req_info);
288         }
289 }
290
291 static void __destroy_proxy_info(proxy_info_t *proxy_info)
292 {
293         if (proxy_info) {
294                 NULL_CHECK_AND_FREE(proxy_info->addr);
295                 proxy_info->addr = DA_NULL;
296                 NULL_CHECK_AND_FREE(proxy_info->user_name);
297                 proxy_info->user_name = DA_NULL;
298                 NULL_CHECK_AND_FREE(proxy_info->password);
299                 proxy_info->password = DA_NULL;
300                 NULL_CHECK_AND_FREE(proxy_info);
301         }
302 }
303
304 void destroy_http_info(http_info_t *http_info)
305 {
306         if (http_info) {
307                 NULL_CHECK_AND_FREE(http_info->location_url);
308                 NULL_CHECK_AND_FREE(http_info->content_type_from_header);
309                 NULL_CHECK_AND_FREE(http_info->etag_from_header);
310                 NULL_CHECK_AND_FREE(http_info->cache_control_from_header);
311                 NULL_CHECK_AND_FREE(http_info->last_modified_from_header);
312                 NULL_CHECK_AND_FREE(http_info->file_name_from_header);
313                 if (http_info->proxy_info) {
314                         __destroy_proxy_info(http_info->proxy_info);
315                         http_info->proxy_info = DA_NULL;
316                 }
317                 if (http_info->http_msg_request) {
318                         __destroy_http_msg_request(http_info->http_msg_request);
319                         http_info->http_msg_request = DA_NULL;
320                 }
321                 if (http_info->http_msg_response) {
322                         __destroy_http_msg_response(http_info->http_msg_response);
323                         http_info->http_msg_response = DA_NULL;
324                 }
325                 if (http_info->http_msg) {
326                         __destroy_http_msg(http_info->http_msg);
327                         http_info->http_msg = DA_NULL;
328                 }
329                 DA_MUTEX_DESTROY(&(http_info->mutex_state));
330                 DA_MUTEX_DESTROY(&(http_info->mutex_http));
331                 DA_COND_DESTROY(&(http_info->cond_http));
332                 NULL_CHECK_AND_FREE(http_info);
333         }
334 }
335
336 void destroy_file_info(file_info_t *file_info)
337 {
338         if (file_info) {
339                 file_info->file_handle = DA_NULL;
340                 NULL_CHECK_AND_FREE(file_info->pure_file_name);
341                 NULL_CHECK_AND_FREE(file_info->extension);
342                 NULL_CHECK_AND_FREE(file_info->file_path);
343                 NULL_CHECK_AND_FREE(file_info->mime_type);
344                 NULL_CHECK_AND_FREE(file_info->buffer);
345                 file_info->buffer_len = 0;
346                 file_info->file_size = 0;
347 #ifdef _RAF_SUPPORT
348                 file_info->file_size_of_temp_file = 0;
349 #endif
350                 file_info->bytes_written_to_file = 0;
351                 file_info->is_updated = DA_FALSE;
352                 NULL_CHECK_AND_FREE(file_info);
353         }
354 }
355
356 // For pause and resume case
357 void reset_http_info_for_resume(http_info_t *http_info)
358 {
359         if (http_info) {
360                 DA_LOGI("[TEST] location_url[%p]", http_info->location_url);
361                 NULL_CHECK_AND_FREE(http_info->location_url);
362                 http_info->location_url = DA_NULL;
363                 NULL_CHECK_AND_FREE(http_info->content_type_from_header);
364                 http_info->content_type_from_header = DA_NULL;
365                 if (http_info->proxy_info) {
366                         __destroy_proxy_info(http_info->proxy_info);
367                         http_info->proxy_info = DA_NULL;
368                 }
369                 if (http_info->http_msg_response) {
370                         __destroy_http_msg_response(http_info->http_msg_response);
371                         http_info->http_msg_response = DA_NULL;
372                 }
373                 if (http_info->http_msg) {
374                         __destroy_http_msg(http_info->http_msg);
375                         http_info->http_msg = DA_NULL;
376                 }
377                 http_info->http_method = HTTP_METHOD_GET;
378                 http_info->content_len_from_header = 0;
379                 http_info->total_size = 0;
380         }
381 }
382
383 da_bool_t is_valid_download_id(int download_id)
384 {
385         da_ret_t ret = DA_RESULT_OK;
386
387         DA_LOGV("");
388         DA_MUTEX_LOCK(&mutex_da_info_list);
389         if (DA_NULL == da_info_list[download_id]) {
390                 DA_MUTEX_UNLOCK(&mutex_da_info_list);
391                 return DA_FALSE;
392         }
393         if (is_stopped_state(da_info_list[download_id])) {
394                 DA_MUTEX_UNLOCK(&mutex_da_info_list);
395                 return DA_TRUE;
396         }
397         if (da_info_list[download_id]->da_id != DA_INVALID_ID) {
398                 DA_MUTEX_UNLOCK(&mutex_da_info_list);
399                 return DA_TRUE;
400         } else {
401                 DA_MUTEX_UNLOCK(&mutex_da_info_list);
402                 return DA_FALSE;
403         }
404         DA_MUTEX_UNLOCK(&mutex_da_info_list);
405         return ret;
406 }
407
408 void destroy_da_info_list()
409 {
410         int i = 0;
411         DA_MUTEX_LOCK(&mutex_da_info_list);
412         for (i = 0; i < DA_MAX_ID; i++) {
413                 if (DA_NULL != da_info_list[i]) {
414                         if (da_info_list[i]->thread_id) {
415                                 DA_LOGI("%lu is running. wait for the download thread.",
416                                                 da_info_list[i]->thread_id);
417                                 pthread_join(da_info_list[i]->thread_id, NULL);
418                         }
419
420                         if (da_info_list[i]->req_info) {
421                                 __destroy_req_info(da_info_list[i]->req_info);
422                                 da_info_list[i]->req_info = DA_NULL;
423                         }
424                         if (da_info_list[i]->http_info) {
425                                 destroy_http_info(da_info_list[i]->http_info);
426                                 da_info_list[i]->http_info = DA_NULL;
427                         }
428                         if (da_info_list[i]->file_info) {
429                                 destroy_file_info(da_info_list[i]->file_info);
430                                 da_info_list[i]->file_info = DA_NULL;
431                         }
432                         free(da_info_list[i]);
433                         da_info_list[i] = DA_NULL;
434                 }
435         }
436         DA_MUTEX_UNLOCK(&mutex_da_info_list);
437 }
438
439 void destroy_da_info(int id)
440 {
441         da_info_t *da_info = DA_NULL;
442         DA_MUTEX_LOCK(&mutex_da_info_list);
443         da_info = da_info_list[id];
444         if (da_info) {
445                 if (da_info->req_info) {
446                         __destroy_req_info(da_info->req_info);
447                         da_info->req_info = DA_NULL;
448                 }
449                 if (da_info->http_info) {
450                         destroy_http_info(da_info->http_info);
451                         da_info->http_info = DA_NULL;
452                 }
453                 if (da_info->file_info) {
454                         destroy_file_info(da_info->file_info);
455                         da_info->file_info = DA_NULL;
456                 }
457                 da_info->da_id = DA_INVALID_ID;
458                 da_info->thread_id = 0;
459                 memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t));
460                 free(da_info);
461                 da_info_list[id] = DA_NULL;
462         }
463         DA_MUTEX_UNLOCK(&mutex_da_info_list);
464 }