merge with master
[platform/framework/web/download-provider.git] / provider / download-provider-thread-request.c
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20
21 #include <time.h>
22 #include <sys/time.h>
23
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sys/stat.h>
27
28 #include <signal.h>
29
30 #include <app_manager.h>
31
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"
42
43 void dp_terminate(int signo);
44
45 static char *__print_command(dp_command_type cmd)
46 {
47         switch(cmd)
48         {
49                 case DP_CMD_CREATE :
50                         return "CREATE";
51                 case DP_CMD_START :
52                         return "START";
53                 case DP_CMD_PAUSE :
54                         return "PAUSE";
55                 case DP_CMD_CANCEL :
56                         return "CANCEL";
57                 case DP_CMD_DESTROY :
58                         return "DESTROY";
59                 case DP_CMD_FREE :
60                         return "FREE";
61                 case DP_CMD_ECHO :
62                         return "ECHO";
63                 case DP_CMD_SET_URL :
64                         return "SET_URL";
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";
85                 case DP_CMD_GET_URL :
86                         return "GET_URL";
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 :
126                         return "GET_STATE";
127                 case DP_CMD_GET_ERROR :
128                         return "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";
133                 default :
134                         break;
135         }
136         return "UNKNOWN COMMAND";
137 }
138
139 /* compare two string */
140 static int __cmp_string(char *s1, char *s2)
141 {
142         size_t s1_len = 0;
143         size_t s2_len = 0;
144
145         if (!s1 || !s2) {
146                 TRACE_ERROR("[CHECK PARAM]");
147                 return -1;
148         }
149
150         s1_len = strlen(s1);
151         if (s1_len <= 0) {
152                 TRACE_ERROR("[CHECK PARAM] len[%d]", s1_len);
153                 return -1;
154         }
155
156         s2_len = strlen(s2);
157         if (s2_len <= 0) {
158                 TRACE_ERROR("[CHECK PARAM] len[%d]", s2_len);
159                 return -1;
160         }
161
162         if (s1_len != s2_len) {
163                 TRACE_ERROR("[DIFF] len[%d:%d]", s1_len, s2_len);
164                 return -1;
165         }
166
167         if (strncmp(s1, s2, s1_len) != 0) {
168                 TRACE_ERROR("[DIFF] cmp[%s:%s]", s1, s2);
169                 return -1;
170         }
171
172         return 0;
173 }
174
175 //////////////////////////////////////////////////////////////////////////
176 /// @brief      return index of empty slot
177 static int __get_empty_request_index(dp_request_slots *slots)
178 {
179         int i = 0;
180
181         if (!slots)
182                 return -1;
183
184         for (i = 0; i < DP_MAX_REQUEST; i++)
185                 if (!slots[i].request)
186                         return i;
187         return -1;
188 }
189
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)
194 {
195         int i = 0;
196
197         if (!slots || id < 0)
198                 return -1;
199
200         for (i = 0; i < DP_MAX_REQUEST; i++) {
201                 if (slots[i].request) {
202                         if (slots[i].request->id == id) {
203                                 return i;
204                         }
205                 }
206         }
207         return -1;
208 }
209
210 //////////////////////////////////////////////////////////////////////////
211 /// @brief      return string via IPC
212 static void __send_return_string(int fd, dp_error_type errcode, char* str)
213 {
214         if (fd < 0 || !str)
215                 return ;
216         dp_ipc_send_errorcode(fd, errcode);
217         dp_ipc_send_string(fd, str);
218 }
219
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)
223 {
224         dp_ipc_send_errorcode(fd, errcode);
225         dp_ipc_send_custom_type(fd, value, type_size);
226 }
227
228 static void __clear_group(dp_privates *privates, dp_client_group *group)
229 {
230         dp_request *request = NULL;
231         int i = 0;
232
233         TRACE_INFO("");
234
235         for (i = 0; i < DP_MAX_REQUEST; i++) {
236                 if (privates->requests[i].request == NULL)
237                         continue;
238                 if (privates->requests[i].request->group == NULL)
239                         continue;
240                 if (privates->requests[i].request->id <= 0)
241                         continue;
242
243                 request = privates->requests[i].request;
244
245                 CLIENT_MUTEX_LOCK(&request->mutex);
246
247                 if (request->group != group ||
248                         request->group->cmd_socket != group->cmd_socket) {
249                         CLIENT_MUTEX_UNLOCK(&request->mutex);
250                         continue;
251                 }
252
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);
262
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);
275                                 } else {
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);
280                                         }
281                                 }
282                         }
283
284                         CLIENT_MUTEX_UNLOCK(&request->mutex);
285                         dp_request_free(request);
286                         privates->requests[i].request = NULL;
287
288                         // call cancel_agent after free.
289                         if (agentid > 0 &&
290                                 dp_is_alive_download(agentid)) {
291                                 TRACE_INFO
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]");
296                         }
297
298                         continue;
299                 }
300
301
302                 // disconnect the request from group.
303                 TRACE_INFO
304                         ("[DISCONNECT][%d] [%s] fd[%d]", request->id,
305                         request->group->pkgname, request->group->cmd_socket);
306
307                 request->group = NULL;
308                 request->state_cb = 0;
309                 request->progress_cb = 0;
310
311                 CLIENT_MUTEX_UNLOCK(&request->mutex);
312                 // yield to agent thread before free
313
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;
326                                 continue;
327                         }
328                         CLIENT_MUTEX_UNLOCK(&request->mutex);
329                 }
330         }
331         // clear this group
332         dp_client_group_free(group);
333 }
334
335 static int __dp_add_extra_param(int fd, int id)
336 {
337         dp_error_type ret = DP_ERROR_NONE;
338         int length = 0;
339         int i = 0;
340         unsigned values_length = 0;
341         char *key = NULL;
342         char **values = NULL;
343
344         if (fd < 0) {
345                 TRACE_ERROR("[CHECK] socket");
346                 return DP_ERROR_IO_ERROR;
347         }
348         if (id < 0) {
349                 TRACE_ERROR("[CHECK] ID");
350                 return DP_ERROR_INVALID_PARAMETER;
351         }
352
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;
356         } else {
357                 TRACE_INFO("[RECV] length %d", length);
358                 if (length <= 0) {
359                         ret = DP_ERROR_INVALID_PARAMETER;
360                 } else {
361                         key = dp_ipc_read_string(fd);
362                         if (key == NULL) {
363                                 TRACE_ERROR("[ERROR][%d][IO_ERROR] key", id);
364                                 ret = DP_ERROR_IO_ERROR;
365                         } else {
366                                 if (length > 1) {
367                                         TRACE_INFO("[RECV] key : %s", key);
368                                         // get values
369                                         values = (char **)calloc((length - 1), sizeof(char *));
370                                         if (values == NULL) {
371                                                 ret = DP_ERROR_OUT_OF_MEMORY;
372                                         } else {
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;
377                                                                 break;
378                                                         }
379                                                         values_length++;
380                                                 }
381                                         }
382                                 } else {
383                                         TRACE_ERROR("[ERROR][%d] length [%d]", id, length);
384                                         ret = DP_ERROR_INVALID_PARAMETER;
385                                 }
386                         }
387                 }
388         }
389         if (ret == DP_ERROR_NONE) {
390                 // store to DB
391                 for (i = 0; i < length - 1; i++) {
392                         int conds_count = 3;
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];
404                         int check_key =
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
408                                 // insert
409                                 if (dp_db_insert_columns(DP_DB_TABLE_NOTIFICATION,
410                                                 conds_count, conds_p) < 0) {
411                                         ret = DP_ERROR_OUT_OF_MEMORY;
412                                         break;
413                                 }
414                         } // else skip. already exist
415                 }
416         }
417         free(key);
418         for (i = 0; i < values_length; i++) {
419                 free(values[i]);
420         }
421         free(values);
422         return ret;
423 }
424
425 static int __dp_get_extra_param_values(int fd, int id, char ***values,
426                 unsigned *count)
427 {
428         dp_error_type ret = DP_ERROR_NONE;
429         int length = 0;
430         char *key = NULL;
431         char **rows_array = NULL;
432
433         if (fd < 0) {
434                 TRACE_ERROR("[CHECK] socket");
435                 return DP_ERROR_IO_ERROR;
436         }
437         if (id < 0) {
438                 TRACE_ERROR("[CHECK] ID");
439                 return DP_ERROR_INVALID_PARAMETER;
440         }
441
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;
445         } else {
446                 TRACE_INFO("[RECV] length %d", length);
447                 if (length != 1) { // only a key
448                         ret = DP_ERROR_INVALID_PARAMETER;
449                 } else {
450                         if ((key = dp_ipc_read_string(fd)) == NULL) {
451                                 TRACE_ERROR("[ERROR][%d][IO_ERROR] key", id);
452                                 ret = DP_ERROR_IO_ERROR;
453                         }
454                 }
455         }
456         if (ret == DP_ERROR_NONE) {
457                 int conds_count = 2;
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) {
470                         // NO_DATA
471                         ret = DP_ERROR_NO_DATA;
472                 } else {
473                         rows_array = (char **)calloc(check_rows, sizeof(char *));
474                         if (rows_array == NULL) {
475                                 ret = DP_ERROR_OUT_OF_MEMORY;
476                         } else {
477                                 // getting the array from DB with key condition
478                                 int rows_count =
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) {
484                                         // NO_DATA
485                                         ret = DP_ERROR_NO_DATA;
486                                         free(rows_array);
487                                 } else {
488                                         *count = rows_count;
489                                         *values = rows_array;
490                                 }
491                         }
492                         free(key);
493                 }
494         }
495         return ret;
496 }
497
498 static int __dp_remove_extra_param(int fd, int id)
499 {
500         dp_error_type ret = DP_ERROR_NONE;
501         char *key = NULL;
502
503         if (fd < 0) {
504                 TRACE_ERROR("[CHECK] socket");
505                 return DP_ERROR_IO_ERROR;
506         }
507         if (id < 0) {
508                 TRACE_ERROR("[CHECK] ID");
509                 return DP_ERROR_INVALID_PARAMETER;
510         }
511
512         if ((key = dp_ipc_read_string(fd)) == NULL) {
513                 TRACE_ERROR("[ERROR][%d] INVALID_PARAMETER", id);
514                 ret = DP_ERROR_IO_ERROR;
515         }
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;
521                 }
522         }
523         TRACE_ERROR
524                 ("[ERROR][%d][%s] key:%s", id, dp_print_errorcode(ret), key);
525         free(key);
526         return ret;
527 }
528
529 static int __dp_set_group_new(int clientfd, dp_group_slots *groups,
530         dp_credential credential, fd_set *listen_fdset)
531 {
532         // search in groups.
533         // if same group. update it.
534         // search same pkg or pid in groups
535         int pkg_len = 0;
536         int i = 0;
537         struct timeval tv_timeo; // 2.5 sec
538         char *pkgname = NULL;
539
540         tv_timeo.tv_sec = 2;
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");
545                 return -1;
546         }
547
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);
552         } else
553                 TRACE_ERROR("[CRITICAL] app_manager_get_package");
554
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);
559         }
560
561         if (pkgname == NULL) {
562                 TRACE_ERROR("[CRITICAL] app_manager_get_package");
563                 return -1;
564         }
565         if ((pkg_len = strlen(pkgname)) <= 0) {
566                 TRACE_ERROR("[CRITICAL] pkgname:%s", pkgname);
567                 return -1;
568         }
569
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;
577                                 continue;
578                         }
579                         if (strlen(groups[i].group->pkgname) == pkg_len &&
580                                         strncmp(groups[i].group->pkgname, pkgname,
581                                                 pkg_len) == 0 ) {
582                                 // Found Same Group
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);
589                                 }
590                                 groups[i].group->cmd_socket = clientfd;
591                                 free(pkgname);
592                                 return 0;
593                         }
594                 }
595         }
596
597         // new client
598         // search emtpy slot in groups
599         for (i = 0; i < DP_MAX_GROUP; i++)
600                 if (groups[i].group == NULL)
601                         break;
602         if (i >= DP_MAX_GROUP) {
603                 TRACE_ERROR("[CRITICAL] No space in groups");
604                 free(pkgname);
605                 return -1;
606         }
607         // allocation
608         groups[i].group =
609                 (dp_client_group *)calloc(1, sizeof(dp_client_group));
610         if (groups[i].group == NULL) {
611                 TRACE_ERROR("[CRITICAL] calloc, ignore this client");
612                 free(pkgname);
613                 return -1;
614         }
615         // fill info
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);
625         free(pkgname);
626         return 0;
627 }
628
629
630 static int __dp_set_group_event_sock(int clientfd,
631         dp_group_slots *groups, dp_credential credential)
632 {
633         int i = 0;
634
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;
644                         TRACE_INFO
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);
648                         break;
649                 }
650         }
651         if (i >= DP_MAX_GROUP) {
652                 TRACE_ERROR
653                         ("[CRITICAL] Not found group for PID [%d]", credential.pid);
654                 return -1;
655         }
656         return 0;
657 }
658
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)
663 {
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;
668         socklen_t clientlen;
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;
674
675         dp_privates *privates = (dp_privates*)arg;
676         if (privates == NULL || privates->groups == NULL) {
677                 TRACE_ERROR("[CRITICAL] Invalid Address");
678                 dp_terminate(SIGTERM);
679                 pthread_exit(NULL);
680                 return 0;
681         }
682
683         listenfd = privates->listen_fd;
684         maxfd = listenfd;
685
686         TRACE_INFO("Ready to listen [%d][%s]", listenfd, DP_IPC);
687
688         FD_ZERO(&listen_fdset);
689         FD_ZERO(&except_fdset);
690         FD_SET(listenfd, &listen_fdset);
691         FD_SET(listenfd, &except_fdset);
692
693         while (privates != NULL && privates->listen_fd >= 0) {
694
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;
699                 clientfd = -1;
700                 credential.pid = -1;
701                 credential.uid = -1;
702                 credential.gid = -1;
703                 is_timeout = 1;
704
705                 rset = listen_fdset;
706                 eset = except_fdset;
707
708                 if (select((maxfd + 1), &rset, 0, &eset, &timeout) < 0) {
709                         TRACE_STRERROR("[CRITICAL] select");
710                         break;
711                 }
712
713                 if (privates == NULL) {
714                         TRACE_INFO("Terminate Thread");
715                         break;
716                 }
717
718                 if (FD_ISSET(listenfd, &eset) > 0) {
719                         TRACE_ERROR("[CRITICAL] listenfd Exception of socket");
720                         break;
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
725
726                         is_timeout = 0;
727
728                         // Anyway accept client.
729                         clientlen = sizeof(clientaddr);
730                         clientfd = accept(listenfd,
731                                                         (struct sockaddr*)&clientaddr,
732                                                         &clientlen);
733                         if (clientfd < 0) {
734                                 TRACE_ERROR("[CRITICAL] accept provider was crashed ?");
735                                 // provider need the time of refresh.
736                                 break;
737                         }
738
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");
743                                 close(clientfd);
744                                 continue;
745                         }
746                         if (connect_cmd <= 0) {
747                                 TRACE_ERROR("[CRITICAL] peer terminate ?");
748                                 close(clientfd);
749                                 continue;
750                         }
751
752 #ifdef SO_PEERCRED
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) {
757                                 TRACE_INFO
758                                         ("credential : pid=%d, uid=%d, gid=%d",
759                                         credential.pid, credential.uid, credential.gid);
760                         }
761 #else // In case of not supported SO_PEERCRED
762                         int client_pid = 0;
763                         if (dp_ipc_read_custom_type(clientfd,
764                                         &client_pid, sizeof(int)) < 0) {
765                                 TRACE_ERROR("[CRITICAL] not support SO_PEERCRED");
766                                 close(clientfd);
767                                 continue;
768                         }
769                         if (client_pid <= 0) {
770                                 TRACE_ERROR("[CRITICAL] not support SO_PEERCRED");
771                                 close(clientfd);
772                                 continue;
773                         }
774                         credential.pid = client_pid;
775                         credential.uid = 5000;
776                         credential.gid = 5000;
777 #endif
778
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)
785                                                 maxfd = clientfd;
786                                 } else {
787                                         close(clientfd);
788                                 }
789                                 break;
790                         case DP_CMD_SET_EVENT_SOCKET:
791                         {
792                                 if (__dp_set_group_event_sock(clientfd,
793                                                 privates->groups, credential) < 0)
794                                         close(clientfd);
795                                 break;
796                         }
797                         default:
798                                 TRACE_ERROR("[CRITICAL] Bad access, ignore this client");
799                                 close(clientfd);
800                                 break;
801                         }
802                 } // New Connection
803
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;
807                         if (group == NULL)
808                                 continue;
809                         if (group->cmd_socket < 0) {
810                                 continue;
811                         }
812                         if (FD_ISSET(group->cmd_socket, &rset) > 0) {
813                                 dp_command client_cmd;
814                                 int index = -1;
815
816                                 is_timeout = 0;
817                                 client_cmd.cmd = DP_CMD_NONE;
818                                 client_cmd.id = -1;
819
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
824                                         continue;
825                                 }
826
827                                 // print detail info
828                                 TRACE_INFO
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);
833
834                                 if (client_cmd.cmd == 0) { // Client meet some Error.
835                                         TRACE_INFO
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;
842                                         continue;
843                                 }
844
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;
855                                         }
856                                         continue;
857                                 }
858
859                                 if (client_cmd.cmd == DP_CMD_CREATE) {
860                                         // search empty slot in privates->requests
861                                         index = __get_empty_request_index(privates->requests);
862                                         if (index < 0) {
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);
867                                         } else {
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) {
872                                                         TRACE_INFO
873                                                                 ("[CREATE] GOOD ID[%d] SLOT[%d]",
874                                                                 privates->requests[index].request->id,
875                                                                 index);
876                                                         __send_return_custom_type(group->cmd_socket,
877                                                                 DP_ERROR_NONE,
878                                                                 &privates->requests[index].request->id,
879                                                                 sizeof(int));
880                                                 } else {
881                                                         TRACE_ERROR
882                                                                 ("[ERROR][%s]", dp_print_errorcode(ret));
883                                                         dp_ipc_send_errorcode
884                                                                 (group->cmd_socket, ret);
885                                                 }
886                                         }
887                                         continue;
888                                 }
889
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;
900                                         continue;
901                                 }
902
903                                 // search id in requests slot
904                                 index = __get_same_request_index
905                                                         (privates->requests, client_cmd.id);
906
907                                 // GET API works even if request is NULL.
908                                 dp_request *request = NULL;
909                                 if (index >= 0)
910                                         request = privates->requests[index].request;
911
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;
919                                 } else {
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;
924                                 }
925                                 if (errorcode == DP_ERROR_NONE) {
926                                         // auth by pkgname
927                                         if (__cmp_string(group->pkgname, auth_pkgname) < 0) {
928                                                 TRACE_ERROR
929                                                         ("[ERROR][%d] Auth [%s]/[%s]", client_cmd.id,
930                                                         group->pkgname, auth_pkgname);
931                                                 errorcode = DP_ERROR_INVALID_PARAMETER;
932                                         }
933                                 }
934                                 free(auth_pkgname);
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);
939                                         continue;
940                                 }
941
942                                 // if no group, update group.
943                                 if (request != NULL && request->group == NULL)
944                                         request->group = group;
945
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]",
957                                                                         client_cmd.id);
958                                                         request->state = DP_STATE_CANCELED;
959                                                         if (dp_db_set_column
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]",
964                                                                         client_cmd.id,
965                                                                         dp_print_state(request->state));
966                                                                 dp_db_remove_all(request->id);
967                                                         }
968                                                 }
969                                                 CLIENT_MUTEX_UNLOCK(&(request->mutex));
970                                         }
971                                         // Always return GOOD
972                                         dp_ipc_send_errorcode
973                                                 (group->cmd_socket, DP_ERROR_NONE);
974                                         #if 0
975                                         // remove tmp file
976                                         char *tmp_path =
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",
985                                                                 client_cmd.id);
986                                                 free(tmp_path);
987                                         }
988                                         // in DESTROY, clear all info
989                                         dp_db_remove_all(client_cmd.id);
990                                         #else
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]",
1008                                                                         client_cmd.id,
1009                                                                         dp_print_state(request->state));
1010                                                         }
1011                                                 }
1012                                                 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1013                                         }
1014                                         #endif
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;
1021                                         }
1022                                 } else if (client_cmd.cmd == DP_CMD_START) {
1023                                         if (request == NULL) { // Support Re-download
1024                                                 index =
1025                                                         __get_empty_request_index(privates->requests);
1026                                                 if (index < 0) {
1027                                                         TRACE_ERROR
1028                                                                 ("[ERROR][%d] DP_ERROR_QUEUE_FULL",
1029                                                                 client_cmd.id);
1030                                                         // Busy, No Space in slot
1031                                                         dp_ipc_send_errorcode(group->cmd_socket,
1032                                                                 DP_ERROR_QUEUE_FULL);
1033                                                         continue;
1034                                                 }
1035                                                 request = dp_request_load_from_log
1036                                                                         (client_cmd.id, &errorcode);
1037                                                 if (request == NULL) {
1038                                                         TRACE_ERROR("[ERROR][%d] [%s]",
1039                                                                 client_cmd.id,
1040                                                                 dp_print_errorcode(errorcode));
1041                                                         dp_ipc_send_errorcode
1042                                                                 (group->cmd_socket, errorcode);
1043                                                         continue;
1044                                                 }
1045                                                 // restore callback info
1046                                                 request->state_cb = 
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;
1055                                         }
1056                                         // Check URL
1057                                         char *url = dp_request_get_url
1058                                                         (client_cmd.id, request, &errorcode);
1059                                         if (url == NULL) {
1060                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_INVALID_URL",
1061                                                         client_cmd.id);
1062                                                 dp_ipc_send_errorcode
1063                                                         (group->cmd_socket, DP_ERROR_INVALID_URL);
1064                                                 continue;
1065                                         } else {
1066                                                 free(url);
1067                                         }
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) {
1072                                                 TRACE_ERROR
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);
1077                                                 continue;
1078                                         }
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,
1083                                                         &state) < 0) {
1084                                                 TRACE_ERROR
1085                                                         ("[ERROR][%d][SQL] try [%s]->[%s]",
1086                                                         client_cmd.id,
1087                                                         dp_print_state(request->state),
1088                                                         dp_print_state(state));
1089                                                 dp_ipc_send_errorcode
1090                                                         (group->cmd_socket, DP_ERROR_IO_ERROR);
1091                                                 continue;
1092                                         }
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) {
1109                                                 TRACE_ERROR
1110                                                         ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1111                                                         client_cmd.id);
1112                                                 dp_ipc_send_errorcode(group->cmd_socket,
1113                                                         DP_ERROR_ID_NOT_FOUND);
1114                                                 continue;
1115                                         }
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);
1119
1120                                         CLIENT_MUTEX_LOCK(&(request->mutex));
1121                                         if (request->state > DP_STATE_DOWNLOADING) {
1122                                                 TRACE_ERROR
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);
1128                                                 continue;
1129                                         }
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]",
1138                                                                 client_cmd.id,
1139                                                                 dp_print_state(request->state));
1140                                                         dp_ipc_send_errorcode
1141                                                                 (group->cmd_socket, DP_ERROR_IO_ERROR);
1142                                                 } else {
1143                                                         dp_ipc_send_errorcode
1144                                                                 (group->cmd_socket, DP_ERROR_NONE);
1145                                                 }
1146                                                 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1147                                                 continue;
1148                                         }
1149                                         if (dp_pause_agent_download(request->agent_id)
1150                                                 < 0) {
1151                                                 TRACE_ERROR
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);
1158                                                 continue;
1159                                         }
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]",
1168                                                                 client_cmd.id,
1169                                                                 dp_print_state(request->state));
1170                                                 dp_ipc_send_errorcode
1171                                                         (group->cmd_socket, DP_ERROR_IO_ERROR);
1172                                         } else {
1173                                                 dp_ipc_send_errorcode
1174                                                         (group->cmd_socket, DP_ERROR_NONE);
1175                                         }
1176                                         CLIENT_MUTEX_UNLOCK(&(request->mutex));
1177                                 } else if (client_cmd.cmd == DP_CMD_CANCEL) {
1178                                         if (request == NULL) {
1179                                                 // find id in DB.
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
1190                                                                                 (client_cmd.id,
1191                                                                                 DP_DB_TABLE_LOG,
1192                                                                                 DP_DB_COL_STATE,
1193                                                                                 DP_DB_COL_TYPE_INT,
1194                                                                                 &state) < 0) {
1195                                                                         TRACE_ERROR
1196                                                                                 ("[ERROR][%d][SQL] try [%s]",
1197                                                                                         client_cmd.id,
1198                                                                                         dp_print_state(state));
1199                                                                         dp_ipc_send_errorcode
1200                                                                                 (group->cmd_socket,
1201                                                                                 DP_ERROR_IO_ERROR);
1202                                                                 } else {
1203                                                                         dp_ipc_send_errorcode
1204                                                                                 (group->cmd_socket,
1205                                                                                 DP_ERROR_NONE);
1206                                                                 }
1207                                                         } else {
1208                                                                 TRACE_ERROR("[ERROR][%d] now [%s]",
1209                                                                                 client_cmd.id,
1210                                                                                 dp_print_state(state));
1211                                                                 dp_ipc_send_errorcode(group->cmd_socket,
1212                                                                         DP_ERROR_INVALID_STATE);
1213                                                         }
1214                                                         continue;
1215                                                 }
1216                                                 // if not match these conditions, invalied param
1217                                                 TRACE_ERROR
1218                                                         ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1219                                                         client_cmd.id);
1220                                                 dp_ipc_send_errorcode(group->cmd_socket,
1221                                                         DP_ERROR_ID_NOT_FOUND);
1222                                                 continue;
1223                                         }
1224                                         CLIENT_MUTEX_LOCK(&(request->mutex));
1225                                         if (request->state >= DP_STATE_COMPLETED) {
1226                                                 // already finished.
1227                                                 TRACE_ERROR("[ERROR][%d] now [%s]",
1228                                                                 client_cmd.id,
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);
1233                                                 continue;
1234                                         }
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]",
1243                                                                 client_cmd.id,
1244                                                                 dp_print_state(request->state));
1245                                                         dp_ipc_send_errorcode
1246                                                                 (group->cmd_socket, DP_ERROR_IO_ERROR);
1247                                                 } else {
1248                                                         dp_ipc_send_errorcode
1249                                                                 (group->cmd_socket, DP_ERROR_NONE);
1250                                                 }
1251                                                 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1252                                                 continue;
1253                                         }
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);
1257
1258                                         if (dp_cancel_agent_download(request->agent_id)
1259                                                 < 0) {
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);
1266                                                 continue;
1267                                         }
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]",
1274                                                                 client_cmd.id,
1275                                                                 dp_print_state(request->state));
1276                                                 dp_ipc_send_errorcode
1277                                                         (group->cmd_socket, DP_ERROR_IO_ERROR);
1278                                         } else {
1279                                                 dp_ipc_send_errorcode
1280                                                         (group->cmd_socket, DP_ERROR_NONE);
1281                                         }
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);
1285                                         if (url == NULL) {
1286                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1287                                                         client_cmd.id);
1288                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1289                                                 __clear_group(privates, group);
1290                                                 privates->groups[i].group = NULL;
1291                                                 continue;
1292                                         }
1293                                         dp_error_type ret =
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);
1297                                         free(url);
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);
1303                                         if (dest == NULL) {
1304                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1305                                                         client_cmd.id);
1306                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1307                                                 __clear_group(privates, group);
1308                                                 privates->groups[i].group = NULL;
1309                                                 continue;
1310                                         }
1311                                         dp_error_type ret =
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);
1316                                         free(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",
1324                                                         client_cmd.id);
1325                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1326                                                 __clear_group(privates, group);
1327                                                 privates->groups[i].group = NULL;
1328                                                 continue;
1329                                         }
1330                                         dp_error_type ret =
1331                                                 dp_request_set_filename
1332                                                         (client_cmd.id, request, fname);
1333                                         dp_ipc_send_errorcode(group->cmd_socket, ret);
1334                                         TRACE_INFO
1335                                                 ("[SET_FILE][%d][%s]", client_cmd.id, fname);
1336                                         free(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) {
1341                                         int value = 0;
1342                                         if (dp_ipc_read_custom_type(group->cmd_socket,
1343                                                         &value, sizeof(int)) < 0) {
1344                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1345                                                         client_cmd.id);
1346                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1347                                                 __clear_group(privates, group);
1348                                                 privates->groups[i].group = NULL;
1349                                                 continue;
1350                                         }
1351                                         dp_error_type ret =
1352                                                 dp_request_set_notification
1353                                                         (client_cmd.id, request, value);
1354                                         dp_ipc_send_errorcode(group->cmd_socket, ret);
1355                                         TRACE_INFO
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) {
1361                                         int value = 0;
1362                                         if (dp_ipc_read_custom_type(group->cmd_socket,
1363                                                         &value, sizeof(int)) < 0) {
1364                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1365                                                         client_cmd.id);
1366                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1367                                                 __clear_group(privates, group);
1368                                                 privates->groups[i].group = NULL;
1369                                                 continue;
1370                                         }
1371                                         dp_error_type ret =
1372                                                 dp_request_set_state_event
1373                                                         (client_cmd.id, request, value);
1374                                         dp_ipc_send_errorcode(group->cmd_socket, ret);
1375                                         TRACE_INFO
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) {
1381                                         int value = 0;
1382                                         if (dp_ipc_read_custom_type(group->cmd_socket,
1383                                                         &value, sizeof(int)) < 0) {
1384                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1385                                                         client_cmd.id);
1386                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1387                                                 __clear_group(privates, group);
1388                                                 privates->groups[i].group = NULL;
1389                                                 continue;
1390                                         }
1391                                         dp_error_type ret =
1392                                                 dp_request_set_progress_event
1393                                                         (client_cmd.id, request, value);
1394                                         dp_ipc_send_errorcode(group->cmd_socket, ret);
1395                                         TRACE_INFO
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) {
1401                                         int value = 0;
1402                                         if (dp_ipc_read_custom_type(group->cmd_socket,
1403                                                         &value, sizeof(int)) < 0) {
1404                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1405                                                         client_cmd.id);
1406                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1407                                                 __clear_group(privates, group);
1408                                                 privates->groups[i].group = NULL;
1409                                                 continue;
1410                                         }
1411                                         dp_error_type ret =
1412                                                 dp_request_set_auto_download
1413                                                         (client_cmd.id, request, value);
1414                                         dp_ipc_send_errorcode(group->cmd_socket, ret);
1415                                         TRACE_INFO
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) {
1421                                         int value = 0;
1422                                         if (dp_ipc_read_custom_type(group->cmd_socket,
1423                                                         &value, sizeof(int)) < 0) {
1424                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1425                                                         client_cmd.id);
1426                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1427                                                 __clear_group(privates, group);
1428                                                 privates->groups[i].group = NULL;
1429                                                 continue;
1430                                         }
1431                                         dp_error_type ret =
1432                                                 dp_request_set_network_type
1433                                                         (client_cmd.id, request, value);
1434                                         dp_ipc_send_errorcode(group->cmd_socket, ret);
1435                                         TRACE_INFO
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",
1444                                                         client_cmd.id);
1445                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1446                                                 __clear_group(privates, group);
1447                                                 privates->groups[i].group = NULL;
1448                                                 continue;
1449                                         }
1450                                         char *value = dp_ipc_read_string(group->cmd_socket);
1451                                         if (value == NULL) {
1452                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1453                                                         client_cmd.id);
1454                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1455                                                 __clear_group(privates, group);
1456                                                 privates->groups[i].group = NULL;
1457                                                 free(field);
1458                                                 continue;
1459                                         }
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) {
1465                                                 // INSERT New Field
1466                                                 if (dp_db_insert_column
1467                                                                 (client_cmd.id,
1468                                                                 DP_DB_TABLE_HTTP_HEADERS,
1469                                                                 DP_DB_COL_HEADER_FIELD,
1470                                                                 DP_DB_COL_TYPE_TEXT, field) < 0) {
1471                                                         TRACE_ERROR
1472                                                                 ("[ERROR][%d][SQL]", client_cmd.id);
1473                                                         free(field);
1474                                                         free(value);
1475                                                         dp_ipc_send_errorcode
1476                                                                 (group->cmd_socket, DP_ERROR_IO_ERROR);
1477                                                         continue;
1478                                                 }
1479                                         } else {
1480                                                 free(check_field);
1481                                         }
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,
1488                                                         field) < 0) {
1489                                                 TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
1490                                                 dp_ipc_send_errorcode
1491                                                         (group->cmd_socket, DP_ERROR_IO_ERROR);
1492                                         } else {
1493                                                 dp_ipc_send_errorcode
1494                                                         (group->cmd_socket, DP_ERROR_NONE);
1495                                         }
1496                                         free(field);
1497                                         free(value);
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",
1502                                                         client_cmd.id);
1503                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1504                                                 __clear_group(privates, group);
1505                                                 privates->groups[i].group = NULL;
1506                                                 continue;
1507                                         }
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) {
1513                                                 TRACE_ERROR
1514                                                         ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1515                                                         client_cmd.id);
1516                                                 dp_ipc_send_errorcode
1517                                                         (group->cmd_socket, DP_ERROR_NO_DATA);
1518                                                 free(field);
1519                                                 continue;
1520                                         }
1521                                         free(check_field);
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,
1525                                                         field) < 0) {
1526                                                 TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
1527                                                 dp_ipc_send_errorcode
1528                                                         (group->cmd_socket, DP_ERROR_IO_ERROR);
1529                                         } else {
1530                                                 dp_ipc_send_errorcode
1531                                                         (group->cmd_socket, DP_ERROR_NONE);
1532                                         }
1533                                         free(field);
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",
1538                                                         client_cmd.id);
1539                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1540                                                 __clear_group(privates, group);
1541                                                 privates->groups[i].group = NULL;
1542                                                 continue;
1543                                         }
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);
1548                                         free(field);
1549                                         if (value == NULL) {
1550                                                 TRACE_ERROR
1551                                                         ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1552                                                         client_cmd.id);
1553                                                 dp_ipc_send_errorcode
1554                                                         (group->cmd_socket, DP_ERROR_NO_DATA);
1555                                         } else {
1556                                                 __send_return_string
1557                                                         (group->cmd_socket, DP_ERROR_NONE, value);
1558                                                 free(value);
1559                                         }
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,
1563                                                         client_cmd.id);
1564                                         if (ret == DP_ERROR_IO_ERROR) {
1565                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1566                                                         client_cmd.id);
1567                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1568                                                 __clear_group(privates, group);
1569                                                 privates->groups[i].group = NULL;
1570                                                 continue;
1571                                         }
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));
1582                                                 // sending strings
1583                                                 int i = 0;
1584                                                 for (i = 0; i < rows_count; i++) {
1585                                                         if (dp_ipc_send_string
1586                                                                         (group->cmd_socket, values[i]) < 0)
1587                                                                 break;
1588                                                 }
1589                                                 for (i = 0; i < rows_count; i++)
1590                                                         free(values[i]);
1591                                         } else {
1592                                                 if (ret == DP_ERROR_IO_ERROR) {
1593                                                         TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1594                                                                 client_cmd.id);
1595                                                         FD_CLR(group->cmd_socket, &listen_fdset);
1596                                                         __clear_group(privates, group);
1597                                                         privates->groups[i].group = NULL;
1598                                                         continue;
1599                                                 }
1600                                                 dp_ipc_send_errorcode(group->cmd_socket, ret);
1601                                         }
1602                                         free(values);
1603                                 } else if (client_cmd.cmd == DP_CMD_REMOVE_EXTRA_PARAM) {
1604                                         dp_error_type ret = DP_ERROR_NONE;
1605                                         ret =
1606                                                 __dp_remove_extra_param(group->cmd_socket,
1607                                                         client_cmd.id);
1608                                         if (ret == DP_ERROR_IO_ERROR) {
1609                                                 TRACE_ERROR("[ERROR][%d] DP_ERROR_IO_ERROR",
1610                                                         client_cmd.id);
1611                                                 FD_CLR(group->cmd_socket, &listen_fdset);
1612                                                 __clear_group(privates, group);
1613                                                 privates->groups[i].group = NULL;
1614                                                 continue;
1615                                         }
1616                                         dp_ipc_send_errorcode(group->cmd_socket, ret);
1617                                 } else if (client_cmd.cmd == DP_CMD_GET_URL) {
1618                                         char *url = NULL;
1619                                         errorcode = DP_ERROR_NONE;
1620                                         url = dp_request_get_url
1621                                                         (client_cmd.id, request, &errorcode);
1622                                         if (url == NULL) {
1623                                                 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1624                                                         dp_print_errorcode(errorcode));
1625                                                 dp_ipc_send_errorcode
1626                                                         (group->cmd_socket, errorcode);
1627                                         } else {
1628                                                 __send_return_string
1629                                                         (group->cmd_socket, DP_ERROR_NONE, url);
1630                                                 free(url);
1631                                         }
1632                                 } else if (client_cmd.cmd == DP_CMD_GET_DESTINATION) {
1633                                         char *dest = NULL;
1634                                         errorcode = DP_ERROR_NONE;
1635                                         dest = dp_request_get_destination
1636                                                         (client_cmd.id, request, &errorcode);
1637                                         if (dest == NULL) {
1638                                                 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1639                                                         dp_print_errorcode(errorcode));
1640                                                 dp_ipc_send_errorcode
1641                                                         (group->cmd_socket, errorcode);
1642                                         } else {
1643                                                 __send_return_string
1644                                                         (group->cmd_socket, DP_ERROR_NONE, dest);
1645                                                 free(dest);
1646                                         }
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);
1657                                         } else {
1658                                                 __send_return_string
1659                                                         (group->cmd_socket, DP_ERROR_NONE, filename);
1660                                                 free(filename);
1661                                         }
1662                                 } else if (client_cmd.cmd == DP_CMD_GET_NOTIFICATION) {
1663                                         int enable = 0;
1664                                         enable = dp_db_get_int_column(client_cmd.id,
1665                                                                         DP_DB_TABLE_REQUEST_INFO,
1666                                                                         DP_DB_COL_NOTIFICATION_ENABLE);
1667                                         if (enable < 0) {
1668                                                 TRACE_ERROR
1669                                                         ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1670                                                         client_cmd.id);
1671                                                 dp_ipc_send_errorcode(group->cmd_socket,
1672                                                         DP_ERROR_NO_DATA);
1673                                         } else {
1674                                                 __send_return_custom_type
1675                                                         (group->cmd_socket, DP_ERROR_NONE,
1676                                                         &enable, sizeof(int));
1677                                         }
1678                                 } else if (client_cmd.cmd == DP_CMD_GET_AUTO_DOWNLOAD) {
1679                                         int enable = 0;
1680                                         enable = dp_db_get_int_column(client_cmd.id,
1681                                                                         DP_DB_TABLE_REQUEST_INFO,
1682                                                                         DP_DB_COL_AUTO_DOWNLOAD);
1683                                         if (enable < 0) {
1684                                                 TRACE_ERROR
1685                                                         ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1686                                                         client_cmd.id);
1687                                                 dp_ipc_send_errorcode(group->cmd_socket,
1688                                                         DP_ERROR_NO_DATA);
1689                                         } else {
1690                                                 __send_return_custom_type
1691                                                         (group->cmd_socket, DP_ERROR_NONE,
1692                                                         &enable, sizeof(int));
1693                                         }
1694                                 } else if (client_cmd.cmd == DP_CMD_GET_NETWORK_TYPE) {
1695                                         int type = 0;
1696                                         type = dp_db_get_int_column(client_cmd.id,
1697                                                                         DP_DB_TABLE_REQUEST_INFO,
1698                                                                         DP_DB_COL_NETWORK_TYPE);
1699                                         if (type < 0) {
1700                                                 TRACE_ERROR
1701                                                         ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1702                                                         client_cmd.id);
1703                                                 dp_ipc_send_errorcode(group->cmd_socket,
1704                                                         DP_ERROR_NO_DATA);
1705                                         } else {
1706                                                 __send_return_custom_type
1707                                                         (group->cmd_socket, DP_ERROR_NONE,
1708                                                         &type, sizeof(dp_network_type));
1709                                         }
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);
1720                                         } else {
1721                                                 __send_return_string
1722                                                         (group->cmd_socket, DP_ERROR_NONE, savedpath);
1723                                                 free(savedpath);
1724                                         }
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);
1735                                         } else {
1736                                                 __send_return_string
1737                                                         (group->cmd_socket, DP_ERROR_NONE, tmppath);
1738                                                 free(tmppath);
1739                                         }
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);
1750                                         } else {
1751                                                 __send_return_string
1752                                                         (group->cmd_socket, DP_ERROR_NONE, mimetype);
1753                                                 free(mimetype);
1754                                         }
1755                                 } else if (client_cmd.cmd == DP_CMD_GET_RECEIVED_SIZE) {
1756                                         if (request == NULL) {
1757                                                 TRACE_ERROR
1758                                                         ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1759                                                         client_cmd.id);
1760                                                 dp_ipc_send_errorcode(group->cmd_socket,
1761                                                         DP_ERROR_ID_NOT_FOUND);
1762                                         } else {
1763                                                 __send_return_custom_type
1764                                                         (group->cmd_socket, DP_ERROR_NONE,
1765                                                         &request->received_size,
1766                                                         sizeof(unsigned long long));
1767                                         }
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));
1773                                                 continue;
1774                                         }
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) {
1780                                                 TRACE_ERROR
1781                                                         ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1782                                                         client_cmd.id);
1783                                                 dp_ipc_send_errorcode(group->cmd_socket,
1784                                                         DP_ERROR_NO_DATA);
1785                                         } else {
1786                                                 // casting
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));
1791                                         }
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);
1802                                         } else {
1803                                                 __send_return_string
1804                                                         (group->cmd_socket, DP_ERROR_NONE, content);
1805                                                 free(content);
1806                                         }
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) {
1813                                                 TRACE_ERROR
1814                                                         ("[ERROR][%d] [DP_ERROR_NO_DATA]",
1815                                                         client_cmd.id);
1816                                                 dp_ipc_send_errorcode(group->cmd_socket,
1817                                                         DP_ERROR_NO_DATA);
1818                                         } else {
1819                                                 __send_return_custom_type
1820                                                         (group->cmd_socket, DP_ERROR_NONE,
1821                                                         &http_status, sizeof(int));
1822                                         }
1823                                 } else if (client_cmd.cmd == DP_CMD_GET_ETAG) {
1824                                         char *etag = NULL;
1825                                         errorcode = DP_ERROR_NONE;
1826                                         etag = dp_request_get_etag
1827                                                         (client_cmd.id, request, &errorcode);
1828                                         if (etag == NULL) {
1829                                                 TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
1830                                                         dp_print_errorcode(errorcode));
1831                                                 dp_ipc_send_errorcode
1832                                                         (group->cmd_socket, errorcode);
1833                                         } else {
1834                                                 __send_return_string
1835                                                         (group->cmd_socket, DP_ERROR_NONE, etag);
1836                                                 free(etag);
1837                                         }
1838                                 } else if (client_cmd.cmd == DP_CMD_GET_STATE) {
1839                                         dp_state_type download_state = DP_STATE_NONE;
1840                                         if (request == NULL) {
1841                                                 download_state =
1842                                                         dp_db_get_int_column(client_cmd.id,
1843                                                                                 DP_DB_TABLE_LOG,
1844                                                                                 DP_DB_COL_STATE);
1845                                                 if (download_state < 0) {
1846                                                         TRACE_ERROR
1847                                                         ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1848                                                         client_cmd.id);
1849                                                         dp_ipc_send_errorcode(group->cmd_socket,
1850                                                                 DP_ERROR_ID_NOT_FOUND);
1851                                                         continue;
1852                                                 }
1853                                         } else {
1854                                                 CLIENT_MUTEX_LOCK(&(request->mutex));
1855                                                 download_state = request->state;
1856                                                 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1857                                         }
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) {
1864                                                 errorcode =
1865                                                         dp_db_get_int_column(client_cmd.id,
1866                                                                                 DP_DB_TABLE_LOG,
1867                                                                                 DP_DB_COL_ERRORCODE);
1868                                                 if (errorcode < 0) {
1869                                                         TRACE_ERROR
1870                                                         ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
1871                                                         client_cmd.id);
1872                                                         dp_ipc_send_errorcode(group->cmd_socket,
1873                                                                 DP_ERROR_ID_NOT_FOUND);
1874                                                         continue;
1875                                                 }
1876                                         } else {
1877                                                 CLIENT_MUTEX_LOCK(&(request->mutex));
1878                                                 errorcode = request->error;
1879                                                 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1880                                         }
1881                                         dp_ipc_send_errorcode
1882                                                 (group->cmd_socket, DP_ERROR_NONE);
1883                                         dp_ipc_send_errorcode
1884                                                 (group->cmd_socket, errorcode);
1885                                 } else {
1886                                         TRACE_INFO
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;
1895                                 }
1896                         } // FD_ISSET
1897                 } // DP_MAX_GROUP
1898
1899                 // timeout
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;
1906                         } else {
1907                                 if ((now_timeout - prev_timeout) <
1908                                         DP_CARE_CLIENT_MIN_INTERVAL) {
1909                                         // this is error.
1910                                         // terminate Process
1911                                         TRACE_STRERROR
1912                                         ("[CRITICAL] Sock exception prev[%ld]now[%ld][%ld]",
1913                                         prev_timeout, now_timeout, flexible_timeout);
1914                                         break;
1915                                 }
1916                         }
1917
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;
1925
1926                                 TRACE_INFO
1927                                         ("[CLEAR] [%d] old reqeusts", old_request_count);
1928
1929                                 dp_request_slots *old_requests =
1930                                         dp_request_slots_new(old_request_count);
1931                                 if (old_requests) {
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.
1937                                                         int index =
1938                                                                 __get_same_request_index
1939                                                                         (privates->requests,
1940                                                                         old_requests[i].request->id);
1941                                                         if (index >= 0) {
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 ||
1948                                                                         request->state ==
1949                                                                         DP_STATE_DOWNLOADING) {
1950                                                                         CLIENT_MUTEX_UNLOCK
1951                                                                                 (&(request->mutex));
1952                                                                         continue;
1953                                                                 }
1954                                                                 CLIENT_MUTEX_UNLOCK(&(request->mutex));
1955                                                                 // unload from slots ( memory )
1956                                                                 dp_request_free(request);
1957                                                                 privates->requests[index].request = NULL;
1958                                                         }
1959                                                         // remove tmp file
1960                                                         char *tmp_path =
1961                                                                 dp_request_get_tmpsavedpath
1962                                                                         (old_requests[i].request->id,
1963                                                                         old_requests[i].request,
1964                                                                         &errorcode);
1965                                                         if ((tmp_path && strlen(tmp_path) > 0) &&
1966                                                                 dp_is_file_exist(tmp_path) == 0) {
1967                                                                 TRACE_INFO
1968                                                                         ("[REMOVE][%d] TEMP FILE [%s]",
1969                                                                         old_requests[i].request->id,
1970                                                                         tmp_path);
1971                                                                 if (unlink(tmp_path) != 0)
1972                                                                         TRACE_STRERROR
1973                                                                                 ("[ERROR][%d] remove file",
1974                                                                                 old_requests[i].request->id);
1975                                                                 free(tmp_path);
1976                                                         }
1977                                                         // remove from DB
1978                                                         dp_db_remove_all(old_requests[i].request->id);
1979                                                 }
1980                                         }
1981                                         dp_request_slots_free(old_requests, old_request_count);
1982                                 }
1983                         }
1984
1985                         // clean slots
1986                         int ready_requests = 0;
1987                         for (i = 0; i < DP_MAX_REQUEST; i++) {
1988                                 if (!privates->requests[i].request)
1989                                         continue;
1990                                 dp_request *request = privates->requests[i].request;
1991
1992                                 CLIENT_MUTEX_LOCK(&(request->mutex));
1993
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));
1999                                         continue;
2000                                 }
2001
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));
2006                                         TRACE_INFO
2007                                         ("[FREE] [%d] unavailable agent ID [%d]",
2008                                                 request->id, request->agent_id);
2009                                         dp_request_free(request);
2010                                         privates->requests[i].request = NULL;
2011                                         continue;
2012                                 }
2013
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;
2022                                         if (request->group
2023                                                 && request->group->event_socket >= 0
2024                                                 && request->state_cb)
2025                                                 dp_ipc_send_event
2026                                                         (request->group->event_socket,
2027                                                         download_id, state, errorcode, 0);
2028                                         CLIENT_MUTEX_UNLOCK(&(request->mutex));
2029                                         TRACE_INFO
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,
2038                                                         &state) < 0) {
2039                                                 TRACE_ERROR("[ERROR][%d][SQL]", request->id);
2040                                         }
2041                                         if (dp_db_set_column
2042                                                         (download_id, DP_DB_TABLE_LOG,
2043                                                         DP_DB_COL_ERRORCODE, DP_DB_COL_TYPE_INT,
2044                                                         &errorcode) < 0) {
2045                                                 TRACE_ERROR("[ERROR][%d][SQL]", request->id);
2046                                         }
2047                                         continue;
2048                                 }
2049
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]",
2060                                                         request->id);
2061                                                 dp_request_free(request);
2062                                                 privates->requests[i].request = NULL;
2063                                                 continue;
2064                                         }
2065                                 }
2066
2067                                 // check after clear
2068                                 if (request->state == DP_STATE_QUEUED)
2069                                         ready_requests++;
2070
2071                                 CLIENT_MUTEX_UNLOCK(&(request->mutex));
2072                         }
2073
2074                         if (ready_requests > 0) {
2075                                 //send signal to queue thread will check queue.
2076                                 dp_thread_queue_manager_wake_up();
2077                         } else {
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");
2084                                         break;
2085                                 }
2086 #endif
2087                         }
2088                         prev_timeout = now_timeout;
2089                 } // timeout
2090         }
2091         TRACE_INFO("terminate main thread ...");
2092         dp_terminate(SIGTERM);
2093         pthread_exit(NULL);
2094         return 0;
2095 }