2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include <sys/socket.h>
30 #include <app_manager.h>
32 #include "download-provider.h"
33 #include "download-provider-log.h"
34 #include "download-provider-config.h"
35 #include "download-provider-slots.h"
36 #include "download-provider-socket.h"
37 #include "download-provider-pthread.h"
38 #include "download-provider-db.h"
39 #include "download-provider-queue.h"
40 #include "download-provider-request.h"
41 #include "download-provider-da-interface.h"
43 void dp_terminate(int signo);
45 static char *__print_command(dp_command_type cmd)
65 case DP_CMD_SET_DESTINATION :
66 return "SET_DESTINATION";
67 case DP_CMD_SET_FILENAME :
68 return "SET_FILENAME";
69 case DP_CMD_SET_NOTIFICATION :
70 return "SET_NOTIFICATION";
71 case DP_CMD_SET_STATE_CALLBACK :
72 return "SET_STATE_CALLBACK";
73 case DP_CMD_SET_PROGRESS_CALLBACK :
74 return "SET_PROGRESS_CALLBACK";
75 case DP_CMD_SET_AUTO_DOWNLOAD :
76 return "SET_AUTO_DOWNLOAD";
77 case DP_CMD_SET_NETWORK_TYPE :
78 return "SET_NETWORK_TYPE";
79 case DP_CMD_SET_HTTP_HEADER :
80 return "SET_HTTP_HEADER";
81 case DP_CMD_DEL_HTTP_HEADER :
82 return "DEL_HTTP_HEADER";
83 case DP_CMD_GET_HTTP_HEADER :
84 return "GET_HTTP_HEADER";
87 case DP_CMD_GET_DESTINATION :
88 return "GET_DESTINATION";
89 case DP_CMD_GET_FILENAME :
90 return "GET_FILENAME";
91 case DP_CMD_GET_NOTIFICATION :
92 return "GET_NOTIFICATION";
93 case DP_CMD_GET_STATE_CALLBACK :
94 return "GET_STATE_CALLBACK";
95 case DP_CMD_GET_PROGRESS_CALLBACK :
96 return "GET_PROGRESS_CALLBACK";
97 case DP_CMD_GET_HTTP_HEADERS :
98 return "GET_HTTP_HEADERS";
99 case DP_CMD_ADD_EXTRA_PARAM :
100 return "ADD_EXTRA_PARAM";
101 case DP_CMD_GET_EXTRA_PARAM :
102 return "GET_EXTRA_PARAM";
103 case DP_CMD_REMOVE_EXTRA_PARAM :
104 return "REMOVE_EXTRA_PARAM";
105 case DP_CMD_GET_AUTO_DOWNLOAD :
106 return "GET_AUTO_DOWNLOAD";
107 case DP_CMD_GET_NETWORK_TYPE :
108 return "GET_NETWORK_TYPE";
109 case DP_CMD_GET_SAVED_PATH :
110 return "GET_SAVED_PATH";
111 case DP_CMD_GET_TEMP_SAVED_PATH :
112 return "GET_TEMP_SAVED_PATH";
113 case DP_CMD_GET_MIME_TYPE :
114 return "GET_MIME_TYPE";
115 case DP_CMD_GET_RECEIVED_SIZE :
116 return "GET_RECEIVED_SIZE";
117 case DP_CMD_GET_TOTAL_FILE_SIZE :
118 return "GET_TOTAL_FILE_SIZE";
119 case DP_CMD_GET_CONTENT_NAME :
120 return "GET_CONTENT_NAME";
121 case DP_CMD_GET_HTTP_STATUS :
122 return "GET_HTTP_STATUS";
123 case DP_CMD_GET_ETAG :
124 return "DP_CMD_GET_ETAG";
125 case DP_CMD_GET_STATE :
127 case DP_CMD_GET_ERROR :
129 case DP_CMD_SET_COMMAND_SOCKET :
130 return "SET_COMMAND_SOCKET";
131 case DP_CMD_SET_EVENT_SOCKET :
132 return "SET_EVENT_SOCKET";
136 return "UNKNOWN COMMAND";
139 /* compare two string */
140 static int __cmp_string(char *s1, char *s2)
146 TRACE_ERROR("[CHECK PARAM]");
152 TRACE_ERROR("[CHECK PARAM] len[%d]", s1_len);
158 TRACE_ERROR("[CHECK PARAM] len[%d]", s2_len);
162 if (s1_len != s2_len) {
163 TRACE_ERROR("[DIFF] len[%d:%d]", s1_len, s2_len);
167 if (strncmp(s1, s2, s1_len) != 0) {
168 TRACE_ERROR("[DIFF] cmp[%s:%s]", s1, s2);
175 //////////////////////////////////////////////////////////////////////////
176 /// @brief return index of empty slot
177 static int __get_empty_request_index(dp_request_slots *slots)
184 for (i = 0; i < DP_MAX_REQUEST; i++)
185 if (!slots[i].request)
190 //////////////////////////////////////////////////////////////////////////
191 /// @brief return index of slot having same ID
192 /// @param ID want to search
193 static int __get_same_request_index(dp_request_slots *slots, int id)
197 if (!slots || id < 0)
200 for (i = 0; i < DP_MAX_REQUEST; i++) {
201 if (slots[i].request) {
202 if (slots[i].request->id == id) {
210 //////////////////////////////////////////////////////////////////////////
211 /// @brief return string via IPC
212 static void __send_return_string(int fd, dp_error_type errcode, char* str)
216 dp_ipc_send_errorcode(fd, errcode);
217 dp_ipc_send_string(fd, str);
220 //////////////////////////////////////////////////////////////////////////
221 /// @brief return custom value via IPC
222 static void __send_return_custom_type(int fd, dp_error_type errcode, void *value, size_t type_size)
224 dp_ipc_send_errorcode(fd, errcode);
225 dp_ipc_send_custom_type(fd, value, type_size);
228 static void __clear_group(dp_privates *privates, dp_client_group *group)
230 dp_request *request = NULL;
235 for (i = 0; i < DP_MAX_REQUEST; i++) {
236 if (privates->requests[i].request == NULL)
238 if (privates->requests[i].request->group == NULL)
240 if (privates->requests[i].request->id <= 0)
243 request = privates->requests[i].request;
245 CLIENT_MUTEX_LOCK(&request->mutex);
247 if (request->group != group ||
248 request->group->cmd_socket != group->cmd_socket) {
249 CLIENT_MUTEX_UNLOCK(&request->mutex);
253 // cancel the requests which not setted auto-downloading
254 int auto_download = dp_db_get_int_column(request->id,
255 DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_AUTO_DOWNLOAD);
256 if (auto_download <= 0) {
257 int agentid = request->agent_id;
258 int requestid = request->id;
259 int state = request->state;
260 TRACE_INFO("[CANCEL][%d] [%s] fd[%d]", requestid,
261 request->group->pkgname, request->group->cmd_socket);
263 if ((state == DP_STATE_READY || state == DP_STATE_QUEUED ||
264 state == DP_STATE_CONNECTING ||
265 state == DP_STATE_DOWNLOADING ||
266 state == DP_STATE_PAUSE_REQUESTED ||
267 state == DP_STATE_PAUSED)) {
268 request->state = DP_STATE_FAILED;
269 request->error = DP_ERROR_CLIENT_DOWN;
270 if (dp_db_set_column(request->id, DP_DB_TABLE_LOG,
271 DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
272 &request->state) < 0) {
273 TRACE_ERROR("[ERROR][%d][SQL]", requestid);
274 dp_db_remove_all(request->id);
276 if (dp_db_set_column(request->id, DP_DB_TABLE_LOG,
277 DP_DB_COL_ERRORCODE, DP_DB_COL_TYPE_INT,
278 &request->error) < 0) {
279 TRACE_ERROR("[ERROR][%d][SQL]", requestid);
284 CLIENT_MUTEX_UNLOCK(&request->mutex);
285 dp_request_free(request);
286 privates->requests[i].request = NULL;
288 // call cancel_agent after free.
290 dp_is_alive_download(agentid)) {
292 ("[CANCEL-AGENT][%d] state [%s]",
293 requestid, dp_print_state(state));
294 if (dp_cancel_agent_download(agentid) < 0)
295 TRACE_INFO("[CANCEL FAILURE]");
302 // disconnect the request from group.
304 ("[DISCONNECT][%d] [%s] fd[%d]", request->id,
305 request->group->pkgname, request->group->cmd_socket);
307 request->group = NULL;
308 request->state_cb = 0;
309 request->progress_cb = 0;
311 CLIENT_MUTEX_UNLOCK(&request->mutex);
312 // yield to agent thread before free
314 // free finished slot without client process
315 request = privates->requests[i].request;
316 if (request != NULL) {
317 CLIENT_MUTEX_LOCK(&request->mutex);
318 if (request->state == DP_STATE_COMPLETED ||
319 request->state == DP_STATE_FAILED ||
320 request->state == DP_STATE_CANCELED) {
321 TRACE_INFO("[FREE][%d] state[%s]", request->id,
322 dp_print_state(request->state));
323 CLIENT_MUTEX_UNLOCK(&request->mutex);
324 dp_request_free(request);
325 privates->requests[i].request = NULL;
328 CLIENT_MUTEX_UNLOCK(&request->mutex);
332 dp_client_group_free(group);
335 static int __dp_add_extra_param(int fd, int id)
337 dp_error_type ret = DP_ERROR_NONE;
340 unsigned values_length = 0;
342 char **values = NULL;
345 TRACE_ERROR("[CHECK] socket");
346 return DP_ERROR_IO_ERROR;
349 TRACE_ERROR("[CHECK] ID");
350 return DP_ERROR_INVALID_PARAMETER;
353 if (dp_ipc_read_custom_type(fd, &length, sizeof(int)) < 0) {
354 TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]", id);
355 ret = DP_ERROR_IO_ERROR;
357 TRACE_INFO("[RECV] length %d", length);
359 ret = DP_ERROR_INVALID_PARAMETER;
361 key = dp_ipc_read_string(fd);
363 TRACE_ERROR("[ERROR][%d][IO_ERROR] key", id);
364 ret = DP_ERROR_IO_ERROR;
367 TRACE_INFO("[RECV] key : %s", key);
369 values = (char **)calloc((length - 1), sizeof(char *));
370 if (values == NULL) {
371 ret = DP_ERROR_OUT_OF_MEMORY;
373 for (i = 0; i < length - 1; i++) {
374 values[i] = dp_ipc_read_string(fd);
375 if (values[i] == NULL) {
376 ret = DP_ERROR_IO_ERROR;
383 TRACE_ERROR("[ERROR][%d] length [%d]", id, length);
384 ret = DP_ERROR_INVALID_PARAMETER;
389 if (ret == DP_ERROR_NONE) {
391 for (i = 0; i < length - 1; i++) {
393 db_conds_list_fmt conds_p[conds_count]; // id + key + value
394 memset(&conds_p, 0x00, conds_count * sizeof(db_conds_list_fmt));
395 conds_p[0].column = DP_DB_COL_ID;
396 conds_p[0].type = DP_DB_COL_TYPE_INT;
397 conds_p[0].value = &id;
398 conds_p[1].column = DP_DB_COL_EXTRA_KEY;
399 conds_p[1].type = DP_DB_COL_TYPE_TEXT;
400 conds_p[1].value = key;
401 conds_p[2].column = DP_DB_COL_EXTRA_VALUE;
402 conds_p[2].type = DP_DB_COL_TYPE_TEXT;
403 conds_p[2].value = values[i];
405 dp_db_get_conds_rows_count(DP_DB_TABLE_NOTIFICATION,
406 DP_DB_COL_ID, "AND", conds_count, conds_p);
407 if (check_key <= 0) { // create newly
409 if (dp_db_insert_columns(DP_DB_TABLE_NOTIFICATION,
410 conds_count, conds_p) < 0) {
411 ret = DP_ERROR_OUT_OF_MEMORY;
414 } // else skip. already exist
418 for (i = 0; i < values_length; i++) {
425 static int __dp_get_extra_param_values(int fd, int id, char ***values,
428 dp_error_type ret = DP_ERROR_NONE;
431 char **rows_array = NULL;
434 TRACE_ERROR("[CHECK] socket");
435 return DP_ERROR_IO_ERROR;
438 TRACE_ERROR("[CHECK] ID");
439 return DP_ERROR_INVALID_PARAMETER;
442 if (dp_ipc_read_custom_type(fd, &length, sizeof(int)) < 0) {
443 TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]", id);
444 ret = DP_ERROR_IO_ERROR;
446 TRACE_INFO("[RECV] length %d", length);
447 if (length != 1) { // only a key
448 ret = DP_ERROR_INVALID_PARAMETER;
450 if ((key = dp_ipc_read_string(fd)) == NULL) {
451 TRACE_ERROR("[ERROR][%d][IO_ERROR] key", id);
452 ret = DP_ERROR_IO_ERROR;
456 if (ret == DP_ERROR_NONE) {
458 db_conds_list_fmt conds_p[conds_count]; // id + key + value
459 memset(&conds_p, 0x00, conds_count * sizeof(db_conds_list_fmt));
460 conds_p[0].column = DP_DB_COL_ID;
461 conds_p[0].type = DP_DB_COL_TYPE_INT;
462 conds_p[0].value = &id;
463 conds_p[1].column = DP_DB_COL_EXTRA_KEY;
464 conds_p[1].type = DP_DB_COL_TYPE_TEXT;
465 conds_p[1].value = key;
466 int check_rows = dp_db_get_conds_rows_count
467 (DP_DB_TABLE_NOTIFICATION, DP_DB_COL_EXTRA_VALUE, "AND",
468 conds_count, conds_p);
469 if (check_rows <= 0) {
471 ret = DP_ERROR_NO_DATA;
473 rows_array = (char **)calloc(check_rows, sizeof(char *));
474 if (rows_array == NULL) {
475 ret = DP_ERROR_OUT_OF_MEMORY;
477 // getting the array from DB with key condition
479 dp_db_get_conds_list(DP_DB_TABLE_NOTIFICATION,
480 DP_DB_COL_EXTRA_VALUE, DP_DB_COL_TYPE_TEXT,
481 (void **)rows_array, check_rows, -1, NULL, NULL,
482 "AND", conds_count, conds_p);
483 if (rows_count <= 0) {
485 ret = DP_ERROR_NO_DATA;
489 *values = rows_array;
498 static int __dp_remove_extra_param(int fd, int id)
500 dp_error_type ret = DP_ERROR_NONE;
504 TRACE_ERROR("[CHECK] socket");
505 return DP_ERROR_IO_ERROR;
508 TRACE_ERROR("[CHECK] ID");
509 return DP_ERROR_INVALID_PARAMETER;
512 if ((key = dp_ipc_read_string(fd)) == NULL) {
513 TRACE_ERROR("[ERROR][%d] INVALID_PARAMETER", id);
514 ret = DP_ERROR_IO_ERROR;
516 if (ret == DP_ERROR_NONE) {
517 if (dp_db_cond_remove(id, DP_DB_TABLE_NOTIFICATION,
518 DP_DB_COL_EXTRA_KEY, DP_DB_COL_TYPE_TEXT, key) < 0) {
519 TRACE_ERROR("[ERROR][%d][SQL]", id);
520 ret = DP_ERROR_IO_ERROR;
524 ("[ERROR][%d][%s] key:%s", id, dp_print_errorcode(ret), key);
529 static int __dp_set_group_new(int clientfd, dp_group_slots *groups,
530 dp_credential credential, fd_set *listen_fdset)
533 // if same group. update it.
534 // search same pkg or pid in groups
537 struct timeval tv_timeo; // 2.5 sec
538 char *pkgname = NULL;
541 tv_timeo.tv_usec = 500000;
542 if (setsockopt(clientfd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo,
543 sizeof(tv_timeo)) < 0) {
544 TRACE_STRERROR("[CRITICAL] setsockopt SO_RCVTIMEO");
548 // getting the package name via pid
549 if (app_manager_get_package(credential.pid, &pkgname) ==
550 APP_MANAGER_ERROR_NONE) {
551 TRACE_INFO("package : %s", pkgname);
553 TRACE_ERROR("[CRITICAL] app_manager_get_package");
555 //// TEST CODE ... to allow sample client ( no package name ).
556 if (pkgname == NULL) {
557 pkgname = dp_strdup("unknown_app");
558 TRACE_INFO("default package naming : %s", pkgname);
561 if (pkgname == NULL) {
562 TRACE_ERROR("[CRITICAL] app_manager_get_package");
565 if ((pkg_len = strlen(pkgname)) <= 0) {
566 TRACE_ERROR("[CRITICAL] pkgname:%s", pkgname);
570 for (i = 0; i < DP_MAX_GROUP; i++) {
571 if (groups[i].group != NULL) {
572 // clean garbage slot
573 if (groups[i].group->cmd_socket <= 0 ||
574 groups[i].group->pkgname == NULL) {
575 dp_client_group_free(groups[i].group);
576 groups[i].group = NULL;
579 if (strlen(groups[i].group->pkgname) == pkg_len &&
580 strncmp(groups[i].group->pkgname, pkgname,
583 TRACE_INFO("UPDATE Group: slot:%d pid:%d sock:%d [%s]",
584 i, credential.pid, clientfd, pkgname);
585 if (groups[i].group->cmd_socket > 0 &&
586 groups[i].group->cmd_socket != clientfd) {
587 FD_CLR(groups[i].group->cmd_socket, listen_fdset);
588 dp_socket_free(groups[i].group->cmd_socket);
590 groups[i].group->cmd_socket = clientfd;
598 // search emtpy slot in groups
599 for (i = 0; i < DP_MAX_GROUP; i++)
600 if (groups[i].group == NULL)
602 if (i >= DP_MAX_GROUP) {
603 TRACE_ERROR("[CRITICAL] No space in groups");
609 (dp_client_group *)calloc(1, sizeof(dp_client_group));
610 if (groups[i].group == NULL) {
611 TRACE_ERROR("[CRITICAL] calloc, ignore this client");
616 groups[i].group->cmd_socket = clientfd;
617 groups[i].group->event_socket = -1;
618 groups[i].group->queued_count = 0;
619 groups[i].group->pkgname = dp_strdup(pkgname);
620 groups[i].group->credential.pid = credential.pid;
621 groups[i].group->credential.uid = credential.uid;
622 groups[i].group->credential.gid = credential.gid;
623 TRACE_INFO("New Group: slot:%d pid:%d sock:%d [%s]", i,
624 credential.pid, clientfd, pkgname);
630 static int __dp_set_group_event_sock(int clientfd,
631 dp_group_slots *groups, dp_credential credential)
635 TRACE_INFO("Check event pid:%d sock:%d", credential.pid, clientfd);
636 // search same pid in groups
637 for (i = 0; i < DP_MAX_GROUP; i++) {
638 if (groups[i].group != NULL &&
639 groups[i].group->credential.pid == credential.pid) {
640 if (groups[i].group->event_socket > 0 &&
641 groups[i].group->event_socket != clientfd)
642 dp_socket_free(groups[i].group->event_socket);
643 groups[i].group->event_socket = clientfd;
645 ("Found Group : slot:%d pid:%d csock:%d esock:%d [%s]",
646 i, credential.pid, groups[i].group->cmd_socket,
647 clientfd, groups[i].group->pkgname);
651 if (i >= DP_MAX_GROUP) {
653 ("[CRITICAL] Not found group for PID [%d]", credential.pid);
659 // in url-download, make 3 connection before send CREATE command.
660 // after accepting, fill info to pacakgelist.
661 // 3 socket per 1 package ( info/request/progress )
662 void *dp_thread_requests_manager(void *arg)
664 fd_set rset, eset, listen_fdset, except_fdset;
665 struct timeval timeout; // for timeout of select
666 long flexible_timeout = DP_CARE_CLIENT_MAX_INTERVAL;
667 int listenfd, clientfd, maxfd;
669 struct sockaddr_un clientaddr;
670 dp_credential credential;
671 unsigned i, is_timeout;
672 int prev_timeout = 0;
673 dp_error_type errorcode = DP_ERROR_NONE;
675 dp_privates *privates = (dp_privates*)arg;
676 if (privates == NULL || privates->groups == NULL) {
677 TRACE_ERROR("[CRITICAL] Invalid Address");
678 dp_terminate(SIGTERM);
683 listenfd = privates->listen_fd;
686 TRACE_INFO("Ready to listen [%d][%s]", listenfd, DP_IPC);
688 FD_ZERO(&listen_fdset);
689 FD_ZERO(&except_fdset);
690 FD_SET(listenfd, &listen_fdset);
691 FD_SET(listenfd, &except_fdset);
693 while (privates != NULL && privates->listen_fd >= 0) {
695 // select with timeout
696 // initialize timeout structure for calling timeout exactly
697 memset(&timeout, 0x00, sizeof(struct timeval));
698 timeout.tv_sec = flexible_timeout;
708 if (select((maxfd + 1), &rset, 0, &eset, &timeout) < 0) {
709 TRACE_STRERROR("[CRITICAL] select");
713 if (privates == NULL) {
714 TRACE_INFO("Terminate Thread");
718 if (FD_ISSET(listenfd, &eset) > 0) {
719 TRACE_ERROR("[CRITICAL] listenfd Exception of socket");
721 } else if (FD_ISSET(listenfd, &rset) > 0) {
722 // new client(package) called url_download_create API.
723 // update g_dp_request_max_fd & g_dp_info_max_fd
724 // add to socket to g_dp_request_rset & g_dp_info_rset
728 // Anyway accept client.
729 clientlen = sizeof(clientaddr);
730 clientfd = accept(listenfd,
731 (struct sockaddr*)&clientaddr,
734 TRACE_ERROR("[CRITICAL] accept provider was crashed ?");
735 // provider need the time of refresh.
739 dp_command_type connect_cmd = DP_CMD_NONE;
740 if (dp_ipc_read_custom_type(clientfd,
741 &connect_cmd, sizeof(dp_command_type)) < 0) {
742 TRACE_ERROR("[CRITICAL] CAPI not support CONNECT CMD");
746 if (connect_cmd <= 0) {
747 TRACE_ERROR("[CRITICAL] peer terminate ?");
753 // getting the info of client
754 socklen_t cr_len = sizeof(credential);
755 if (getsockopt(clientfd, SOL_SOCKET, SO_PEERCRED,
756 &credential, &cr_len) == 0) {
758 ("credential : pid=%d, uid=%d, gid=%d",
759 credential.pid, credential.uid, credential.gid);
761 #else // In case of not supported SO_PEERCRED
763 if (dp_ipc_read_custom_type(clientfd,
764 &client_pid, sizeof(int)) < 0) {
765 TRACE_ERROR("[CRITICAL] not support SO_PEERCRED");
769 if (client_pid <= 0) {
770 TRACE_ERROR("[CRITICAL] not support SO_PEERCRED");
774 credential.pid = client_pid;
775 credential.uid = 5000;
776 credential.gid = 5000;
779 switch(connect_cmd) {
780 case DP_CMD_SET_COMMAND_SOCKET:
781 if (__dp_set_group_new(clientfd, privates->groups,
782 credential, &listen_fdset) == 0) {
783 FD_SET(clientfd, &listen_fdset);
784 if (clientfd > maxfd)
790 case DP_CMD_SET_EVENT_SOCKET:
792 if (__dp_set_group_event_sock(clientfd,
793 privates->groups, credential) < 0)
798 TRACE_ERROR("[CRITICAL] Bad access, ignore this client");
804 // listen cmd_socket of all group
805 for (i = 0; i < DP_MAX_GROUP; i++) {
806 dp_client_group *group = privates->groups[i].group;
809 if (group->cmd_socket < 0) {
812 if (FD_ISSET(group->cmd_socket, &rset) > 0) {
813 dp_command client_cmd;
817 client_cmd.cmd = DP_CMD_NONE;
820 if (dp_ipc_read_custom_type(group->cmd_socket,
821 &client_cmd, sizeof(dp_command)) < 0) {
822 TRACE_STRERROR("failed to read cmd");
823 //Resource temporarily unavailable
829 ("[%s][%d] FD[%d] CLIENT[%s] PID[%d] GINDEX[%d]",
830 __print_command(client_cmd.cmd), client_cmd.id,
831 group->cmd_socket, group->pkgname,
832 group->credential.pid, i);
834 if (client_cmd.cmd == 0) { // Client meet some Error.
836 ("[Closed Peer] group[%d][%s] socket[%d]",
837 i, group->pkgname, group->cmd_socket);
838 // check all request included to this group
839 FD_CLR(group->cmd_socket, &listen_fdset);
840 __clear_group(privates, group);
841 privates->groups[i].group = NULL;
845 // Echo .client can check whether provider is busy
846 if (client_cmd.cmd == DP_CMD_ECHO) {
847 // provider can clear read buffer here
848 TRACE_INFO("[ECHO] fd[%d]", group->cmd_socket);
849 if (dp_ipc_send_errorcode
850 (group->cmd_socket, DP_ERROR_NONE) < 0) {
851 // disconnect this group, bad client
852 FD_CLR(group->cmd_socket, &listen_fdset);
853 __clear_group(privates, group);
854 privates->groups[i].group = NULL;
859 if (client_cmd.cmd == DP_CMD_CREATE) {
860 // search empty slot in privates->requests
861 index = __get_empty_request_index(privates->requests);
863 TRACE_ERROR("[CHECK] [DP_ERROR_QUEUE_FULL]");
864 // Busy, No Space in slot
865 dp_ipc_send_errorcode(group->cmd_socket,
866 DP_ERROR_QUEUE_FULL);
868 dp_error_type ret = DP_ERROR_NONE;
869 ret = dp_request_create(client_cmd.id, group,
870 &privates->requests[index].request);
871 if (ret == DP_ERROR_NONE) {
873 ("[CREATE] GOOD ID[%d] SLOT[%d]",
874 privates->requests[index].request->id,
876 __send_return_custom_type(group->cmd_socket,
878 &privates->requests[index].request->id,
882 ("[ERROR][%s]", dp_print_errorcode(ret));
883 dp_ipc_send_errorcode
884 (group->cmd_socket, ret);
890 // below commands must need ID
891 // check exception before searching slots.
892 if (client_cmd.id < 0) {
893 TRACE_ERROR("[CHECK PROTOCOL] ID should not be -1");
894 dp_ipc_send_errorcode(group->cmd_socket,
895 DP_ERROR_INVALID_PARAMETER);
896 // disconnect this group, bad client
897 FD_CLR(group->cmd_socket, &listen_fdset);
898 __clear_group(privates, group);
899 privates->groups[i].group = NULL;
903 // search id in requests slot
904 index = __get_same_request_index
905 (privates->requests, client_cmd.id);
907 // GET API works even if request is NULL.
908 dp_request *request = NULL;
910 request = privates->requests[index].request;
912 // Authentication by packagename.
913 char *auth_pkgname = NULL;
914 errorcode = DP_ERROR_NONE;
915 if (request != NULL) {
916 auth_pkgname = dp_strdup(request->packagename);
917 if (auth_pkgname == NULL)
918 errorcode = DP_ERROR_OUT_OF_MEMORY;
920 auth_pkgname = dp_db_get_text_column(client_cmd.id,
921 DP_DB_TABLE_LOG, DP_DB_COL_PACKAGENAME);
922 if (auth_pkgname == NULL)
923 errorcode = DP_ERROR_ID_NOT_FOUND;
925 if (errorcode == DP_ERROR_NONE) {
927 if (__cmp_string(group->pkgname, auth_pkgname) < 0) {
929 ("[ERROR][%d] Auth [%s]/[%s]", client_cmd.id,
930 group->pkgname, auth_pkgname);
931 errorcode = DP_ERROR_INVALID_PARAMETER;
935 if (errorcode != DP_ERROR_NONE) {
936 TRACE_ERROR("[ERROR][%d][%s]", client_cmd.id,
937 dp_print_errorcode(errorcode));
938 dp_ipc_send_errorcode(group->cmd_socket, errorcode);
942 // if no group, update group.
943 if (request != NULL && request->group == NULL)
944 request->group = group;
946 if (client_cmd.cmd == DP_CMD_DESTROY) {
947 if (request != NULL) {
948 CLIENT_MUTEX_LOCK(&(request->mutex));
949 // call download_cancel API
950 if (request->agent_id > 0 &&
951 dp_is_alive_download(request->agent_id)) {
952 TRACE_INFO("[CANCEL-AGENT][%d] agent_id[%d]",
953 client_cmd.id, request->agent_id);
954 if (dp_cancel_agent_download
955 (request->agent_id) < 0)
956 TRACE_INFO("[CANCEL FAILURE][%d]",
958 request->state = DP_STATE_CANCELED;
960 (request->id, DP_DB_TABLE_LOG,
961 DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
962 &request->state) < 0) {
963 TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
965 dp_print_state(request->state));
966 dp_db_remove_all(request->id);
969 CLIENT_MUTEX_UNLOCK(&(request->mutex));
971 // Always return GOOD
972 dp_ipc_send_errorcode
973 (group->cmd_socket, DP_ERROR_NONE);
977 dp_request_get_tmpsavedpath
978 (client_cmd.id, &errorcode);
979 if ((tmp_path != NULL && strlen(tmp_path) > 0) &&
980 dp_is_file_exist(tmp_path) == 0) {
981 TRACE_INFO("[REMOVE][%d] TEMP FILE [%s]",
982 client_cmd.id, tmp_path);
983 if (unlink(tmp_path) != 0)
984 TRACE_STRERROR("[ERROR][%d] remove file",
988 // in DESTROY, clear all info
989 dp_db_remove_all(client_cmd.id);
991 // in DESTROY, maintain DB logging
992 if (request != NULL) {
993 CLIENT_MUTEX_LOCK(&(request->mutex));
994 // change state to CANCELED.
995 if (request->state == DP_STATE_NONE ||
996 request->state == DP_STATE_READY ||
997 request->state == DP_STATE_QUEUED ||
998 request->state == DP_STATE_CONNECTING ||
999 request->state == DP_STATE_DOWNLOADING ||
1000 request->state == DP_STATE_PAUSE_REQUESTED ||
1001 request->state == DP_STATE_PAUSED) {
1002 request->state = DP_STATE_CANCELED;
1003 if (dp_db_set_column
1004 (request->id, DP_DB_TABLE_LOG,
1005 DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
1006 &request->state) < 0) {
1007 TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
1009 dp_print_state(request->state));
1012 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1015 } else if (client_cmd.cmd == DP_CMD_FREE) {
1016 // [destory]-[return]-[free]
1017 // No return errorcode
1018 if (request != NULL) {
1019 dp_request_free(request);
1020 privates->requests[index].request = NULL;
1022 } else if (client_cmd.cmd == DP_CMD_START) {
1023 if (request == NULL) { // Support Re-download
1025 __get_empty_request_index(privates->requests);
1028 ("[ERROR][%d] DP_ERROR_QUEUE_FULL",
1030 // Busy, No Space in slot
1031 dp_ipc_send_errorcode(group->cmd_socket,
1032 DP_ERROR_QUEUE_FULL);
1035 request = dp_request_load_from_log
1036 (client_cmd.id, &errorcode);
1037 if (request == NULL) {
1038 TRACE_ERROR("[ERROR][%d] [%s]",
1040 dp_print_errorcode(errorcode));
1041 dp_ipc_send_errorcode
1042 (group->cmd_socket, errorcode);
1045 // restore callback info
1047 dp_db_get_int_column(client_cmd.id,
1048 DP_DB_TABLE_REQUEST_INFO,
1049 DP_DB_COL_STATE_EVENT);
1050 request->progress_cb =
1051 dp_db_get_int_column(client_cmd.id,
1052 DP_DB_TABLE_REQUEST_INFO,
1053 DP_DB_COL_PROGRESS_EVENT);
1054 privates->requests[index].request = request;
1057 char *url = dp_request_get_url
1058 (client_cmd.id, request, &errorcode);
1060 TRACE_ERROR("[ERROR][%d] DP_ERROR_INVALID_URL",
1062 dp_ipc_send_errorcode
1063 (group->cmd_socket, DP_ERROR_INVALID_URL);
1068 if (request->state == DP_STATE_QUEUED ||
1069 request->state == DP_STATE_CONNECTING ||
1070 request->state == DP_STATE_DOWNLOADING ||
1071 request->state == DP_STATE_COMPLETED) {
1073 ("[ERROR][%d] now [%s]", client_cmd.id,
1074 dp_print_state(request->state));
1075 dp_ipc_send_errorcode
1076 (group->cmd_socket, DP_ERROR_INVALID_STATE);
1079 dp_state_type state = DP_STATE_QUEUED;
1080 if (dp_db_set_column
1081 (request->id, DP_DB_TABLE_LOG,
1082 DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
1085 ("[ERROR][%d][SQL] try [%s]->[%s]",
1087 dp_print_state(request->state),
1088 dp_print_state(state));
1089 dp_ipc_send_errorcode
1090 (group->cmd_socket, DP_ERROR_IO_ERROR);
1093 group->queued_count++;
1094 if (dp_db_update_date(request->id, DP_DB_TABLE_LOG,
1095 DP_DB_COL_ACCESS_TIME) < 0)
1096 TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
1097 request->start_time = (int)time(NULL);
1098 request->pause_time = 0;
1099 request->stop_time = 0;
1100 request->state = state;
1101 request->error = DP_ERROR_NONE;
1102 // need to check how long take to come here.
1103 dp_ipc_send_errorcode
1104 (group->cmd_socket, DP_ERROR_NONE);
1105 //send signal to queue thread
1106 dp_thread_queue_manager_wake_up();
1107 } else if (client_cmd.cmd == DP_CMD_PAUSE) {
1108 if (request == NULL) {
1110 ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1112 dp_ipc_send_errorcode(group->cmd_socket,
1113 DP_ERROR_ID_NOT_FOUND);
1116 if (dp_db_update_date(request->id, DP_DB_TABLE_LOG,
1117 DP_DB_COL_ACCESS_TIME) < 0)
1118 TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
1120 CLIENT_MUTEX_LOCK(&(request->mutex));
1121 if (request->state > DP_STATE_DOWNLOADING) {
1123 ("[ERROR][%d] now [%s]", client_cmd.id,
1124 dp_print_state(request->state));
1125 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1126 dp_ipc_send_errorcode(group->cmd_socket,
1127 DP_ERROR_INVALID_STATE);
1130 if (request->state <= DP_STATE_QUEUED) {
1131 request->state = DP_STATE_PAUSED;
1132 request->error = DP_ERROR_NONE;
1133 if (dp_db_set_column
1134 (request->id, DP_DB_TABLE_LOG,
1135 DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
1136 &request->state) < 0) {
1137 TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
1139 dp_print_state(request->state));
1140 dp_ipc_send_errorcode
1141 (group->cmd_socket, DP_ERROR_IO_ERROR);
1143 dp_ipc_send_errorcode
1144 (group->cmd_socket, DP_ERROR_NONE);
1146 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1149 if (dp_pause_agent_download(request->agent_id)
1152 ("[ERROR][%d][AGENT][ID:%d] now [%s]",
1153 client_cmd.id, request->agent_id,
1154 dp_print_state(request->state));
1155 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1156 dp_ipc_send_errorcode(group->cmd_socket,
1157 DP_ERROR_INVALID_STATE);
1160 request->pause_time = (int)time(NULL);
1161 request->state = DP_STATE_PAUSE_REQUESTED;
1162 request->error = DP_ERROR_NONE;
1163 if (dp_db_set_column
1164 (request->id, DP_DB_TABLE_LOG,
1165 DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
1166 &request->state) < 0) {
1167 TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
1169 dp_print_state(request->state));
1170 dp_ipc_send_errorcode
1171 (group->cmd_socket, DP_ERROR_IO_ERROR);
1173 dp_ipc_send_errorcode
1174 (group->cmd_socket, DP_ERROR_NONE);
1176 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1177 } else if (client_cmd.cmd == DP_CMD_CANCEL) {
1178 if (request == NULL) {
1180 dp_state_type state =
1181 dp_db_get_int_column(client_cmd.id,
1182 DP_DB_TABLE_LOG, DP_DB_COL_STATE);
1183 if (state > DP_STATE_NONE) {
1184 // if exist & it is paused, change to canceled.
1185 if (state == DP_STATE_PAUSED ||
1186 state == DP_STATE_PAUSE_REQUESTED) {
1187 // change state to canceled.
1188 state = DP_STATE_CANCELED;
1189 if (dp_db_set_column
1196 ("[ERROR][%d][SQL] try [%s]",
1198 dp_print_state(state));
1199 dp_ipc_send_errorcode
1203 dp_ipc_send_errorcode
1208 TRACE_ERROR("[ERROR][%d] now [%s]",
1210 dp_print_state(state));
1211 dp_ipc_send_errorcode(group->cmd_socket,
1212 DP_ERROR_INVALID_STATE);
1216 // if not match these conditions, invalied param
1218 ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1220 dp_ipc_send_errorcode(group->cmd_socket,
1221 DP_ERROR_ID_NOT_FOUND);
1224 CLIENT_MUTEX_LOCK(&(request->mutex));
1225 if (request->state >= DP_STATE_COMPLETED) {
1226 // already finished.
1227 TRACE_ERROR("[ERROR][%d] now [%s]",
1229 dp_print_state(request->state));
1230 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1231 dp_ipc_send_errorcode(group->cmd_socket,
1232 DP_ERROR_INVALID_STATE);
1235 if (request->state <= DP_STATE_QUEUED) {
1236 request->state = DP_STATE_CANCELED;
1237 request->error = DP_ERROR_NONE;
1238 if (dp_db_set_column
1239 (request->id, DP_DB_TABLE_LOG,
1240 DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
1241 &request->state) < 0) {
1242 TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
1244 dp_print_state(request->state));
1245 dp_ipc_send_errorcode
1246 (group->cmd_socket, DP_ERROR_IO_ERROR);
1248 dp_ipc_send_errorcode
1249 (group->cmd_socket, DP_ERROR_NONE);
1251 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1254 if (dp_db_update_date(request->id, DP_DB_TABLE_LOG,
1255 DP_DB_COL_ACCESS_TIME) < 0)
1256 TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
1258 if (dp_cancel_agent_download(request->agent_id)
1260 TRACE_ERROR("[ERROR][%d][AGENT][ID:%d] now [%s]",
1261 client_cmd.id, request->agent_id,
1262 dp_print_state(request->state));
1263 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1264 dp_ipc_send_errorcode
1265 (group->cmd_socket, DP_ERROR_INVALID_STATE);
1268 // need to check how long take to come here.
1269 if (dp_db_set_column
1270 (request->id, DP_DB_TABLE_LOG,
1271 DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
1272 &request->state) < 0) {
1273 TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
1275 dp_print_state(request->state));
1276 dp_ipc_send_errorcode
1277 (group->cmd_socket, DP_ERROR_IO_ERROR);
1279 dp_ipc_send_errorcode
1280 (group->cmd_socket, DP_ERROR_NONE);
1282 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1283 } else if (client_cmd.cmd == DP_CMD_SET_URL) {
1284 char *url = dp_ipc_read_string(group->cmd_socket);
1286 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1288 FD_CLR(group->cmd_socket, &listen_fdset);
1289 __clear_group(privates, group);
1290 privates->groups[i].group = NULL;
1294 dp_request_set_url(client_cmd.id, request, url);
1295 TRACE_INFO("[SET_URL][%d][%s]", client_cmd.id, url);
1296 dp_ipc_send_errorcode(group->cmd_socket, ret);
1298 if (ret != DP_ERROR_NONE)
1299 TRACE_ERROR("[ERROR][%d][%s]",
1300 client_cmd.id, dp_print_errorcode(ret));
1301 } else if (client_cmd.cmd == DP_CMD_SET_DESTINATION) {
1302 char *dest = dp_ipc_read_string(group->cmd_socket);
1304 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1306 FD_CLR(group->cmd_socket, &listen_fdset);
1307 __clear_group(privates, group);
1308 privates->groups[i].group = NULL;
1312 dp_request_set_destination
1313 (client_cmd.id, request, dest);
1314 dp_ipc_send_errorcode(group->cmd_socket, ret);
1315 TRACE_INFO("[SET_DEST][%d][%s]", client_cmd.id, dest);
1317 if (ret != DP_ERROR_NONE)
1318 TRACE_ERROR("[ERROR][%d][%s]",
1319 client_cmd.id, dp_print_errorcode(ret));
1320 } else if (client_cmd.cmd == DP_CMD_SET_FILENAME) {
1321 char *fname = dp_ipc_read_string(group->cmd_socket);
1322 if (fname == NULL) {
1323 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1325 FD_CLR(group->cmd_socket, &listen_fdset);
1326 __clear_group(privates, group);
1327 privates->groups[i].group = NULL;
1331 dp_request_set_filename
1332 (client_cmd.id, request, fname);
1333 dp_ipc_send_errorcode(group->cmd_socket, ret);
1335 ("[SET_FILE][%d][%s]", client_cmd.id, fname);
1337 if (ret != DP_ERROR_NONE)
1338 TRACE_ERROR("[ERROR][%d][%s]",
1339 client_cmd.id, dp_print_errorcode(ret));
1340 } else if (client_cmd.cmd == DP_CMD_SET_NOTIFICATION) {
1342 if (dp_ipc_read_custom_type(group->cmd_socket,
1343 &value, sizeof(int)) < 0) {
1344 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1346 FD_CLR(group->cmd_socket, &listen_fdset);
1347 __clear_group(privates, group);
1348 privates->groups[i].group = NULL;
1352 dp_request_set_notification
1353 (client_cmd.id, request, value);
1354 dp_ipc_send_errorcode(group->cmd_socket, ret);
1356 ("[SET_NOTI][%d] [%d]", client_cmd.id, value);
1357 if (ret != DP_ERROR_NONE)
1358 TRACE_ERROR("[ERROR][%d][%s]",
1359 client_cmd.id, dp_print_errorcode(ret));
1360 } else if (client_cmd.cmd == DP_CMD_SET_STATE_CALLBACK) {
1362 if (dp_ipc_read_custom_type(group->cmd_socket,
1363 &value, sizeof(int)) < 0) {
1364 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1366 FD_CLR(group->cmd_socket, &listen_fdset);
1367 __clear_group(privates, group);
1368 privates->groups[i].group = NULL;
1372 dp_request_set_state_event
1373 (client_cmd.id, request, value);
1374 dp_ipc_send_errorcode(group->cmd_socket, ret);
1376 ("[STATE-EVENT][%d][%d]", client_cmd.id, value);
1377 if (ret != DP_ERROR_NONE)
1378 TRACE_ERROR("[ERROR][%d][%s]",
1379 client_cmd.id, dp_print_errorcode(ret));
1380 } else if (client_cmd.cmd == DP_CMD_SET_PROGRESS_CALLBACK) {
1382 if (dp_ipc_read_custom_type(group->cmd_socket,
1383 &value, sizeof(int)) < 0) {
1384 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1386 FD_CLR(group->cmd_socket, &listen_fdset);
1387 __clear_group(privates, group);
1388 privates->groups[i].group = NULL;
1392 dp_request_set_progress_event
1393 (client_cmd.id, request, value);
1394 dp_ipc_send_errorcode(group->cmd_socket, ret);
1396 ("[PROG-EVENT][%d][%d]", client_cmd.id, value);
1397 if (ret != DP_ERROR_NONE)
1398 TRACE_ERROR("[ERROR][%d][%s]",
1399 client_cmd.id, dp_print_errorcode(ret));
1400 } else if (client_cmd.cmd == DP_CMD_SET_AUTO_DOWNLOAD) {
1402 if (dp_ipc_read_custom_type(group->cmd_socket,
1403 &value, sizeof(int)) < 0) {
1404 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1406 FD_CLR(group->cmd_socket, &listen_fdset);
1407 __clear_group(privates, group);
1408 privates->groups[i].group = NULL;
1412 dp_request_set_auto_download
1413 (client_cmd.id, request, value);
1414 dp_ipc_send_errorcode(group->cmd_socket, ret);
1416 ("[SET_AUTO][%d][%d]", client_cmd.id, value);
1417 if (ret != DP_ERROR_NONE)
1418 TRACE_ERROR("[ERROR][%d][%s]",
1419 client_cmd.id, dp_print_errorcode(ret));
1420 } else if (client_cmd.cmd == DP_CMD_SET_NETWORK_TYPE) {
1422 if (dp_ipc_read_custom_type(group->cmd_socket,
1423 &value, sizeof(int)) < 0) {
1424 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1426 FD_CLR(group->cmd_socket, &listen_fdset);
1427 __clear_group(privates, group);
1428 privates->groups[i].group = NULL;
1432 dp_request_set_network_type
1433 (client_cmd.id, request, value);
1434 dp_ipc_send_errorcode(group->cmd_socket, ret);
1436 ("[SET_NETTYPE][%d][%d]", client_cmd.id, value);
1437 if (ret != DP_ERROR_NONE)
1438 TRACE_ERROR("[ERROR][%d][%s]",
1439 client_cmd.id, dp_print_errorcode(ret));
1440 } else if (client_cmd.cmd == DP_CMD_SET_HTTP_HEADER) {
1441 char *field = dp_ipc_read_string(group->cmd_socket);
1442 if (field == NULL) {
1443 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1445 FD_CLR(group->cmd_socket, &listen_fdset);
1446 __clear_group(privates, group);
1447 privates->groups[i].group = NULL;
1450 char *value = dp_ipc_read_string(group->cmd_socket);
1451 if (value == NULL) {
1452 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1454 FD_CLR(group->cmd_socket, &listen_fdset);
1455 __clear_group(privates, group);
1456 privates->groups[i].group = NULL;
1460 char *check_field = dp_db_cond_get_text_column
1461 (client_cmd.id, DP_DB_TABLE_HTTP_HEADERS,
1462 DP_DB_COL_HEADER_FIELD, DP_DB_COL_HEADER_FIELD,
1463 DP_DB_COL_TYPE_TEXT, field);
1464 if (check_field == NULL) {
1466 if (dp_db_insert_column
1468 DP_DB_TABLE_HTTP_HEADERS,
1469 DP_DB_COL_HEADER_FIELD,
1470 DP_DB_COL_TYPE_TEXT, field) < 0) {
1472 ("[ERROR][%d][SQL]", client_cmd.id);
1475 dp_ipc_send_errorcode
1476 (group->cmd_socket, DP_ERROR_IO_ERROR);
1482 // UPDATE Value for Field
1483 if (dp_db_cond_set_column(client_cmd.id,
1484 DP_DB_TABLE_HTTP_HEADERS,
1485 DP_DB_COL_HEADER_DATA,
1486 DP_DB_COL_TYPE_TEXT, value,
1487 DP_DB_COL_HEADER_FIELD, DP_DB_COL_TYPE_TEXT,
1489 TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
1490 dp_ipc_send_errorcode
1491 (group->cmd_socket, DP_ERROR_IO_ERROR);
1493 dp_ipc_send_errorcode
1494 (group->cmd_socket, DP_ERROR_NONE);
1498 } else if (client_cmd.cmd == DP_CMD_DEL_HTTP_HEADER) {
1499 char *field = dp_ipc_read_string(group->cmd_socket);
1500 if (field == NULL) {
1501 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1503 FD_CLR(group->cmd_socket, &listen_fdset);
1504 __clear_group(privates, group);
1505 privates->groups[i].group = NULL;
1508 char *check_field = dp_db_cond_get_text_column
1509 (client_cmd.id, DP_DB_TABLE_HTTP_HEADERS,
1510 DP_DB_COL_HEADER_FIELD, DP_DB_COL_HEADER_FIELD,
1511 DP_DB_COL_TYPE_TEXT, field);
1512 if (check_field == NULL) {
1514 ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1516 dp_ipc_send_errorcode
1517 (group->cmd_socket, DP_ERROR_NO_DATA);
1522 if (dp_db_cond_remove(client_cmd.id,
1523 DP_DB_TABLE_HTTP_HEADERS,
1524 DP_DB_COL_HEADER_FIELD, DP_DB_COL_TYPE_TEXT,
1526 TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
1527 dp_ipc_send_errorcode
1528 (group->cmd_socket, DP_ERROR_IO_ERROR);
1530 dp_ipc_send_errorcode
1531 (group->cmd_socket, DP_ERROR_NONE);
1534 } else if (client_cmd.cmd == DP_CMD_GET_HTTP_HEADER) {
1535 char *field = dp_ipc_read_string(group->cmd_socket);
1536 if (field == NULL) {
1537 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1539 FD_CLR(group->cmd_socket, &listen_fdset);
1540 __clear_group(privates, group);
1541 privates->groups[i].group = NULL;
1544 char *value = dp_db_cond_get_text_column
1545 (client_cmd.id, DP_DB_TABLE_HTTP_HEADERS,
1546 DP_DB_COL_HEADER_DATA, DP_DB_COL_HEADER_FIELD,
1547 DP_DB_COL_TYPE_TEXT, field);
1549 if (value == NULL) {
1551 ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1553 dp_ipc_send_errorcode
1554 (group->cmd_socket, DP_ERROR_NO_DATA);
1556 __send_return_string
1557 (group->cmd_socket, DP_ERROR_NONE, value);
1560 } else if (client_cmd.cmd == DP_CMD_ADD_EXTRA_PARAM) {
1561 dp_error_type ret = DP_ERROR_NONE;
1562 ret = __dp_add_extra_param(group->cmd_socket,
1564 if (ret == DP_ERROR_IO_ERROR) {
1565 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1567 FD_CLR(group->cmd_socket, &listen_fdset);
1568 __clear_group(privates, group);
1569 privates->groups[i].group = NULL;
1572 dp_ipc_send_errorcode(group->cmd_socket, ret);
1573 } else if (client_cmd.cmd == DP_CMD_GET_EXTRA_PARAM) {
1574 dp_error_type ret = DP_ERROR_NONE;
1575 char **values = NULL;
1576 unsigned rows_count = 0;
1577 ret = __dp_get_extra_param_values(group->cmd_socket,
1578 client_cmd.id, &values, &rows_count);
1579 if (ret == DP_ERROR_NONE) {
1580 __send_return_custom_type(group->cmd_socket,
1581 DP_ERROR_NONE, &rows_count, sizeof(int));
1584 for (i = 0; i < rows_count; i++) {
1585 if (dp_ipc_send_string
1586 (group->cmd_socket, values[i]) < 0)
1589 for (i = 0; i < rows_count; i++)
1592 if (ret == DP_ERROR_IO_ERROR) {
1593 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1595 FD_CLR(group->cmd_socket, &listen_fdset);
1596 __clear_group(privates, group);
1597 privates->groups[i].group = NULL;
1600 dp_ipc_send_errorcode(group->cmd_socket, ret);
1603 } else if (client_cmd.cmd == DP_CMD_REMOVE_EXTRA_PARAM) {
1604 dp_error_type ret = DP_ERROR_NONE;
1606 __dp_remove_extra_param(group->cmd_socket,
1608 if (ret == DP_ERROR_IO_ERROR) {
1609 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1611 FD_CLR(group->cmd_socket, &listen_fdset);
1612 __clear_group(privates, group);
1613 privates->groups[i].group = NULL;
1616 dp_ipc_send_errorcode(group->cmd_socket, ret);
1617 } else if (client_cmd.cmd == DP_CMD_GET_URL) {
1619 errorcode = DP_ERROR_NONE;
1620 url = dp_request_get_url
1621 (client_cmd.id, request, &errorcode);
1623 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1624 dp_print_errorcode(errorcode));
1625 dp_ipc_send_errorcode
1626 (group->cmd_socket, errorcode);
1628 __send_return_string
1629 (group->cmd_socket, DP_ERROR_NONE, url);
1632 } else if (client_cmd.cmd == DP_CMD_GET_DESTINATION) {
1634 errorcode = DP_ERROR_NONE;
1635 dest = dp_request_get_destination
1636 (client_cmd.id, request, &errorcode);
1638 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1639 dp_print_errorcode(errorcode));
1640 dp_ipc_send_errorcode
1641 (group->cmd_socket, errorcode);
1643 __send_return_string
1644 (group->cmd_socket, DP_ERROR_NONE, dest);
1647 } else if (client_cmd.cmd == DP_CMD_GET_FILENAME) {
1648 char *filename = NULL;
1649 errorcode = DP_ERROR_NONE;
1650 filename = dp_request_get_filename
1651 (client_cmd.id, request, &errorcode);
1652 if (filename == NULL) {
1653 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1654 dp_print_errorcode(errorcode));
1655 dp_ipc_send_errorcode
1656 (group->cmd_socket, errorcode);
1658 __send_return_string
1659 (group->cmd_socket, DP_ERROR_NONE, filename);
1662 } else if (client_cmd.cmd == DP_CMD_GET_NOTIFICATION) {
1664 enable = dp_db_get_int_column(client_cmd.id,
1665 DP_DB_TABLE_REQUEST_INFO,
1666 DP_DB_COL_NOTIFICATION_ENABLE);
1669 ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1671 dp_ipc_send_errorcode(group->cmd_socket,
1674 __send_return_custom_type
1675 (group->cmd_socket, DP_ERROR_NONE,
1676 &enable, sizeof(int));
1678 } else if (client_cmd.cmd == DP_CMD_GET_AUTO_DOWNLOAD) {
1680 enable = dp_db_get_int_column(client_cmd.id,
1681 DP_DB_TABLE_REQUEST_INFO,
1682 DP_DB_COL_AUTO_DOWNLOAD);
1685 ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1687 dp_ipc_send_errorcode(group->cmd_socket,
1690 __send_return_custom_type
1691 (group->cmd_socket, DP_ERROR_NONE,
1692 &enable, sizeof(int));
1694 } else if (client_cmd.cmd == DP_CMD_GET_NETWORK_TYPE) {
1696 type = dp_db_get_int_column(client_cmd.id,
1697 DP_DB_TABLE_REQUEST_INFO,
1698 DP_DB_COL_NETWORK_TYPE);
1701 ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1703 dp_ipc_send_errorcode(group->cmd_socket,
1706 __send_return_custom_type
1707 (group->cmd_socket, DP_ERROR_NONE,
1708 &type, sizeof(dp_network_type));
1710 } else if (client_cmd.cmd == DP_CMD_GET_SAVED_PATH) {
1711 char *savedpath = NULL;
1712 errorcode = DP_ERROR_NONE;
1713 savedpath = dp_request_get_savedpath
1714 (client_cmd.id, request, &errorcode);
1715 if (savedpath == NULL) {
1716 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1717 dp_print_errorcode(errorcode));
1718 dp_ipc_send_errorcode
1719 (group->cmd_socket, errorcode);
1721 __send_return_string
1722 (group->cmd_socket, DP_ERROR_NONE, savedpath);
1725 } else if (client_cmd.cmd == DP_CMD_GET_TEMP_SAVED_PATH) {
1726 char *tmppath = NULL;
1727 errorcode = DP_ERROR_NONE;
1728 tmppath = dp_request_get_tmpsavedpath
1729 (client_cmd.id, request, &errorcode);
1730 if (tmppath == NULL) {
1731 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1732 dp_print_errorcode(errorcode));
1733 dp_ipc_send_errorcode
1734 (group->cmd_socket, errorcode);
1736 __send_return_string
1737 (group->cmd_socket, DP_ERROR_NONE, tmppath);
1740 } else if (client_cmd.cmd == DP_CMD_GET_MIME_TYPE) {
1741 char *mimetype = NULL;
1742 errorcode = DP_ERROR_NONE;
1743 mimetype = dp_request_get_mimetype
1744 (client_cmd.id, request, &errorcode);
1745 if (mimetype == NULL) {
1746 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1747 dp_print_errorcode(errorcode));
1748 dp_ipc_send_errorcode
1749 (group->cmd_socket, errorcode);
1751 __send_return_string
1752 (group->cmd_socket, DP_ERROR_NONE, mimetype);
1755 } else if (client_cmd.cmd == DP_CMD_GET_RECEIVED_SIZE) {
1756 if (request == NULL) {
1758 ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1760 dp_ipc_send_errorcode(group->cmd_socket,
1761 DP_ERROR_ID_NOT_FOUND);
1763 __send_return_custom_type
1764 (group->cmd_socket, DP_ERROR_NONE,
1765 &request->received_size,
1766 sizeof(unsigned long long));
1768 } else if (client_cmd.cmd == DP_CMD_GET_TOTAL_FILE_SIZE) {
1769 if (request != NULL) {
1770 __send_return_custom_type(group->cmd_socket,
1771 DP_ERROR_NONE, &request->file_size,
1772 sizeof(unsigned long long));
1775 long long file_size =
1776 dp_db_get_int64_column(client_cmd.id,
1777 DP_DB_TABLE_DOWNLOAD_INFO,
1778 DP_DB_COL_CONTENT_SIZE);
1779 if (file_size < 0) {
1781 ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1783 dp_ipc_send_errorcode(group->cmd_socket,
1787 unsigned long long total_file_size = file_size;
1788 __send_return_custom_type
1789 (group->cmd_socket, DP_ERROR_NONE,
1790 &total_file_size, sizeof(total_file_size));
1792 } else if (client_cmd.cmd == DP_CMD_GET_CONTENT_NAME) {
1793 char *content = NULL;
1794 errorcode = DP_ERROR_NONE;
1795 content = dp_request_get_contentname
1796 (client_cmd.id, request, &errorcode);
1797 if (content == NULL) {
1798 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1799 dp_print_errorcode(errorcode));
1800 dp_ipc_send_errorcode
1801 (group->cmd_socket, errorcode);
1803 __send_return_string
1804 (group->cmd_socket, DP_ERROR_NONE, content);
1807 } else if (client_cmd.cmd == DP_CMD_GET_HTTP_STATUS) {
1808 int http_status = 0;
1809 http_status = dp_db_get_int_column(client_cmd.id,
1810 DP_DB_TABLE_DOWNLOAD_INFO,
1811 DP_DB_COL_HTTP_STATUS);
1812 if (http_status < 0) {
1814 ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1816 dp_ipc_send_errorcode(group->cmd_socket,
1819 __send_return_custom_type
1820 (group->cmd_socket, DP_ERROR_NONE,
1821 &http_status, sizeof(int));
1823 } else if (client_cmd.cmd == DP_CMD_GET_ETAG) {
1825 errorcode = DP_ERROR_NONE;
1826 etag = dp_request_get_etag
1827 (client_cmd.id, request, &errorcode);
1829 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1830 dp_print_errorcode(errorcode));
1831 dp_ipc_send_errorcode
1832 (group->cmd_socket, errorcode);
1834 __send_return_string
1835 (group->cmd_socket, DP_ERROR_NONE, etag);
1838 } else if (client_cmd.cmd == DP_CMD_GET_STATE) {
1839 dp_state_type download_state = DP_STATE_NONE;
1840 if (request == NULL) {
1842 dp_db_get_int_column(client_cmd.id,
1845 if (download_state < 0) {
1847 ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1849 dp_ipc_send_errorcode(group->cmd_socket,
1850 DP_ERROR_ID_NOT_FOUND);
1854 CLIENT_MUTEX_LOCK(&(request->mutex));
1855 download_state = request->state;
1856 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1858 __send_return_custom_type
1859 (group->cmd_socket, DP_ERROR_NONE,
1860 &download_state, sizeof(dp_state_type));
1861 } else if (client_cmd.cmd == DP_CMD_GET_ERROR) {
1862 errorcode = DP_ERROR_NONE;
1863 if (request == NULL) {
1865 dp_db_get_int_column(client_cmd.id,
1867 DP_DB_COL_ERRORCODE);
1868 if (errorcode < 0) {
1870 ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1872 dp_ipc_send_errorcode(group->cmd_socket,
1873 DP_ERROR_ID_NOT_FOUND);
1877 CLIENT_MUTEX_LOCK(&(request->mutex));
1878 errorcode = request->error;
1879 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1881 dp_ipc_send_errorcode
1882 (group->cmd_socket, DP_ERROR_NONE);
1883 dp_ipc_send_errorcode
1884 (group->cmd_socket, errorcode);
1887 ("[UNKNOWN] I [%d] PID [%d]", i,
1888 privates->groups[i].group->credential.pid);
1889 dp_ipc_send_errorcode(group->cmd_socket,
1890 DP_ERROR_INVALID_PARAMETER);
1891 // disconnect this group, bad client
1892 FD_CLR(group->cmd_socket, &listen_fdset);
1893 __clear_group(privates, group);
1894 privates->groups[i].group = NULL;
1900 if (is_timeout == 1) {
1901 int now_timeout = (int)time(NULL);
1902 TRACE_INFO("[TIMEOUT] prev %ld, now %ld, setted %ld sec",
1903 prev_timeout, now_timeout, flexible_timeout);
1904 if (prev_timeout == 0) {
1905 prev_timeout = now_timeout;
1907 if ((now_timeout - prev_timeout) <
1908 DP_CARE_CLIENT_MIN_INTERVAL) {
1910 // terminate Process
1912 ("[CRITICAL] Sock exception prev[%ld]now[%ld][%ld]",
1913 prev_timeout, now_timeout, flexible_timeout);
1918 // get 48hour old request from log DB
1919 // clear old request
1920 dp_db_limit_rows(DP_LOG_DB_LIMIT_ROWS);
1921 int old_request_count = dp_db_get_count_by_limit_time();
1922 if (old_request_count > 0) {
1923 if (old_request_count > DP_LOG_DB_CLEAR_LIMIT_ONE_TIME)
1924 old_request_count = DP_LOG_DB_CLEAR_LIMIT_ONE_TIME;
1927 ("[CLEAR] [%d] old reqeusts", old_request_count);
1929 dp_request_slots *old_requests =
1930 dp_request_slots_new(old_request_count);
1932 int list_count = dp_db_get_list_by_limit_time
1933 (old_requests, old_request_count);
1934 if (list_count > 0) {
1935 for (i = 0; i < list_count; i++) {
1936 // search on slots by ID.
1938 __get_same_request_index
1939 (privates->requests,
1940 old_requests[i].request->id);
1942 dp_request *request =
1943 privates->requests[index].request;
1944 // if downloading..remain it.
1945 CLIENT_MUTEX_LOCK(&(request->mutex));
1946 if (request->state ==
1947 DP_STATE_CONNECTING ||
1949 DP_STATE_DOWNLOADING) {
1951 (&(request->mutex));
1954 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1955 // unload from slots ( memory )
1956 dp_request_free(request);
1957 privates->requests[index].request = NULL;
1961 dp_request_get_tmpsavedpath
1962 (old_requests[i].request->id,
1963 old_requests[i].request,
1965 if ((tmp_path && strlen(tmp_path) > 0) &&
1966 dp_is_file_exist(tmp_path) == 0) {
1968 ("[REMOVE][%d] TEMP FILE [%s]",
1969 old_requests[i].request->id,
1971 if (unlink(tmp_path) != 0)
1973 ("[ERROR][%d] remove file",
1974 old_requests[i].request->id);
1978 dp_db_remove_all(old_requests[i].request->id);
1981 dp_request_slots_free(old_requests, old_request_count);
1986 int ready_requests = 0;
1987 for (i = 0; i < DP_MAX_REQUEST; i++) {
1988 if (!privates->requests[i].request)
1990 dp_request *request = privates->requests[i].request;
1992 CLIENT_MUTEX_LOCK(&(request->mutex));
1994 // If downloading is too slow ? how to deal this request?
1995 // can limit too slot download using starttime.(48 hours)
1996 if (request->state == DP_STATE_CONNECTING ||
1997 request->state == DP_STATE_DOWNLOADING) {
1998 CLIENT_MUTEX_UNLOCK(&(request->mutex));
2002 // paused & agent_id not exist.... unload from memory.
2003 if (request->state == DP_STATE_PAUSED &&
2004 dp_is_alive_download(request->agent_id) == 0) {
2005 CLIENT_MUTEX_UNLOCK(&(request->mutex));
2007 ("[FREE] [%d] unavailable agent ID [%d]",
2008 request->id, request->agent_id);
2009 dp_request_free(request);
2010 privates->requests[i].request = NULL;
2014 // client should call START command in 60 sec
2015 // unload from memory
2016 if (request->start_time <= 0 &&
2017 (now_timeout - request->create_time) >
2018 DP_CARE_CLIENT_MAX_INTERVAL) {
2019 int download_id = request->id;
2020 dp_state_type state = DP_STATE_FAILED;
2021 errorcode = DP_ERROR_RESPONSE_TIMEOUT;
2023 && request->group->event_socket >= 0
2024 && request->state_cb)
2026 (request->group->event_socket,
2027 download_id, state, errorcode, 0);
2028 CLIENT_MUTEX_UNLOCK(&(request->mutex));
2030 ("[FREE] no response ID[%d] last access [%ld]",
2031 request->id, request->start_time);
2032 dp_request_free(request);
2033 privates->requests[i].request = NULL;
2034 // no problem although updating is failed.
2035 if (dp_db_set_column
2036 (download_id, DP_DB_TABLE_LOG,
2037 DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
2039 TRACE_ERROR("[ERROR][%d][SQL]", request->id);
2041 if (dp_db_set_column
2042 (download_id, DP_DB_TABLE_LOG,
2043 DP_DB_COL_ERRORCODE, DP_DB_COL_TYPE_INT,
2045 TRACE_ERROR("[ERROR][%d][SQL]", request->id);
2050 // client should call DESTROY command in 60 sec after finished
2051 if (request->stop_time > 0 &&
2052 (now_timeout - request->stop_time) >
2053 DP_CARE_CLIENT_MAX_INTERVAL) {
2054 // check state again. stop_time means it's stopped
2055 if (request->state == DP_STATE_COMPLETED ||
2056 request->state == DP_STATE_FAILED ||
2057 request->state == DP_STATE_CANCELED) {
2058 CLIENT_MUTEX_UNLOCK(&(request->mutex));
2059 TRACE_INFO("[FREE] by timeout cleaner ID[%d]",
2061 dp_request_free(request);
2062 privates->requests[i].request = NULL;
2067 // check after clear
2068 if (request->state == DP_STATE_QUEUED)
2071 CLIENT_MUTEX_UNLOCK(&(request->mutex));
2074 if (ready_requests > 0) {
2075 //send signal to queue thread will check queue.
2076 dp_thread_queue_manager_wake_up();
2078 #ifdef DP_SUPPORT_DBUS_ACTIVATION
2079 // if no request & timeout is bigger than 60 sec
2080 // terminate by self.
2081 if ((now_timeout - prev_timeout) >= flexible_timeout &&
2082 dp_get_request_count(privates->requests) <= 0) {
2083 TRACE_INFO("No Request. Terminate Daemon");
2088 prev_timeout = now_timeout;
2091 TRACE_INFO("terminate main thread ...");
2092 dp_terminate(SIGTERM);