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_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_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_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_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 // get requestid from socket.
253 if (request_clientinfo->requestinfo
254 && request_clientinfo->requestinfo->requestid > 0) {
255 // search requestid in slots.
256 int searchindex = get_same_request_slot_index
258 request_clientinfo->requestinfo->requestid);
259 if (type == DOWNLOAD_CONTROL_STOP) {
260 TRACE_DEBUG_MSG("Request : DOWNLOAD_CONTROL_STOP");
261 if (searchindex >= 0) {
262 if (da_cancel_download
263 (clientinfo_list[searchindex].clientinfo->req_id)
265 request_clientinfo->state = DOWNLOAD_STATE_STOPPED;
266 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
267 if (clientinfo_list[searchindex].clientinfo->requestinfo
268 && clientinfo_list[searchindex].clientinfo->requestinfo->notification)
269 set_downloadedinfo_appfw_notification(clientinfo_list[searchindex].clientinfo);
270 download_provider_db_requestinfo_remove(request_clientinfo->requestinfo->requestid);
271 download_provider_db_history_new(clientinfo_list[searchindex].clientinfo);
273 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
274 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
277 request_clientinfo->state = DOWNLOAD_STATE_NONE;
278 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
280 ipc_send_stateinfo(request_clientinfo);
281 } else if (type == DOWNLOAD_CONTROL_GET_STATE_INFO) {
282 // search slots/downloading db/history db
283 if (searchindex > 0) { // exist in slots (memory)
284 request_clientinfo->state =
285 clientinfo_list[searchindex].clientinfo->state;
286 request_clientinfo->err =
287 clientinfo_list[searchindex].clientinfo->err;
288 } else { //search downloading db or history db
289 download_dbinfo* dbinfo =
290 download_provider_db_get_info(
291 request_clientinfo->requestinfo->requestid);
292 if (dbinfo) { // found in downloading db..it means crashed job
293 request_clientinfo->state = DOWNLOAD_STATE_PENDED;
294 request_clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
295 } else { // no exist in downloading db
296 dbinfo = download_provider_db_history_get_info(
297 request_clientinfo->requestinfo->requestid);
298 if (!dbinfo) { // no info anywhere
299 request_clientinfo->state = DOWNLOAD_STATE_NONE;
300 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
301 } else { //history info
302 request_clientinfo->state = dbinfo->state;
303 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
306 download_provider_db_info_free(dbinfo);
308 ipc_send_stateinfo(request_clientinfo);
309 // estabilish the spec of return value.
312 clear_clientinfo(request_clientinfo);
316 if (type != DOWNLOAD_CONTROL_START) {
318 ("Now, DOWNLOAD_CONTROL_START is only supported");
319 clear_clientinfo(request_clientinfo);
323 // check whether requestinfo has requestid or not.
324 if (request_clientinfo->requestinfo
325 && request_clientinfo->requestinfo->requestid > 0) {
326 // search same request id.
327 int searchindex = get_same_request_slot_index(clientinfo_list,
328 request_clientinfo->requestinfo->requestid);
329 if (searchindex < 0) {
330 TRACE_DEBUG_MSG("Not Found Same Request ID");
332 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
333 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
334 ipc_send_request_stateinfo(request_clientinfo);
335 clear_clientinfo(request_clientinfo);
337 } else { // found request id. // how to deal etag ?
339 TRACE_DEBUG_MSG("Found Same Request ID slot[%d]", searchindex);
340 CLIENT_MUTEX_LOCK(&(request_clientinfo->client_mutex));
341 // close previous socket.
342 if (clientinfo_list[searchindex].clientinfo->clientfd > 0)
343 close(clientinfo_list[searchindex].clientinfo->clientfd);
344 // change to new socket.
345 clientinfo_list[searchindex].clientinfo->clientfd =
346 request_clientinfo->clientfd;
347 ipc_send_request_stateinfo(clientinfo_list[searchindex].clientinfo);
349 clientinfo_list[searchindex].clientinfo->requestinfo->callbackinfo =
350 request_clientinfo->requestinfo->callbackinfo;
351 clientinfo_list[searchindex].clientinfo->requestinfo->notification =
352 request_clientinfo->requestinfo->notification;
353 request_clientinfo->clientfd = 0; // prevent to not be disconnected.
354 CLIENT_MUTEX_UNLOCK(&(request_clientinfo->client_mutex));
355 clear_clientinfo(request_clientinfo);
361 searchslot = get_empty_slot_index(clientinfo_list);
362 if (searchslot < 0) {
363 TRACE_DEBUG_MSG("download-provider is busy, try later");
364 clear_clientinfo(request_clientinfo);
365 sleep(5); // provider need the time of refresh.
368 // create new unique id, and insert info to DB.
369 if (request_clientinfo->requestinfo
370 && request_clientinfo->requestinfo->requestid <= 0) {
371 request_clientinfo->requestinfo->requestid =
372 get_download_request_id();
373 if (download_provider_db_requestinfo_new
374 (request_clientinfo) < 0) {
375 clear_clientinfo(request_clientinfo);
376 sleep(5); // provider need the time of refresh.
381 clientinfo_list[searchslot].clientinfo = request_clientinfo;
383 TRACE_DEBUG_MSG("New Connection slot [%d] max [%d] max once [%d]",
386 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
388 if (get_downloading_count(clientinfo_list) >=
389 DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
390 CLIENT_MUTEX_LOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
391 // deal as pended job.
392 clientinfo_list[searchslot].clientinfo->state = DOWNLOAD_STATE_PENDED;
393 clientinfo_list[searchslot].clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
394 download_provider_db_requestinfo_update_column
395 (clientinfo_list[searchslot].clientinfo,
397 ipc_send_request_stateinfo(clientinfo_list[searchslot].clientinfo);
398 TRACE_DEBUG_MSG ("Pended Request is saved to [%d/%d]",
399 searchslot, MAX_CLIENT);
400 CLIENT_MUTEX_UNLOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
401 sleep(5); // provider need the time of refresh.
403 // create thread for receiving the reqeust info from client.
404 // and if possible, it will create the thread for listening the event.
406 (&clientinfo_list[searchslot].clientinfo->thread_pid,
407 &g_download_provider_thread_attr, _start_download,
408 &clientinfo_list[searchslot]) != 0) {
409 TRACE_DEBUG_MSG("failed to call pthread_create for client");
410 TRACE_DEBUG_MSG("Change to pended job");
411 CLIENT_MUTEX_LOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
412 clientinfo_list[searchslot].clientinfo->state =
413 DOWNLOAD_STATE_PENDED;
414 clientinfo_list[searchslot].clientinfo->err =
415 DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
416 download_provider_db_requestinfo_update_column
417 (clientinfo_list[searchslot].clientinfo,
419 ipc_send_request_stateinfo(clientinfo_list[searchslot].clientinfo);
420 CLIENT_MUTEX_UNLOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
421 sleep(5); // provider need the time of refresh.
427 int _handle_client_request(download_clientinfo* clientinfo)
434 TRACE_DEBUG_MSG("NULL-CHECK");
438 switch (msgType = ipc_receive_header(clientinfo->clientfd)) {
439 case DOWNLOAD_CONTROL_STOP:
440 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_STOP");
441 da_ret = da_cancel_download(clientinfo->req_id);
442 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
443 if (da_ret != DA_RESULT_OK) {
444 /* FIXME : need to seperate in detail according to error return values */
445 clientinfo->state = DOWNLOAD_STATE_FAILED;
446 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
447 TRACE_DEBUG_MSG("Fail to request cancel [%d]", da_ret);
449 clientinfo->state = DOWNLOAD_STATE_STOPPED;
450 clientinfo->err = DOWNLOAD_ERROR_NONE;
451 if (clientinfo->requestinfo) {
452 if (clientinfo->requestinfo->notification)
453 set_downloadedinfo_appfw_notification(clientinfo);
454 download_provider_db_requestinfo_remove(clientinfo->
455 requestinfo->requestid);
457 download_provider_db_history_new(clientinfo);
459 ipc_send_stateinfo(clientinfo);
460 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
462 case DOWNLOAD_CONTROL_PAUSE:
463 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_PAUSE");
464 da_ret = da_suspend_download(clientinfo->req_id);
465 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
466 if (da_ret != DA_RESULT_OK) {
467 /* FIXME : need to seperate in detail according to error return values */
468 clientinfo->state = DOWNLOAD_STATE_FAILED;
469 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
470 TRACE_DEBUG_MSG("Fail to request suspend [%d]", da_ret);
472 clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED;
473 clientinfo->err = DOWNLOAD_ERROR_NONE;
475 ipc_send_stateinfo(clientinfo);
476 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
478 case DOWNLOAD_CONTROL_RESUME:
479 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_RESUME");
480 da_ret = da_resume_download(clientinfo->req_id);
481 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
482 if (da_ret != DA_RESULT_OK) {
483 /* FIXME : need to seperate in detail according to error return values */
484 clientinfo->state = DOWNLOAD_STATE_FAILED;
485 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
486 TRACE_DEBUG_MSG("Fail to request resume [%d]", da_ret);
488 clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
489 clientinfo->err = DOWNLOAD_ERROR_NONE;
491 ipc_send_stateinfo(clientinfo);
492 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
494 case DOWNLOAD_CONTROL_GET_STATE_INFO: // sync call
495 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_GET_STATE_INFO");
496 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
497 ipc_send_stateinfo(clientinfo);
498 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
500 case DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO: // sync call
501 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO");
502 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
503 ipc_send_downloadinfo(clientinfo);
504 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
508 TRACE_DEBUG_MSG("(Closed Socket ) terminate event thread (%d)",
510 // bloken socket... it seems the client is dead or closed by agent thread.
511 // close socket, this will break the loop. and terminate this thread.
512 clear_socket(clientinfo);
515 TRACE_DEBUG_MSG("Unknow message [%d]", msgType);
521 void *run_manage_download_server(void *args)
523 int listenfd = 0; // main socket to be albe to listen the new connection
526 fd_set rset, exceptset;
527 struct timeval timeout;
528 long flexible_timeout;
529 download_clientinfo_slot *clientinfo_list;
531 uint count_downloading_threads = 0;
532 download_clientinfo *request_clientinfo;
537 struct sockaddr_un listenaddr, clientaddr;
539 GMainLoop *mainloop = (GMainLoop *) args;
542 if (ret != DOWNLOAD_ERROR_NONE) {
543 TRACE_DEBUG_MSG("failed to init agent");
544 TerminateDaemon(SIGTERM);
547 clear_downloadinginfo_appfw_notification();
549 if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
550 TRACE_DEBUG_MSG("failed to create socket");
551 TerminateDaemon(SIGTERM);
555 bzero(&listenaddr, sizeof(listenaddr));
556 listenaddr.sun_family = AF_UNIX;
557 strcpy(listenaddr.sun_path, DOWNLOAD_PROVIDER_IPC);
559 if (bind(listenfd, (struct sockaddr *)&listenaddr, sizeof listenaddr) !=
561 TRACE_DEBUG_MSG("failed to call bind");
562 TerminateDaemon(SIGTERM);
566 if (chmod(listenaddr.sun_path, 0777) < 0) {
568 ("failed to change the permission of socket file");
569 TerminateDaemon(SIGTERM);
573 if (listen(listenfd, MAX_CLIENT) != 0) {
574 TRACE_DEBUG_MSG("failed to call listen");
575 TerminateDaemon(SIGTERM);
580 TRACE_DEBUG_MSG("Ready to listen IPC [%d][%s]", listenfd,
581 DOWNLOAD_PROVIDER_IPC);
583 // allocation the array structure for managing the clients.
585 (download_clientinfo_slot *) calloc(MAX_CLIENT,
586 sizeof(download_clientinfo_slot));
587 if (clientinfo_list == NULL) {
588 TRACE_DEBUG_MSG("failed to allocate the memory for client list");
589 TerminateDaemon(SIGTERM);
593 if (pthread_attr_init(&g_download_provider_thread_attr) != 0) {
594 TRACE_DEBUG_MSG("failed to call pthread_attr_init for client");
595 TerminateDaemon(SIGTERM);
598 if (pthread_attr_setdetachstate(&g_download_provider_thread_attr,
599 PTHREAD_CREATE_DETACHED) != 0) {
600 TRACE_DEBUG_MSG("failed to set detach option");
601 TerminateDaemon(SIGTERM);
605 flexible_timeout = DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
607 FD_ZERO(&g_download_provider_socket_readset);
608 FD_ZERO(&g_download_provider_socket_exceptset);
609 FD_SET(listenfd, &g_download_provider_socket_readset);
610 FD_SET(listenfd, &g_download_provider_socket_exceptset);
612 while (g_main_loop_is_running(mainloop)) {
615 for (i=0; i < MAX_CLIENT; i++) {
616 if (!clientinfo_list[i].clientinfo)
619 if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
620 clear_clientinfoslot(&clientinfo_list[i]);
625 rset = g_download_provider_socket_readset;
626 exceptset = g_download_provider_socket_exceptset;
628 timeout.tv_sec = flexible_timeout;
630 if (select((maxfd + 1), &rset, 0, &exceptset, &timeout) < 0) {
632 ("select error, provider can't receive any request from client.");
633 TerminateDaemon(SIGTERM);
637 for (i=0; i < MAX_CLIENT; i++) { // find the socket received the packet.
638 if (!clientinfo_list[i].clientinfo)
640 // ignore it is not started yet.
641 if (clientinfo_list[i].clientinfo->state <= DOWNLOAD_STATE_READY)
643 // ignore if finished
644 if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED)
646 //Even if no socket, downloading should be progressed.
647 if (clientinfo_list[i].clientinfo->clientfd <= 0)
649 if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &rset) > 0) {
650 TRACE_DEBUG_MSG("FD_ISSET [%d] readset slot[%d]",
651 clientinfo_list[i].clientinfo->clientfd, i);
652 _handle_client_request(clientinfo_list[i].clientinfo);
653 } else if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &exceptset) > 0) {
654 TRACE_DEBUG_MSG("FD_ISSET [%d] exceptset slot[%d]", clientinfo_list[i].clientinfo->clientfd, i);
655 clear_clientinfoslot(&clientinfo_list[i]);
659 if (FD_ISSET(listenfd, &exceptset) > 0) {
660 TRACE_DEBUG_MSG("meet listenfd Exception of socket");
661 TerminateDaemon(SIGTERM);
663 } else if (FD_ISSET(listenfd, &rset) > 0) { // new connection
664 TRACE_DEBUG_MSG("FD_ISSET listenfd rset");
667 DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
670 (download_clientinfo *) calloc(1,
671 sizeof(download_clientinfo));
672 if (!request_clientinfo) {
674 ("download-provider can't allocate the memory, try later");
675 clientlen = sizeof(clientaddr);
676 int clientfd = accept(listenfd,
677 (struct sockaddr *)&clientaddr, &clientlen);
678 close(clientfd); // disconnect.
679 sleep(5); // provider need the time of refresh.
683 clientlen = sizeof(clientaddr);
684 request_clientinfo->clientfd = accept(listenfd,
685 (struct sockaddr*)&clientaddr,
687 if (request_clientinfo->clientfd < 0) {
688 clear_clientinfo(request_clientinfo);
689 sleep(5); // provider need the time of refresh.
692 if (_handle_new_connection(clientinfo_list, request_clientinfo) < 0) {
696 // after starting the download by DA, event thread will start to get the event from client.
697 if (request_clientinfo && request_clientinfo->clientfd > 0) {
698 FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_readset); // add new descriptor to set
699 FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_exceptset);
700 if (request_clientinfo->clientfd > maxfd )
701 maxfd = request_clientinfo->clientfd; /* for select */
705 if (i >= MAX_CLIENT) { // timeout
706 // If there is better solution to be able to know
707 // the number of downloading threads, replace below rough codes.
708 count_downloading_threads =
709 get_downloading_count(clientinfo_list);
710 // check whether the number of downloading is already maximum.
711 if (count_downloading_threads >=
712 DA_MAX_DOWNLOAD_REQ_AT_ONCE)
715 // search pended request
716 for (searchslot = 0; searchslot < MAX_CLIENT;
718 if (clientinfo_list[searchslot].clientinfo) {
719 if (clientinfo_list[searchslot].clientinfo->state ==
720 DOWNLOAD_STATE_PENDED) {
722 ("Retry Pended Request [%d/%d] state [%d/%d]",
723 searchslot, MAX_CLIENT,
724 count_downloading_threads,
725 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
726 // create thread for restarting the pended download.
728 (&clientinfo_list[searchslot].clientinfo->thread_pid,
729 &g_download_provider_thread_attr,
731 &clientinfo_list[searchslot]) != 0) {
733 ("failed to call pthread_create for client");
735 count_downloading_threads++;
736 usleep(1000); // sleep in busy state.
743 && count_downloading_threads <
744 DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
745 // Auto re-download feature. ethernet may be connected with other downloading items.
746 connection_h network_handle = NULL;
747 connection_ethernet_state_e system_network_state
748 = CONNECTION_ETHERNET_STATE_DISCONNECTED;
749 if (connection_create(&network_handle) < 0) {
751 ("Failed connection_create");
754 if (connection_get_ethernet_state(network_handle,
755 &system_network_state) !=
756 CONNECTION_ERROR_NONE)
758 ("Failed connection_get_ethernet_state");
759 if (connection_destroy(network_handle) !=
760 CONNECTION_ERROR_NONE)
762 ("Failed connection_destroy");
763 if (system_network_state !=
764 CONNECTION_ETHERNET_STATE_CONNECTED)
766 // check auto-retrying list regardless state. pended state is also included to checking list.
768 download_dbinfo_list *db_list =
769 download_provider_db_get_list(DOWNLOAD_STATE_NONE);
770 if (!db_list || db_list->count <= 0) {
772 ("provider does not need to check DB anymore. in this life.");
773 check_retry = 0; // provider does not need to check DB anymore. in this life.
775 download_provider_db_list_free(db_list);
779 count_downloading_threads <
780 DA_MAX_DOWNLOAD_REQ_AT_ONCE
781 && i < db_list->count; i++) {
782 if (db_list->item[i].requestid <= 0)
784 if (get_same_request_slot_index
785 (clientinfo_list,db_list->item[i].requestid) < 0) {
786 // not found requestid in memory
788 ("Retry download [%d]",
789 db_list->item[i].requestid);
790 //search empty slot. copy db info to slot.
792 get_empty_slot_index(clientinfo_list);
793 if (searchslot < 0) {
795 ("download-provider is busy, try later");
797 flexible_timeout * 2;
800 // allocte requestinfo to empty slot.
802 (download_clientinfo *)
803 calloc(1, sizeof(download_clientinfo));
804 if (!request_clientinfo)
806 request_clientinfo->requestinfo
808 download_provider_db_get_requestinfo
810 if (!request_clientinfo->requestinfo) {
811 free(request_clientinfo);
812 request_clientinfo = NULL;
816 clientinfo_list[searchslot].clientinfo =
820 ("Retry download [%d/%d][%d/%d]",
821 searchslot, MAX_CLIENT,
822 count_downloading_threads,
823 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
825 (&clientinfo_list[searchslot].clientinfo->thread_pid,
826 &g_download_provider_thread_attr,
828 &clientinfo_list[searchslot])
831 ("failed to call pthread_create for client");
832 clientinfo_list[searchslot].clientinfo->state =
833 DOWNLOAD_STATE_PENDED;
834 clientinfo_list[searchslot].clientinfo->err =
835 DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
838 count_downloading_threads++;
839 usleep(1000); // sleep in busy state.
842 if (i >= db_list->count) // do not search anymore.
844 download_provider_db_list_free(db_list);
847 // save system resource (CPU)
848 if (check_retry == 0 && count_downloading_threads == 0
849 && flexible_timeout <
850 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
851 flexible_timeout = flexible_timeout * 2;
852 if (flexible_timeout >
853 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
855 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL;
856 TRACE_DEBUG_MSG("Next Timeout after [%ld] sec",
859 } // if (i >= MAX_CLIENT) { // timeout
862 FD_CLR(listenfd, &rset);
863 FD_CLR(listenfd, &exceptset);
864 FD_CLR(listenfd, &g_download_provider_socket_readset);
865 FD_CLR(listenfd, &g_download_provider_socket_exceptset);
867 // close accept socket.
873 // close all sockets for client. ..
874 // client thread will terminate by itself through catching this closing.
875 for (searchslot = 0; searchslot < MAX_CLIENT; searchslot++)
876 if (clientinfo_list[searchslot].clientinfo)
877 clear_clientinfoslot(&clientinfo_list[searchslot]);
880 free(clientinfo_list);
886 void __download_info_cb(user_download_info_t *download_info, void *user_data)
890 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
893 download_clientinfo_slot *clientinfoslot =
894 (download_clientinfo_slot *) user_data;
895 download_clientinfo *clientinfo =
896 (download_clientinfo *) clientinfoslot->clientinfo;
898 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
901 TRACE_DEBUG_MSG("id[%d],size[%lu]",
902 download_info->da_dl_req_id, download_info->file_size)
904 if (clientinfo->req_id != download_info->da_dl_req_id) {
905 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
907 download_info->da_dl_req_id);
910 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
911 if (!clientinfo->downloadinfo)
912 clientinfo->downloadinfo =
913 (download_content_info *) calloc(1, sizeof(download_content_info));
914 if (clientinfo->downloadinfo)
915 clientinfo->downloadinfo->file_size = download_info->file_size;
916 if (download_info->file_type) {
917 TRACE_DEBUG_MSG("mime[%s]", download_info->file_type);
919 len = strlen(download_info->file_type);
920 if (len > (DP_MAX_STR_LEN - 1))
921 len = DP_MAX_STR_LEN - 1;
922 if (clientinfo->downloadinfo) {
923 strncpy(clientinfo->downloadinfo->mime_type,
924 download_info->file_type, len);
925 download_provider_db_requestinfo_update_column
926 (clientinfo, DOWNLOAD_DB_MIMETYPE);
929 if (download_info->tmp_saved_path) {
931 TRACE_DEBUG_MSG("tmp path[%s]", download_info->tmp_saved_path);
932 clientinfo->tmp_saved_path =
933 strdup(download_info->tmp_saved_path);
934 download_provider_db_requestinfo_update_column(clientinfo,
935 DOWNLOAD_DB_SAVEDPATH);
936 str = strrchr(download_info->tmp_saved_path, '/');
940 if (len > (DP_MAX_STR_LEN - 1))
941 len = DP_MAX_STR_LEN - 1;
942 if (clientinfo->downloadinfo) {
943 strncpy(clientinfo->downloadinfo->content_name,
945 download_provider_db_requestinfo_update_column
946 (clientinfo, DOWNLOAD_DB_FILENAME);
947 TRACE_DEBUG_MSG("content_name[%s]",
948 clientinfo->downloadinfo->
954 if (clientinfo->requestinfo->callbackinfo.started)
955 ipc_send_downloadinfo(clientinfo);
957 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
960 void __downloading_info_cb(user_downloading_info_t *download_info,
965 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
968 download_clientinfo_slot *clientinfoslot =
969 (download_clientinfo_slot *) user_data;
970 download_clientinfo *clientinfo =
971 (download_clientinfo *) clientinfoslot->clientinfo;
973 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
976 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
977 if (clientinfo->req_id != download_info->da_dl_req_id) {
978 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
980 download_info->da_dl_req_id);
981 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
984 if (!clientinfo->downloadinginfo)
985 clientinfo->downloadinginfo = (downloading_state_info *) calloc(1,
986 sizeof(downloading_state_info));
987 if (clientinfo->downloadinginfo)
988 clientinfo->downloadinginfo->received_size =
989 download_info->total_received_size;
990 if (download_info->saved_path) {
991 TRACE_DEBUG_MSG("tmp path[%s]", download_info->saved_path);
992 len = strlen(download_info->saved_path);
993 if (len > (DP_MAX_PATH_LEN - 1))
994 len = DP_MAX_PATH_LEN - 1;
995 if (clientinfo->downloadinginfo)
996 strncpy(clientinfo->downloadinginfo->saved_path,
997 download_info->saved_path, len);
1000 static size_t updated_second;
1001 time_t tt = time(NULL);
1002 struct tm *localTime = localtime(&tt);
1004 if (updated_second != localTime->tm_sec || download_info->saved_path) { // every 1 second.
1005 if (clientinfo->requestinfo
1006 && clientinfo->requestinfo->notification)
1007 set_downloadinginfo_appfw_notification(clientinfo);
1008 if (clientinfo->requestinfo->callbackinfo.progress)
1009 ipc_send_downloadinginfo(clientinfo);
1010 updated_second = localTime->tm_sec;
1012 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1015 void __notify_cb(user_notify_info_t *notify_info, void *user_data)
1018 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
1021 download_clientinfo_slot *clientinfoslot =
1022 (download_clientinfo_slot *) user_data;
1023 download_clientinfo *clientinfo =
1024 (download_clientinfo *) clientinfoslot->clientinfo;
1026 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
1030 TRACE_DEBUG_MSG("id[%d],state[%d],err[%d]",
1031 notify_info->da_dl_req_id,
1032 notify_info->state, notify_info->err);
1033 if (clientinfo->req_id != notify_info->da_dl_req_id) {
1034 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
1035 clientinfo->req_id, notify_info->da_dl_req_id);
1039 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
1041 clientinfo->state = __change_state(notify_info->state);
1042 clientinfo->err = __change_error(notify_info->err);
1043 if (clientinfo->state == DOWNLOAD_STATE_FINISHED ||
1044 clientinfo->state == DOWNLOAD_STATE_FAILED) {
1045 if (clientinfo->requestinfo) {
1046 if (clientinfo->requestinfo->notification)
1047 set_downloadedinfo_appfw_notification(clientinfo);
1048 download_provider_db_requestinfo_remove(clientinfo->
1049 requestinfo->requestid);
1051 download_provider_db_history_new(clientinfo);
1052 TRACE_DEBUG_MSG("[TEST]Finish clientinfo[%p],fd[%d]",
1053 clientinfo, clientinfo->clientfd);
1056 TRACE_DEBUG_MSG("state[%d]", clientinfo->state);
1057 ipc_send_stateinfo(clientinfo);
1059 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1062 int __change_state(da_state state)
1064 int ret = DOWNLOAD_STATE_NONE;
1066 case DA_STATE_WAITING:
1067 case DA_STATE_DOWNLOAD_STARTED:
1068 TRACE_DEBUG_MSG("DA_STATE_DOWNLOAD_STARTED");
1069 ret = DOWNLOAD_STATE_READY;
1071 case DA_STATE_DOWNLOADING:
1072 TRACE_DEBUG_MSG("DA_STATE_DOWNLOADING");
1073 ret = DOWNLOAD_STATE_DOWNLOADING;
1075 case DA_STATE_DOWNLOAD_COMPLETE:
1076 TRACE_DEBUG_MSG("DA_STATE_COMPLETE");
1077 ret = DOWNLOAD_STATE_INSTALLING;
1079 case DA_STATE_CANCELED:
1080 TRACE_DEBUG_MSG("DA_STATE_CANCELED");
1081 ret = DOWNLOAD_STATE_STOPPED;
1083 case DA_STATE_CANCELED_ALL:
1084 TRACE_DEBUG_MSG("DA_STATE_CANCELED_ALL");
1086 case DA_STATE_SUSPENDED:
1087 TRACE_DEBUG_MSG("DA_STATE_SUSPENDED");
1088 ret = DOWNLOAD_STATE_PAUSED;
1090 case DA_STATE_SUSPENDED_ALL:
1091 TRACE_DEBUG_MSG("DA_STATE_SUSPENDED_ALL");
1093 case DA_STATE_RESUMED:
1094 TRACE_DEBUG_MSG("DA_STATE_RESUMED");
1095 ret = DOWNLOAD_STATE_DOWNLOADING;
1097 case DA_STATE_RESUMED_ALL:
1098 TRACE_DEBUG_MSG("DA_STATE_RESUMED_ALL");
1100 case DA_STATE_FINISHED:
1101 TRACE_DEBUG_MSG("DA_STATE_FINISHED");
1102 ret = DOWNLOAD_STATE_FINISHED;
1104 case DA_STATE_FAILED:
1105 TRACE_DEBUG_MSG("DA_STATE_FAILED");
1106 ret = DOWNLOAD_STATE_FAILED;
1114 int __change_error(int err)
1116 int ret = DOWNLOAD_ERROR_UNKOWN;
1119 ret = DOWNLOAD_ERROR_NONE;
1121 case DA_ERR_INVALID_ARGUMENT:
1122 ret = DOWNLOAD_ERROR_INVALID_PARAMETER;
1124 case DA_ERR_FAIL_TO_MEMALLOC:
1125 ret = DOWNLOAD_ERROR_OUT_OF_MEMORY;
1127 case DA_ERR_UNREACHABLE_SERVER:
1128 ret = DOWNLOAD_ERROR_NETWORK_UNREACHABLE;
1130 case DA_ERR_HTTP_TIMEOUT:
1131 ret = DOWNLOAD_ERROR_CONNECTION_TIMED_OUT;
1133 case DA_ERR_DISK_FULL:
1134 ret = DOWNLOAD_ERROR_NO_SPACE;
1136 case DA_ERR_INVALID_STATE:
1137 ret = DOWNLOAD_ERROR_INVALID_STATE;
1139 case DA_ERR_NETWORK_FAIL:
1140 ret = DOWNLOAD_ERROR_CONNECTION_FAILED;
1142 case DA_ERR_INVALID_URL:
1143 ret = DOWNLOAD_ERROR_INVALID_URL;
1145 case DA_ERR_INVALID_INSTALL_PATH:
1146 ret = DOWNLOAD_ERROR_INVALID_DESTINATION;
1148 case DA_ERR_ALREADY_MAX_DOWNLOAD:
1149 ret = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
1151 case DA_ERR_FAIL_TO_INSTALL_FILE:
1152 ret = DOWNLOAD_ERROR_INSTALL_FAIL;
1154 case DA_ERR_FAIL_TO_CREATE_THREAD:
1155 case DA_ERR_FAIL_TO_OBTAIN_MUTEX:
1156 case DA_ERR_FAIL_TO_ACCESS_FILE:
1157 case DA_ERR_FAIL_TO_GET_CONF_VALUE:
1158 case DA_ERR_FAIL_TO_ACCESS_STORAGE:
1159 case DA_ERR_DLOPEN_FAIL:
1160 ret = DOWNLOAD_ERROR_IO_ERROR;
1169 da_client_cb_t da_cb = {
1172 __downloading_info_cb
1174 da_ret = da_init(&da_cb, DA_DOWNLOAD_MANAGING_METHOD_AUTO);
1175 if (da_ret != DA_RESULT_OK) {
1176 return DOWNLOAD_ERROR_FAIL_INIT_AGENT;
1178 return DOWNLOAD_ERROR_NONE;
1181 void _deinit_agent()