Add to search download id from history db
[profile/ivi/download-provider.git] / src / download-provider-receiver.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/socket.h>
4 #include <sys/un.h>
5 #include <unistd.h>
6 #include <sys/stat.h>
7 #include <time.h>
8 #include <sys/time.h>
9
10 #include <glib.h>
11
12 #include "download-provider-config.h"
13 #include "download-provider-log.h"
14 #include "download-provider-pthread.h"
15 #include "download-provider-notification.h"
16 #include "download-provider-ipc.h"
17 #include "download-provider-db.h"
18 #include "download-provider-utils.h"
19
20 #include "download-agent-defs.h"
21 #include "download-agent-interface.h"
22
23 int _init_agent(void);
24 void _deinit_agent(void);
25 static void __downloading_info_cb(user_downloading_info_t *download_info,
26                                         void *user_data);
27 static void __download_info_cb(user_download_info_t *download_info,
28                                         void *user_data);
29 static void __notify_cb(user_notify_info_t *notify_info, void *user_data);
30 static int __change_error(int err);
31 static int __change_state(da_state state);
32
33 void TerminateDaemon(int signo);
34
35 pthread_attr_t g_download_provider_thread_attr;
36 fd_set g_download_provider_socket_readset;
37 fd_set g_download_provider_socket_exceptset;
38
39 int _change_pended_download(download_clientinfo *clientinfo)
40 {
41         if (!clientinfo)
42                 return -1;
43         clientinfo->state = DOWNLOAD_STATE_PENDED;
44         clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
45         download_provider_db_requestinfo_update_column(clientinfo, DOWNLOAD_DB_STATE);
46         ipc_send_request_stateinfo(clientinfo);
47         return 0;
48 }
49
50 void *_start_download(void *args)
51 {
52         int da_ret = -1;
53         int req_dl_id = -1;
54
55         download_clientinfo_slot *clientinfoslot =
56                 (download_clientinfo_slot *) args;
57         if (!clientinfoslot) {
58                 TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo_slot");
59                 return 0;
60         }
61         download_clientinfo *clientinfo =
62                 (download_clientinfo *) clientinfoslot->clientinfo;
63         if (!clientinfo) {
64                 TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo");
65                 return 0;
66         }
67
68         CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
69         clientinfo->state = DOWNLOAD_STATE_READY;
70         clientinfo->err = DOWNLOAD_ERROR_NONE;
71         CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
72
73         // call start_download() of download-agent
74         if (clientinfo->requestinfo->headers.rows > 0) {
75                 int len = 0;
76                 int i = 0;
77                 char **req_header = NULL;
78                 len = clientinfo->requestinfo->headers.rows;
79                 req_header = calloc(len, sizeof(char *));
80                 if (!req_header) {
81                         TRACE_DEBUG_MSG("fail to calloc");
82                         return 0;
83                 }
84                 for (i = 0; i < len; i++)
85                         req_header[i] =
86                                 strdup(clientinfo->requestinfo->headers.str[i].str);
87                 if (clientinfo->requestinfo->install_path.length > 1) {
88                         if (clientinfo->requestinfo->filename.length > 1)
89                                 da_ret =
90                                         da_start_download_with_extension(clientinfo->requestinfo->
91                                                         url.str, &req_dl_id,
92                                                         DA_FEATURE_REQUEST_HEADER,
93                                                         req_header, &len,
94                                                         DA_FEATURE_INSTALL_PATH,
95                                                         clientinfo->requestinfo->install_path.str,
96                                                         DA_FEATURE_FILE_NAME,
97                                                         clientinfo->requestinfo->filename.str,
98                                                         DA_FEATURE_USER_DATA,
99                                                         (void *)clientinfoslot,
100                                                         NULL);
101                         else
102                                 da_ret =
103                                         da_start_download_with_extension(clientinfo->requestinfo->
104                                                         url.str, &req_dl_id,
105                                                         DA_FEATURE_REQUEST_HEADER,
106                                                         req_header, &len,
107                                                         DA_FEATURE_INSTALL_PATH,
108                                                         clientinfo->requestinfo->install_path.str,
109                                                         DA_FEATURE_USER_DATA,
110                                                         (void *)clientinfoslot,
111                                                         NULL);
112                 } else {
113                         if (clientinfo->requestinfo->filename.length > 1)
114                                 da_ret =
115                                         da_start_download_with_extension(clientinfo->requestinfo->
116                                                         url.str, &req_dl_id,
117                                                         DA_FEATURE_REQUEST_HEADER,
118                                                         req_header, &len,
119                                                         DA_FEATURE_FILE_NAME,
120                                                         clientinfo->requestinfo->filename.str,
121                                                         DA_FEATURE_USER_DATA,
122                                                         (void *)clientinfoslot,
123                                                         NULL);
124                         else
125                                 da_ret =
126                                         da_start_download_with_extension(clientinfo->requestinfo->
127                                                         url.str, &req_dl_id,
128                                                         DA_FEATURE_REQUEST_HEADER,
129                                                         req_header, &len,
130                                                         DA_FEATURE_USER_DATA,
131                                                         (void *)clientinfoslot,
132                                                         NULL);
133                 }
134                 for (i = 0; i < len; i++) {
135                         if (req_header[i])
136                                 free(req_header[i]);
137                 }
138         } else {
139                 if (clientinfo->requestinfo->install_path.length > 1) {
140                         if (clientinfo->requestinfo->filename.length > 1)
141                                 da_ret =
142                                         da_start_download_with_extension(clientinfo->requestinfo->
143                                                         url.str, &req_dl_id,
144                                                         DA_FEATURE_INSTALL_PATH,
145                                                         clientinfo->requestinfo->install_path.str,
146                                                         DA_FEATURE_FILE_NAME,
147                                                         clientinfo->requestinfo->filename.str,
148                                                         DA_FEATURE_USER_DATA,
149                                                         (void *)clientinfoslot,
150                                                         NULL);
151                         else
152                                 da_ret =
153                                         da_start_download_with_extension(clientinfo->requestinfo->
154                                                         url.str, &req_dl_id,
155                                                         DA_FEATURE_INSTALL_PATH,
156                                                         clientinfo->requestinfo->install_path.str,
157                                                         DA_FEATURE_USER_DATA,
158                                                         (void *)clientinfoslot,
159                                                         NULL);
160                 } else {
161                         if (clientinfo->requestinfo->filename.length > 1)
162                                 da_ret =
163                                         da_start_download_with_extension(clientinfo->requestinfo->
164                                                         url.str, &req_dl_id,
165                                                         DA_FEATURE_FILE_NAME,
166                                                         clientinfo->requestinfo->filename.str,
167                                                         DA_FEATURE_USER_DATA,
168                                                         (void *)clientinfoslot,
169                                                         NULL);
170                         else
171                                 da_ret =
172                                         da_start_download_with_extension(clientinfo->requestinfo->
173                                                         url.str, &req_dl_id,
174                                                         DA_FEATURE_USER_DATA,
175                                                         (void *)clientinfoslot,
176                                                         NULL);
177                 }
178         }
179
180         // if start_download() return error cause of maximun download limitation,
181         // set state to DOWNLOAD_STATE_PENDED.
182         if (da_ret == DA_ERR_ALREADY_MAX_DOWNLOAD) {
183                 TRACE_DEBUG_INFO_MSG("change to pended request [%d]", da_ret);
184                 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
185                 _change_pended_download(clientinfo);
186                 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
187                 return 0;
188         } else if (da_ret != DA_RESULT_OK) {
189                 TRACE_DEBUG_INFO_MSG("Fail to request start [%d]", da_ret);
190                 /* FIXME : need to seperate in detail according to error return values */
191                 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
192                 clientinfo->state = DOWNLOAD_STATE_FAILED;
193                 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
194                 download_provider_db_requestinfo_remove(clientinfo->
195                                                         requestinfo->requestid);
196                 ipc_send_request_stateinfo(clientinfo);
197                 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
198                 return 0;
199         }
200
201         CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
202
203         TRACE_DEBUG_INFO_MSG("started download [%d]", da_ret);
204
205         clientinfo->req_id = req_dl_id;
206         clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
207         clientinfo->err = DOWNLOAD_ERROR_NONE;
208
209         download_provider_db_requestinfo_update_column(clientinfo,
210                                                                 DOWNLOAD_DB_STATE);
211
212         // sync return  // client should be alive till this line at least.
213         ipc_send_request_stateinfo(clientinfo);
214
215         CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
216         return 0;
217 }
218
219 int _create_download_thread(download_clientinfo_slot *clientinfo_slot)
220 {
221         if (!clientinfo_slot)
222                 return -1;
223
224         // create thread for receiving the reqeust info from client.
225         // and if possible, it will create the thread for listening the event.
226         clientinfo_slot->clientinfo->state = DOWNLOAD_STATE_READY;
227         clientinfo_slot->clientinfo->err = DOWNLOAD_ERROR_NONE;
228         if (pthread_create
229                 (&clientinfo_slot->clientinfo->thread_pid,
230                 &g_download_provider_thread_attr, _start_download,
231                 clientinfo_slot) != 0) {
232                 TRACE_DEBUG_INFO_MSG("failed to call pthread_create for client");
233                 TRACE_DEBUG_INFO_MSG("Change to pended job");
234                 _change_pended_download(clientinfo_slot->clientinfo);
235                 return -1;
236         }
237         return 0;
238 }
239
240 int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_clientinfo *request_clientinfo)
241 {
242         int searchslot = 0;
243         unsigned active_count = 0;
244
245         // NULL - checking
246         if (!clientinfo_list || !request_clientinfo ) {
247                 TRACE_DEBUG_MSG("NULL-CHECK");
248                 return -1;
249         }
250
251         CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL);
252
253 #ifdef SO_PEERCRED
254         socklen_t cr_len =
255                 sizeof(request_clientinfo->credentials);
256         if (getsockopt
257                 (request_clientinfo->clientfd, SOL_SOCKET,
258                 SO_PEERCRED, &request_clientinfo->credentials,
259                 &cr_len) == 0) {
260                 TRACE_DEBUG_INFO_MSG
261                         ("Client Info : pid=%d, uid=%d, gid=%d\n",
262                         request_clientinfo->credentials.pid,
263                         request_clientinfo->credentials.uid,
264                         request_clientinfo->credentials.gid);
265         }
266 #endif
267
268         download_controls type =
269                 ipc_receive_header(request_clientinfo->clientfd);
270         TRACE_DEBUG_INFO_MSG("[ACCEPT] HEADER : [%d] ", type);
271         // first of all, receive requestinfo .
272         if (type <= 0 || ipc_receive_request_msg(request_clientinfo) < 0) {
273                 TRACE_DEBUG_MSG("Ignore this connection, Invalid command");
274                 clear_clientinfo(request_clientinfo);
275                 return -1;
276         }
277
278         if (type == DOWNLOAD_CONTROL_STOP
279                 || type == DOWNLOAD_CONTROL_GET_STATE_INFO
280                 || type == DOWNLOAD_CONTROL_RESUME
281                 || type == DOWNLOAD_CONTROL_PAUSE) {
282                 // get requestid from socket.
283                 if (request_clientinfo->requestinfo
284                         && request_clientinfo->requestinfo->requestid > 0) {
285                         // search requestid in slots.
286                         int searchindex = get_same_request_slot_index
287                                                         (clientinfo_list,
288                                                         request_clientinfo->requestinfo->requestid);
289                         if (type == DOWNLOAD_CONTROL_STOP) {
290                                 TRACE_DEBUG_INFO_MSG("Request : DOWNLOAD_CONTROL_STOP");
291                                 if (searchindex >= 0) {
292                                         if (da_cancel_download
293                                                 (clientinfo_list[searchindex].clientinfo->req_id)
294                                                 == DA_RESULT_OK) {
295                                                 request_clientinfo->state = DOWNLOAD_STATE_STOPPED;
296                                                 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
297                                                 if (clientinfo_list[searchindex].clientinfo->requestinfo
298                                                         && clientinfo_list[searchindex].clientinfo->requestinfo->notification)
299                                                         set_downloadedinfo_appfw_notification(clientinfo_list[searchindex].clientinfo);
300                                                 download_provider_db_requestinfo_remove(request_clientinfo->requestinfo->requestid);
301                                                 download_provider_db_history_new(clientinfo_list[searchindex].clientinfo);
302                                         } else {
303                                                 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
304                                                 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
305                                         }
306                                 } else { // no found
307                                         request_clientinfo->state = DOWNLOAD_STATE_NONE;
308                                         request_clientinfo->err = DOWNLOAD_ERROR_NONE;
309                                 }
310                                 ipc_send_stateinfo(request_clientinfo);
311                         } else if (type == DOWNLOAD_CONTROL_GET_STATE_INFO) {
312                                 // search slots/downloading db/history db
313                                 if (searchindex > 0) { // exist in slots (memory)
314                                         request_clientinfo->state =
315                                                 clientinfo_list[searchindex].clientinfo->state;
316                                         request_clientinfo->err =
317                                                 clientinfo_list[searchindex].clientinfo->err;
318                                 } else {  //search downloading db or history db
319                                         download_dbinfo* dbinfo =
320                                                 download_provider_db_get_info(
321                                                         request_clientinfo->requestinfo->requestid);
322                                         if (dbinfo) { // found in downloading db..it means crashed job
323                                                 request_clientinfo->state = DOWNLOAD_STATE_PENDED;
324                                                 request_clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
325                                         } else { // no exist in downloading db
326                                                 dbinfo = download_provider_db_history_get_info(
327                                                         request_clientinfo->requestinfo->requestid);
328                                                 if (!dbinfo) { // no info anywhere
329                                                         request_clientinfo->state = DOWNLOAD_STATE_NONE;
330                                                         request_clientinfo->err = DOWNLOAD_ERROR_NONE;
331                                                 } else { //history info
332                                                         request_clientinfo->state = dbinfo->state;
333                                                         request_clientinfo->err = DOWNLOAD_ERROR_NONE;
334                                                 }
335                                         }
336                                         download_provider_db_info_free(dbinfo);
337                                         free(dbinfo);
338                                 }
339                                 ipc_send_stateinfo(request_clientinfo);
340                                 // estabilish the spec of return value.
341                         } else if (type == DOWNLOAD_CONTROL_PAUSE) {
342                                 if (searchindex >= 0) {
343                                         if (da_suspend_download
344                                                 (clientinfo_list[searchindex].clientinfo->req_id)
345                                                 == DA_RESULT_OK) {
346                                                 request_clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED;
347                                                 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
348                                         } else {
349                                                 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
350                                                 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
351                                         }
352                                 } else { // no found
353                                         request_clientinfo->state = DOWNLOAD_STATE_NONE;
354                                         request_clientinfo->err = DOWNLOAD_ERROR_NONE;
355                                 }
356                                 ipc_send_stateinfo(request_clientinfo);
357                         } else if (type == DOWNLOAD_CONTROL_RESUME) {
358                                 if (searchindex >= 0) {
359                                         if (da_resume_download
360                                                 (clientinfo_list[searchindex].clientinfo->req_id)
361                                                 == DA_RESULT_OK) {
362                                                 request_clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
363                                                 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
364                                         } else {
365                                                 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
366                                                 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
367                                         }
368                                 } else { // no found
369                                         request_clientinfo->state = DOWNLOAD_STATE_NONE;
370                                         request_clientinfo->err = DOWNLOAD_ERROR_NONE;
371                                 }
372                                 ipc_send_stateinfo(request_clientinfo);
373                         }
374                         ipc_receive_header(request_clientinfo->clientfd);
375                 }
376                 clear_clientinfo(request_clientinfo);
377                 return 0;
378         }
379
380         if (type != DOWNLOAD_CONTROL_START) {
381                 TRACE_DEBUG_MSG
382                         ("Now, DOWNLOAD_CONTROL_START is only supported");
383                 clear_clientinfo(request_clientinfo);
384                 return -1;
385         }
386
387         // check whether requestinfo has requestid or not.
388         if (request_clientinfo->requestinfo
389                 && request_clientinfo->requestinfo->requestid > 0) {
390                 // search same request id.
391                 int searchindex = get_same_request_slot_index(clientinfo_list,
392                                                 request_clientinfo->requestinfo->requestid);
393                 if (searchindex < 0) {
394                         TRACE_DEBUG_INFO_MSG("Not Found Same Request ID");
395                         /* Try to search history db */
396                         download_dbinfo *dbinfo = download_provider_db_history_get_info(
397                                         request_clientinfo->requestinfo->requestid);
398                         if (dbinfo == NULL) {
399                                 /* Try to serach downloading db. The crashed job can not be uploaded to memory */
400                                 dbinfo = download_provider_db_get_info(
401                                                 request_clientinfo->requestinfo->requestid);
402                                 if (dbinfo == NULL) {
403                                         /* Invalid id */
404                                         request_clientinfo->state = DOWNLOAD_STATE_FAILED;
405                                         request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
406                                         ipc_send_request_stateinfo(request_clientinfo);
407                                         clear_clientinfo(request_clientinfo);
408                                         return 0;
409                                 }
410                         }
411                         download_provider_db_info_free(dbinfo);
412                         free(dbinfo);
413                 } else {        // found request id. // how to deal etag ?
414                         // connect to slot.
415                         TRACE_DEBUG_INFO_MSG("Found Same Request ID slot[%d]", searchindex);
416                         CLIENT_MUTEX_LOCK(&(request_clientinfo->client_mutex));
417                         // close previous socket.
418                         if (clientinfo_list[searchindex].clientinfo->clientfd > 0)
419                                 close(clientinfo_list[searchindex].clientinfo->clientfd);
420                         // change to new socket.
421                         clientinfo_list[searchindex].clientinfo->clientfd =
422                                 request_clientinfo->clientfd;
423                         // update some info.
424                         clientinfo_list[searchindex].clientinfo->requestinfo->callbackinfo =
425                                 request_clientinfo->requestinfo->callbackinfo;
426                         clientinfo_list[searchindex].clientinfo->requestinfo->notification =
427                                 request_clientinfo->requestinfo->notification;
428                         request_clientinfo->clientfd = 0;       // prevent to not be disconnected.
429                         CLIENT_MUTEX_UNLOCK(&(request_clientinfo->client_mutex));
430                         clear_clientinfo(request_clientinfo);
431
432                         if (clientinfo_list[searchindex].clientinfo->state
433                                 == DOWNLOAD_STATE_READY
434                                 || clientinfo_list[searchindex].clientinfo->state
435                                 >= DOWNLOAD_STATE_FINISHED) {
436                                 active_count = get_downloading_count(clientinfo_list);
437                                 if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
438                                         // deal as pended job.
439                                         _change_pended_download(clientinfo_list[searchindex].clientinfo);
440                                         TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]",
441                                         searchslot, MAX_CLIENT);
442                                 } else
443                                         _create_download_thread(&clientinfo_list[searchindex]);
444                         } else
445                                 ipc_send_request_stateinfo(clientinfo_list[searchindex].clientinfo);
446                         return 0;
447                 }
448         }
449
450         // new request.
451         searchslot = get_empty_slot_index(clientinfo_list);
452         if (searchslot < 0) {
453                 TRACE_DEBUG_MSG("download-provider is busy, try later");
454                 clear_clientinfo(request_clientinfo);
455                 sleep(5);       // provider need the time of refresh.
456                 return -1;
457         }
458         // create new unique id, and insert info to DB.
459         if (request_clientinfo->requestinfo
460                 && request_clientinfo->requestinfo->requestid <= 0) {
461                 request_clientinfo->requestinfo->requestid =
462                         get_download_request_id();
463                 if (download_provider_db_requestinfo_new
464                         (request_clientinfo) < 0) {
465                         clear_clientinfo(request_clientinfo);
466                         sleep(5);       // provider need the time of refresh.
467                         return -1;
468                 }
469         }
470
471         clientinfo_list[searchslot].clientinfo = request_clientinfo;
472
473         active_count = get_downloading_count(clientinfo_list);
474
475         TRACE_DEBUG_INFO_MSG("New Connection slot [%d/%d] active [%d/%d]",
476                                                                                         searchslot,
477                                                                                         MAX_CLIENT,
478                                                                                         active_count,
479                                                                                         DA_MAX_DOWNLOAD_REQ_AT_ONCE);
480
481         if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
482                 // deal as pended job.
483                 _change_pended_download(clientinfo_list[searchslot].clientinfo);
484                 TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]",
485                         searchslot, MAX_CLIENT);
486         } else {
487                 // Pending First
488                 unsigned free_slot_count
489                         = DA_MAX_DOWNLOAD_REQ_AT_ONCE - active_count;
490                 int pendedslot = get_pended_slot_index(clientinfo_list);
491                 if(pendedslot >= 0) {
492                         TRACE_DEBUG_INFO_MSG ("Free Space [%d]", free_slot_count);
493                         for (;free_slot_count > 0 && pendedslot >= 0; free_slot_count--) {
494                                 TRACE_DEBUG_INFO_MSG ("Start pended job [%d]", pendedslot);
495                                 _create_download_thread(&clientinfo_list[pendedslot]);
496                                 pendedslot = get_pended_slot_index(clientinfo_list);
497                         }
498                 }
499
500                 if (free_slot_count <= 0) { // change to PENDED
501                         // start pended job, deal this job to pended
502                         _change_pended_download(clientinfo_list[searchslot].clientinfo);
503                         TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]",
504                                 searchslot, MAX_CLIENT);
505                 } else
506                         _create_download_thread(&clientinfo_list[searchslot]);
507         }
508         return 0;
509 }
510
511 int _handle_client_request(download_clientinfo* clientinfo)
512 {
513         int da_ret = 0;
514         int msgType = 0;
515
516         // NULL - checking
517         if (!clientinfo) {
518                 TRACE_DEBUG_MSG("NULL-CHECK");
519                 return -1;
520         }
521
522         switch (msgType = ipc_receive_header(clientinfo->clientfd)) {
523         case DOWNLOAD_CONTROL_STOP:
524                 if (clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
525                         // clear slot requested by client after finished download
526                         TRACE_DEBUG_INFO_MSG("request Free slot to main thread");
527                         clear_socket(clientinfo);
528                         break;
529                 }
530                 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_STOP");
531                 da_ret = da_cancel_download(clientinfo->req_id);
532                 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
533                 if (da_ret != DA_RESULT_OK) {
534                         /* FIXME : need to seperate in detail according to error return values */
535                         clientinfo->state = DOWNLOAD_STATE_FAILED;
536                         clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
537                         TRACE_DEBUG_MSG("Fail to request cancel [%d]", da_ret);
538                 } else {
539                         clientinfo->state = DOWNLOAD_STATE_STOPPED;
540                         clientinfo->err = DOWNLOAD_ERROR_NONE;
541                         if (clientinfo->requestinfo) {
542                                 if (clientinfo->requestinfo->notification)
543                                         set_downloadedinfo_appfw_notification(clientinfo);
544                                 download_provider_db_requestinfo_remove(clientinfo->
545                                         requestinfo->requestid);
546                         }
547                         download_provider_db_history_new(clientinfo);
548                 }
549                 ipc_send_stateinfo(clientinfo);
550                 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
551                 break;
552         case DOWNLOAD_CONTROL_PAUSE:
553                 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_PAUSE");
554                 da_ret = da_suspend_download(clientinfo->req_id);
555                 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
556                 if (da_ret != DA_RESULT_OK) {
557                         /* FIXME : need to seperate in detail according to error return values */
558                         clientinfo->state = DOWNLOAD_STATE_FAILED;
559                         clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
560                         TRACE_DEBUG_MSG("Fail to request suspend [%d]", da_ret);
561                 } else {
562                         clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED;
563                         clientinfo->err = DOWNLOAD_ERROR_NONE;
564                 }
565                 ipc_send_stateinfo(clientinfo);
566                 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
567                 break;
568         case DOWNLOAD_CONTROL_RESUME:
569                 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_RESUME");
570                 da_ret = da_resume_download(clientinfo->req_id);
571                 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
572                 if (da_ret != DA_RESULT_OK) {
573                         /* FIXME : need to seperate in detail according to error return values */
574                         clientinfo->state = DOWNLOAD_STATE_FAILED;
575                         clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
576                         TRACE_DEBUG_MSG("Fail to request resume [%d]", da_ret);
577                 } else {
578                         clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
579                         clientinfo->err = DOWNLOAD_ERROR_NONE;
580                 }
581                 ipc_send_stateinfo(clientinfo);
582                 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
583                 break;
584         case DOWNLOAD_CONTROL_GET_STATE_INFO:   // sync call
585                 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_GET_STATE_INFO");
586                 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
587                 ipc_send_stateinfo(clientinfo);
588                 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
589                 break;
590         case DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO:        // sync call
591                 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO");
592                 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
593                 ipc_send_downloadinfo(clientinfo);
594                 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
595                 break;
596         case -1:
597         case 0:
598                 TRACE_DEBUG_MSG("(Closed Socket ) terminate event thread (%d)",
599                         msgType);
600                 // bloken socket... it seems the client is dead or closed by agent thread.
601                 // close socket, this will break the loop. and terminate this thread.
602                 clear_socket(clientinfo);
603                 return -1;
604         default:
605                 TRACE_DEBUG_MSG("Unknow message [%d]", msgType);
606                 return -1;
607         }
608         return 0;
609 }
610
611 void *run_manage_download_server(void *args)
612 {
613         int listenfd = 0;       // main socket to be albe to listen the new connection
614         int maxfd;
615         int ret = 0;
616         fd_set rset, exceptset;
617         struct timeval timeout;
618         long flexible_timeout;
619         download_clientinfo_slot *clientinfo_list;
620         int searchslot = 0;
621         unsigned active_count = 0;
622         download_clientinfo *request_clientinfo;
623         int check_retry = 1;
624         int i = 0;
625         int is_timeout = 0;
626
627         socklen_t clientlen;
628         struct sockaddr_un listenaddr, clientaddr;
629
630         GMainLoop *mainloop = (GMainLoop *) args;
631
632         ret = _init_agent();
633         if (ret != DOWNLOAD_ERROR_NONE) {
634                 TRACE_DEBUG_MSG("failed to init agent");
635                 TerminateDaemon(SIGTERM);
636                 return 0;
637         }
638         clear_downloadinginfo_appfw_notification();
639
640         if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
641                 TRACE_DEBUG_MSG("failed to create socket");
642                 TerminateDaemon(SIGTERM);
643                 return 0;
644         }
645
646         bzero(&listenaddr, sizeof(listenaddr));
647         listenaddr.sun_family = AF_UNIX;
648         strcpy(listenaddr.sun_path, DOWNLOAD_PROVIDER_IPC);
649
650         if (bind(listenfd, (struct sockaddr *)&listenaddr, sizeof listenaddr) !=
651                 0) {
652                 TRACE_DEBUG_MSG("failed to call bind");
653                 TerminateDaemon(SIGTERM);
654                 return 0;
655         }
656
657         if (chmod(listenaddr.sun_path, 0777) < 0) {
658                 TRACE_DEBUG_MSG
659                         ("failed to change the permission of socket file");
660                 TerminateDaemon(SIGTERM);
661                 return 0;
662         }
663
664         if (listen(listenfd, MAX_CLIENT) != 0) {
665                 TRACE_DEBUG_MSG("failed to call listen");
666                 TerminateDaemon(SIGTERM);
667                 return 0;
668         }
669
670         maxfd = listenfd;
671         TRACE_DEBUG_INFO_MSG("Ready to listen IPC [%d][%s]", listenfd,
672                         DOWNLOAD_PROVIDER_IPC);
673
674         // allocation the array structure for managing the clients.
675         clientinfo_list =
676                 (download_clientinfo_slot *) calloc(MAX_CLIENT,
677                                                         sizeof(download_clientinfo_slot));
678         if (clientinfo_list == NULL) {
679                 TRACE_DEBUG_MSG("failed to allocate the memory for client list");
680                 TerminateDaemon(SIGTERM);
681                 return 0;
682         }
683
684         if (pthread_attr_init(&g_download_provider_thread_attr) != 0) {
685                 TRACE_DEBUG_MSG("failed to call pthread_attr_init for client");
686                 TerminateDaemon(SIGTERM);
687                 return 0;
688         }
689         if (pthread_attr_setdetachstate(&g_download_provider_thread_attr,
690                                                                         PTHREAD_CREATE_DETACHED) != 0) {
691                 TRACE_DEBUG_MSG("failed to set detach option");
692                 TerminateDaemon(SIGTERM);
693                 return 0;
694         }
695
696         flexible_timeout = DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
697
698         FD_ZERO(&g_download_provider_socket_readset);
699         FD_ZERO(&g_download_provider_socket_exceptset);
700         FD_SET(listenfd, &g_download_provider_socket_readset);
701         FD_SET(listenfd, &g_download_provider_socket_exceptset);
702
703         while (g_main_loop_is_running(mainloop)) {
704
705                 // clean slots
706                 for (i = 0; i < MAX_CLIENT; i++) {
707                         if (!clientinfo_list[i].clientinfo)
708                                 continue;
709                         // clear slot.
710                         if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
711                                 if (clientinfo_list[i].clientinfo->clientfd <= 0)
712                                         clear_clientinfoslot(&clientinfo_list[i]);
713                                 continue;
714                         }
715                 }
716
717                 is_timeout = 1;
718                 rset = g_download_provider_socket_readset;
719                 exceptset = g_download_provider_socket_exceptset;
720
721                 memset(&timeout, 0x00, sizeof(struct timeval));
722                 timeout.tv_sec = flexible_timeout;
723
724                 if (select((maxfd + 1), &rset, 0, &exceptset, &timeout) < 0) {
725                         TRACE_DEBUG_MSG
726                                 ("select error, provider can't receive any request from client.");
727                         TerminateDaemon(SIGTERM);
728                         break;
729                 }
730
731                 for (i = 0; i < MAX_CLIENT; i++) {  // find the socket received the packet.
732                         if (!clientinfo_list[i].clientinfo)
733                                 continue;
734                         //Even if no socket, downloading should be progressed.
735                         if (clientinfo_list[i].clientinfo->clientfd <= 0)
736                                 continue;
737                         if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &rset) > 0) {
738                                 // ignore it is not started yet.
739                                 if (clientinfo_list[i].clientinfo->state <= DOWNLOAD_STATE_READY)
740                                         continue;
741                                 TRACE_DEBUG_INFO_MSG("FD_ISSET [%d] readset slot[%d]",
742                                         clientinfo_list[i].clientinfo->clientfd, i);
743                                 _handle_client_request(clientinfo_list[i].clientinfo);
744                                 if (is_timeout)
745                                         is_timeout = 0;
746                         } else if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &exceptset) > 0) {
747                                 TRACE_DEBUG_MSG("FD_ISSET [%d] exceptset slot[%d]", clientinfo_list[i].clientinfo->clientfd, i);
748                                 clear_clientinfoslot(&clientinfo_list[i]);
749                         }
750                 } // MAX_CLIENT
751
752                 if (FD_ISSET(listenfd, &exceptset) > 0) {
753                         TRACE_DEBUG_MSG("meet listenfd Exception of socket");
754                         TerminateDaemon(SIGTERM);
755                         break;
756                 } else if (FD_ISSET(listenfd, &rset) > 0) { // new connection
757                         TRACE_DEBUG_INFO_MSG("FD_ISSET listenfd rset");
758                         if (is_timeout)
759                                 is_timeout = 0;
760                         // reset timeout.
761                         flexible_timeout =
762                                 DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
763                         // ready the buffer.
764                         request_clientinfo =
765                                 (download_clientinfo *) calloc(1,
766                                                         sizeof(download_clientinfo));
767                         if (!request_clientinfo) {
768                                 TRACE_DEBUG_MSG
769                                         ("download-provider can't allocate the memory, try later");
770                                 clientlen = sizeof(clientaddr);
771                                 int clientfd = accept(listenfd,
772                                         (struct sockaddr *)&clientaddr, &clientlen);
773                                 close(clientfd);        // disconnect.
774                                 sleep(5);       // provider need the time of refresh.
775                                 continue;
776                         }
777                         // accept client.
778                         clientlen = sizeof(clientaddr);
779                         request_clientinfo->clientfd = accept(listenfd,
780                                                                 (struct sockaddr*)&clientaddr,
781                                                                 &clientlen);
782                         if (request_clientinfo->clientfd < 0) {
783                                 clear_clientinfo(request_clientinfo);
784                                 sleep(5);       // provider need the time of refresh.
785                                 continue;
786                         }
787                         if (_handle_new_connection(clientinfo_list, request_clientinfo) < 0) {
788                                 sleep(1);
789                                 continue;
790                         }
791                         // after starting the download by DA, event thread will start to get the event from client.
792                         if (request_clientinfo && request_clientinfo->clientfd > 0) {
793                                 FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_readset);      // add new descriptor to set
794                                 FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_exceptset);
795                                 if (request_clientinfo->clientfd > maxfd )
796                                         maxfd = request_clientinfo->clientfd;   /* for select */
797                         }
798                 }
799
800                 if (is_timeout) { // timeout
801                         // If there is better solution to be able to know
802                         // the number of downloading threads, replace below rough codes.
803                         active_count = get_downloading_count(clientinfo_list);
804                         // check whether the number of downloading is already maximum.
805                         if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE)
806                                 continue;
807
808                         unsigned free_slot_count
809                                         = DA_MAX_DOWNLOAD_REQ_AT_ONCE - active_count;
810                         int pendedslot = get_pended_slot_index(clientinfo_list);
811                         if(pendedslot >= 0) {
812                                 TRACE_DEBUG_INFO_MSG ("Free Space [%d]", free_slot_count);
813                                 for (;free_slot_count > 0 && pendedslot >= 0; free_slot_count--) {
814                                         TRACE_DEBUG_INFO_MSG ("start pended job [%d]", pendedslot);
815                                         if (_create_download_thread(&clientinfo_list[pendedslot]) > 0)
816                                                 active_count++;
817                                         pendedslot = get_pended_slot_index(clientinfo_list);
818                                 }
819                         }
820
821                         if (check_retry && free_slot_count > 0) {
822                                 // Auto re-download feature. 
823                                 // ethernet may be connected with other downloading items.
824                                 if (get_network_status() < 0)
825                                         continue;
826
827                                 // check auto-retrying list regardless state. pended state is also included to checking list.
828                                 int i = 0;
829                                 download_dbinfo_list *db_list =
830                                         download_provider_db_get_list(DOWNLOAD_STATE_NONE);
831                                 if (!db_list || db_list->count <= 0) {
832                                         TRACE_DEBUG_INFO_MSG
833                                                 ("provider does not need to check DB anymore. in this life.");
834                                         // provider does not need to check DB anymore. in this life.
835                                         check_retry = 0;
836                                         if (db_list)
837                                                 download_provider_db_list_free(db_list);
838                                         continue;
839                                 }
840                                 for (i = 0;
841                                         active_count <
842                                         DA_MAX_DOWNLOAD_REQ_AT_ONCE
843                                         && i < db_list->count; i++) {
844                                         if (db_list->item[i].requestid <= 0)
845                                                 continue;
846                                         if (get_same_request_slot_index
847                                                 (clientinfo_list,db_list->item[i].requestid) < 0) {
848                                                 // not found requestid in memory
849                                                 TRACE_DEBUG_INFO_MSG
850                                                         ("Retry download [%d]",
851                                                         db_list->item[i].requestid);
852                                                 //search empty slot. copy db info to slot.
853                                                 searchslot =
854                                                         get_empty_slot_index(clientinfo_list);
855                                                 if (searchslot < 0) {
856                                                         TRACE_DEBUG_INFO_MSG
857                                                                 ("download-provider is busy, try later");
858                                                         flexible_timeout =
859                                                                 flexible_timeout * 2;
860                                                         break;
861                                                 }
862                                                 // allocte requestinfo to empty slot.
863                                                 request_clientinfo =
864                                                         (download_clientinfo *)
865                                                         calloc(1, sizeof(download_clientinfo));
866                                                 if (!request_clientinfo)
867                                                         continue;
868                                                 request_clientinfo->requestinfo
869                                                         =
870                                                         download_provider_db_get_requestinfo
871                                                         (&db_list->item[i]);
872                                                 if (!request_clientinfo->requestinfo) {
873                                                         free(request_clientinfo);
874                                                         request_clientinfo = NULL;
875                                                         continue;
876                                                 }
877
878                                                 CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL);
879                                                 request_clientinfo->state = DOWNLOAD_STATE_READY;
880                                                 clientinfo_list[searchslot].clientinfo =
881                                                         request_clientinfo;
882
883                                                 TRACE_DEBUG_INFO_MSG
884                                                         ("Retry download [%d/%d][%d/%d]",
885                                                         searchslot, MAX_CLIENT,
886                                                         active_count,
887                                                         DA_MAX_DOWNLOAD_REQ_AT_ONCE);
888                                                 if (_create_download_thread(&clientinfo_list[searchslot]) > 0)
889                                                         active_count++;
890                                         }
891                                 }
892                                 if (i >= db_list->count)        // do not search anymore.
893                                         check_retry = 0;
894                                 download_provider_db_list_free(db_list);
895                         }
896
897                         // save system resource (CPU)
898                         if (check_retry == 0 && active_count == 0
899                                 && flexible_timeout <
900                                 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
901                                 flexible_timeout = flexible_timeout * 2;
902                         if (flexible_timeout >
903                                 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
904                                 flexible_timeout =
905                                         DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL;
906                         TRACE_DEBUG_INFO_MSG("Next Timeout after [%ld] sec",
907                                         flexible_timeout);
908
909                 } // if (i >= MAX_CLIENT) { // timeout
910         }
911
912         FD_CLR(listenfd, &rset);
913         FD_CLR(listenfd, &exceptset);
914         FD_CLR(listenfd, &g_download_provider_socket_readset);
915         FD_CLR(listenfd, &g_download_provider_socket_exceptset);
916
917         // close accept socket.
918         if (listenfd)
919                 close(listenfd);
920
921         _deinit_agent();
922
923         // close all sockets for client. .. 
924         // client thread will terminate by itself through catching this closing.
925         for (searchslot = 0; searchslot < MAX_CLIENT; searchslot++)
926                 if (clientinfo_list[searchslot].clientinfo)
927                         clear_clientinfoslot(&clientinfo_list[searchslot]);
928
929         if (clientinfo_list)
930                 free(clientinfo_list);
931
932         pthread_exit(NULL);
933         return 0;
934 }
935
936 void __download_info_cb(user_download_info_t *download_info, void *user_data)
937 {
938         int len = 0;
939         if (!user_data) {
940                 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
941                 return;
942         }
943         download_clientinfo_slot *clientinfoslot =
944                 (download_clientinfo_slot *) user_data;
945         download_clientinfo *clientinfo =
946                 (download_clientinfo *) clientinfoslot->clientinfo;
947         if (!clientinfo) {
948                 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
949                 return;
950         }
951         TRACE_DEBUG_INFO_MSG("id[%d],size[%lu]",
952                         download_info->da_dl_req_id, download_info->file_size);
953
954         if (clientinfo->req_id != download_info->da_dl_req_id) {
955                 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
956                                 clientinfo->req_id,
957                                 download_info->da_dl_req_id);
958                 return;
959         }
960         CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
961         if (!clientinfo->downloadinfo)
962                 clientinfo->downloadinfo =
963                         (download_content_info *) calloc(1, sizeof(download_content_info));
964         if (clientinfo->downloadinfo)
965                 clientinfo->downloadinfo->file_size = download_info->file_size;
966         if (download_info->file_type) {
967                 TRACE_DEBUG_INFO_MSG("mime[%s]", download_info->file_type);
968
969                 len = strlen(download_info->file_type);
970                 if (len > (DP_MAX_STR_LEN - 1))
971                         len = DP_MAX_STR_LEN - 1;
972                 if (clientinfo->downloadinfo) {
973                         strncpy(clientinfo->downloadinfo->mime_type,
974                                 download_info->file_type, len);
975                         download_provider_db_requestinfo_update_column
976                                 (clientinfo, DOWNLOAD_DB_MIMETYPE);
977                 }
978         }
979         if (download_info->tmp_saved_path) {
980                 char *str = NULL;
981                 TRACE_DEBUG_INFO_MSG("tmp path[%s]", download_info->tmp_saved_path);
982                 clientinfo->tmp_saved_path =
983                         strdup(download_info->tmp_saved_path);
984                 download_provider_db_requestinfo_update_column(clientinfo,
985                                                                         DOWNLOAD_DB_SAVEDPATH);
986                 str = strrchr(download_info->tmp_saved_path, '/');
987                 if (str) {
988                         str++;
989                         len = strlen(str);
990                         if (len > (DP_MAX_STR_LEN - 1))
991                                 len = DP_MAX_STR_LEN - 1;
992                         if (clientinfo->downloadinfo) {
993                                 strncpy(clientinfo->downloadinfo->content_name,
994                                         str, len);
995                                 download_provider_db_requestinfo_update_column
996                                         (clientinfo, DOWNLOAD_DB_FILENAME);
997                                 TRACE_DEBUG_INFO_MSG("content_name[%s]",
998                                                 clientinfo->downloadinfo->
999                                                 content_name);
1000                         }
1001                 }
1002         }
1003
1004         if (clientinfo->requestinfo->callbackinfo.started)
1005                 ipc_send_downloadinfo(clientinfo);
1006
1007         CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1008 }
1009
1010 void __downloading_info_cb(user_downloading_info_t *download_info,
1011                            void *user_data)
1012 {
1013         int len = 0;
1014         if (!user_data) {
1015                 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
1016                 return;
1017         }
1018         download_clientinfo_slot *clientinfoslot =
1019                 (download_clientinfo_slot *) user_data;
1020         download_clientinfo *clientinfo =
1021                 (download_clientinfo *) clientinfoslot->clientinfo;
1022         if (!clientinfo) {
1023                 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
1024                 return;
1025         }
1026         CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
1027         if (clientinfo->req_id != download_info->da_dl_req_id) {
1028                 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
1029                                 clientinfo->req_id,
1030                                 download_info->da_dl_req_id);
1031                 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1032                 return;
1033         }
1034         if (!clientinfo->downloadinginfo)
1035                 clientinfo->downloadinginfo = (downloading_state_info *) calloc(1,
1036                                                                         sizeof(downloading_state_info));
1037         if (clientinfo->downloadinginfo)
1038                 clientinfo->downloadinginfo->received_size =
1039                         download_info->total_received_size;
1040         if (download_info->saved_path) {
1041                 TRACE_DEBUG_INFO_MSG("tmp path[%s]", download_info->saved_path);
1042                 len = strlen(download_info->saved_path);
1043                 if (len > (DP_MAX_PATH_LEN - 1))
1044                         len = DP_MAX_PATH_LEN - 1;
1045                 if (clientinfo->downloadinginfo)
1046                         strncpy(clientinfo->downloadinginfo->saved_path,
1047                                 download_info->saved_path, len);
1048                 /* FIXME : This should be reviewd again after smack rules is applied */
1049                 if (chown(clientinfo->downloadinginfo->saved_path,
1050                                 clientinfo->credentials.uid,
1051                                 clientinfo->credentials.gid) < 0)
1052                         TRACE_DEBUG_INFO_MSG("Fail to chown [%s]", strerror(errno));
1053         }
1054
1055         static size_t updated_second;
1056         time_t tt = time(NULL);
1057         struct tm *localTime = localtime(&tt);
1058
1059         if (updated_second != localTime->tm_sec || download_info->saved_path) { // every 1 second.
1060                 if (clientinfo->requestinfo
1061                         && clientinfo->requestinfo->notification)
1062                         set_downloadinginfo_appfw_notification(clientinfo);
1063                 if (clientinfo->requestinfo->callbackinfo.progress)
1064                         ipc_send_downloadinginfo(clientinfo);
1065                 updated_second = localTime->tm_sec;
1066         }
1067         CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1068 }
1069
1070 void __notify_cb(user_notify_info_t *notify_info, void *user_data)
1071 {
1072         if (!user_data) {
1073                 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
1074                 return;
1075         }
1076         download_clientinfo_slot *clientinfoslot =
1077                 (download_clientinfo_slot *) user_data;
1078         download_clientinfo *clientinfo =
1079                 (download_clientinfo *) clientinfoslot->clientinfo;
1080         if (!clientinfo) {
1081                 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
1082                 return;
1083         }
1084
1085         TRACE_DEBUG_INFO_MSG("id[%d],state[%d],err[%d]",
1086                         notify_info->da_dl_req_id,
1087                         notify_info->state, notify_info->err);
1088         if (clientinfo->req_id != notify_info->da_dl_req_id) {
1089                 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
1090                                 clientinfo->req_id, notify_info->da_dl_req_id);
1091                 return;
1092         }
1093
1094         CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
1095
1096         clientinfo->state = __change_state(notify_info->state);
1097         clientinfo->err = __change_error(notify_info->err);
1098         if (clientinfo->state == DOWNLOAD_STATE_FINISHED ||
1099                         clientinfo->state == DOWNLOAD_STATE_FAILED) {
1100                 if (clientinfo->requestinfo) {
1101                         if (clientinfo->requestinfo->notification)
1102                                 set_downloadedinfo_appfw_notification(clientinfo);
1103                         download_provider_db_requestinfo_remove(clientinfo->
1104                                 requestinfo->requestid);
1105                 }
1106                 download_provider_db_history_new(clientinfo);
1107                 TRACE_DEBUG_INFO_MSG("[TEST]Finish clientinfo[%p], fd[%d]",
1108                         clientinfo, clientinfo->clientfd);
1109         }
1110
1111         TRACE_DEBUG_INFO_MSG("state[%d]", clientinfo->state);
1112         ipc_send_stateinfo(clientinfo);
1113
1114         CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1115 }
1116
1117 int __change_state(da_state state)
1118 {
1119         int ret = DOWNLOAD_STATE_NONE;
1120         switch (state) {
1121         case DA_STATE_WAITING:
1122         case DA_STATE_DOWNLOAD_STARTED:
1123                 TRACE_DEBUG_INFO_MSG("DA_STATE_DOWNLOAD_STARTED");
1124                 ret = DOWNLOAD_STATE_READY;
1125                 break;
1126         case DA_STATE_DOWNLOADING:
1127                 TRACE_DEBUG_INFO_MSG("DA_STATE_DOWNLOADING");
1128                 ret = DOWNLOAD_STATE_DOWNLOADING;
1129                 break;
1130         case DA_STATE_DOWNLOAD_COMPLETE:
1131                 TRACE_DEBUG_INFO_MSG("DA_STATE_COMPLETE");
1132                 ret = DOWNLOAD_STATE_INSTALLING;
1133                 break;
1134         case DA_STATE_CANCELED:
1135                 TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED");
1136                 ret = DOWNLOAD_STATE_STOPPED;
1137                 break;
1138         case DA_STATE_CANCELED_ALL:
1139                 TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED_ALL");
1140                 break;
1141         case DA_STATE_SUSPENDED:
1142                 TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED");
1143                 ret = DOWNLOAD_STATE_PAUSED;
1144                 break;
1145         case DA_STATE_SUSPENDED_ALL:
1146                 TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED_ALL");
1147                 break;
1148         case DA_STATE_RESUMED:
1149                 TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED");
1150                 ret = DOWNLOAD_STATE_DOWNLOADING;
1151                 break;
1152         case DA_STATE_RESUMED_ALL:
1153                 TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED_ALL");
1154                 break;
1155         case DA_STATE_FINISHED:
1156                 TRACE_DEBUG_INFO_MSG("DA_STATE_FINISHED");
1157                 ret = DOWNLOAD_STATE_FINISHED;
1158                 break;
1159         case DA_STATE_FAILED:
1160                 TRACE_DEBUG_INFO_MSG("DA_STATE_FAILED");
1161                 ret = DOWNLOAD_STATE_FAILED;
1162                 break;
1163         default:
1164                 break;
1165         }
1166         return ret;
1167 }
1168
1169 int __change_error(int err)
1170 {
1171         int ret = DOWNLOAD_ERROR_UNKOWN;
1172         switch (err) {
1173         case DA_RESULT_OK:
1174                 ret = DOWNLOAD_ERROR_NONE;
1175                 break;
1176         case DA_ERR_INVALID_ARGUMENT:
1177                 ret = DOWNLOAD_ERROR_INVALID_PARAMETER;
1178                 break;
1179         case DA_ERR_FAIL_TO_MEMALLOC:
1180                 ret = DOWNLOAD_ERROR_OUT_OF_MEMORY;
1181                 break;
1182         case DA_ERR_UNREACHABLE_SERVER:
1183                 ret = DOWNLOAD_ERROR_NETWORK_UNREACHABLE;
1184                 break;
1185         case DA_ERR_HTTP_TIMEOUT:
1186                 ret = DOWNLOAD_ERROR_CONNECTION_TIMED_OUT;
1187                 break;
1188         case DA_ERR_DISK_FULL:
1189                 ret = DOWNLOAD_ERROR_NO_SPACE;
1190                 break;
1191         case DA_ERR_INVALID_STATE:
1192                 ret = DOWNLOAD_ERROR_INVALID_STATE;
1193                 break;
1194         case DA_ERR_NETWORK_FAIL:
1195                 ret = DOWNLOAD_ERROR_CONNECTION_FAILED;
1196                 break;
1197         case DA_ERR_INVALID_URL:
1198                 ret = DOWNLOAD_ERROR_INVALID_URL;
1199                 break;
1200         case DA_ERR_INVALID_INSTALL_PATH:
1201                 ret = DOWNLOAD_ERROR_INVALID_DESTINATION;
1202                 break;
1203         case DA_ERR_ALREADY_MAX_DOWNLOAD:
1204                 ret = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
1205                 break;
1206         case DA_ERR_FAIL_TO_INSTALL_FILE:
1207                 ret = DOWNLOAD_ERROR_INSTALL_FAIL;
1208                 break;
1209         case DA_ERR_FAIL_TO_CREATE_THREAD:
1210         case DA_ERR_FAIL_TO_OBTAIN_MUTEX:
1211         case DA_ERR_FAIL_TO_ACCESS_FILE:
1212         case DA_ERR_FAIL_TO_GET_CONF_VALUE:
1213         case DA_ERR_FAIL_TO_ACCESS_STORAGE:
1214         case DA_ERR_DLOPEN_FAIL:
1215                 ret = DOWNLOAD_ERROR_IO_ERROR;
1216                 break;
1217         }
1218         return ret;
1219 }
1220
1221 int _init_agent()
1222 {
1223         int da_ret = 0;
1224         da_client_cb_t da_cb = {
1225                 __notify_cb,
1226                 __download_info_cb,
1227                 __downloading_info_cb
1228         };
1229         da_ret = da_init(&da_cb, DA_DOWNLOAD_MANAGING_METHOD_AUTO);
1230         if (da_ret != DA_RESULT_OK) {
1231                 return DOWNLOAD_ERROR_FAIL_INIT_AGENT;
1232         }
1233         return DOWNLOAD_ERROR_NONE;
1234 }
1235
1236 void _deinit_agent()
1237 {
1238         da_deinit();
1239 }