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