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 > 0)
80 da_start_download_with_extension(clientinfo->requestinfo->
82 DA_FEATURE_REQUEST_HEADER,
84 DA_FEATURE_INSTALL_PATH,
85 clientinfo->requestinfo->install_path.str,
87 (void *)clientinfoslot,
91 da_start_download_with_extension(clientinfo->requestinfo->
93 DA_FEATURE_REQUEST_HEADER,
96 (void *)clientinfoslot,
98 for (i = 0; i < len; i++) {
103 if (clientinfo->requestinfo->install_path.length > 0)
105 da_start_download_with_extension(clientinfo->requestinfo->
107 DA_FEATURE_INSTALL_PATH,
108 clientinfo->requestinfo->install_path.str,
109 DA_FEATURE_USER_DATA,
110 (void *)clientinfoslot,
114 da_start_download_with_extension(clientinfo->requestinfo->
116 DA_FEATURE_USER_DATA,
117 (void *)clientinfoslot,
121 // if start_download() return error cause of maximun download limitation, set state to DOWNLOAD_STATE_PENDED.
122 if (da_ret == DA_ERR_ALREADY_MAX_DOWNLOAD) {
123 TRACE_DEBUG_MSG("change to pended request [%d]", da_ret);
124 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
125 clientinfo->state = DOWNLOAD_STATE_PENDED;
126 clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
127 download_provider_db_requestinfo_update_column(clientinfo,
129 ipc_send_request_stateinfo(clientinfo);
130 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
132 } else if (da_ret != DA_RESULT_OK) {
133 TRACE_DEBUG_MSG("Fail to request start [%d]", da_ret);
134 /* FIXME : need to seperate in detail according to error return values */
135 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
136 clientinfo->state = DOWNLOAD_STATE_FAILED;
137 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
138 download_provider_db_requestinfo_remove(clientinfo->
139 requestinfo->requestid);
140 ipc_send_request_stateinfo(clientinfo);
141 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
142 clear_clientinfoslot(clientinfoslot);
146 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
148 TRACE_DEBUG_MSG("started download [%d]", da_ret);
150 clientinfo->req_id = req_dl_id;
151 clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
152 clientinfo->err = DOWNLOAD_ERROR_NONE;
154 download_provider_db_requestinfo_update_column(clientinfo,
157 // sync return // client should be alive till this line at least.
158 ipc_send_request_stateinfo(clientinfo);
160 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
164 int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_clientinfo *request_clientinfo)
169 if (!clientinfo_list || !request_clientinfo ) {
170 TRACE_DEBUG_MSG("NULL-CHECK");
174 CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL);
178 sizeof(request_clientinfo->credentials);
180 (request_clientinfo->clientfd, SOL_SOCKET,
181 SO_PEERCRED, &request_clientinfo->credentials,
184 ("Client Info : pid=%d, uid=%d, gid=%d\n",
185 request_clientinfo->credentials.pid,
186 request_clientinfo->credentials.uid,
187 request_clientinfo->credentials.gid);
191 download_controls type =
192 ipc_receive_header(request_clientinfo->clientfd);
193 TRACE_DEBUG_MSG("[ACCEPT] HEADER : [%d] ", type);
194 // first of all, receive requestinfo .
195 if (type <= 0 || ipc_receive_request_msg(request_clientinfo) < 0) {
196 TRACE_DEBUG_MSG("Ignore this connection, Invalid command");
197 clear_clientinfo(request_clientinfo);
201 if (type == DOWNLOAD_CONTROL_STOP
202 || type == DOWNLOAD_CONTROL_GET_STATE_INFO) {
203 // get requestid from socket.
204 if (request_clientinfo->requestinfo
205 && request_clientinfo->requestinfo->requestid > 0) {
206 // search requestid in slots.
207 int searchindex = get_same_request_slot_index
209 request_clientinfo->requestinfo->requestid);
210 if (type == DOWNLOAD_CONTROL_STOP) {
211 TRACE_DEBUG_MSG("Request : DOWNLOAD_CONTROL_STOP");
212 // remove info from downloading table.
213 download_provider_db_requestinfo_remove
214 (request_clientinfo->requestinfo->requestid);
215 if (searchindex >= 0) {
217 (clientinfo_list[searchindex].clientinfo->client_mutex));
218 if (da_cancel_download
219 (clientinfo_list[searchindex].clientinfo->req_id)
221 request_clientinfo->state = DOWNLOAD_STATE_STOPPED;
222 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
224 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
225 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
227 ipc_send_stateinfo(request_clientinfo);
228 CLIENT_MUTEX_UNLOCK(&
229 (clientinfo_list[searchindex].clientinfo->client_mutex));
231 } else if (type == DOWNLOAD_CONTROL_GET_STATE_INFO)
233 // not implemented yet
234 // search slots/downloading db/history db
235 // estabilish the spec of return value.
238 clear_clientinfo(request_clientinfo);
242 if (type != DOWNLOAD_CONTROL_START) {
244 ("Now, DOWNLOAD_CONTROL_START is only supported");
245 clear_clientinfo(request_clientinfo);
249 // check whether requestinfo has requestid or not.
250 if (request_clientinfo->requestinfo
251 && request_clientinfo->requestinfo->requestid > 0) {
252 // search same request id.
253 int searchindex = get_same_request_slot_index(clientinfo_list,
254 request_clientinfo->requestinfo->requestid);
255 if (searchindex < 0) {
256 CLIENT_MUTEX_LOCK(&(request_clientinfo->client_mutex));
257 TRACE_DEBUG_MSG("Not Found Same Request ID");
258 request_clientinfo->requestinfo->requestid = 0;
260 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
261 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
262 ipc_send_request_stateinfo(request_clientinfo);
263 CLIENT_MUTEX_UNLOCK(&(request_clientinfo->client_mutex));
264 clear_clientinfo(request_clientinfo);
266 } else { // found request id. // how to deal etag ?
268 TRACE_DEBUG_MSG("Found Same Request ID slot[%d]", searchindex);
269 CLIENT_MUTEX_LOCK(&(request_clientinfo->client_mutex));
270 // close previous socket.
271 if (clientinfo_list[searchindex].clientinfo->clientfd > 0)
272 close(clientinfo_list[searchindex].clientinfo->clientfd);
273 // change to new socket.
274 clientinfo_list[searchindex].clientinfo->clientfd =
275 request_clientinfo->clientfd;
276 ipc_send_request_stateinfo(clientinfo_list[searchindex].clientinfo);
278 clientinfo_list[searchindex].clientinfo->requestinfo->callbackinfo =
279 request_clientinfo->requestinfo->callbackinfo;
280 clientinfo_list[searchindex].clientinfo->requestinfo->notification =
281 request_clientinfo->requestinfo->notification;
282 request_clientinfo->clientfd = 0; // prevent to not be disconnected.
283 CLIENT_MUTEX_UNLOCK(&(request_clientinfo->client_mutex));
284 clear_clientinfo(request_clientinfo);
290 searchslot = get_empty_slot_index(clientinfo_list);
291 if (searchslot < 0) {
292 TRACE_DEBUG_MSG("download-provider is busy, try later");
293 clear_clientinfo(request_clientinfo);
294 sleep(5); // provider need the time of refresh.
297 // create new unique id, and insert info to DB.
298 if (request_clientinfo->requestinfo
299 && request_clientinfo->requestinfo->requestid <= 0) {
300 request_clientinfo->requestinfo->requestid =
301 get_download_request_id();
302 if (download_provider_db_requestinfo_new
303 (request_clientinfo) < 0) {
304 clear_clientinfo(request_clientinfo);
305 sleep(5); // provider need the time of refresh.
310 clientinfo_list[searchslot].clientinfo = request_clientinfo;
312 TRACE_DEBUG_MSG("New Connection slot [%d] max [%d] max once [%d]",
315 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
317 if (get_downloading_count(clientinfo_list) >=
318 DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
319 CLIENT_MUTEX_LOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
320 // deal as pended job.
321 clientinfo_list[searchslot].clientinfo->state = DOWNLOAD_STATE_PENDED;
322 clientinfo_list[searchslot].clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
323 download_provider_db_requestinfo_update_column
324 (clientinfo_list[searchslot].clientinfo,
326 ipc_send_request_stateinfo(clientinfo_list[searchslot].clientinfo);
327 TRACE_DEBUG_MSG ("Pended Request is saved to [%d/%d]",
328 searchslot, MAX_CLIENT);
329 CLIENT_MUTEX_UNLOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
330 sleep(5); // provider need the time of refresh.
332 // create thread for receiving the reqeust info from client.
333 // and if possible, it will create the thread for listening the event.
335 (&clientinfo_list[searchslot].clientinfo->thread_pid,
336 &g_download_provider_thread_attr, _start_download,
337 &clientinfo_list[searchslot]) != 0) {
338 TRACE_DEBUG_MSG("failed to call pthread_create for client");
339 TRACE_DEBUG_MSG("Change to pended job");
340 CLIENT_MUTEX_LOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
341 clientinfo_list[searchslot].clientinfo->state =
342 DOWNLOAD_STATE_PENDED;
343 clientinfo_list[searchslot].clientinfo->err =
344 DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
345 download_provider_db_requestinfo_update_column
346 (clientinfo_list[searchslot].clientinfo,
348 ipc_send_request_stateinfo(clientinfo_list[searchslot].clientinfo);
349 CLIENT_MUTEX_UNLOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex));
350 sleep(5); // provider need the time of refresh.
356 int _handle_client_request(download_clientinfo* clientinfo)
363 TRACE_DEBUG_MSG("NULL-CHECK");
367 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
368 switch (msgType = ipc_receive_header(clientinfo->clientfd)) {
369 case DOWNLOAD_CONTROL_STOP:
370 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_STOP");
371 da_ret = da_cancel_download(clientinfo->req_id);
372 if (da_ret != DA_RESULT_OK) {
373 /* FIXME : need to seperate in detail according to error return values */
374 clientinfo->state = DOWNLOAD_STATE_FAILED;
375 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
376 TRACE_DEBUG_MSG("Fail to request cancel [%d]", da_ret);
378 clientinfo->state = DOWNLOAD_STATE_STOPPED;
379 clientinfo->err = DOWNLOAD_ERROR_NONE;
381 ipc_send_stateinfo(clientinfo);
383 case DOWNLOAD_CONTROL_PAUSE:
384 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_PAUSE");
385 da_ret = da_suspend_download(clientinfo->req_id);
386 if (da_ret != DA_RESULT_OK) {
387 /* FIXME : need to seperate in detail according to error return values */
388 clientinfo->state = DOWNLOAD_STATE_FAILED;
389 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
390 TRACE_DEBUG_MSG("Fail to request suspend [%d]", da_ret);
392 clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED;
393 clientinfo->err = DOWNLOAD_ERROR_NONE;
395 ipc_send_stateinfo(clientinfo);
397 case DOWNLOAD_CONTROL_RESUME:
398 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_RESUME");
399 da_ret = da_resume_download(clientinfo->req_id);
400 if (da_ret != DA_RESULT_OK) {
401 /* FIXME : need to seperate in detail according to error return values */
402 clientinfo->state = DOWNLOAD_STATE_FAILED;
403 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
404 TRACE_DEBUG_MSG("Fail to request resume [%d]", da_ret);
406 clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
407 clientinfo->err = DOWNLOAD_ERROR_NONE;
409 ipc_send_stateinfo(clientinfo);
411 case DOWNLOAD_CONTROL_GET_STATE_INFO: // sync call
412 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_GET_STATE_INFO");
413 ipc_send_stateinfo(clientinfo);
415 case DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO: // sync call
416 TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO");
417 ipc_send_downloadinfo(clientinfo);
421 TRACE_DEBUG_MSG("(Closed Socket ) terminate event thread (%d)",
423 // bloken socket... it seems the client is dead or closed by agent thread.
424 // close socket, this will break the loop. and terminate this thread.
425 clear_socket(clientinfo);
426 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
429 TRACE_DEBUG_MSG("Unknow message [%d]", msgType);
430 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
433 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
437 void *run_manage_download_server(void *args)
439 int listenfd = 0; // main socket to be albe to listen the new connection
442 fd_set rset, exceptset;
443 struct timeval timeout;
444 long flexible_timeout;
445 download_clientinfo_slot *clientinfo_list;
447 uint count_downloading_threads = 0;
448 download_clientinfo *request_clientinfo;
453 struct sockaddr_un listenaddr, clientaddr;
455 GMainLoop *mainloop = (GMainLoop *) args;
458 if (ret != DOWNLOAD_ERROR_NONE) {
459 TRACE_DEBUG_MSG("failed to init agent");
460 TerminateDaemon(SIGTERM);
464 if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
465 TRACE_DEBUG_MSG("failed to create socket");
466 TerminateDaemon(SIGTERM);
470 bzero(&listenaddr, sizeof(listenaddr));
471 listenaddr.sun_family = AF_UNIX;
472 strcpy(listenaddr.sun_path, DOWNLOAD_PROVIDER_IPC);
474 if (bind(listenfd, (struct sockaddr *)&listenaddr, sizeof listenaddr) !=
476 TRACE_DEBUG_MSG("failed to call bind");
477 TerminateDaemon(SIGTERM);
481 if (chmod(listenaddr.sun_path, 0777) < 0) {
483 ("failed to change the permission of socket file");
484 TerminateDaemon(SIGTERM);
488 if (listen(listenfd, MAX_CLIENT) != 0) {
489 TRACE_DEBUG_MSG("failed to call listen");
490 TerminateDaemon(SIGTERM);
495 TRACE_DEBUG_MSG("Ready to listen IPC [%d][%s]", listenfd,
496 DOWNLOAD_PROVIDER_IPC);
498 // allocation the array structure for managing the clients.
500 (download_clientinfo_slot *) calloc(MAX_CLIENT,
501 sizeof(download_clientinfo_slot));
502 if (clientinfo_list == NULL) {
503 TRACE_DEBUG_MSG("failed to allocate the memory for client list");
504 TerminateDaemon(SIGTERM);
508 if (pthread_attr_init(&g_download_provider_thread_attr) != 0) {
509 TRACE_DEBUG_MSG("failed to call pthread_attr_init for client");
510 TerminateDaemon(SIGTERM);
513 if (pthread_attr_setdetachstate(&g_download_provider_thread_attr,
514 PTHREAD_CREATE_DETACHED) != 0) {
515 TRACE_DEBUG_MSG("failed to set detach option");
516 TerminateDaemon(SIGTERM);
520 flexible_timeout = DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
522 FD_ZERO(&g_download_provider_socket_readset);
523 FD_ZERO(&g_download_provider_socket_exceptset);
524 FD_SET(listenfd, &g_download_provider_socket_readset);
525 FD_SET(listenfd, &g_download_provider_socket_exceptset);
527 while (g_main_loop_is_running(mainloop)) {
530 for (i=0; i < MAX_CLIENT; i++) {
531 if (!clientinfo_list[i].clientinfo)
533 CLIENT_MUTEX_LOCK(&(clientinfo_list[i].clientinfo->client_mutex));
535 if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
536 CLIENT_MUTEX_UNLOCK(&(clientinfo_list[i].clientinfo->client_mutex));
537 clear_clientinfoslot(&clientinfo_list[i]);
540 CLIENT_MUTEX_UNLOCK(&(clientinfo_list[i].clientinfo->client_mutex));
543 rset = g_download_provider_socket_readset;
544 exceptset = g_download_provider_socket_exceptset;
546 timeout.tv_sec = flexible_timeout;
548 if (select((maxfd + 1), &rset, 0, &exceptset, &timeout) < 0) {
550 ("select error, provider can't receive any request from client.");
551 TerminateDaemon(SIGTERM);
555 for (i=0; i < MAX_CLIENT; i++) { // find the socket received the packet.
556 if (!clientinfo_list[i].clientinfo)
558 // ignore if finished
559 //if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED)
561 //Even if no socket, downloading should be progressed.
562 if (clientinfo_list[i].clientinfo->clientfd <= 0)
564 if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &rset) > 0) {
565 TRACE_DEBUG_MSG("FD_ISSET [%d] readset slot[%d]",
566 clientinfo_list[i].clientinfo->clientfd, i);
567 _handle_client_request(clientinfo_list[i].clientinfo);
568 } else if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &exceptset) > 0) {
569 TRACE_DEBUG_MSG("FD_ISSET [%d] exceptset slot[%d]", clientinfo_list[i].clientinfo->clientfd, i);
570 clear_clientinfoslot(&clientinfo_list[i]);
574 if (FD_ISSET(listenfd, &exceptset) > 0) {
575 TRACE_DEBUG_MSG("meet listenfd Exception of socket");
576 TerminateDaemon(SIGTERM);
578 } else if (FD_ISSET(listenfd, &rset) > 0) { // new connection
579 TRACE_DEBUG_MSG("FD_ISSET listenfd rset");
582 DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
585 (download_clientinfo *) calloc(1,
586 sizeof(download_clientinfo));
587 if (!request_clientinfo) {
589 ("download-provider can't allocate the memory, try later");
590 clientlen = sizeof(clientaddr);
591 int clientfd = accept(listenfd,
592 (struct sockaddr *)&clientaddr, &clientlen);
593 close(clientfd); // disconnect.
594 sleep(5); // provider need the time of refresh.
598 clientlen = sizeof(clientaddr);
599 request_clientinfo->clientfd = accept(listenfd,
600 (struct sockaddr*)&clientaddr,
602 if (request_clientinfo->clientfd < 0) {
603 clear_clientinfo(request_clientinfo);
604 sleep(5); // provider need the time of refresh.
607 FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_readset); // add new descriptor to set
608 FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_exceptset);
609 if (request_clientinfo->clientfd > maxfd )
610 maxfd = request_clientinfo->clientfd; /* for select */
612 if (_handle_new_connection(clientinfo_list, request_clientinfo) < 0) {
618 if (i >= MAX_CLIENT) { // timeout
619 // If there is better solution to be able to know
620 // the number of downloading threads, replace below rough codes.
621 count_downloading_threads =
622 get_downloading_count(clientinfo_list);
623 // check whether the number of downloading is already maximum.
624 if (count_downloading_threads >=
625 DA_MAX_DOWNLOAD_REQ_AT_ONCE)
628 // search pended request
629 for (searchslot = 0; searchslot < MAX_CLIENT;
631 if (clientinfo_list[searchslot].clientinfo) {
632 if (clientinfo_list[searchslot].clientinfo->state ==
633 DOWNLOAD_STATE_PENDED) {
635 ("Retry Pended Request [%d/%d] state [%d/%d]",
636 searchslot, MAX_CLIENT,
637 count_downloading_threads,
638 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
639 // create thread for restarting the pended download.
641 (&clientinfo_list[searchslot].clientinfo->thread_pid,
642 &g_download_provider_thread_attr,
644 &clientinfo_list[searchslot]) != 0) {
646 ("failed to call pthread_create for client");
648 count_downloading_threads++;
649 usleep(1000); // sleep in busy state.
656 && count_downloading_threads <
657 DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
658 // Auto re-download feature. ethernet may be connected with other downloading items.
659 connection_h network_handle = NULL;
660 connection_ethernet_state_e system_network_state
661 = CONNECTION_ETHERNET_STATE_DISCONNECTED;
662 if (connection_create(&network_handle) < 0) {
664 ("Failed connection_create");
667 if (connection_get_ethernet_state(network_handle,
668 &system_network_state) !=
669 CONNECTION_ERROR_NONE)
671 ("Failed connection_get_ethernet_state");
672 if (connection_destroy(network_handle) !=
673 CONNECTION_ERROR_NONE)
675 ("Failed connection_destroy");
676 if (system_network_state !=
677 CONNECTION_ETHERNET_STATE_CONNECTED)
679 // check auto-retrying list regardless state. pended state is also included to checking list.
681 download_dbinfo_list *db_list =
682 download_provider_db_get_list(DOWNLOAD_STATE_NONE);
683 if (!db_list || db_list->count <= 0) {
685 ("provider does not need to check DB anymore. in this life.");
686 check_retry = 0; // provider does not need to check DB anymore. in this life.
688 download_provider_db_list_free(db_list);
692 count_downloading_threads <
693 DA_MAX_DOWNLOAD_REQ_AT_ONCE
694 && i < db_list->count; i++) {
695 if (db_list->item[i].requestid <= 0)
697 if (get_same_request_slot_index
698 (clientinfo_list,db_list->item[i].requestid) < 0) {
699 // not found requestid in memory
701 ("Retry download [%d]",
702 db_list->item[i].requestid);
703 //search empty slot. copy db info to slot.
705 get_empty_slot_index(clientinfo_list);
706 if (searchslot < 0) {
708 ("download-provider is busy, try later");
710 flexible_timeout * 2;
713 // allocte requestinfo to empty slot.
715 (download_clientinfo *)
716 calloc(1, sizeof(download_clientinfo));
717 if (!request_clientinfo)
719 request_clientinfo->requestinfo
721 download_provider_db_get_requestinfo
723 if (!request_clientinfo->requestinfo) {
724 free(request_clientinfo);
725 request_clientinfo = NULL;
729 clientinfo_list[searchslot].clientinfo =
733 ("Retry download [%d/%d][%d/%d]",
734 searchslot, MAX_CLIENT,
735 count_downloading_threads,
736 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
738 (&clientinfo_list[searchslot].clientinfo->thread_pid,
739 &g_download_provider_thread_attr,
741 &clientinfo_list[searchslot])
744 ("failed to call pthread_create for client");
745 clientinfo_list[searchslot].clientinfo->state =
746 DOWNLOAD_STATE_PENDED;
747 clientinfo_list[searchslot].clientinfo->err =
748 DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
751 count_downloading_threads++;
752 usleep(1000); // sleep in busy state.
755 if (i >= db_list->count) // do not search anymore.
757 download_provider_db_list_free(db_list);
760 // save system resource (CPU)
761 if (check_retry == 0 && count_downloading_threads == 0
762 && flexible_timeout <
763 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
764 flexible_timeout = flexible_timeout * 2;
765 if (flexible_timeout >
766 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
768 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL;
769 TRACE_DEBUG_MSG("Next Timeout after [%ld] sec",
772 } // if (i >= MAX_CLIENT) { // timeout
775 FD_CLR(listenfd, &rset);
776 FD_CLR(listenfd, &exceptset);
777 FD_CLR(listenfd, &g_download_provider_socket_readset);
778 FD_CLR(listenfd, &g_download_provider_socket_exceptset);
780 // close accept socket.
786 // close all sockets for client. ..
787 // client thread will terminate by itself through catching this closing.
788 for (searchslot = 0; searchslot < MAX_CLIENT; searchslot++)
789 if (clientinfo_list[searchslot].clientinfo)
790 clear_clientinfoslot(&clientinfo_list[searchslot]);
793 free(clientinfo_list);
799 void __download_info_cb(user_download_info_t *download_info, void *user_data)
803 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
806 download_clientinfo_slot *clientinfoslot =
807 (download_clientinfo_slot *) user_data;
808 download_clientinfo *clientinfo =
809 (download_clientinfo *) clientinfoslot->clientinfo;
811 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
814 TRACE_DEBUG_MSG("id[%d],size[%lu]",
815 download_info->da_dl_req_id, download_info->file_size)
817 if (clientinfo->req_id != download_info->da_dl_req_id) {
818 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
820 download_info->da_dl_req_id);
823 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
824 if (!clientinfo->downloadinfo)
825 clientinfo->downloadinfo =
826 (download_content_info *) calloc(1, sizeof(download_content_info));
827 if (clientinfo->downloadinfo)
828 clientinfo->downloadinfo->file_size = download_info->file_size;
829 if (download_info->file_type) {
830 TRACE_DEBUG_MSG("mime[%s]", download_info->file_type);
832 len = strlen(download_info->file_type);
833 if (len > (DP_MAX_STR_LEN - 1))
834 len = DP_MAX_STR_LEN - 1;
835 if (clientinfo->downloadinfo) {
836 strncpy(clientinfo->downloadinfo->mime_type,
837 download_info->file_type, len);
838 download_provider_db_requestinfo_update_column
839 (clientinfo, DOWNLOAD_DB_MIMETYPE);
842 if (download_info->tmp_saved_path) {
844 TRACE_DEBUG_MSG("tmp path[%s]", download_info->tmp_saved_path);
845 clientinfo->tmp_saved_path =
846 strdup(download_info->tmp_saved_path);
847 download_provider_db_requestinfo_update_column(clientinfo,
848 DOWNLOAD_DB_SAVEDPATH);
849 str = strrchr(download_info->tmp_saved_path, '/');
853 if (len > (DP_MAX_STR_LEN - 1))
854 len = DP_MAX_STR_LEN - 1;
855 if (clientinfo->downloadinfo) {
856 strncpy(clientinfo->downloadinfo->content_name,
858 download_provider_db_requestinfo_update_column
859 (clientinfo, DOWNLOAD_DB_FILENAME);
860 TRACE_DEBUG_MSG("content_name[%s]",
861 clientinfo->downloadinfo->
867 if (clientinfo->requestinfo->callbackinfo.started)
868 ipc_send_downloadinfo(clientinfo);
870 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
873 void __downloading_info_cb(user_downloading_info_t *download_info,
878 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
881 download_clientinfo_slot *clientinfoslot =
882 (download_clientinfo_slot *) user_data;
883 download_clientinfo *clientinfo =
884 (download_clientinfo *) clientinfoslot->clientinfo;
886 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
889 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
890 if (clientinfo->req_id != download_info->da_dl_req_id) {
891 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
893 download_info->da_dl_req_id);
894 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
897 if (!clientinfo->downloadinginfo)
898 clientinfo->downloadinginfo = (downloading_state_info *) calloc(1,
899 sizeof(downloading_state_info));
900 if (clientinfo->downloadinginfo)
901 clientinfo->downloadinginfo->received_size =
902 download_info->total_received_size;
903 if (download_info->saved_path) {
904 TRACE_DEBUG_MSG("tmp path[%s]", download_info->saved_path);
905 len = strlen(download_info->saved_path);
906 if (len > (DP_MAX_PATH_LEN - 1))
907 len = DP_MAX_PATH_LEN - 1;
908 if (clientinfo->downloadinginfo)
909 strncpy(clientinfo->downloadinginfo->saved_path,
910 download_info->saved_path, len);
913 static size_t updated_second;
914 time_t tt = time(NULL);
915 struct tm *localTime = localtime(&tt);
917 if (updated_second != localTime->tm_sec || download_info->saved_path) { // every 1 second.
918 if (clientinfo->requestinfo
919 && clientinfo->requestinfo->notification)
920 set_downloadinginfo_appfw_notification(clientinfo);
921 if (clientinfo->requestinfo->callbackinfo.progress)
922 ipc_send_downloadinginfo(clientinfo);
923 updated_second = localTime->tm_sec;
925 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
928 void __notify_cb(user_notify_info_t *notify_info, void *user_data)
931 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
934 download_clientinfo_slot *clientinfoslot =
935 (download_clientinfo_slot *) user_data;
936 download_clientinfo *clientinfo =
937 (download_clientinfo *) clientinfoslot->clientinfo;
939 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
942 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
943 TRACE_DEBUG_MSG("id[%d],state[%d],err[%d]",
944 notify_info->da_dl_req_id,
945 notify_info->state, notify_info->err);
946 if (clientinfo->req_id != notify_info->da_dl_req_id) {
947 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
948 clientinfo->req_id, notify_info->da_dl_req_id);
949 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
953 clientinfo->state = __change_state(notify_info->state);
954 clientinfo->err = __change_error(notify_info->err);
955 if (clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
956 if (clientinfo->requestinfo) {
957 if (clientinfo->requestinfo->notification)
958 set_downloadedinfo_appfw_notification(clientinfo);
959 download_provider_db_requestinfo_remove(clientinfo->
960 requestinfo->requestid);
962 download_provider_db_history_new(clientinfo);
963 TRACE_DEBUG_MSG("[TEST]Finish clientinfo[%p],fd[%d]",
964 clientinfo, clientinfo->clientfd);
967 TRACE_DEBUG_MSG("state[%d]", clientinfo->state);
968 ipc_send_stateinfo(clientinfo);
970 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
973 int __change_state(da_state state)
975 int ret = DOWNLOAD_STATE_NONE;
977 case DA_STATE_WAITING:
978 case DA_STATE_DOWNLOAD_STARTED:
979 TRACE_DEBUG_MSG("DA_STATE_DOWNLOAD_STARTED");
980 ret = DOWNLOAD_STATE_READY;
982 case DA_STATE_DOWNLOADING:
983 TRACE_DEBUG_MSG("DA_STATE_DOWNLOADING");
984 ret = DOWNLOAD_STATE_DOWNLOADING;
986 case DA_STATE_DOWNLOAD_COMPLETE:
987 TRACE_DEBUG_MSG("DA_STATE_COMPLETE");
988 ret = DOWNLOAD_STATE_INSTALLING;
990 case DA_STATE_CANCELED:
991 TRACE_DEBUG_MSG("DA_STATE_CANCELED");
992 ret = DOWNLOAD_STATE_STOPPED;
994 case DA_STATE_CANCELED_ALL:
995 TRACE_DEBUG_MSG("DA_STATE_CANCELED_ALL");
997 case DA_STATE_SUSPENDED:
998 TRACE_DEBUG_MSG("DA_STATE_SUSPENDED");
999 ret = DOWNLOAD_STATE_PAUSED;
1001 case DA_STATE_SUSPENDED_ALL:
1002 TRACE_DEBUG_MSG("DA_STATE_SUSPENDED_ALL");
1004 case DA_STATE_RESUMED:
1005 TRACE_DEBUG_MSG("DA_STATE_RESUMED");
1006 ret = DOWNLOAD_STATE_DOWNLOADING;
1008 case DA_STATE_RESUMED_ALL:
1009 TRACE_DEBUG_MSG("DA_STATE_RESUMED_ALL");
1011 case DA_STATE_FINISHED:
1012 TRACE_DEBUG_MSG("DA_STATE_FINISHED");
1013 ret = DOWNLOAD_STATE_FINISHED;
1015 case DA_STATE_FAILED:
1016 TRACE_DEBUG_MSG("DA_STATE_FAILED");
1017 ret = DOWNLOAD_STATE_FAILED;
1025 int __change_error(int err)
1027 int ret = DOWNLOAD_ERROR_UNKOWN;
1030 ret = DOWNLOAD_ERROR_NONE;
1032 case DA_ERR_INVALID_ARGUMENT:
1033 ret = DOWNLOAD_ERROR_INVALID_PARAMETER;
1035 case DA_ERR_FAIL_TO_MEMALLOC:
1036 ret = DOWNLOAD_ERROR_OUT_OF_MEMORY;
1038 case DA_ERR_UNREACHABLE_SERVER:
1039 ret = DOWNLOAD_ERROR_NETWORK_UNREACHABLE;
1041 case DA_ERR_HTTP_TIMEOUT:
1042 ret = DOWNLOAD_ERROR_CONNECTION_TIMED_OUT;
1044 case DA_ERR_DISK_FULL:
1045 ret = DOWNLOAD_ERROR_NO_SPACE;
1047 case DA_ERR_INVALID_STATE:
1048 ret = DOWNLOAD_ERROR_INVALID_STATE;
1050 case DA_ERR_NETWORK_FAIL:
1051 ret = DOWNLOAD_ERROR_CONNECTION_FAILED;
1053 case DA_ERR_INVALID_URL:
1054 ret = DOWNLOAD_ERROR_INVALID_URL;
1056 case DA_ERR_INVALID_INSTALL_PATH:
1057 ret = DOWNLOAD_ERROR_INVALID_DESTINATION;
1059 case DA_ERR_ALREADY_MAX_DOWNLOAD:
1060 ret = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
1062 case DA_ERR_FAIL_TO_INSTALL_FILE:
1063 ret = DOWNLOAD_ERROR_INSTALL_FAIL;
1065 case DA_ERR_FAIL_TO_CREATE_THREAD:
1066 case DA_ERR_FAIL_TO_OBTAIN_MUTEX:
1067 case DA_ERR_FAIL_TO_ACCESS_FILE:
1068 case DA_ERR_FAIL_TO_GET_CONF_VALUE:
1069 case DA_ERR_FAIL_TO_ACCESS_STORAGE:
1070 case DA_ERR_DLOPEN_FAIL:
1071 ret = DOWNLOAD_ERROR_IO_ERROR;
1080 da_client_cb_t da_cb = {
1083 __downloading_info_cb
1085 da_ret = da_init(&da_cb, DA_DOWNLOAD_MANAGING_METHOD_AUTO);
1086 if (da_ret != DA_RESULT_OK) {
1087 return DOWNLOAD_ERROR_FAIL_INIT_AGENT;
1089 return DOWNLOAD_ERROR_NONE;
1092 void _deinit_agent()