3 #include <sys/socket.h>
12 #include <net_connection.h>
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"
22 #include "download-agent-defs.h"
23 #include "download-agent-interface.h"
25 int _init_agent(void);
26 void _deinit_agent(void);
27 static void __downloading_info_cb(user_downloading_info_t *download_info,
29 static void __download_info_cb(user_download_info_t *download_info,
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);
35 void TerminateDaemon(int signo);
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;
41 void *_start_download(void *args)
46 download_clientinfo_slot *clientinfoslot =
47 (download_clientinfo_slot *) args;
48 if (!clientinfoslot) {
49 TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo_slot");
52 download_clientinfo *clientinfo =
53 (download_clientinfo *) clientinfoslot->clientinfo;
55 TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo");
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));
64 // call start_download() of download-agent
65 if (clientinfo->requestinfo->headers.rows > 0) {
68 char **req_header = NULL;
69 len = clientinfo->requestinfo->headers.rows;
70 req_header = calloc(len, sizeof(char *));
72 TRACE_DEBUG_MSG("fail to calloc");
75 for (i = 0; i < len; i++)
77 strdup(clientinfo->requestinfo->headers.str[i].str);
78 if (clientinfo->requestinfo->install_path.length > 1) {
79 if (clientinfo->requestinfo->filename.length > 1)
81 da_start_download_with_extension(clientinfo->requestinfo->
83 DA_FEATURE_REQUEST_HEADER,
85 DA_FEATURE_INSTALL_PATH,
86 clientinfo->requestinfo->install_path.str,
88 clientinfo->requestinfo->filename.str,
90 (void *)clientinfoslot,
94 da_start_download_with_extension(clientinfo->requestinfo->
96 DA_FEATURE_REQUEST_HEADER,
98 DA_FEATURE_INSTALL_PATH,
99 clientinfo->requestinfo->install_path.str,
100 DA_FEATURE_USER_DATA,
101 (void *)clientinfoslot,
104 if (clientinfo->requestinfo->filename.length > 1)
106 da_start_download_with_extension(clientinfo->requestinfo->
108 DA_FEATURE_REQUEST_HEADER,
110 DA_FEATURE_FILE_NAME,
111 clientinfo->requestinfo->filename.str,
112 DA_FEATURE_USER_DATA,
113 (void *)clientinfoslot,
117 da_start_download_with_extension(clientinfo->requestinfo->
119 DA_FEATURE_REQUEST_HEADER,
121 DA_FEATURE_USER_DATA,
122 (void *)clientinfoslot,
125 for (i = 0; i < len; i++) {
130 if (clientinfo->requestinfo->install_path.length > 1) {
131 if (clientinfo->requestinfo->filename.length > 1)
133 da_start_download_with_extension(clientinfo->requestinfo->
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,
144 da_start_download_with_extension(clientinfo->requestinfo->
146 DA_FEATURE_INSTALL_PATH,
147 clientinfo->requestinfo->install_path.str,
148 DA_FEATURE_USER_DATA,
149 (void *)clientinfoslot,
152 if (clientinfo->requestinfo->filename.length > 1)
154 da_start_download_with_extension(clientinfo->requestinfo->
156 DA_FEATURE_FILE_NAME,
157 clientinfo->requestinfo->filename.str,
158 DA_FEATURE_USER_DATA,
159 (void *)clientinfoslot,
163 da_start_download_with_extension(clientinfo->requestinfo->
165 DA_FEATURE_USER_DATA,
166 (void *)clientinfoslot,
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,
179 ipc_send_request_stateinfo(clientinfo);
180 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
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));
195 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
197 TRACE_DEBUG_INFO_MSG("started download [%d]", da_ret);
199 clientinfo->req_id = req_dl_id;
200 clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
201 clientinfo->err = DOWNLOAD_ERROR_NONE;
203 download_provider_db_requestinfo_update_column(clientinfo,
206 // sync return // client should be alive till this line at least.
207 ipc_send_request_stateinfo(clientinfo);
209 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
213 int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_clientinfo *request_clientinfo)
218 if (!clientinfo_list || !request_clientinfo ) {
219 TRACE_DEBUG_MSG("NULL-CHECK");
223 CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL);
227 sizeof(request_clientinfo->credentials);
229 (request_clientinfo->clientfd, SOL_SOCKET,
230 SO_PEERCRED, &request_clientinfo->credentials,
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);
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);
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
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)
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);
275 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
276 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
279 request_clientinfo->state = DOWNLOAD_STATE_NONE;
280 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
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;
308 download_provider_db_info_free(dbinfo);
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)
318 request_clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED;
319 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
321 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
322 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
325 request_clientinfo->state = DOWNLOAD_STATE_NONE;
326 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
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)
334 request_clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
335 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
337 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
338 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
341 request_clientinfo->state = DOWNLOAD_STATE_NONE;
342 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
344 ipc_send_stateinfo(request_clientinfo);
346 ipc_receive_header(request_clientinfo->clientfd);
348 clear_clientinfo(request_clientinfo);
352 if (type != DOWNLOAD_CONTROL_START) {
354 ("Now, DOWNLOAD_CONTROL_START is only supported");
355 clear_clientinfo(request_clientinfo);
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");
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);
373 } else { // found request id. // how to deal etag ?
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);
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);
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.
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.
417 clientinfo_list[searchslot].clientinfo = request_clientinfo;
419 TRACE_DEBUG_INFO_MSG("New Connection slot [%d] max [%d] max once [%d]",
422 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
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,
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.
439 // create thread for receiving the reqeust info from client.
440 // and if possible, it will create the thread for listening the event.
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,
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.
463 int _handle_client_request(download_clientinfo* clientinfo)
470 TRACE_DEBUG_MSG("NULL-CHECK");
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);
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);
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);
499 download_provider_db_history_new(clientinfo);
501 ipc_send_stateinfo(clientinfo);
502 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
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);
514 clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED;
515 clientinfo->err = DOWNLOAD_ERROR_NONE;
517 ipc_send_stateinfo(clientinfo);
518 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
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);
530 clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
531 clientinfo->err = DOWNLOAD_ERROR_NONE;
533 ipc_send_stateinfo(clientinfo);
534 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
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));
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));
550 TRACE_DEBUG_MSG("(Closed Socket ) terminate event thread (%d)",
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);
557 TRACE_DEBUG_MSG("Unknow message [%d]", msgType);
563 void *run_manage_download_server(void *args)
565 int listenfd = 0; // main socket to be albe to listen the new connection
568 fd_set rset, exceptset;
569 struct timeval timeout;
570 long flexible_timeout;
571 download_clientinfo_slot *clientinfo_list;
573 uint count_downloading_threads = 0;
574 download_clientinfo *request_clientinfo;
580 struct sockaddr_un listenaddr, clientaddr;
582 GMainLoop *mainloop = (GMainLoop *) args;
585 if (ret != DOWNLOAD_ERROR_NONE) {
586 TRACE_DEBUG_MSG("failed to init agent");
587 TerminateDaemon(SIGTERM);
590 clear_downloadinginfo_appfw_notification();
592 if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
593 TRACE_DEBUG_MSG("failed to create socket");
594 TerminateDaemon(SIGTERM);
598 bzero(&listenaddr, sizeof(listenaddr));
599 listenaddr.sun_family = AF_UNIX;
600 strcpy(listenaddr.sun_path, DOWNLOAD_PROVIDER_IPC);
602 if (bind(listenfd, (struct sockaddr *)&listenaddr, sizeof listenaddr) !=
604 TRACE_DEBUG_MSG("failed to call bind");
605 TerminateDaemon(SIGTERM);
609 if (chmod(listenaddr.sun_path, 0777) < 0) {
611 ("failed to change the permission of socket file");
612 TerminateDaemon(SIGTERM);
616 if (listen(listenfd, MAX_CLIENT) != 0) {
617 TRACE_DEBUG_MSG("failed to call listen");
618 TerminateDaemon(SIGTERM);
623 TRACE_DEBUG_INFO_MSG("Ready to listen IPC [%d][%s]", listenfd,
624 DOWNLOAD_PROVIDER_IPC);
626 // allocation the array structure for managing the clients.
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);
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);
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);
648 flexible_timeout = DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
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);
655 while (g_main_loop_is_running(mainloop)) {
658 for (i = 0; i < MAX_CLIENT; i++) {
659 if (!clientinfo_list[i].clientinfo)
662 if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
663 if (clientinfo_list[i].clientinfo->clientfd <= 0)
664 clear_clientinfoslot(&clientinfo_list[i]);
670 rset = g_download_provider_socket_readset;
671 exceptset = g_download_provider_socket_exceptset;
673 memset(&timeout, 0x00, sizeof(struct timeval));
674 timeout.tv_sec = flexible_timeout;
676 if (select((maxfd + 1), &rset, 0, &exceptset, &timeout) < 0) {
678 ("select error, provider can't receive any request from client.");
679 TerminateDaemon(SIGTERM);
683 for (i = 0; i < MAX_CLIENT; i++) { // find the socket received the packet.
684 if (!clientinfo_list[i].clientinfo)
686 //Even if no socket, downloading should be progressed.
687 if (clientinfo_list[i].clientinfo->clientfd <= 0)
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)
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);
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]);
704 if (FD_ISSET(listenfd, &exceptset) > 0) {
705 TRACE_DEBUG_MSG("meet listenfd Exception of socket");
706 TerminateDaemon(SIGTERM);
708 } else if (FD_ISSET(listenfd, &rset) > 0) { // new connection
709 TRACE_DEBUG_INFO_MSG("FD_ISSET listenfd rset");
714 DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
717 (download_clientinfo *) calloc(1,
718 sizeof(download_clientinfo));
719 if (!request_clientinfo) {
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.
730 clientlen = sizeof(clientaddr);
731 request_clientinfo->clientfd = accept(listenfd,
732 (struct sockaddr*)&clientaddr,
734 if (request_clientinfo->clientfd < 0) {
735 clear_clientinfo(request_clientinfo);
736 sleep(5); // provider need the time of refresh.
739 if (_handle_new_connection(clientinfo_list, request_clientinfo) < 0) {
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 */
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)
762 // search pended request
763 for (searchslot = 0; searchslot < MAX_CLIENT;
765 if (clientinfo_list[searchslot].clientinfo) {
766 if (clientinfo_list[searchslot].clientinfo->state ==
767 DOWNLOAD_STATE_PENDED) {
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.
775 (&clientinfo_list[searchslot].clientinfo->thread_pid,
776 &g_download_provider_thread_attr,
778 &clientinfo_list[searchslot]) != 0) {
780 ("failed to call pthread_create for client");
782 count_downloading_threads++;
783 usleep(1000); // sleep in busy state.
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) {
796 ("Failed connection_create");
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)
806 ("Failed connection_get_ethernet_state");
808 ("ethernet check result : [%d]", (int)system_network_state);
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)
816 ("Failed connection_get_ethernet_state");
818 ("cellula check result : [%d]", (int)system_cellular_state);
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)
826 ("Failed connection_get_ethernet_state");
828 ("wifi check result : [%d]", (int)system_wifi_state);
830 if (connection_destroy(network_handle) !=
831 CONNECTION_ERROR_NONE)
833 ("Failed connection_destroy");
835 if (!(system_network_state
836 == CONNECTION_ETHERNET_STATE_CONNECTED
837 || system_cellular_state
838 == CONNECTION_CELLULAR_STATE_AVAILABLE
840 == CONNECTION_WIFI_STATE_CONNECTED))
843 // check auto-retrying list regardless state. pended state is also included to checking list.
845 download_dbinfo_list *db_list =
846 download_provider_db_get_list(DOWNLOAD_STATE_NONE);
847 if (!db_list || db_list->count <= 0) {
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.
852 download_provider_db_list_free(db_list);
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)
861 if (get_same_request_slot_index
862 (clientinfo_list,db_list->item[i].requestid) < 0) {
863 // not found requestid in memory
865 ("Retry download [%d]",
866 db_list->item[i].requestid);
867 //search empty slot. copy db info to slot.
869 get_empty_slot_index(clientinfo_list);
870 if (searchslot < 0) {
872 ("download-provider is busy, try later");
874 flexible_timeout * 2;
877 // allocte requestinfo to empty slot.
879 (download_clientinfo *)
880 calloc(1, sizeof(download_clientinfo));
881 if (!request_clientinfo)
883 request_clientinfo->requestinfo
885 download_provider_db_get_requestinfo
887 if (!request_clientinfo->requestinfo) {
888 free(request_clientinfo);
889 request_clientinfo = NULL;
893 CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL);
894 request_clientinfo->state = DOWNLOAD_STATE_READY;
895 clientinfo_list[searchslot].clientinfo =
899 ("Retry download [%d/%d][%d/%d]",
900 searchslot, MAX_CLIENT,
901 count_downloading_threads,
902 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
904 (&clientinfo_list[searchslot].clientinfo->thread_pid,
905 &g_download_provider_thread_attr,
907 &clientinfo_list[searchslot])
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;
917 count_downloading_threads++;
918 usleep(1000); // sleep in busy state.
921 if (i >= db_list->count) // do not search anymore.
923 download_provider_db_list_free(db_list);
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)
934 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL;
935 TRACE_DEBUG_INFO_MSG("Next Timeout after [%ld] sec",
938 } // if (i >= MAX_CLIENT) { // timeout
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);
946 // close accept socket.
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]);
959 free(clientinfo_list);
965 void __download_info_cb(user_download_info_t *download_info, void *user_data)
969 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
972 download_clientinfo_slot *clientinfoslot =
973 (download_clientinfo_slot *) user_data;
974 download_clientinfo *clientinfo =
975 (download_clientinfo *) clientinfoslot->clientinfo;
977 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
980 TRACE_DEBUG_INFO_MSG("id[%d],size[%lu]",
981 download_info->da_dl_req_id, download_info->file_size);
983 if (clientinfo->req_id != download_info->da_dl_req_id) {
984 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
986 download_info->da_dl_req_id);
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);
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);
1008 if (download_info->tmp_saved_path) {
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, '/');
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,
1024 download_provider_db_requestinfo_update_column
1025 (clientinfo, DOWNLOAD_DB_FILENAME);
1026 TRACE_DEBUG_INFO_MSG("content_name[%s]",
1027 clientinfo->downloadinfo->
1033 if (clientinfo->requestinfo->callbackinfo.started)
1034 ipc_send_downloadinfo(clientinfo);
1036 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1039 void __downloading_info_cb(user_downloading_info_t *download_info,
1044 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
1047 download_clientinfo_slot *clientinfoslot =
1048 (download_clientinfo_slot *) user_data;
1049 download_clientinfo *clientinfo =
1050 (download_clientinfo *) clientinfoslot->clientinfo;
1052 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
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}",
1059 download_info->da_dl_req_id);
1060 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
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));
1084 static size_t updated_second;
1085 time_t tt = time(NULL);
1086 struct tm *localTime = localtime(&tt);
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;
1096 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1099 void __notify_cb(user_notify_info_t *notify_info, void *user_data)
1102 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
1105 download_clientinfo_slot *clientinfoslot =
1106 (download_clientinfo_slot *) user_data;
1107 download_clientinfo *clientinfo =
1108 (download_clientinfo *) clientinfoslot->clientinfo;
1110 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
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);
1123 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
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);
1135 download_provider_db_history_new(clientinfo);
1136 TRACE_DEBUG_INFO_MSG("[TEST]Finish clientinfo[%p], fd[%d]",
1137 clientinfo, clientinfo->clientfd);
1140 TRACE_DEBUG_INFO_MSG("state[%d]", clientinfo->state);
1141 ipc_send_stateinfo(clientinfo);
1143 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1146 int __change_state(da_state state)
1148 int ret = DOWNLOAD_STATE_NONE;
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;
1155 case DA_STATE_DOWNLOADING:
1156 TRACE_DEBUG_INFO_MSG("DA_STATE_DOWNLOADING");
1157 ret = DOWNLOAD_STATE_DOWNLOADING;
1159 case DA_STATE_DOWNLOAD_COMPLETE:
1160 TRACE_DEBUG_INFO_MSG("DA_STATE_COMPLETE");
1161 ret = DOWNLOAD_STATE_INSTALLING;
1163 case DA_STATE_CANCELED:
1164 TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED");
1165 ret = DOWNLOAD_STATE_STOPPED;
1167 case DA_STATE_CANCELED_ALL:
1168 TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED_ALL");
1170 case DA_STATE_SUSPENDED:
1171 TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED");
1172 ret = DOWNLOAD_STATE_PAUSED;
1174 case DA_STATE_SUSPENDED_ALL:
1175 TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED_ALL");
1177 case DA_STATE_RESUMED:
1178 TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED");
1179 ret = DOWNLOAD_STATE_DOWNLOADING;
1181 case DA_STATE_RESUMED_ALL:
1182 TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED_ALL");
1184 case DA_STATE_FINISHED:
1185 TRACE_DEBUG_INFO_MSG("DA_STATE_FINISHED");
1186 ret = DOWNLOAD_STATE_FINISHED;
1188 case DA_STATE_FAILED:
1189 TRACE_DEBUG_INFO_MSG("DA_STATE_FAILED");
1190 ret = DOWNLOAD_STATE_FAILED;
1198 int __change_error(int err)
1200 int ret = DOWNLOAD_ERROR_UNKOWN;
1203 ret = DOWNLOAD_ERROR_NONE;
1205 case DA_ERR_INVALID_ARGUMENT:
1206 ret = DOWNLOAD_ERROR_INVALID_PARAMETER;
1208 case DA_ERR_FAIL_TO_MEMALLOC:
1209 ret = DOWNLOAD_ERROR_OUT_OF_MEMORY;
1211 case DA_ERR_UNREACHABLE_SERVER:
1212 ret = DOWNLOAD_ERROR_NETWORK_UNREACHABLE;
1214 case DA_ERR_HTTP_TIMEOUT:
1215 ret = DOWNLOAD_ERROR_CONNECTION_TIMED_OUT;
1217 case DA_ERR_DISK_FULL:
1218 ret = DOWNLOAD_ERROR_NO_SPACE;
1220 case DA_ERR_INVALID_STATE:
1221 ret = DOWNLOAD_ERROR_INVALID_STATE;
1223 case DA_ERR_NETWORK_FAIL:
1224 ret = DOWNLOAD_ERROR_CONNECTION_FAILED;
1226 case DA_ERR_INVALID_URL:
1227 ret = DOWNLOAD_ERROR_INVALID_URL;
1229 case DA_ERR_INVALID_INSTALL_PATH:
1230 ret = DOWNLOAD_ERROR_INVALID_DESTINATION;
1232 case DA_ERR_ALREADY_MAX_DOWNLOAD:
1233 ret = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
1235 case DA_ERR_FAIL_TO_INSTALL_FILE:
1236 ret = DOWNLOAD_ERROR_INSTALL_FAIL;
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;
1253 da_client_cb_t da_cb = {
1256 __downloading_info_cb
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;
1262 return DOWNLOAD_ERROR_NONE;
1265 void _deinit_agent()