3 #include <sys/socket.h>
12 #include "download-provider-config.h"
13 #include "download-provider-log.h"
14 #include "download-provider-pthread.h"
15 #include "download-provider-notification.h"
16 #include "download-provider-ipc.h"
17 #include "download-provider-db.h"
18 #include "download-provider-utils.h"
20 #include "download-agent-defs.h"
21 #include "download-agent-interface.h"
23 int _init_agent(void);
24 void _deinit_agent(void);
25 static void __downloading_info_cb(user_downloading_info_t *download_info,
27 static void __download_info_cb(user_download_info_t *download_info,
29 static void __notify_cb(user_notify_info_t *notify_info, void *user_data);
30 static int __change_error(int err);
31 static int __change_state(da_state state);
33 void TerminateDaemon(int signo);
35 pthread_attr_t g_download_provider_thread_attr;
36 fd_set g_download_provider_socket_readset;
37 fd_set g_download_provider_socket_exceptset;
39 int _change_pended_download(download_clientinfo *clientinfo)
43 clientinfo->state = DOWNLOAD_STATE_PENDED;
44 clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
45 download_provider_db_requestinfo_update_column(clientinfo, DOWNLOAD_DB_STATE);
46 ipc_send_request_stateinfo(clientinfo);
50 void *_start_download(void *args)
55 download_clientinfo_slot *clientinfoslot =
56 (download_clientinfo_slot *) args;
57 if (!clientinfoslot) {
58 TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo_slot");
61 download_clientinfo *clientinfo =
62 (download_clientinfo *) clientinfoslot->clientinfo;
64 TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo");
68 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
69 clientinfo->state = DOWNLOAD_STATE_READY;
70 clientinfo->err = DOWNLOAD_ERROR_NONE;
71 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
73 // call start_download() of download-agent
74 if (clientinfo->requestinfo->headers.rows > 0) {
77 char **req_header = NULL;
78 len = clientinfo->requestinfo->headers.rows;
79 req_header = calloc(len, sizeof(char *));
81 TRACE_DEBUG_MSG("fail to calloc");
84 for (i = 0; i < len; i++)
86 strdup(clientinfo->requestinfo->headers.str[i].str);
87 if (clientinfo->requestinfo->install_path.length > 1) {
88 if (clientinfo->requestinfo->filename.length > 1)
90 da_start_download_with_extension(clientinfo->requestinfo->
92 DA_FEATURE_REQUEST_HEADER,
94 DA_FEATURE_INSTALL_PATH,
95 clientinfo->requestinfo->install_path.str,
97 clientinfo->requestinfo->filename.str,
99 (void *)clientinfoslot,
103 da_start_download_with_extension(clientinfo->requestinfo->
105 DA_FEATURE_REQUEST_HEADER,
107 DA_FEATURE_INSTALL_PATH,
108 clientinfo->requestinfo->install_path.str,
109 DA_FEATURE_USER_DATA,
110 (void *)clientinfoslot,
113 if (clientinfo->requestinfo->filename.length > 1)
115 da_start_download_with_extension(clientinfo->requestinfo->
117 DA_FEATURE_REQUEST_HEADER,
119 DA_FEATURE_FILE_NAME,
120 clientinfo->requestinfo->filename.str,
121 DA_FEATURE_USER_DATA,
122 (void *)clientinfoslot,
126 da_start_download_with_extension(clientinfo->requestinfo->
128 DA_FEATURE_REQUEST_HEADER,
130 DA_FEATURE_USER_DATA,
131 (void *)clientinfoslot,
134 for (i = 0; i < len; i++) {
139 if (clientinfo->requestinfo->install_path.length > 1) {
140 if (clientinfo->requestinfo->filename.length > 1)
142 da_start_download_with_extension(clientinfo->requestinfo->
144 DA_FEATURE_INSTALL_PATH,
145 clientinfo->requestinfo->install_path.str,
146 DA_FEATURE_FILE_NAME,
147 clientinfo->requestinfo->filename.str,
148 DA_FEATURE_USER_DATA,
149 (void *)clientinfoslot,
153 da_start_download_with_extension(clientinfo->requestinfo->
155 DA_FEATURE_INSTALL_PATH,
156 clientinfo->requestinfo->install_path.str,
157 DA_FEATURE_USER_DATA,
158 (void *)clientinfoslot,
161 if (clientinfo->requestinfo->filename.length > 1)
163 da_start_download_with_extension(clientinfo->requestinfo->
165 DA_FEATURE_FILE_NAME,
166 clientinfo->requestinfo->filename.str,
167 DA_FEATURE_USER_DATA,
168 (void *)clientinfoslot,
172 da_start_download_with_extension(clientinfo->requestinfo->
174 DA_FEATURE_USER_DATA,
175 (void *)clientinfoslot,
180 // if start_download() return error cause of maximun download limitation,
181 // set state to DOWNLOAD_STATE_PENDED.
182 if (da_ret == DA_ERR_ALREADY_MAX_DOWNLOAD) {
183 TRACE_DEBUG_INFO_MSG("change to pended request [%d]", da_ret);
184 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
185 _change_pended_download(clientinfo);
186 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
188 } else if (da_ret != DA_RESULT_OK) {
189 TRACE_DEBUG_INFO_MSG("Fail to request start [%d]", da_ret);
190 /* FIXME : need to seperate in detail according to error return values */
191 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
192 clientinfo->state = DOWNLOAD_STATE_FAILED;
193 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
194 download_provider_db_requestinfo_remove(clientinfo->
195 requestinfo->requestid);
196 ipc_send_request_stateinfo(clientinfo);
197 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
201 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
203 TRACE_DEBUG_INFO_MSG("started download [%d]", da_ret);
205 clientinfo->req_id = req_dl_id;
206 clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
207 clientinfo->err = DOWNLOAD_ERROR_NONE;
209 download_provider_db_requestinfo_update_column(clientinfo,
212 // sync return // client should be alive till this line at least.
213 ipc_send_request_stateinfo(clientinfo);
215 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
219 int _create_download_thread(download_clientinfo_slot *clientinfo_slot)
221 if (!clientinfo_slot)
224 // create thread for receiving the reqeust info from client.
225 // and if possible, it will create the thread for listening the event.
226 clientinfo_slot->clientinfo->state = DOWNLOAD_STATE_READY;
227 clientinfo_slot->clientinfo->err = DOWNLOAD_ERROR_NONE;
229 (&clientinfo_slot->clientinfo->thread_pid,
230 &g_download_provider_thread_attr, _start_download,
231 clientinfo_slot) != 0) {
232 TRACE_DEBUG_INFO_MSG("failed to call pthread_create for client");
233 TRACE_DEBUG_INFO_MSG("Change to pended job");
234 _change_pended_download(clientinfo_slot->clientinfo);
240 int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_clientinfo *request_clientinfo)
243 unsigned active_count = 0;
246 if (!clientinfo_list || !request_clientinfo ) {
247 TRACE_DEBUG_MSG("NULL-CHECK");
251 CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL);
255 sizeof(request_clientinfo->credentials);
257 (request_clientinfo->clientfd, SOL_SOCKET,
258 SO_PEERCRED, &request_clientinfo->credentials,
261 ("Client Info : pid=%d, uid=%d, gid=%d\n",
262 request_clientinfo->credentials.pid,
263 request_clientinfo->credentials.uid,
264 request_clientinfo->credentials.gid);
268 download_controls type =
269 ipc_receive_header(request_clientinfo->clientfd);
270 TRACE_DEBUG_INFO_MSG("[ACCEPT] HEADER : [%d] ", type);
271 // first of all, receive requestinfo .
272 if (type <= 0 || ipc_receive_request_msg(request_clientinfo) < 0) {
273 TRACE_DEBUG_MSG("Ignore this connection, Invalid command");
274 clear_clientinfo(request_clientinfo);
278 if (type == DOWNLOAD_CONTROL_STOP
279 || type == DOWNLOAD_CONTROL_GET_STATE_INFO
280 || type == DOWNLOAD_CONTROL_RESUME
281 || type == DOWNLOAD_CONTROL_PAUSE) {
282 // get requestid from socket.
283 if (request_clientinfo->requestinfo
284 && request_clientinfo->requestinfo->requestid > 0) {
285 // search requestid in slots.
286 int searchindex = get_same_request_slot_index
288 request_clientinfo->requestinfo->requestid);
289 if (type == DOWNLOAD_CONTROL_STOP) {
290 TRACE_DEBUG_INFO_MSG("Request : DOWNLOAD_CONTROL_STOP");
291 if (searchindex >= 0) {
292 if (da_cancel_download
293 (clientinfo_list[searchindex].clientinfo->req_id)
295 request_clientinfo->state = DOWNLOAD_STATE_STOPPED;
296 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
297 if (clientinfo_list[searchindex].clientinfo->requestinfo
298 && clientinfo_list[searchindex].clientinfo->requestinfo->notification)
299 set_downloadedinfo_appfw_notification(clientinfo_list[searchindex].clientinfo);
300 download_provider_db_requestinfo_remove(request_clientinfo->requestinfo->requestid);
301 download_provider_db_history_new(clientinfo_list[searchindex].clientinfo);
303 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
304 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
307 request_clientinfo->state = DOWNLOAD_STATE_NONE;
308 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
310 ipc_send_stateinfo(request_clientinfo);
311 } else if (type == DOWNLOAD_CONTROL_GET_STATE_INFO) {
312 // search slots/downloading db/history db
313 if (searchindex > 0) { // exist in slots (memory)
314 request_clientinfo->state =
315 clientinfo_list[searchindex].clientinfo->state;
316 request_clientinfo->err =
317 clientinfo_list[searchindex].clientinfo->err;
318 } else { //search downloading db or history db
319 download_dbinfo* dbinfo =
320 download_provider_db_get_info(
321 request_clientinfo->requestinfo->requestid);
322 if (dbinfo) { // found in downloading db..it means crashed job
323 request_clientinfo->state = DOWNLOAD_STATE_PENDED;
324 request_clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
325 } else { // no exist in downloading db
326 dbinfo = download_provider_db_history_get_info(
327 request_clientinfo->requestinfo->requestid);
328 if (!dbinfo) { // no info anywhere
329 request_clientinfo->state = DOWNLOAD_STATE_NONE;
330 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
331 } else { //history info
332 request_clientinfo->state = dbinfo->state;
333 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
336 download_provider_db_info_free(dbinfo);
339 ipc_send_stateinfo(request_clientinfo);
340 // estabilish the spec of return value.
341 } else if (type == DOWNLOAD_CONTROL_PAUSE) {
342 if (searchindex >= 0) {
343 if (da_suspend_download
344 (clientinfo_list[searchindex].clientinfo->req_id)
346 request_clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED;
347 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
349 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
350 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
353 request_clientinfo->state = DOWNLOAD_STATE_NONE;
354 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
356 ipc_send_stateinfo(request_clientinfo);
357 } else if (type == DOWNLOAD_CONTROL_RESUME) {
358 if (searchindex >= 0) {
359 if (da_resume_download
360 (clientinfo_list[searchindex].clientinfo->req_id)
362 request_clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
363 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
365 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
366 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
369 request_clientinfo->state = DOWNLOAD_STATE_NONE;
370 request_clientinfo->err = DOWNLOAD_ERROR_NONE;
372 ipc_send_stateinfo(request_clientinfo);
374 ipc_receive_header(request_clientinfo->clientfd);
376 clear_clientinfo(request_clientinfo);
380 if (type != DOWNLOAD_CONTROL_START) {
382 ("Now, DOWNLOAD_CONTROL_START is only supported");
383 clear_clientinfo(request_clientinfo);
387 // check whether requestinfo has requestid or not.
388 if (request_clientinfo->requestinfo
389 && request_clientinfo->requestinfo->requestid > 0) {
390 // search same request id.
391 int searchindex = get_same_request_slot_index(clientinfo_list,
392 request_clientinfo->requestinfo->requestid);
393 if (searchindex < 0) {
394 TRACE_DEBUG_INFO_MSG("Not Found Same Request ID");
396 request_clientinfo->state = DOWNLOAD_STATE_FAILED;
397 request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
398 ipc_send_request_stateinfo(request_clientinfo);
399 clear_clientinfo(request_clientinfo);
401 } else { // found request id. // how to deal etag ?
403 TRACE_DEBUG_INFO_MSG("Found Same Request ID slot[%d]", searchindex);
404 CLIENT_MUTEX_LOCK(&(request_clientinfo->client_mutex));
405 // close previous socket.
406 if (clientinfo_list[searchindex].clientinfo->clientfd > 0)
407 close(clientinfo_list[searchindex].clientinfo->clientfd);
408 // change to new socket.
409 clientinfo_list[searchindex].clientinfo->clientfd =
410 request_clientinfo->clientfd;
411 ipc_send_request_stateinfo(clientinfo_list[searchindex].clientinfo);
413 clientinfo_list[searchindex].clientinfo->requestinfo->callbackinfo =
414 request_clientinfo->requestinfo->callbackinfo;
415 clientinfo_list[searchindex].clientinfo->requestinfo->notification =
416 request_clientinfo->requestinfo->notification;
417 request_clientinfo->clientfd = 0; // prevent to not be disconnected.
418 CLIENT_MUTEX_UNLOCK(&(request_clientinfo->client_mutex));
419 clear_clientinfo(request_clientinfo);
425 searchslot = get_empty_slot_index(clientinfo_list);
426 if (searchslot < 0) {
427 TRACE_DEBUG_MSG("download-provider is busy, try later");
428 clear_clientinfo(request_clientinfo);
429 sleep(5); // provider need the time of refresh.
432 // create new unique id, and insert info to DB.
433 if (request_clientinfo->requestinfo
434 && request_clientinfo->requestinfo->requestid <= 0) {
435 request_clientinfo->requestinfo->requestid =
436 get_download_request_id();
437 if (download_provider_db_requestinfo_new
438 (request_clientinfo) < 0) {
439 clear_clientinfo(request_clientinfo);
440 sleep(5); // provider need the time of refresh.
445 clientinfo_list[searchslot].clientinfo = request_clientinfo;
447 active_count = get_downloading_count(clientinfo_list);
449 TRACE_DEBUG_INFO_MSG("New Connection slot [%d/%d] active [%d/%d]",
453 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
455 if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE) {
456 // deal as pended job.
457 _change_pended_download(clientinfo_list[searchslot].clientinfo);
458 TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]",
459 searchslot, MAX_CLIENT);
462 unsigned free_slot_count
463 = DA_MAX_DOWNLOAD_REQ_AT_ONCE - active_count;
464 int pendedslot = get_pended_slot_index(clientinfo_list);
465 if(pendedslot >= 0) {
466 TRACE_DEBUG_INFO_MSG ("Free Space [%d]", free_slot_count);
467 for (;free_slot_count > 0 && pendedslot >= 0; free_slot_count--) {
468 TRACE_DEBUG_INFO_MSG ("Start pended job [%d]", pendedslot);
469 _create_download_thread(&clientinfo_list[pendedslot]);
470 pendedslot = get_pended_slot_index(clientinfo_list);
474 if (free_slot_count <= 0) { // change to PENDED
475 // start pended job, deal this job to pended
476 _change_pended_download(clientinfo_list[searchslot].clientinfo);
477 TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]",
478 searchslot, MAX_CLIENT);
480 _create_download_thread(&clientinfo_list[searchslot]);
485 int _handle_client_request(download_clientinfo* clientinfo)
492 TRACE_DEBUG_MSG("NULL-CHECK");
496 switch (msgType = ipc_receive_header(clientinfo->clientfd)) {
497 case DOWNLOAD_CONTROL_STOP:
498 if (clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
499 // clear slot requested by client after finished download
500 TRACE_DEBUG_INFO_MSG("request Free slot to main thread");
501 clear_socket(clientinfo);
504 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_STOP");
505 da_ret = da_cancel_download(clientinfo->req_id);
506 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
507 if (da_ret != DA_RESULT_OK) {
508 /* FIXME : need to seperate in detail according to error return values */
509 clientinfo->state = DOWNLOAD_STATE_FAILED;
510 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
511 TRACE_DEBUG_MSG("Fail to request cancel [%d]", da_ret);
513 clientinfo->state = DOWNLOAD_STATE_STOPPED;
514 clientinfo->err = DOWNLOAD_ERROR_NONE;
515 if (clientinfo->requestinfo) {
516 if (clientinfo->requestinfo->notification)
517 set_downloadedinfo_appfw_notification(clientinfo);
518 download_provider_db_requestinfo_remove(clientinfo->
519 requestinfo->requestid);
521 download_provider_db_history_new(clientinfo);
523 ipc_send_stateinfo(clientinfo);
524 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
526 case DOWNLOAD_CONTROL_PAUSE:
527 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_PAUSE");
528 da_ret = da_suspend_download(clientinfo->req_id);
529 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
530 if (da_ret != DA_RESULT_OK) {
531 /* FIXME : need to seperate in detail according to error return values */
532 clientinfo->state = DOWNLOAD_STATE_FAILED;
533 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
534 TRACE_DEBUG_MSG("Fail to request suspend [%d]", da_ret);
536 clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED;
537 clientinfo->err = DOWNLOAD_ERROR_NONE;
539 ipc_send_stateinfo(clientinfo);
540 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
542 case DOWNLOAD_CONTROL_RESUME:
543 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_RESUME");
544 da_ret = da_resume_download(clientinfo->req_id);
545 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
546 if (da_ret != DA_RESULT_OK) {
547 /* FIXME : need to seperate in detail according to error return values */
548 clientinfo->state = DOWNLOAD_STATE_FAILED;
549 clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER;
550 TRACE_DEBUG_MSG("Fail to request resume [%d]", da_ret);
552 clientinfo->state = DOWNLOAD_STATE_DOWNLOADING;
553 clientinfo->err = DOWNLOAD_ERROR_NONE;
555 ipc_send_stateinfo(clientinfo);
556 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
558 case DOWNLOAD_CONTROL_GET_STATE_INFO: // sync call
559 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_GET_STATE_INFO");
560 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
561 ipc_send_stateinfo(clientinfo);
562 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
564 case DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO: // sync call
565 TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO");
566 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
567 ipc_send_downloadinfo(clientinfo);
568 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
572 TRACE_DEBUG_MSG("(Closed Socket ) terminate event thread (%d)",
574 // bloken socket... it seems the client is dead or closed by agent thread.
575 // close socket, this will break the loop. and terminate this thread.
576 clear_socket(clientinfo);
579 TRACE_DEBUG_MSG("Unknow message [%d]", msgType);
585 void *run_manage_download_server(void *args)
587 int listenfd = 0; // main socket to be albe to listen the new connection
590 fd_set rset, exceptset;
591 struct timeval timeout;
592 long flexible_timeout;
593 download_clientinfo_slot *clientinfo_list;
595 unsigned active_count = 0;
596 download_clientinfo *request_clientinfo;
602 struct sockaddr_un listenaddr, clientaddr;
604 GMainLoop *mainloop = (GMainLoop *) args;
607 if (ret != DOWNLOAD_ERROR_NONE) {
608 TRACE_DEBUG_MSG("failed to init agent");
609 TerminateDaemon(SIGTERM);
612 clear_downloadinginfo_appfw_notification();
614 if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
615 TRACE_DEBUG_MSG("failed to create socket");
616 TerminateDaemon(SIGTERM);
620 bzero(&listenaddr, sizeof(listenaddr));
621 listenaddr.sun_family = AF_UNIX;
622 strcpy(listenaddr.sun_path, DOWNLOAD_PROVIDER_IPC);
624 if (bind(listenfd, (struct sockaddr *)&listenaddr, sizeof listenaddr) !=
626 TRACE_DEBUG_MSG("failed to call bind");
627 TerminateDaemon(SIGTERM);
631 if (chmod(listenaddr.sun_path, 0777) < 0) {
633 ("failed to change the permission of socket file");
634 TerminateDaemon(SIGTERM);
638 if (listen(listenfd, MAX_CLIENT) != 0) {
639 TRACE_DEBUG_MSG("failed to call listen");
640 TerminateDaemon(SIGTERM);
645 TRACE_DEBUG_INFO_MSG("Ready to listen IPC [%d][%s]", listenfd,
646 DOWNLOAD_PROVIDER_IPC);
648 // allocation the array structure for managing the clients.
650 (download_clientinfo_slot *) calloc(MAX_CLIENT,
651 sizeof(download_clientinfo_slot));
652 if (clientinfo_list == NULL) {
653 TRACE_DEBUG_MSG("failed to allocate the memory for client list");
654 TerminateDaemon(SIGTERM);
658 if (pthread_attr_init(&g_download_provider_thread_attr) != 0) {
659 TRACE_DEBUG_MSG("failed to call pthread_attr_init for client");
660 TerminateDaemon(SIGTERM);
663 if (pthread_attr_setdetachstate(&g_download_provider_thread_attr,
664 PTHREAD_CREATE_DETACHED) != 0) {
665 TRACE_DEBUG_MSG("failed to set detach option");
666 TerminateDaemon(SIGTERM);
670 flexible_timeout = DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
672 FD_ZERO(&g_download_provider_socket_readset);
673 FD_ZERO(&g_download_provider_socket_exceptset);
674 FD_SET(listenfd, &g_download_provider_socket_readset);
675 FD_SET(listenfd, &g_download_provider_socket_exceptset);
677 while (g_main_loop_is_running(mainloop)) {
680 for (i = 0; i < MAX_CLIENT; i++) {
681 if (!clientinfo_list[i].clientinfo)
684 if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED) {
685 if (clientinfo_list[i].clientinfo->clientfd <= 0)
686 clear_clientinfoslot(&clientinfo_list[i]);
692 rset = g_download_provider_socket_readset;
693 exceptset = g_download_provider_socket_exceptset;
695 memset(&timeout, 0x00, sizeof(struct timeval));
696 timeout.tv_sec = flexible_timeout;
698 if (select((maxfd + 1), &rset, 0, &exceptset, &timeout) < 0) {
700 ("select error, provider can't receive any request from client.");
701 TerminateDaemon(SIGTERM);
705 for (i = 0; i < MAX_CLIENT; i++) { // find the socket received the packet.
706 if (!clientinfo_list[i].clientinfo)
708 //Even if no socket, downloading should be progressed.
709 if (clientinfo_list[i].clientinfo->clientfd <= 0)
711 if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &rset) > 0) {
712 // ignore it is not started yet.
713 if (clientinfo_list[i].clientinfo->state <= DOWNLOAD_STATE_READY)
715 TRACE_DEBUG_INFO_MSG("FD_ISSET [%d] readset slot[%d]",
716 clientinfo_list[i].clientinfo->clientfd, i);
717 _handle_client_request(clientinfo_list[i].clientinfo);
720 } else if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &exceptset) > 0) {
721 TRACE_DEBUG_MSG("FD_ISSET [%d] exceptset slot[%d]", clientinfo_list[i].clientinfo->clientfd, i);
722 clear_clientinfoslot(&clientinfo_list[i]);
726 if (FD_ISSET(listenfd, &exceptset) > 0) {
727 TRACE_DEBUG_MSG("meet listenfd Exception of socket");
728 TerminateDaemon(SIGTERM);
730 } else if (FD_ISSET(listenfd, &rset) > 0) { // new connection
731 TRACE_DEBUG_INFO_MSG("FD_ISSET listenfd rset");
736 DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL;
739 (download_clientinfo *) calloc(1,
740 sizeof(download_clientinfo));
741 if (!request_clientinfo) {
743 ("download-provider can't allocate the memory, try later");
744 clientlen = sizeof(clientaddr);
745 int clientfd = accept(listenfd,
746 (struct sockaddr *)&clientaddr, &clientlen);
747 close(clientfd); // disconnect.
748 sleep(5); // provider need the time of refresh.
752 clientlen = sizeof(clientaddr);
753 request_clientinfo->clientfd = accept(listenfd,
754 (struct sockaddr*)&clientaddr,
756 if (request_clientinfo->clientfd < 0) {
757 clear_clientinfo(request_clientinfo);
758 sleep(5); // provider need the time of refresh.
761 if (_handle_new_connection(clientinfo_list, request_clientinfo) < 0) {
765 // after starting the download by DA, event thread will start to get the event from client.
766 if (request_clientinfo && request_clientinfo->clientfd > 0) {
767 FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_readset); // add new descriptor to set
768 FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_exceptset);
769 if (request_clientinfo->clientfd > maxfd )
770 maxfd = request_clientinfo->clientfd; /* for select */
774 if (is_timeout) { // timeout
775 // If there is better solution to be able to know
776 // the number of downloading threads, replace below rough codes.
777 active_count = get_downloading_count(clientinfo_list);
778 // check whether the number of downloading is already maximum.
779 if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE)
782 unsigned free_slot_count
783 = DA_MAX_DOWNLOAD_REQ_AT_ONCE - active_count;
784 int pendedslot = get_pended_slot_index(clientinfo_list);
785 if(pendedslot >= 0) {
786 TRACE_DEBUG_INFO_MSG ("Free Space [%d]", free_slot_count);
787 for (;free_slot_count > 0 && pendedslot >= 0; free_slot_count--) {
788 TRACE_DEBUG_INFO_MSG ("start pended job [%d]", pendedslot);
789 if (_create_download_thread(&clientinfo_list[pendedslot]) > 0)
791 pendedslot = get_pended_slot_index(clientinfo_list);
795 if (check_retry && free_slot_count > 0) {
796 // Auto re-download feature.
797 // ethernet may be connected with other downloading items.
798 if (get_network_status() < 0)
801 // check auto-retrying list regardless state. pended state is also included to checking list.
803 download_dbinfo_list *db_list =
804 download_provider_db_get_list(DOWNLOAD_STATE_NONE);
805 if (!db_list || db_list->count <= 0) {
807 ("provider does not need to check DB anymore. in this life.");
808 // provider does not need to check DB anymore. in this life.
811 download_provider_db_list_free(db_list);
816 DA_MAX_DOWNLOAD_REQ_AT_ONCE
817 && i < db_list->count; i++) {
818 if (db_list->item[i].requestid <= 0)
820 if (get_same_request_slot_index
821 (clientinfo_list,db_list->item[i].requestid) < 0) {
822 // not found requestid in memory
824 ("Retry download [%d]",
825 db_list->item[i].requestid);
826 //search empty slot. copy db info to slot.
828 get_empty_slot_index(clientinfo_list);
829 if (searchslot < 0) {
831 ("download-provider is busy, try later");
833 flexible_timeout * 2;
836 // allocte requestinfo to empty slot.
838 (download_clientinfo *)
839 calloc(1, sizeof(download_clientinfo));
840 if (!request_clientinfo)
842 request_clientinfo->requestinfo
844 download_provider_db_get_requestinfo
846 if (!request_clientinfo->requestinfo) {
847 free(request_clientinfo);
848 request_clientinfo = NULL;
852 CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL);
853 request_clientinfo->state = DOWNLOAD_STATE_READY;
854 clientinfo_list[searchslot].clientinfo =
858 ("Retry download [%d/%d][%d/%d]",
859 searchslot, MAX_CLIENT,
861 DA_MAX_DOWNLOAD_REQ_AT_ONCE);
862 if (_create_download_thread(&clientinfo_list[searchslot]) > 0)
866 if (i >= db_list->count) // do not search anymore.
868 download_provider_db_list_free(db_list);
871 // save system resource (CPU)
872 if (check_retry == 0 && active_count == 0
873 && flexible_timeout <
874 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
875 flexible_timeout = flexible_timeout * 2;
876 if (flexible_timeout >
877 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL)
879 DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL;
880 TRACE_DEBUG_INFO_MSG("Next Timeout after [%ld] sec",
883 } // if (i >= MAX_CLIENT) { // timeout
886 FD_CLR(listenfd, &rset);
887 FD_CLR(listenfd, &exceptset);
888 FD_CLR(listenfd, &g_download_provider_socket_readset);
889 FD_CLR(listenfd, &g_download_provider_socket_exceptset);
891 // close accept socket.
897 // close all sockets for client. ..
898 // client thread will terminate by itself through catching this closing.
899 for (searchslot = 0; searchslot < MAX_CLIENT; searchslot++)
900 if (clientinfo_list[searchslot].clientinfo)
901 clear_clientinfoslot(&clientinfo_list[searchslot]);
904 free(clientinfo_list);
910 void __download_info_cb(user_download_info_t *download_info, void *user_data)
914 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
917 download_clientinfo_slot *clientinfoslot =
918 (download_clientinfo_slot *) user_data;
919 download_clientinfo *clientinfo =
920 (download_clientinfo *) clientinfoslot->clientinfo;
922 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
925 TRACE_DEBUG_INFO_MSG("id[%d],size[%lu]",
926 download_info->da_dl_req_id, download_info->file_size);
928 if (clientinfo->req_id != download_info->da_dl_req_id) {
929 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
931 download_info->da_dl_req_id);
934 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
935 if (!clientinfo->downloadinfo)
936 clientinfo->downloadinfo =
937 (download_content_info *) calloc(1, sizeof(download_content_info));
938 if (clientinfo->downloadinfo)
939 clientinfo->downloadinfo->file_size = download_info->file_size;
940 if (download_info->file_type) {
941 TRACE_DEBUG_INFO_MSG("mime[%s]", download_info->file_type);
943 len = strlen(download_info->file_type);
944 if (len > (DP_MAX_STR_LEN - 1))
945 len = DP_MAX_STR_LEN - 1;
946 if (clientinfo->downloadinfo) {
947 strncpy(clientinfo->downloadinfo->mime_type,
948 download_info->file_type, len);
949 download_provider_db_requestinfo_update_column
950 (clientinfo, DOWNLOAD_DB_MIMETYPE);
953 if (download_info->tmp_saved_path) {
955 TRACE_DEBUG_INFO_MSG("tmp path[%s]", download_info->tmp_saved_path);
956 clientinfo->tmp_saved_path =
957 strdup(download_info->tmp_saved_path);
958 download_provider_db_requestinfo_update_column(clientinfo,
959 DOWNLOAD_DB_SAVEDPATH);
960 str = strrchr(download_info->tmp_saved_path, '/');
964 if (len > (DP_MAX_STR_LEN - 1))
965 len = DP_MAX_STR_LEN - 1;
966 if (clientinfo->downloadinfo) {
967 strncpy(clientinfo->downloadinfo->content_name,
969 download_provider_db_requestinfo_update_column
970 (clientinfo, DOWNLOAD_DB_FILENAME);
971 TRACE_DEBUG_INFO_MSG("content_name[%s]",
972 clientinfo->downloadinfo->
978 if (clientinfo->requestinfo->callbackinfo.started)
979 ipc_send_downloadinfo(clientinfo);
981 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
984 void __downloading_info_cb(user_downloading_info_t *download_info,
989 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
992 download_clientinfo_slot *clientinfoslot =
993 (download_clientinfo_slot *) user_data;
994 download_clientinfo *clientinfo =
995 (download_clientinfo *) clientinfoslot->clientinfo;
997 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
1000 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
1001 if (clientinfo->req_id != download_info->da_dl_req_id) {
1002 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
1004 download_info->da_dl_req_id);
1005 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1008 if (!clientinfo->downloadinginfo)
1009 clientinfo->downloadinginfo = (downloading_state_info *) calloc(1,
1010 sizeof(downloading_state_info));
1011 if (clientinfo->downloadinginfo)
1012 clientinfo->downloadinginfo->received_size =
1013 download_info->total_received_size;
1014 if (download_info->saved_path) {
1015 TRACE_DEBUG_INFO_MSG("tmp path[%s]", download_info->saved_path);
1016 len = strlen(download_info->saved_path);
1017 if (len > (DP_MAX_PATH_LEN - 1))
1018 len = DP_MAX_PATH_LEN - 1;
1019 if (clientinfo->downloadinginfo)
1020 strncpy(clientinfo->downloadinginfo->saved_path,
1021 download_info->saved_path, len);
1022 /* FIXME : This should be reviewd again after smack rules is applied */
1023 if (chown(clientinfo->downloadinginfo->saved_path,
1024 clientinfo->credentials.uid,
1025 clientinfo->credentials.gid) < 0)
1026 TRACE_DEBUG_INFO_MSG("Fail to chown [%s]", strerror(errno));
1029 static size_t updated_second;
1030 time_t tt = time(NULL);
1031 struct tm *localTime = localtime(&tt);
1033 if (updated_second != localTime->tm_sec || download_info->saved_path) { // every 1 second.
1034 if (clientinfo->requestinfo
1035 && clientinfo->requestinfo->notification)
1036 set_downloadinginfo_appfw_notification(clientinfo);
1037 if (clientinfo->requestinfo->callbackinfo.progress)
1038 ipc_send_downloadinginfo(clientinfo);
1039 updated_second = localTime->tm_sec;
1041 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1044 void __notify_cb(user_notify_info_t *notify_info, void *user_data)
1047 TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL");
1050 download_clientinfo_slot *clientinfoslot =
1051 (download_clientinfo_slot *) user_data;
1052 download_clientinfo *clientinfo =
1053 (download_clientinfo *) clientinfoslot->clientinfo;
1055 TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL");
1059 TRACE_DEBUG_INFO_MSG("id[%d],state[%d],err[%d]",
1060 notify_info->da_dl_req_id,
1061 notify_info->state, notify_info->err);
1062 if (clientinfo->req_id != notify_info->da_dl_req_id) {
1063 TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}",
1064 clientinfo->req_id, notify_info->da_dl_req_id);
1068 CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex));
1070 clientinfo->state = __change_state(notify_info->state);
1071 clientinfo->err = __change_error(notify_info->err);
1072 if (clientinfo->state == DOWNLOAD_STATE_FINISHED ||
1073 clientinfo->state == DOWNLOAD_STATE_FAILED) {
1074 if (clientinfo->requestinfo) {
1075 if (clientinfo->requestinfo->notification)
1076 set_downloadedinfo_appfw_notification(clientinfo);
1077 download_provider_db_requestinfo_remove(clientinfo->
1078 requestinfo->requestid);
1080 download_provider_db_history_new(clientinfo);
1081 TRACE_DEBUG_INFO_MSG("[TEST]Finish clientinfo[%p], fd[%d]",
1082 clientinfo, clientinfo->clientfd);
1085 TRACE_DEBUG_INFO_MSG("state[%d]", clientinfo->state);
1086 ipc_send_stateinfo(clientinfo);
1088 CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex));
1091 int __change_state(da_state state)
1093 int ret = DOWNLOAD_STATE_NONE;
1095 case DA_STATE_WAITING:
1096 case DA_STATE_DOWNLOAD_STARTED:
1097 TRACE_DEBUG_INFO_MSG("DA_STATE_DOWNLOAD_STARTED");
1098 ret = DOWNLOAD_STATE_READY;
1100 case DA_STATE_DOWNLOADING:
1101 TRACE_DEBUG_INFO_MSG("DA_STATE_DOWNLOADING");
1102 ret = DOWNLOAD_STATE_DOWNLOADING;
1104 case DA_STATE_DOWNLOAD_COMPLETE:
1105 TRACE_DEBUG_INFO_MSG("DA_STATE_COMPLETE");
1106 ret = DOWNLOAD_STATE_INSTALLING;
1108 case DA_STATE_CANCELED:
1109 TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED");
1110 ret = DOWNLOAD_STATE_STOPPED;
1112 case DA_STATE_CANCELED_ALL:
1113 TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED_ALL");
1115 case DA_STATE_SUSPENDED:
1116 TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED");
1117 ret = DOWNLOAD_STATE_PAUSED;
1119 case DA_STATE_SUSPENDED_ALL:
1120 TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED_ALL");
1122 case DA_STATE_RESUMED:
1123 TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED");
1124 ret = DOWNLOAD_STATE_DOWNLOADING;
1126 case DA_STATE_RESUMED_ALL:
1127 TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED_ALL");
1129 case DA_STATE_FINISHED:
1130 TRACE_DEBUG_INFO_MSG("DA_STATE_FINISHED");
1131 ret = DOWNLOAD_STATE_FINISHED;
1133 case DA_STATE_FAILED:
1134 TRACE_DEBUG_INFO_MSG("DA_STATE_FAILED");
1135 ret = DOWNLOAD_STATE_FAILED;
1143 int __change_error(int err)
1145 int ret = DOWNLOAD_ERROR_UNKOWN;
1148 ret = DOWNLOAD_ERROR_NONE;
1150 case DA_ERR_INVALID_ARGUMENT:
1151 ret = DOWNLOAD_ERROR_INVALID_PARAMETER;
1153 case DA_ERR_FAIL_TO_MEMALLOC:
1154 ret = DOWNLOAD_ERROR_OUT_OF_MEMORY;
1156 case DA_ERR_UNREACHABLE_SERVER:
1157 ret = DOWNLOAD_ERROR_NETWORK_UNREACHABLE;
1159 case DA_ERR_HTTP_TIMEOUT:
1160 ret = DOWNLOAD_ERROR_CONNECTION_TIMED_OUT;
1162 case DA_ERR_DISK_FULL:
1163 ret = DOWNLOAD_ERROR_NO_SPACE;
1165 case DA_ERR_INVALID_STATE:
1166 ret = DOWNLOAD_ERROR_INVALID_STATE;
1168 case DA_ERR_NETWORK_FAIL:
1169 ret = DOWNLOAD_ERROR_CONNECTION_FAILED;
1171 case DA_ERR_INVALID_URL:
1172 ret = DOWNLOAD_ERROR_INVALID_URL;
1174 case DA_ERR_INVALID_INSTALL_PATH:
1175 ret = DOWNLOAD_ERROR_INVALID_DESTINATION;
1177 case DA_ERR_ALREADY_MAX_DOWNLOAD:
1178 ret = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS;
1180 case DA_ERR_FAIL_TO_INSTALL_FILE:
1181 ret = DOWNLOAD_ERROR_INSTALL_FAIL;
1183 case DA_ERR_FAIL_TO_CREATE_THREAD:
1184 case DA_ERR_FAIL_TO_OBTAIN_MUTEX:
1185 case DA_ERR_FAIL_TO_ACCESS_FILE:
1186 case DA_ERR_FAIL_TO_GET_CONF_VALUE:
1187 case DA_ERR_FAIL_TO_ACCESS_STORAGE:
1188 case DA_ERR_DLOPEN_FAIL:
1189 ret = DOWNLOAD_ERROR_IO_ERROR;
1198 da_client_cb_t da_cb = {
1201 __downloading_info_cb
1203 da_ret = da_init(&da_cb, DA_DOWNLOAD_MANAGING_METHOD_AUTO);
1204 if (da_ret != DA_RESULT_OK) {
1205 return DOWNLOAD_ERROR_FAIL_INIT_AGENT;
1207 return DOWNLOAD_ERROR_NONE;
1210 void _deinit_agent()