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