Fix invalid path issue
[platform/framework/web/download-provider.git] / provider / download-provider-client.c
1 /*
2  * Copyright (c) 2013 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 #include <sys/time.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <sys/stat.h>
21 #include <signal.h>
22 #include <limits.h>
23
24 #include <download-provider-log.h>
25 #include <download-provider-config.h>
26 #include <download-provider-ipc.h>
27 #include <download-provider-network.h>
28 #include <download-provider-client.h>
29 #include <download-provider-pthread.h>
30 #include <download-provider-notify.h>
31 #include <download-provider-notification-manager.h>
32 #include <download-provider-queue-manager.h>
33 #include <download-provider-client-manager.h>
34 #include <download-provider-db-defs.h>
35 #include <download-provider-db.h>
36 #include <download-provider-plugin-download-agent.h>
37 #include <download-provider-security.h>
38
39 #ifndef SIZE_MAX
40 #define SIZE_MAX ((size_t) - 1)
41 #endif
42
43 char *dp_print_state(int state)
44 {
45         switch (state) {
46         case DP_STATE_NONE:
47                 return "NONE";
48         case DP_STATE_READY:
49                 return "READY";
50         case DP_STATE_QUEUED:
51                 return "QUEUED";
52         case DP_STATE_CONNECTING:
53                 return "CONNECTING";
54         case DP_STATE_DOWNLOADING:
55                 return "DOWNLOADING";
56         case DP_STATE_PAUSED:
57                 return "PAUSED";
58         case DP_STATE_COMPLETED:
59                 return "COMPLETED";
60         case DP_STATE_CANCELED:
61                 return "CANCELED";
62         case DP_STATE_FAILED:
63                 return "FAILED";
64         default:
65                 break;
66         }
67         return "UNKNOWN";
68 }
69
70 char *dp_print_errorcode(int errorcode)
71 {
72         switch (errorcode) {
73         case DP_ERROR_NONE:
74                 return "NONE";
75         case DP_ERROR_INVALID_PARAMETER:
76                 return "INVALID_PARAMETER";
77         case DP_ERROR_OUT_OF_MEMORY:
78                 return "OUT_OF_MEMORY";
79         case DP_ERROR_IO_ERROR:
80                 return "IO_ERROR";
81         case DP_ERROR_NETWORK_UNREACHABLE:
82                 return "NETWORK_UNREACHABLE";
83         case DP_ERROR_CONNECTION_TIMED_OUT:
84                 return "CONNECTION_TIMED_OUT";
85         case DP_ERROR_NO_SPACE:
86                 return "NO_SPACE";
87         case DP_ERROR_FIELD_NOT_FOUND:
88                 return "FIELD_NOT_FOUND";
89         case DP_ERROR_INVALID_STATE:
90                 return "INVALID_STATE";
91         case DP_ERROR_CONNECTION_FAILED:
92                 return "CONNECTION_FAILED";
93         case DP_ERROR_INVALID_URL:
94                 return "INVALID_URL";
95         case DP_ERROR_INVALID_DESTINATION:
96                 return "INVALID_DESTINATION";
97         case DP_ERROR_QUEUE_FULL:
98                 return "QUEUE_FULL";
99         case DP_ERROR_ALREADY_COMPLETED:
100                 return "ALREADY_COMPLETED";
101         case DP_ERROR_FILE_ALREADY_EXISTS:
102                 return "FILE_ALREADY_EXISTS";
103         case DP_ERROR_TOO_MANY_DOWNLOADS:
104                 return "TOO_MANY_DOWNLOADS";
105         case DP_ERROR_NO_DATA:
106                 return "NO_DATA";
107         case DP_ERROR_UNHANDLED_HTTP_CODE:
108                 return "UNHANDLED_HTTP_CODE";
109         case DP_ERROR_CANNOT_RESUME:
110                 return "CANNOT_RESUME";
111         case DP_ERROR_PERMISSION_DENIED:
112                 return "PERMISSION_DENIED";
113         case DP_ERROR_RESPONSE_TIMEOUT:
114                 return "RESPONSE_TIMEOUT";
115         case DP_ERROR_REQUEST_TIMEOUT:
116                 return "REQUEST_TIMEOUT";
117         case DP_ERROR_SYSTEM_DOWN:
118                 return "SYSTEM_DOWN";
119         case DP_ERROR_CLIENT_DOWN:
120                 return "CLIENT_DOWN";
121         case DP_ERROR_DISK_BUSY:
122                 return "DISK_BUSY";
123         case DP_ERROR_ID_NOT_FOUND:
124                 return "ID_NOT_FOUND";
125         default:
126                         break;
127         }
128         return "UNKNOWN";
129 }
130
131 char *dp_print_section(short section)
132 {
133         switch (section) {
134         case DP_SEC_NONE:
135                 return "NONE";
136         case DP_SEC_INIT:
137                 return "INIT";
138         case DP_SEC_DEINIT:
139                 return "DEINIT";
140         case DP_SEC_CONTROL:
141                 return "CONTROL";
142         case DP_SEC_GET:
143                 return "GET";
144         case DP_SEC_SET:
145                 return "SET";
146         case DP_SEC_UNSET:
147                 return "UNSET";
148         default:
149                 break;
150         }
151         return "UNKNOWN";
152 }
153
154 char *dp_print_property(unsigned property)
155 {
156         switch (property) {
157         case DP_PROP_NONE:
158                 return "NONE";
159         case DP_PROP_CREATE:
160                 return "CREATE";
161         case DP_PROP_START:
162                 return "START";
163         case DP_PROP_PAUSE:
164                 return "PAUSE";
165         case DP_PROP_CANCEL:
166                 return "CANCEL";
167         case DP_PROP_DESTROY:
168                 return "DESTROY";
169         case DP_PROP_URL:
170                 return "URL";
171         case DP_PROP_DESTINATION:
172                 return "DESTINATION";
173         case DP_PROP_FILENAME:
174                 return "FILENAME";
175         case DP_PROP_STATE_CALLBACK:
176                 return "STATE_CB";
177         case DP_PROP_PROGRESS_CALLBACK:
178                 return "PROGRESS_CB";
179         case DP_PROP_AUTO_DOWNLOAD:
180                 return "AUTO_DOWNLOAD";
181         case DP_PROP_NETWORK_TYPE:
182                 return "NETWORK_TYPE";
183         case DP_PROP_NETWORK_BONDING:
184                 return "NETWORK_BONDING";
185         case DP_PROP_SAVED_PATH:
186                 return "SAVED_PATH";
187         case DP_PROP_TEMP_SAVED_PATH:
188                 return "TEMP_SAVED_PATH";
189         case DP_PROP_MIME_TYPE:
190                 return "MIME_TYPE";
191         case DP_PROP_RECEIVED_SIZE:
192                 return "RECEIVED_SIZE";
193         case DP_PROP_TOTAL_FILE_SIZE:
194                 return "TOTAL_FILE_SIZE";
195         case DP_PROP_CONTENT_NAME:
196                 return "CONTENT_NAME";
197         case DP_PROP_HTTP_STATUS:
198                 return "HTTP_STATUS";
199         case DP_PROP_ETAG:
200                 return "ETAG";
201         case DP_PROP_STATE:
202                 return "STATE";
203         case DP_PROP_ERROR:
204                 return "ERROR";
205         case DP_PROP_NOTIFICATION_RAW:
206                 return "NOTIFICATION_RAW";
207         case DP_PROP_NOTIFICATION_SUBJECT:
208                 return "NOTIFICATION_SUBJECT";
209         case DP_PROP_NOTIFICATION_DESCRIPTION:
210                 return "NOTIFICATION_DESCRIPTION";
211         case DP_PROP_NOTIFICATION_TYPE:
212                 return "NOTIFICATION_TYPE";
213         case DP_PROP_HTTP_HEADERS:
214                 return "HTTP_HEADERS";
215         case DP_PROP_HTTP_HEADER:
216                 return "HTTP_HEADER";
217         default:
218                 break;
219         }
220         return "UNKNOWN";
221 }
222
223 static int __dp_get_download_id(dp_client_fmt *client)
224 {
225         int download_id = -1;
226         int check_duplicate = 1;
227         int retry_count = 0;
228         int errorcode = DP_ERROR_NONE;
229         struct timeval tval;
230
231         if (dp_db_get_max_download_id(client->dbhandle,
232                                 DP_TABLE_LOGGING, &download_id, &errorcode) < 0) {
233                 TRACE_ERROR("ERROR [%d]", errorcode);
234                 // database is empty start with id : 1
235                 download_id = DP_FIRST_DOWNLOAD_ID;
236         } else {
237                 if (download_id < INT_MAX)
238                         download_id++;
239         }
240
241         retry_count = 0;
242         do {
243                 retry_count++;
244                 if (download_id < INT_MAX) {
245                         TRACE_DEBUG("download_id [%d]", download_id);
246                         check_duplicate = dp_db_check_duplicated_int(client->dbhandle,
247                                         DP_TABLE_LOGGING, DP_DB_COL_ID, download_id, &errorcode);
248                         if (errorcode == DP_ERROR_NONE) {
249                                 if (check_duplicate == 0)
250                                         break;
251                         } else {
252                                 TRACE_ERROR("ERROR [%d]", errorcode);
253                         }
254                         if (retry_count < 3) {
255                                 download_id++;
256                         } else if (retry_count < 10) {
257                                 gettimeofday(&tval, NULL);
258                                 tval.tv_usec = (tval.tv_usec & 0x0fff);
259                                 download_id += 1171 * retry_count + tval.tv_usec;
260                         } else if (retry_count < 20) {
261                                 gettimeofday(&tval, NULL);
262                                 tval.tv_usec = (tval.tv_usec & 0xff33ff) + retry_count;
263                                 download_id += tval.tv_usec;
264                         } else {
265                                 TRACE_ERROR("failed to generate unique download_id [%d]", download_id);
266                                 return -1;
267                         }
268                 } else {
269                         TRACE_ERROR("reached INT_MAX limit");
270                         download_id = DP_FIRST_DOWNLOAD_ID;
271                 }
272         } while (check_duplicate != 0);
273         return download_id;
274 }
275
276 void dp_request_create(dp_client_fmt *client, dp_request_fmt *request)
277 {
278         // new request
279         // find the tail of linked list & check limitation
280         int i = 0;
281         dp_request_fmt *tailp = client->requests;
282         dp_request_fmt *prevp = NULL;
283         for (; i < MAX_DOWNLOAD_HANDLE; i++) {
284                 if (tailp == NULL)
285                         break;
286                 TRACE_DEBUG("link %d info: id:%d access-time:%d", i, tailp->id, tailp->access_time);
287                 prevp = tailp;
288                 tailp = tailp->next;
289         }
290         request->next = NULL;
291         if (prevp == NULL) // it's first link
292                 client->requests = request;
293         else
294                 prevp->next = request; // attach at the tail
295
296         TRACE_DEBUG("sock:%d download-id:%d", client->channel, request->id);
297 }
298
299 static int __dp_request_create(dp_client_fmt *client, dp_ipc_fmt *ipc_info)
300 {
301         int errorcode = DP_ERROR_NONE;
302
303         int download_id = __dp_get_download_id(client);
304
305         // allocation new request.
306         dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt));
307         if (request == NULL) {
308                 TRACE_ERROR("check memory sock:%d download-id:%d", client->channel, download_id);
309                 return DP_ERROR_OUT_OF_MEMORY;
310         }
311
312         if (dp_db_new_logging(client->dbhandle, download_id, DP_STATE_READY, DP_ERROR_NONE, &errorcode) < 0) {
313                 TRACE_ERROR("new log sock:%d download-id:%d errorcode:%s", client->channel, download_id, dp_print_errorcode(errorcode));
314                 free(request);
315                 return errorcode;
316         }
317
318         request->id = download_id;
319         request->agent_id = -1;
320         request->state = DP_STATE_READY;
321         request->error = DP_ERROR_NONE;
322         request->network_type = DP_NETWORK_ALL;
323         request->access_time = (int)time(NULL);
324         request->state_cb = 0;
325         request->progress_cb = 0;
326         request->startcount = 0;
327         request->noti_type = DP_NOTIFICATION_TYPE_NONE;
328         request->progress_lasttime = 0;
329         request->received_size = 0;
330         request->content_type = DP_CONTENT_UNKNOWN;
331         request->file_size = 0;
332         request->noti_priv_id = -1;
333
334         dp_request_create(client, request);
335         ipc_info->id = download_id;
336         return errorcode;
337 }
338
339 void dp_request_free(dp_request_fmt *request)
340 {
341         // free notification handle here
342         TRACE_DEBUG("destory id:%d", request->id);
343         free(request);
344 }
345
346 void dp_client_clear_requests(void *slotp)
347 {
348         dp_client_slots_fmt *slot = (dp_client_slots_fmt *)slotp;
349         if (slot == NULL) {
350                 TRACE_ERROR("check slot memory");
351                 return ;
352         }
353         dp_client_fmt *client = &slot->client;
354
355         int now_time = (int)time(NULL);
356         int i = 0;
357         unsigned queued_count = 0;
358         unsigned ongoing_count = 0;
359         dp_request_fmt *tailp = client->requests;
360         dp_request_fmt *prevp = NULL;
361         for (; tailp != NULL; i++) {
362
363                 unsigned can_unload = 0;
364                 if (tailp->id <= 0 || tailp->state == DP_STATE_NONE) {
365                         TRACE_ERROR("id:%d unexpected request (%d/%d)", tailp->id, tailp->access_time, now_time);
366                         can_unload = 1;
367                 } else if (tailp->access_time > 0 &&
368                                 (now_time - tailp->access_time) > DP_CARE_CLIENT_CLEAR_INTERVAL) {
369                         // check accesstime. if difference is bigger than DP_CARE_CLIENT_CLEAR_INTERVAL, clear.
370
371                         if (tailp->state == DP_STATE_READY ||
372                                         tailp->state == DP_STATE_COMPLETED ||
373                                         tailp->state == DP_STATE_CANCELED ||
374                                         tailp->state == DP_STATE_FAILED) {
375                                 can_unload = 1;
376                         } else if (tailp->state == DP_STATE_CONNECTING) { // it take 120 sec over to connect. it means zombie.
377                                 TRACE_ERROR("id:%d connection timeout (%d/%d)", tailp->id, tailp->access_time, now_time);
378                                 if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0)
379                                         TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id);
380                                 tailp->state = DP_STATE_FAILED;
381                                 tailp->error = DP_ERROR_CONNECTION_TIMED_OUT;
382                                 if (tailp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
383                                                 tailp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
384                                         if (dp_notification_manager_push_notification(slot, tailp, DP_NOTIFICATION) < 0)
385                                                 TRACE_ERROR("failed to register notification for id:%d", tailp->id);
386                                 }
387                         }
388                 } else if (tailp->state == DP_STATE_PAUSED &&
389                                 dp_is_alive_download(tailp->agent_id) == 0) {
390                         // paused & agent_id not exist.... unload from memory.
391                         TRACE_ERROR("id:%d hanged as paused (%d/%d)", tailp->id, tailp->access_time, now_time);
392                         can_unload = 1;
393                 }
394
395                 if (can_unload == 1) {
396                         dp_request_fmt *removep = tailp;
397                         if (prevp == NULL) // first request.
398                                 client->requests = tailp->next;
399                         else
400                                 prevp->next = tailp->next;
401                         tailp = tailp->next;
402                         TRACE_DEBUG("request %d clear: id:%d state:%s", i, removep->id, dp_print_state(removep->state));
403                         dp_request_free(removep);
404                         continue;
405                 } else {
406                         ongoing_count++;
407                 }
408
409                 if (tailp->state == DP_STATE_QUEUED)
410                         queued_count++;
411
412                 prevp = tailp;
413                 tailp = tailp->next;
414         }
415         TRACE_DEBUG("info requests:%d queued:%d", ongoing_count, queued_count);
416         if (queued_count > 0)
417                 dp_queue_manager_wake_up();
418 }
419
420 int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
421 {
422         int errorcode = DP_ERROR_NONE;
423
424         if (requestp != NULL && client->requests != NULL) {
425                 if (requestp == client->requests) {
426                         // cancel downloading ... after checking status
427                         client->requests = requestp->next;
428                         dp_request_free(requestp);
429                 } else {
430                         int i = 1;
431                         dp_request_fmt *prevp = client->requests;
432                         dp_request_fmt *removep = client->requests->next;
433                         for (; i < MAX_DOWNLOAD_HANDLE; i++) {
434                                 if (removep == NULL) {
435                                         errorcode = DP_ERROR_ID_NOT_FOUND;
436                                         break;
437                                 }
438                                 if (removep == requestp) {
439                                         // cancel downloading ... after checking status
440                                         prevp->next = removep->next;
441                                         dp_request_free(removep);
442                                         break;
443                                 }
444                                 prevp = removep;
445                                 removep = removep->next;
446                         }
447                 }
448         }
449
450         TRACE_DEBUG("sock:%d id:%d errorcode:%s", client->channel,
451                         (ipc_info) ? ipc_info->id : -1, dp_print_errorcode(errorcode));
452
453         return errorcode;
454 }
455
456 static int __dp_request_read_int(int sock, dp_ipc_fmt *ipc_info, int *value)
457 {
458         int errorcode = DP_ERROR_NONE;
459         if (ipc_info->size == sizeof(int)) {
460                 if (dp_ipc_read(sock, value, ipc_info->size, __FUNCTION__) < 0) {
461                         TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size);
462                         errorcode = DP_ERROR_IO_ERROR;
463                 }
464         } else {
465                 errorcode = DP_ERROR_IO_ERROR;
466         }
467         return errorcode;
468 }
469
470 static int __dp_request_feedback_string(int sock, dp_ipc_fmt *ipc_info, void *string, size_t length, int errorvalue)
471 {
472         int errorcode = DP_ERROR_NONE;
473
474         if (length == 0 && errorvalue == DP_ERROR_NONE)
475                 errorvalue = DP_ERROR_NO_DATA;
476
477         if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, length * sizeof(char)) < 0) {
478                 errorcode = DP_ERROR_IO_ERROR;
479                 TRACE_ERROR("sock:%d check ipc length:%d", sock, length);
480         }
481         if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) {
482                 if (dp_ipc_write(sock, string, sizeof(char) * length) < 0) {
483                         errorcode = DP_ERROR_IO_ERROR;
484                         TRACE_ERROR("sock:%d check ipc length:%d", sock, length);
485                 }
486         }
487         return errorcode;
488 }
489
490 static int __dp_request_read_string(int sock, dp_ipc_fmt *ipc_info, char **string)
491 {
492         int errorcode = DP_ERROR_NONE;
493         if (ipc_info->size > 0) {
494                 char *recv_str = (char *)calloc((ipc_info->size + (size_t)1), sizeof(char));
495                 if (recv_str == NULL) {
496                         TRACE_ERROR("sock:%d check memory length:%d", sock, ipc_info->size);
497                         errorcode = DP_ERROR_OUT_OF_MEMORY;
498                 } else {
499                         if (dp_ipc_read(sock, recv_str, ipc_info->size, __FUNCTION__) <= 0) {
500                                 TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size);
501                                 errorcode = DP_ERROR_IO_ERROR;
502                                 free(recv_str);
503                         } else {
504                                 recv_str[ipc_info->size] = '\0';
505                                 TRACE_DEBUG("sock:%d length:%d string:%s", sock, ipc_info->size, recv_str);
506                                 *string = recv_str;
507                         }
508                 }
509         } else {
510                 errorcode = DP_ERROR_IO_ERROR;
511         }
512         return errorcode;
513 }
514
515 static int __dp_request_feedback_int(int sock, dp_ipc_fmt *ipc_info, void *value, int errorvalue, size_t extra_size)
516 {
517         int errorcode = DP_ERROR_NONE;
518         if (errorvalue != DP_ERROR_NONE)
519                 extra_size = 0;
520         if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, extra_size) < 0) {
521                 errorcode = DP_ERROR_IO_ERROR;
522                 TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size);
523         }
524         if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) {
525                 if (dp_ipc_write(sock, value, extra_size) < 0) {
526                         errorcode = DP_ERROR_IO_ERROR;
527                         TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size);
528                 }
529         }
530         return errorcode;
531 }
532
533 static int __dp_request_get_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
534 {
535         int errorcode = DP_ERROR_NONE;
536         switch (ipc_info->property) {
537         case DP_PROP_URL:
538                 {
539                         char *string = NULL;
540                         unsigned length = 0;
541                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (unsigned char **)&string, &length, &errorcode) < 0) {
542                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
543                                 errorcode = DP_ERROR_NO_DATA;
544                         }
545                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
546                         if (result == DP_ERROR_IO_ERROR) {
547                                 errorcode = DP_ERROR_IO_ERROR;
548                                 TRACE_ERROR("check ipc sock:%d", client->channel);
549                         }
550                         free(string);
551                         break;
552                 }
553         case DP_PROP_DESTINATION:
554                 {
555                         char *string = NULL;
556                         unsigned length = 0;
557                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (unsigned char **)&string, &length, &errorcode) < 0) {
558                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
559                                 errorcode = DP_ERROR_NO_DATA;
560                         }
561                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
562                         if (result == DP_ERROR_IO_ERROR) {
563                                 errorcode = DP_ERROR_IO_ERROR;
564                                 TRACE_ERROR("check ipc sock:%d", client->channel);
565                         }
566                         free(string);
567                         break;
568                 }
569         case DP_PROP_FILENAME:
570                 {
571                         char *string = NULL;
572                         unsigned length = 0;
573                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (unsigned char **)&string, &length, &errorcode) < 0) {
574                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
575                                 errorcode = DP_ERROR_NO_DATA;
576                         }
577                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
578                         if (result == DP_ERROR_IO_ERROR) {
579                                 errorcode = DP_ERROR_IO_ERROR;
580                                 TRACE_ERROR("check ipc sock:%d", client->channel);
581                         }
582                         free(string);
583                         break;
584                 }
585         case DP_PROP_STATE_CALLBACK:
586                 {
587                         int callback = 0;
588                         if (requestp != NULL) {
589                                 callback = requestp->state_cb;
590                         } else {
591                                 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, &callback, &errorcode) < 0) {
592                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
593                                         errorcode = DP_ERROR_NO_DATA;
594                                 }
595                         }
596                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int));
597                         if (result == DP_ERROR_IO_ERROR) {
598                                 errorcode = DP_ERROR_IO_ERROR;
599                                 TRACE_ERROR("check ipc sock:%d", client->channel);
600                         }
601                         break;
602                 }
603         case DP_PROP_PROGRESS_CALLBACK:
604                 {
605                         int callback = 0;
606                         if (requestp != NULL) {
607                                 callback = requestp->progress_cb;
608                         } else {
609                                 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, &callback, &errorcode) < 0) {
610                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
611                                         errorcode = DP_ERROR_NO_DATA;
612                                 }
613                         }
614                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int));
615                         if (result == DP_ERROR_IO_ERROR) {
616                                 errorcode = DP_ERROR_IO_ERROR;
617                                 TRACE_ERROR("check ipc sock:%d", client->channel);
618                         }
619                         break;
620                 }
621         case DP_PROP_AUTO_DOWNLOAD:
622                 {
623                         int autodownload = 0;
624                         if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, &autodownload, &errorcode) < 0) {
625                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
626                                 errorcode = DP_ERROR_NO_DATA;
627                         }
628                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&autodownload, errorcode, sizeof(int));
629                         if (result == DP_ERROR_IO_ERROR) {
630                                 errorcode = DP_ERROR_IO_ERROR;
631                                 TRACE_ERROR("check ipc sock:%d", client->channel);
632                         }
633                         break;
634                 }
635         case DP_PROP_NETWORK_TYPE:
636                 {
637                         int network = 0;
638                         if (requestp != NULL) {
639                                 network = requestp->network_type;
640                         } else {
641                                 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, &network, &errorcode) < 0) {
642                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
643                                         errorcode = DP_ERROR_NO_DATA;
644                                 }
645                         }
646                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network, errorcode, sizeof(int));
647                         if (result == DP_ERROR_IO_ERROR) {
648                                 errorcode = DP_ERROR_IO_ERROR;
649                                 TRACE_ERROR("check ipc sock:%d", client->channel);
650                         }
651                         break;
652                 }
653         case DP_PROP_NETWORK_BONDING:
654                 {
655                         int network_bonding = 0;
656                         if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, &network_bonding, &errorcode) < 0) {
657                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
658                                 errorcode = DP_ERROR_NO_DATA;
659                         }
660                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network_bonding, errorcode, sizeof(int));
661                         if (result == DP_ERROR_IO_ERROR) {
662                                 errorcode = DP_ERROR_IO_ERROR;
663                                 TRACE_ERROR("check ipc sock:%d", client->channel);
664                         }
665                         break;
666                 }
667         case DP_PROP_SAVED_PATH:
668                 {
669                         char *string = NULL;
670                         unsigned length = 0;
671                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) {
672                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
673                                 errorcode = DP_ERROR_NO_DATA;
674                         }
675                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
676                         if (result == DP_ERROR_IO_ERROR) {
677                                 errorcode = DP_ERROR_IO_ERROR;
678                                 TRACE_ERROR("check ipc sock:%d", client->channel);
679                         }
680                         free(string);
681                         break;
682                 }
683         case DP_PROP_TEMP_SAVED_PATH:
684                 {
685                         char *string = NULL;
686                         unsigned length = 0;
687                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) {
688                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
689                                 errorcode = DP_ERROR_NO_DATA;
690                         }
691                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
692                         if (result == DP_ERROR_IO_ERROR) {
693                                 errorcode = DP_ERROR_IO_ERROR;
694                                 TRACE_ERROR("check ipc sock:%d", client->channel);
695                         }
696                         free(string);
697                         break;
698                 }
699         case DP_PROP_MIME_TYPE:
700                 {
701                         char *string = NULL;
702                         unsigned length = 0;
703                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_MIMETYPE, (unsigned char **)&string, &length, &errorcode) < 0) {
704                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
705                                 errorcode = DP_ERROR_NO_DATA;
706                         }
707                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
708                         if (result == DP_ERROR_IO_ERROR) {
709                                 errorcode = DP_ERROR_IO_ERROR;
710                                 TRACE_ERROR("check ipc sock:%d", client->channel);
711                         }
712                         free(string);
713                         break;
714                 }
715         case DP_PROP_RECEIVED_SIZE:
716                 {
717                         unsigned long long recv_size = 0;
718                         if (requestp != NULL)
719                                 recv_size = requestp->received_size;
720                         else
721                                 errorcode = DP_ERROR_INVALID_STATE;
722
723                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&recv_size, errorcode, sizeof(unsigned long long));
724                         if (result == DP_ERROR_IO_ERROR) {
725                                 errorcode = DP_ERROR_IO_ERROR;
726                                 TRACE_ERROR("check ipc sock:%d", client->channel);
727                         }
728                         break;
729                 }
730         case DP_PROP_TOTAL_FILE_SIZE:
731                 {
732                         unsigned long long file_size = 0;
733                         if (requestp != NULL) {
734                                 file_size = requestp->file_size;
735                         } else {
736                                 // load content_size(INT64) from database;
737                                 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, &file_size, &errorcode) < 0) {
738                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
739                                         errorcode = DP_ERROR_NO_DATA;
740                                 }
741                         }
742                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&file_size, errorcode, sizeof(unsigned long long));
743                         if (result == DP_ERROR_IO_ERROR) {
744                                 errorcode = DP_ERROR_IO_ERROR;
745                                 TRACE_ERROR("check ipc sock:%d", client->channel);
746                         }
747                         break;
748                 }
749         case DP_PROP_CONTENT_NAME:
750                 {
751                         char *string = NULL;
752                         unsigned length = 0;
753                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&string, &length, &errorcode) < 0) {
754                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
755                                 errorcode = DP_ERROR_NO_DATA;
756                         }
757                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
758                         if (result == DP_ERROR_IO_ERROR) {
759                                 errorcode = DP_ERROR_IO_ERROR;
760                                 TRACE_ERROR("check ipc sock:%d", client->channel);
761                         }
762                         free(string);
763                         break;
764                 }
765         case DP_PROP_HTTP_STATUS:
766                 {
767                         int httpstatus = 0;
768                         if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_HTTP_STATUS, &httpstatus, &errorcode) < 0) {
769                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
770                                 errorcode = DP_ERROR_NO_DATA;
771                         }
772                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&httpstatus, errorcode, sizeof(int));
773                         if (result == DP_ERROR_IO_ERROR) {
774                                 errorcode = DP_ERROR_IO_ERROR;
775                                 TRACE_ERROR("check ipc sock:%d", client->channel);
776                         }
777                         break;
778                 }
779         case DP_PROP_ETAG:
780                 {
781                         char *string = NULL;
782                         unsigned length = 0;
783                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (unsigned char **)&string, &length, &errorcode) < 0) {
784                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
785                                 errorcode = DP_ERROR_NO_DATA;
786                         }
787                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
788                         if (result == DP_ERROR_IO_ERROR) {
789                                 errorcode = DP_ERROR_IO_ERROR;
790                                 TRACE_ERROR("check ipc sock:%d", client->channel);
791                         }
792                         free(string);
793                         break;
794                 }
795         case DP_PROP_STATE:
796                 {
797                         int state = DP_STATE_NONE;
798                         if (requestp != NULL) {
799                                 state = requestp->state;
800                         } else {
801                                 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &state, &errorcode) < 0) {
802                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
803                                         errorcode = DP_ERROR_ID_NOT_FOUND;
804                                 }
805                         }
806                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&state, errorcode, sizeof(int));
807                         if (result == DP_ERROR_IO_ERROR) {
808                                 errorcode = DP_ERROR_IO_ERROR;
809                                 TRACE_ERROR("check ipc sock:%d", client->channel);
810                         }
811                         break;
812                 }
813         case DP_PROP_ERROR:
814                 {
815                         int errorvalue = DP_ERROR_NONE;
816                         if (requestp != NULL) {
817                                 errorvalue = requestp->error;
818                         } else {
819                                 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_ERRORCODE, &errorvalue, &errorcode) < 0) {
820                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
821                                         errorcode = DP_ERROR_ID_NOT_FOUND;
822                                 }
823                         }
824                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&errorvalue, errorcode, sizeof(int));
825                         if (result == DP_ERROR_IO_ERROR) {
826                                 errorcode = DP_ERROR_IO_ERROR;
827                                 TRACE_ERROR("check ipc sock:%d", client->channel);
828                         }
829                         break;
830                 }
831         case DP_PROP_NOTIFICATION_TYPE:
832                 {
833                         int noti_type = 0;
834                         if (requestp != NULL) {
835                                 noti_type = requestp->noti_type;
836                                 // if already notification, unregister from notification bar.
837                         } else {
838                                 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, &noti_type, &errorcode) < 0) {
839                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
840                                         errorcode = DP_ERROR_NO_DATA;
841                                 }
842                         }
843                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&noti_type, errorcode, sizeof(int));
844                         if (result == DP_ERROR_IO_ERROR) {
845                                 errorcode = DP_ERROR_IO_ERROR;
846                                 TRACE_ERROR("check ipc sock:%d", client->channel);
847                         }
848                         break;
849                 }
850         case DP_PROP_NOTIFICATION_SUBJECT:
851                 {
852                         char *string = NULL;
853                         unsigned length = 0;
854                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&string, &length, &errorcode) < 0) {
855                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
856                                 errorcode = DP_ERROR_NO_DATA;
857                         }
858                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
859                         if (result == DP_ERROR_IO_ERROR) {
860                                 errorcode = DP_ERROR_IO_ERROR;
861                                 TRACE_ERROR("check ipc sock:%d", client->channel);
862                         }
863                         free(string);
864                         break;
865                 }
866         case DP_PROP_NOTIFICATION_DESCRIPTION:
867                 {
868                         char *string = NULL;
869                         unsigned length = 0;
870                         if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (unsigned char **)&string, &length, &errorcode) < 0) {
871                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
872                                 errorcode = DP_ERROR_NO_DATA;
873                         }
874                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
875                         if (result == DP_ERROR_IO_ERROR) {
876                                 errorcode = DP_ERROR_IO_ERROR;
877                                 TRACE_ERROR("check ipc sock:%d", client->channel);
878                         }
879                         free(string);
880                         break;
881                 }
882         case DP_PROP_NOTIFICATION_RAW: // read type, send raw binary for type
883                 {
884                         int bundle_type = -1;
885                         errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type);
886                         TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type);
887                         char *raw_column = NULL;
888                         if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING)
889                                 raw_column = DP_DB_COL_NOTI_RAW_ONGOING;
890                         else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE)
891                                 raw_column = DP_DB_COL_NOTI_RAW_COMPLETE;
892                         else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED)
893                                 raw_column = DP_DB_COL_NOTI_RAW_FAIL;
894
895                         if (raw_column == NULL) {
896                                 errorcode = DP_ERROR_INVALID_PARAMETER;
897                                 TRACE_ERROR("invalid type %s type:%d", dp_print_property(ipc_info->property), bundle_type);
898                                 if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, ipc_info->property, errorcode, 0) < 0) {
899                                         errorcode = DP_ERROR_IO_ERROR;
900                                         TRACE_ERROR("check ipc sock:%d", client->channel);
901                                 }
902                         }
903                         if (errorcode == DP_ERROR_NONE) {
904                                 unsigned char *raws_buffer = NULL;
905                                 unsigned length = 0;
906                                 // get blob binary from database by raw_column
907                                 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &raws_buffer, &length, &errorcode) < 0) {
908                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
909                                         errorcode = DP_ERROR_NO_DATA;
910                                 }
911                                 int result = __dp_request_feedback_string(client->channel, ipc_info, raws_buffer, (size_t)length, errorcode);
912                                 if (result == DP_ERROR_IO_ERROR) {
913                                         errorcode = DP_ERROR_IO_ERROR;
914                                         TRACE_ERROR("check ipc sock:%d", client->channel);
915                                 }
916                                 free(raws_buffer);
917                         }
918                         break;
919                 }
920         case DP_PROP_HTTP_HEADERS:
921                 {
922                         // 1. response
923                         // 2. send the number of header fields by id
924                         // 3. send response & field string for each fields
925                         int field_count = dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ID, ipc_info->id, &errorcode);
926                         if (field_count < 0) {
927                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
928                                 errorcode = DP_ERROR_DISK_BUSY;
929                                 field_count = 0;
930                         }
931                         int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&field_count, errorcode, sizeof(int));
932                         if (result == DP_ERROR_IO_ERROR) {
933                                 errorcode = DP_ERROR_IO_ERROR;
934                                 TRACE_ERROR("check ipc sock:%d", client->channel);
935                         } else if (field_count > 0) {
936                                 // get fields from database.
937                                 int *ids = (int *)calloc(field_count, sizeof(int));
938                                 if (ids == NULL) {
939                                         TRACE_ERROR("failed to allocate the clients");
940                                         errorcode = DP_ERROR_OUT_OF_MEMORY;
941                                 } else {
942                                         // getting ids of clients
943                                         int i = 0;
944                                         int rows_count = dp_db_get_cond_ids(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, DP_DB_COL_ID, ipc_info->id, ids, field_count, &errorcode);
945                                         for (; i < rows_count; i++) {
946                                                 char *string = NULL;
947                                                 unsigned length = 0;
948                                                 if (dp_db_get_cond_string(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, ids[i], DP_DB_COL_HEADER_FIELD, (unsigned char **)&string, &length, &errorcode) < 0) {
949                                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
950                                                         errorcode = DP_ERROR_NO_DATA;
951                                                 }
952                                                 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
953                                                 free(string);
954                                                 if (result == DP_ERROR_IO_ERROR) {
955                                                         errorcode = DP_ERROR_IO_ERROR;
956                                                         TRACE_ERROR("check ipc sock:%d", client->channel);
957                                                         break;
958                                                 }
959                                         }
960                                 }
961                                 if (ids)
962                                         free(ids);
963                         }
964                         break;
965                 }
966         case DP_PROP_HTTP_HEADER:
967                 {
968                         // 1. read field string
969                         // 2. response with extra size
970                         // 3. send string.
971                         char *header_field = NULL;
972                         char *string = NULL;
973                         unsigned length = 0;
974                         errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
975                         if (errorcode == DP_ERROR_NONE && header_field != NULL) {
976                                 if (dp_db_get_header_value(client->dbhandle, ipc_info->id, header_field, (unsigned char **)&string, &length, &errorcode) < 0) {
977                                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
978                                         errorcode = DP_ERROR_NO_DATA;
979                                 }
980                         } else {
981                                 if (errorcode != DP_ERROR_NONE)
982                                         TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
983                                 if (header_field == NULL) {
984                                         TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
985                                         errorcode = DP_ERROR_INVALID_PARAMETER;
986                                 }
987                         }
988                         int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
989                         if (result == DP_ERROR_IO_ERROR) {
990                                 errorcode = DP_ERROR_IO_ERROR;
991                                 TRACE_ERROR("check ipc sock:%d", client->channel);
992                         }
993                         free(header_field);
994                         free(string);
995                         break;
996                 }
997         default:
998                 errorcode = DP_ERROR_INVALID_PARAMETER;
999                 break;
1000         }
1001         return errorcode;
1002 }
1003
1004 static int __dp_request_set_info(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1005 {
1006         if (slot == NULL) {
1007                 TRACE_ERROR("check slot memory");
1008                 return DP_ERROR_INVALID_PARAMETER;
1009         }
1010         dp_client_fmt *client = &slot->client;
1011         if (client == NULL || ipc_info == NULL) {
1012                 TRACE_ERROR("check client or ipc info.");
1013                 return DP_ERROR_INVALID_PARAMETER;
1014         }
1015
1016         int errorcode = DP_ERROR_NONE;
1017
1018         // if completed or downloading, invalid state.
1019         int download_state = DP_STATE_NONE;
1020         if (requestp != NULL) {
1021                 download_state = requestp->state;
1022         } else {
1023                 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) {
1024                         TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
1025                         errorcode = DP_ERROR_ID_NOT_FOUND;
1026                         // feedback
1027                         if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1028                                                 ipc_info->property, errorcode, 0) < 0) {
1029                                 TRACE_ERROR("check ipc sock:%d", client->channel);
1030                         }
1031                         return errorcode;
1032                 }
1033         }
1034         // should the state be checked ?
1035         TRACE_DEBUG("state:%s set property:%s", dp_print_state(download_state), dp_print_property(ipc_info->property));
1036
1037         switch (ipc_info->property) {
1038         case DP_PROP_URL:
1039                 {
1040                         char *recv_str = NULL;
1041                         errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1042                         if (errorcode == DP_ERROR_NONE) {
1043                                 if (recv_str == NULL) {
1044                                         errorcode = DP_ERROR_INVALID_PARAMETER;
1045                                 } else {
1046                                         // write to database here
1047                                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1048                                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1049                                                 errorcode = DP_ERROR_DISK_BUSY;
1050                                         }
1051                                         free(recv_str);
1052                                 }
1053                         }
1054                         break;
1055                 }
1056         case DP_PROP_DESTINATION:
1057                 {
1058                         char *recv_str = NULL;
1059                         errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1060                         if (errorcode == DP_ERROR_NONE) {
1061                                 if (recv_str == NULL) {
1062                                         errorcode = DP_ERROR_INVALID_PARAMETER;
1063                                 } else {
1064                                         // check here destination is available
1065                                         errorcode = dp_is_valid_dir(slot->credential, recv_str);
1066                                         if (errorcode == DP_ERROR_NONE &&
1067                                                 dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1068                                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1069                                                 errorcode = DP_ERROR_DISK_BUSY;
1070                                         }
1071                                         free(recv_str);
1072                                 }
1073                         }
1074                         break;
1075                 }
1076         case DP_PROP_TEMP_SAVED_PATH:
1077                 {
1078                         char *recv_str = NULL;
1079                         errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1080                         if (errorcode == DP_ERROR_NONE) {
1081                                 if (recv_str == NULL) {
1082                                         errorcode = DP_ERROR_INVALID_PARAMETER;
1083                                 } else {
1084                                         errorcode = dp_is_valid_dir(slot->credential, recv_str);
1085                                         if (errorcode == DP_ERROR_NONE &&
1086                                                 dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_TEMP_FILE_PATH, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1087                                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1088                                                 errorcode = DP_ERROR_DISK_BUSY;
1089                                         }
1090                                         free(recv_str);
1091                                 }
1092                         }
1093                         break;
1094                 }
1095         case DP_PROP_FILENAME:
1096                 {
1097                         char *recv_str = NULL;
1098                         errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1099                         if (errorcode == DP_ERROR_NONE) {
1100                                 if (recv_str == NULL) {
1101                                         errorcode = DP_ERROR_INVALID_PARAMETER;
1102                                 } else {
1103                                         // write to database here
1104                                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1105                                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1106                                                 errorcode = DP_ERROR_DISK_BUSY;
1107                                         }
1108                                         free(recv_str);
1109                                 }
1110                         }
1111                         break;
1112                 }
1113         case DP_PROP_STATE_CALLBACK:
1114                 {
1115                         // check state here
1116                         // DP_ERROR_INVALID_STATE if downloading or finished
1117                         // update database here
1118                         if (requestp != NULL)
1119                                 requestp->state_cb = 1;
1120
1121                         int enable_cb = 1;
1122                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1123                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1124                                 errorcode = DP_ERROR_DISK_BUSY;
1125                         }
1126                         break;
1127                 }
1128         case DP_PROP_PROGRESS_CALLBACK:
1129                 {
1130                         // check state here
1131                         // DP_ERROR_INVALID_STATE if downloading or finished
1132                         // update database here
1133                         if (requestp != NULL)
1134                                 requestp->progress_cb = 1;
1135
1136                         int enable_cb = 1;
1137                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1138                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1139                                 errorcode = DP_ERROR_DISK_BUSY;
1140                         }
1141                         break;
1142                 }
1143         case DP_PROP_AUTO_DOWNLOAD:
1144                 {
1145                         // update autodownload property as 1 in database
1146                         int enable_cb = 1;
1147                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1148                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1149                                 errorcode = DP_ERROR_DISK_BUSY;
1150                         }
1151                         break;
1152                 }
1153         case DP_PROP_NETWORK_TYPE:
1154                 {
1155                         int recv_int = -1;
1156                         errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1157                         if (recv_int <= DP_NETWORK_OFF ||
1158                                         recv_int > DP_NETWORK_ALL) {
1159                                 errorcode = DP_ERROR_INVALID_PARAMETER;
1160                         } else {
1161                                 // update in database
1162                                 if (requestp != NULL) {
1163                                         if (requestp->state == DP_STATE_QUEUED) {
1164                                                 dp_queue_manager_clear_queue(requestp);
1165                                         } else {
1166                                                 requestp->network_type = recv_int;
1167                                                 if (requestp->state == DP_STATE_CONNECTING ||
1168                                                                 requestp->state == DP_STATE_DOWNLOADING) {
1169                                                         // pause & push queue
1170                                                         if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) {
1171                                                                 TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id);
1172                                                         } else {
1173                                                                 requestp->state = DP_STATE_PAUSED;
1174                                                                 requestp->error = DP_ERROR_NONE;
1175                                                                 if (dp_queue_manager_push_queue(slot, requestp) < 0) {
1176                                                                         if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0)
1177                                                                                 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1178                                                                         requestp->state = DP_STATE_FAILED;
1179                                                                         requestp->error = DP_ERROR_QUEUE_FULL;
1180                                                                         errorcode = DP_ERROR_QUEUE_FULL;
1181                                                                 }
1182                                                         }
1183                                                 }
1184                                         }
1185                                 }
1186                                 int enable_cb = recv_int;
1187                                 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1188                                         TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1189                                         errorcode = DP_ERROR_DISK_BUSY;
1190                                 }
1191                         }
1192                         break;
1193                 }
1194         case DP_PROP_NETWORK_BONDING:
1195                 {
1196                         int recv_int = -1;
1197                         errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1198                         if (errorcode == DP_ERROR_NONE) {
1199                                 if (requestp != NULL && requestp->network_type != DP_NETWORK_ALL) {
1200                                         errorcode =  DP_ERROR_INVALID_NETWORK_TYPE;
1201                                         TRACE_ERROR("[ERROR] wrong network type");
1202                                 } else if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, (void *)&recv_int, ipc_info->size, 0, &errorcode) < 0) {
1203                                         TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1204                                         errorcode = DP_ERROR_DISK_BUSY;
1205                                 }
1206                         }
1207                         break;
1208                 }
1209         case DP_PROP_NOTIFICATION_TYPE:
1210                 {
1211                         int recv_int = -1;
1212                         errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1213                         if (recv_int == DP_NOTIFICATION_TYPE_NONE ||
1214                                         recv_int == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
1215                                         recv_int == DP_NOTIFICATION_TYPE_ALL) {
1216                                 // check state request->state == DP_STATE_COMPLETED
1217                                 // DP_ERROR_INVALID_STATE
1218                                 // update notificatio type in database
1219                                 int noti_type = recv_int;
1220                                 if (requestp != NULL) {
1221                                         if (recv_int < requestp->noti_type) {
1222                                                 // if already notification, unregister from notification bar.
1223                                                 if (recv_int == DP_NOTIFICATION_TYPE_NONE) {
1224                                                         if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION) < 0)
1225                                                                 TRACE_ERROR("failed to clear notification %s", dp_print_property(ipc_info->property));
1226                                                 }
1227                                                 if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0)
1228                                                         TRACE_ERROR("failed to clear ongoing %s", dp_print_property(ipc_info->property));
1229                                         }
1230                                         requestp->noti_type = recv_int;
1231                                 }
1232                                 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)&noti_type, ipc_info->size, 0, &errorcode) < 0) {
1233                                         TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1234                                         errorcode = DP_ERROR_DISK_BUSY;
1235                                 }
1236                         } else {
1237                                 errorcode = DP_ERROR_INVALID_PARAMETER;
1238                         }
1239                         break;
1240                 }
1241         case DP_PROP_NOTIFICATION_SUBJECT:
1242                 {
1243                         char *recv_str = NULL;
1244                         errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1245                         if (errorcode == DP_ERROR_NONE) {
1246                                 if (recv_str == NULL) {
1247                                         errorcode = DP_ERROR_INVALID_PARAMETER;
1248                                 } else {
1249                                         // write to database here
1250                                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1251                                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1252                                                 errorcode = DP_ERROR_DISK_BUSY;
1253                                         }
1254                                         free(recv_str);
1255                                 }
1256                         }
1257                         break;
1258                 }
1259         case DP_PROP_NOTIFICATION_DESCRIPTION:
1260                 {
1261                         char *recv_str = NULL;
1262                         errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1263                         if (errorcode == DP_ERROR_NONE) {
1264                                 if (recv_str == NULL) {
1265                                         errorcode = DP_ERROR_INVALID_PARAMETER;
1266                                 } else {
1267                                         // write to database here
1268                                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1269                                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1270                                                 errorcode = DP_ERROR_DISK_BUSY;
1271                                         }
1272                                         free(recv_str);
1273                                 }
1274                         }
1275                         break;
1276                 }
1277         case DP_PROP_NOTIFICATION_RAW: // bundle_type(db column) + bundle_binary
1278                 {
1279                         int bundle_type = -1;
1280                         errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type);
1281                         TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1282                         char *raw_column = NULL;
1283                         if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING)
1284                                 raw_column = DP_DB_COL_NOTI_RAW_ONGOING;
1285                         else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE)
1286                                 raw_column = DP_DB_COL_NOTI_RAW_COMPLETE;
1287                         else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED)
1288                                 raw_column = DP_DB_COL_NOTI_RAW_FAIL;
1289                         else
1290                                 errorcode = DP_ERROR_INVALID_PARAMETER;
1291                         // feedback
1292                         if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1293                                                 ipc_info->property, errorcode, 0) < 0) {
1294                                 TRACE_ERROR("check ipc sock:%d", client->channel);
1295                                 errorcode = DP_ERROR_IO_ERROR;
1296                         }
1297                         if (errorcode == DP_ERROR_NONE) {
1298                                 dp_ipc_fmt *raw_info = dp_ipc_get_fmt(client->channel);
1299                                 if (raw_info == NULL || raw_info->section != ipc_info->section ||
1300                                                 raw_info->property != ipc_info->property ||
1301                                                 (raw_info->id != ipc_info->id)) {
1302                                         TRACE_ERROR("there is a confusion waiting raw binary in %s section", dp_print_property(ipc_info->property));
1303                                         errorcode = DP_ERROR_IO_ERROR;
1304                                 }
1305                                 if (raw_info != NULL && raw_info->size > 0 && raw_info->size < SIZE_MAX) {
1306                                         unsigned char *recv_raws = (unsigned char *)calloc(raw_info->size, sizeof(unsigned char));
1307                                         if (recv_raws == NULL) {
1308                                                 TRACE_ERROR("sock:%d check memory length:%d", client->channel, raw_info->size);
1309                                                 errorcode = DP_ERROR_OUT_OF_MEMORY;
1310                                         } else {
1311                                                 if (dp_ipc_read(client->channel, recv_raws, raw_info->size, __FUNCTION__) <= 0) {
1312                                                         TRACE_ERROR("sock:%d check ipc length:%d", client->channel, raw_info->size);
1313                                                         errorcode = DP_ERROR_IO_ERROR;
1314                                                 } else {
1315                                                         TRACE_DEBUG("sock:%d length:%d raws", client->channel, raw_info->size);
1316                                                         // save to database
1317                                                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, (void *)recv_raws, raw_info->size, 3, &errorcode) < 0) {
1318                                                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1319                                                                 errorcode = DP_ERROR_DISK_BUSY;
1320                                                         }
1321                                                 }
1322                                                 free(recv_raws);
1323                                         }
1324                                 } else {
1325                                         errorcode = DP_ERROR_IO_ERROR;
1326                                 }
1327                                 free(raw_info);
1328                         }
1329                         break;
1330                 }
1331         case DP_PROP_HTTP_HEADER: //  a request can have one or more fields, a fields can have only one value.
1332                 {
1333                         char *header_field = NULL;
1334                         char *header_value = NULL;
1335                         // 1. read field string
1336                         // 2. response after checking sql status
1337                         // 3. read query IPC for checking IPC
1338                         // 4. read value string
1339                         // 5. response
1340                         errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
1341                         if (errorcode == DP_ERROR_NONE && header_field != NULL) {
1342                                 // check sql
1343                                 int check_field = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode);
1344                                 if (check_field < 0) {
1345                                         errorcode = DP_ERROR_DISK_BUSY;
1346                                 } else {
1347                                         errorcode = DP_ERROR_NONE;
1348                                         // feedback
1349                                         if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section,
1350                                                                 ipc_info->property, errorcode, 0) < 0) {
1351                                                 TRACE_ERROR("check ipc sock:%d", client->channel);
1352                                                 errorcode = DP_ERROR_IO_ERROR;
1353                                         } else {
1354                                                 dp_ipc_fmt *header_ipc = dp_ipc_get_fmt(client->channel);
1355                                                 if (header_ipc == NULL || header_ipc->section != ipc_info->section ||
1356                                                                 header_ipc->property != ipc_info->property ||
1357                                                                 (header_ipc->id != ipc_info->id)) {
1358                                                         TRACE_ERROR("there is a confusion during waiting http string in %s section", dp_print_property(ipc_info->property));
1359                                                         errorcode = DP_ERROR_IO_ERROR;
1360                                                 } else {
1361                                                         errorcode = __dp_request_read_string(client->channel, header_ipc, &header_value);
1362                                                         if (errorcode == DP_ERROR_NONE && header_value != NULL) {
1363                                                                 if (check_field == 0) { // insert
1364                                                                         if (dp_db_new_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) {
1365                                                                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1366                                                                                 errorcode = DP_ERROR_DISK_BUSY;
1367                                                                         }
1368                                                                 } else { // update
1369                                                                         if (dp_db_update_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) {
1370                                                                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1371                                                                                 errorcode = DP_ERROR_DISK_BUSY;
1372                                                                         }
1373                                                                 }
1374                                                         } else {
1375                                                                 if (errorcode != DP_ERROR_NONE)
1376                                                                         TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1377                                                                 if (header_value == NULL) {
1378                                                                         TRACE_ERROR("failed to set %s, do you want to run as unset?", dp_print_property(ipc_info->property));
1379                                                                         errorcode = DP_ERROR_INVALID_PARAMETER;
1380                                                                 }
1381                                                         }
1382                                                 }
1383                                                 free(header_ipc);
1384                                         }
1385                                 }
1386                         } else {
1387                                 if (errorcode != DP_ERROR_NONE)
1388                                         TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1389                                 if (header_field == NULL) {
1390                                         TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1391                                         errorcode = DP_ERROR_INVALID_PARAMETER;
1392                                 }
1393                         }
1394                         free(header_field);
1395                         free(header_value);
1396                         break;
1397                 }
1398         default:
1399                 errorcode = DP_ERROR_INVALID_PARAMETER;
1400                 break;
1401         }
1402         // feedback
1403         if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1404                                 ipc_info->property, errorcode, 0) < 0) {
1405                 TRACE_ERROR("check ipc sock:%d", client->channel);
1406         }
1407         return errorcode;
1408 }
1409
1410 static int __dp_request_unset_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1411 {
1412         if (client == NULL || ipc_info == NULL) {
1413                 TRACE_ERROR("check client or ipc info.");
1414                 return DP_ERROR_INVALID_PARAMETER;
1415         }
1416
1417         int errorcode = DP_ERROR_NONE;
1418
1419         switch (ipc_info->property) {
1420         case DP_PROP_URL:
1421                 // it would be run like cancel operation
1422                 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, &errorcode) < 0)
1423                         TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1424                 break;
1425         case DP_PROP_DESTINATION:
1426                 // if downloading, change destination to da_agent
1427                 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, &errorcode) < 0)
1428                         TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1429                 break;
1430         case DP_PROP_FILENAME:
1431                 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, &errorcode) < 0)
1432                         TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1433                 break;
1434         case DP_PROP_STATE_CALLBACK:
1435                 {
1436                         if (requestp != NULL)
1437                                 requestp->state_cb = 0;
1438
1439                         int enable_cb = 0;
1440                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) {
1441                                 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1442                                 errorcode = DP_ERROR_DISK_BUSY;
1443                         }
1444                         break;
1445                 }
1446         case DP_PROP_PROGRESS_CALLBACK:
1447                 {
1448                         if (requestp != NULL)
1449                                 requestp->progress_cb = 0;
1450
1451                         int enable_cb = 0;
1452                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) {
1453                                 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1454                                 errorcode = DP_ERROR_DISK_BUSY;
1455                         }
1456                         break;
1457                 }
1458         case DP_PROP_AUTO_DOWNLOAD:
1459                 {
1460                         // update autodownload property as 0 in database
1461                         int enable_cb = 0;
1462                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, 0, 0, &errorcode) < 0) {
1463                                 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1464                                 errorcode = DP_ERROR_DISK_BUSY;
1465                         }
1466                         break;
1467                 }
1468         case DP_PROP_NETWORK_TYPE:
1469                 {
1470                         // check state here
1471                         // update database here
1472                         if (requestp != NULL)
1473                                 requestp->network_type = DP_NETWORK_OFF;
1474
1475                         int enable_cb = DP_NETWORK_OFF;
1476                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1477                                 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1478                                 errorcode = DP_ERROR_DISK_BUSY;
1479                         }
1480                         break;
1481                 }
1482         case DP_PROP_NOTIFICATION_TYPE:
1483                 {
1484                         int noti_type = DP_NOTIFICATION_TYPE_NONE;
1485                         if (requestp != NULL)
1486                                 requestp->noti_type = noti_type;
1487
1488                         if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)&noti_type, ipc_info->size, 0, &errorcode) < 0) {
1489                                 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1490                                 errorcode = DP_ERROR_DISK_BUSY;
1491                         }
1492                         break;
1493                 }
1494         case DP_PROP_NOTIFICATION_SUBJECT:
1495                 {
1496                         if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, &errorcode) < 0)
1497                                 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1498                         break;
1499                 }
1500         case DP_PROP_NOTIFICATION_DESCRIPTION:
1501                 {
1502                         if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, &errorcode) < 0)
1503                                 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1504                         break;
1505                 }
1506         case DP_PROP_NOTIFICATION_RAW:
1507                 {
1508                         int bundle_type = -1;
1509                         errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type);
1510                         TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1511                         char *raw_column = NULL;
1512                         if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING)
1513                                 raw_column = DP_DB_COL_NOTI_RAW_ONGOING;
1514                         else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE)
1515                                 raw_column = DP_DB_COL_NOTI_RAW_COMPLETE;
1516                         else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED)
1517                                 raw_column = DP_DB_COL_NOTI_RAW_FAIL;
1518                         if (raw_column != NULL) {
1519                                 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &errorcode) < 0)
1520                                         TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1521                         } else {
1522                                 TRACE_ERROR("invalid param set: %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1523                                 errorcode = DP_ERROR_INVALID_PARAMETER;
1524                         }
1525                         break;
1526                 }
1527         case DP_PROP_HTTP_HEADER: // unset value by field
1528                 {
1529                         char *header_field = NULL;
1530                         errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
1531                         if (errorcode == DP_ERROR_NONE && header_field != NULL) {
1532                                 int is_present = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode);
1533                                 if (is_present < 0)
1534                                         errorcode = DP_ERROR_DISK_BUSY;
1535                                 else if (is_present == 0)
1536                                         errorcode = DP_ERROR_FIELD_NOT_FOUND;
1537                                 else if (dp_db_cond_delete(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, header_field, 2, &errorcode) < 0) {
1538                                         TRACE_ERROR("failed to unset %s for %s", dp_print_property(ipc_info->property), header_field);
1539                                         errorcode = DP_ERROR_DISK_BUSY;
1540                                 }
1541                         } else {
1542                                 if (errorcode != DP_ERROR_NONE)
1543                                         TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1544                                 if (header_field == NULL) {
1545                                         TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1546                                         errorcode = DP_ERROR_INVALID_PARAMETER;
1547                                 }
1548                         }
1549                         free(header_field);
1550                         break;
1551                 }
1552         default:
1553                 errorcode = DP_ERROR_INVALID_PARAMETER;
1554                 break;
1555         }
1556         // feedback
1557         if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_UNSET,
1558                                 ipc_info->property, errorcode, 0) < 0) {
1559                 TRACE_ERROR("check ipc sock:%d", client->channel);
1560         }
1561         return errorcode;
1562 }
1563
1564 static int __dp_call_cancel_agent(dp_request_fmt *request)
1565 {
1566         int ret = -1;
1567         if (request != NULL) {
1568                 if (request->agent_id >= 0) {
1569                         TRACE_INFO("cancel download(%d) id: %d state:%s", request->agent_id,
1570                                         request->id, dp_print_state(request->state));
1571                         if (dp_cancel_agent_download_without_update(request->agent_id) == 0)
1572                                 ret = 0;
1573                 } else {
1574                         TRACE_ERROR("invalid agent-id:%d id:%d", request->agent_id,     request->id);
1575                 }
1576         }
1577         return ret;
1578 }
1579
1580 static int __dp_request_controls(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1581 {
1582         if (slot == NULL) {
1583                 TRACE_ERROR("check slot memory");
1584                 return DP_ERROR_INVALID_PARAMETER;
1585         }
1586         dp_client_fmt *client = &slot->client;
1587         if (client == NULL || ipc_info == NULL) {
1588                 TRACE_ERROR("check client or ipc info.");
1589                 return DP_ERROR_INVALID_PARAMETER;
1590         }
1591
1592         int errorcode = DP_ERROR_NONE;
1593
1594         if (ipc_info->property == DP_PROP_CREATE) {
1595                 // check packets again
1596                 if (ipc_info->size != 0 || ipc_info->id != -1)
1597                         errorcode = DP_ERROR_IO_ERROR;
1598                 else
1599                         errorcode = __dp_request_create(client, ipc_info);
1600         } else {
1601
1602                 // get now state.
1603                 int download_state = DP_STATE_NONE;
1604                 if (requestp != NULL) {
1605                         download_state = requestp->state;
1606                 } else {
1607                         if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) {
1608                                 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
1609                                 errorcode = DP_ERROR_ID_NOT_FOUND;
1610                                 // feedback
1611                                 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1612                                                         ipc_info->property, errorcode, 0) < 0) {
1613                                         TRACE_ERROR("check ipc sock:%d", client->channel);
1614                                 }
1615                                 return errorcode;
1616                         }
1617                 }
1618                 TRACE_DEBUG("id:%d state:%s set property:%s", ipc_info->id, dp_print_state(download_state), dp_print_property(ipc_info->property));
1619
1620                 if (ipc_info->property == DP_PROP_START) {
1621
1622                         if (download_state == DP_STATE_COMPLETED ||
1623                                         download_state == DP_STATE_DOWNLOADING) {
1624                                 errorcode = DP_ERROR_INVALID_STATE;
1625                         } else {
1626
1627                                 if (requestp == NULL) { // load from databse
1628                                         // check state
1629                                         // load and add new request to client->requests.
1630                                 }
1631                                 if (requestp == NULL) {
1632                                         TRACE_ERROR("failed to load id:%d from database sock:%d", ipc_info->id, client->channel);
1633                                         errorcode = DP_ERROR_DISK_BUSY;
1634                                 }
1635                                 if (errorcode == DP_ERROR_NONE) {
1636                                         // update database
1637                                         if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) {
1638                                                 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1639                                                 errorcode = DP_ERROR_DISK_BUSY;
1640                                         } else {
1641                                                 requestp->state = DP_STATE_QUEUED;
1642                                                 requestp->error = DP_ERROR_NONE;
1643                                                 // if it's the first request for this client-> push a request at the head of queue.
1644                                                 // check count queued, connecting.downloading in requets of client
1645                                                 // else push at the tail of queue.
1646                                                 // push to queue
1647                                                 if (dp_queue_manager_push_queue(slot, requestp) < 0) {
1648                                                         if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0)
1649                                                                 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1650                                                         requestp->state = DP_STATE_FAILED;
1651                                                         requestp->error = DP_ERROR_QUEUE_FULL;
1652                                                         errorcode = DP_ERROR_QUEUE_FULL;
1653                                                 } else { // push ok
1654                                                         dp_queue_manager_wake_up();
1655                                                         // notification
1656                                                         if (requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
1657                                                                 if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0)
1658                                                                         TRACE_ERROR("failed to register notification for id:%d", ipc_info->id);
1659                                                         }
1660                                                 }
1661                                         }
1662                                 }
1663                                 TRACE_DEBUG("id:%d check start error:%s", ipc_info->id, dp_print_errorcode(errorcode));
1664                         }
1665
1666                 } else if (ipc_info->property == DP_PROP_PAUSE) {
1667
1668                         if (download_state > DP_STATE_DOWNLOADING) {
1669                                 errorcode = DP_ERROR_INVALID_STATE;
1670                         } else { // change state regardless it's on memory or not.
1671                                 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_PAUSED, DP_ERROR_NONE, &errorcode) < 0) {
1672                                         TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1673                                         errorcode = DP_ERROR_DISK_BUSY;
1674                                 } else {
1675                                         // call da_pause API
1676                                         if (requestp != NULL) {
1677                                                 // pop from queue. if state is queued.
1678                                                 if (requestp->state == DP_STATE_QUEUED) {
1679                                                         dp_queue_manager_clear_queue(requestp);
1680                                                 } else if (requestp->state == DP_STATE_CONNECTING ||
1681                                                                 requestp->state == DP_STATE_DOWNLOADING) {
1682                                                         if (dp_pause_agent_download_without_update(requestp->agent_id) < 0)
1683                                                                 TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id);
1684                                                 }
1685                                                 requestp->state = DP_STATE_PAUSED;
1686                                                 requestp->error = DP_ERROR_NONE;
1687                                         }
1688                                 }
1689                         }
1690
1691                 } else if (ipc_info->property == DP_PROP_CANCEL) {
1692
1693                         if (download_state > DP_STATE_COMPLETED) {
1694                                 errorcode = DP_ERROR_INVALID_STATE;
1695                         } else { // change state regardless it's on memory or not.
1696                                 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) {
1697                                         TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1698                                         errorcode = DP_ERROR_DISK_BUSY;
1699                                 } else {
1700                                         // call da_cancel API
1701                                         if (requestp != NULL) {
1702                                                 // pop from queue. if state is queued.
1703                                                 if (requestp->state == DP_STATE_QUEUED) {
1704                                                         dp_queue_manager_clear_queue(requestp);
1705                                                 } else if (requestp->state == DP_STATE_CONNECTING ||
1706                                                                 requestp->state == DP_STATE_DOWNLOADING) {
1707                                                         if (__dp_call_cancel_agent(requestp) < 0)
1708                                                                 TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id);
1709                                                 }
1710                                                 requestp->agent_id = -1;
1711                                                 requestp->state = DP_STATE_CANCELED;
1712                                                 requestp->error = DP_ERROR_NONE;
1713                                                 if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
1714                                                                 requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
1715                                                         if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0)
1716                                                                 TRACE_ERROR("failed to register notification for id:%d", ipc_info->id);
1717                                                 }
1718                                         }
1719                                 }
1720                         }
1721
1722                 } else if (ipc_info->property == DP_PROP_DESTROY) {
1723
1724                         // check state
1725                         // pop from queue. if state is queued.
1726                         if (requestp != NULL) {
1727                                 if (requestp->state == DP_STATE_QUEUED)
1728                                         dp_queue_manager_clear_queue(requestp);
1729                                 if (requestp->state == DP_STATE_CONNECTING ||
1730                                                 requestp->state == DP_STATE_DOWNLOADING) {
1731                                         // update state property database;
1732                                         if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) {
1733                                                 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1734                                         } else {
1735                                                 // call da_cancel API
1736                                                 if (__dp_call_cancel_agent(requestp) < 0)
1737                                                         TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id);
1738                                         }
1739                                         requestp->state = DP_STATE_CANCELED;
1740                                 }
1741                                 if (requestp->state == DP_STATE_QUEUED || requestp->state == DP_STATE_CANCELED) {
1742
1743                                         if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
1744                                                         requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
1745                                                 if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0)
1746                                                         TRACE_ERROR("failed to register notification for id:%d", ipc_info->id);
1747                                         }
1748                                 }
1749                                 requestp->agent_id = -1;
1750                         }
1751                         errorcode = dp_request_destroy(client, ipc_info, requestp);
1752
1753                 } else {
1754                         errorcode = DP_ERROR_INVALID_PARAMETER;
1755                         TRACE_ERROR("invalid param - id:%d set property:%s", ipc_info->id, dp_print_property(ipc_info->property));
1756                 }
1757         }
1758
1759         // feedback
1760         if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_CONTROL,
1761                                 ipc_info->property, errorcode, 0) < 0) {
1762                 TRACE_ERROR("check ipc sock:%d", client->channel);
1763         }
1764
1765         // workaround. client still request the feedback by cancelation
1766         if (ipc_info->property == DP_PROP_CANCEL ||
1767                         ipc_info->property == DP_PROP_PAUSE) {
1768                 if (requestp != NULL && requestp->state_cb == 1) {
1769                         if (slot->client.notify < 0 ||
1770                                         dp_notify_feedback(slot->client.notify, slot, ipc_info->id, requestp->state, errorcode, 0) < 0) {
1771                                 TRACE_ERROR("id:%d disable state callback by IO_ERROR", ipc_info->id);
1772                                 requestp->state_cb = 0;
1773                         }
1774                 }
1775         }
1776
1777         return errorcode;
1778 }
1779
1780 static int __dp_client_requests(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info)
1781 {
1782         if (slot == NULL) {
1783                 TRACE_ERROR("check slot memory");
1784                 return DP_ERROR_INVALID_PARAMETER;
1785         }
1786         dp_client_fmt *client = &slot->client;
1787         if (client == NULL || ipc_info == NULL) {
1788                 TRACE_ERROR("check client or ipc info.");
1789                 return DP_ERROR_INVALID_PARAMETER;
1790         }
1791
1792         int errorcode = DP_ERROR_NONE;
1793
1794         // check id except create command  /////////// DP_ERROR_ID_NOT_FOUND
1795         dp_request_fmt *requestp = NULL;
1796         if (ipc_info->section != DP_SEC_CONTROL ||
1797                         ipc_info->property != DP_PROP_CREATE) {
1798                 // check on requests
1799                 int i = 0;
1800                 requestp = client->requests;
1801                 errorcode = DP_ERROR_ID_NOT_FOUND;
1802                 for (; i < MAX_DOWNLOAD_HANDLE; i++) {
1803                         if (requestp == NULL)
1804                                 break;
1805                         //TRACE_DEBUG("link %d info: id:%d access-time:%d", i, requestp->id, requestp->access_time);
1806                         if (requestp->id == ipc_info->id) {
1807                                 errorcode = DP_ERROR_NONE;
1808                                 break;
1809                         }
1810                         requestp = requestp->next;
1811                 }
1812                 if (errorcode == DP_ERROR_ID_NOT_FOUND) {
1813                         // check in database
1814                         if (dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_LOGGING, DP_DB_COL_ID, ipc_info->id, &errorcode) > 0) {
1815                                 //TRACE_DEBUG("found %d from database", ipc_info->id);
1816                                 errorcode = DP_ERROR_NONE;
1817                         }
1818                 }
1819         }
1820
1821         if (errorcode != DP_ERROR_NONE) { // prechecking
1822                 TRACE_ERROR("precheck errorcode:%s sock:%d id:%d section:%s property:%s",
1823                                 dp_print_errorcode(errorcode),
1824                                 client->channel, ipc_info->id,
1825                                 dp_print_section(ipc_info->section),
1826                                 dp_print_property(ipc_info->property));
1827
1828                 // clear followed packets.
1829                 if (ipc_info->size > 0) {
1830                         char garbage[ipc_info->size];
1831                         if (read(client->channel, &garbage, ipc_info->size) == 0) {
1832                                 TRACE_ERROR("sock:%d closed peer", client->channel);
1833                                 errorcode = DP_ERROR_IO_ERROR;
1834                         }
1835                 }
1836
1837                 if (dp_ipc_query(client->channel, ipc_info->id,
1838                                         ipc_info->section, ipc_info->property, errorcode, 0) < 0) {
1839                         TRACE_ERROR("check ipc sock:%d", client->channel);
1840                         errorcode = DP_ERROR_IO_ERROR;
1841                 }
1842                 return errorcode;
1843         }
1844
1845         switch (ipc_info->section) {
1846         case DP_SEC_CONTROL:
1847                 errorcode = __dp_request_controls(slot, ipc_info, requestp);
1848                 break;
1849         case DP_SEC_GET:
1850                 errorcode = __dp_request_get_info(client, ipc_info, requestp);
1851                 break;
1852         case DP_SEC_SET:
1853                 errorcode = __dp_request_set_info(slot, ipc_info, requestp);
1854                 break;
1855         case DP_SEC_UNSET:
1856                 errorcode = __dp_request_unset_info(client, ipc_info, requestp);
1857                 break;
1858         default:
1859                 errorcode = DP_ERROR_INVALID_PARAMETER;
1860                 break;
1861         }
1862         return errorcode;
1863 }
1864
1865 static void __dp_client_stop_all_requests(dp_client_slots_fmt *slot)
1866 {
1867         unsigned push_count = 0;
1868         int errorcode = DP_ERROR_NONE;
1869         int i = 0;
1870         dp_request_fmt *tailp = slot->client.requests;
1871         for (; tailp != NULL; i++) {
1872                 TRACE_DEBUG("request %d stop id:%d state:%s", i, tailp->id, dp_print_state(tailp->state));
1873                 int state = tailp->state;
1874                 if (state == DP_STATE_CONNECTING) {
1875                         if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0)
1876                                 TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id);
1877                 } else if (state == DP_STATE_DOWNLOADING) {
1878                         if (dp_pause_agent_download(tailp->agent_id) < 0)
1879                                 TRACE_ERROR("failed to pause download(%d) id:%d", tailp->agent_id, tailp->id);
1880                 }
1881                 if (state == DP_STATE_DOWNLOADING || state == DP_STATE_CONNECTING) {
1882                         tailp->state = DP_STATE_QUEUED;
1883                         // This is error code for checking the reason when changing ip configuration process
1884                         tailp->error = DP_ERROR_IO_EAGAIN;
1885                         // push to queue now
1886                         // in da callback, check DP_ERROR_IO_EAGAIN, then ignore.
1887                         if (dp_db_update_logging(slot->client.dbhandle, tailp->id, tailp->state, DP_ERROR_NONE, &errorcode) < 0)
1888                                 TRACE_ERROR("update log sock:%d download-id:%d", slot->client.channel, tailp->id);
1889                         if (dp_queue_manager_push_queue(slot, tailp) < 0) {
1890                                 TRACE_ERROR("Fail to push queueg sock:%d download-id:%d", slot->client.channel, tailp->id);
1891                                 // FIXME later : error case. How can handle this item?
1892                         } else {
1893                                 push_count++;
1894                         }
1895                 }
1896                 tailp = tailp->next;
1897         }
1898         if (push_count > 0)
1899                 dp_queue_manager_wake_up();
1900 }
1901
1902 void dp_client_sig_handler(int signo)
1903 {
1904         TRACE_INFO("thread:%lu signal:%d", pthread_self(), signo);
1905 }
1906
1907 void *dp_client_request_thread(void *arg)
1908 {
1909         dp_client_slots_fmt *slot = (dp_client_slots_fmt *)arg;
1910         if (slot == NULL) {
1911                 TRACE_ERROR("slot null, can not launch the thread for client");
1912                 return 0;
1913         }
1914
1915         // wait detaching thread
1916         CLIENT_MUTEX_LOCK(&slot->mutex);
1917
1918         TRACE_INFO("slot %p thread:%lu", slot, slot->thread);
1919
1920         struct sigaction act = {{0},};
1921         sigset_t newmask;
1922         sigemptyset(&newmask);
1923         sigaddset(&newmask, SIGUSR1);
1924         act.sa_handler = dp_client_sig_handler;
1925         sigaction(SIGUSR1, &act, NULL);
1926
1927         fd_set imask, emask;
1928         int errorcode = DP_ERROR_NONE;
1929         dp_client_fmt *client = &slot->client;
1930         int client_sock = client->channel;
1931         struct timeval timeout; // for timeout of select
1932
1933         CLIENT_MUTEX_UNLOCK(&slot->mutex);
1934
1935         pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
1936
1937         while (slot != NULL && client_sock >= 0 &&
1938                         client_sock == slot->client.channel) {
1939
1940                 memset(&timeout, 0x00, sizeof(struct timeval));
1941                 timeout.tv_sec = DP_CARE_CLIENT_REQUEST_INTERVAL;
1942                 FD_ZERO(&imask);
1943                 FD_ZERO(&emask);
1944                 FD_SET(client_sock, &imask);
1945                 FD_SET(client_sock, &emask);
1946                 if (select(client_sock + 1, &imask, 0, &emask, &timeout) < 0) {
1947                         if (slot != NULL && slot->client.channel >= 0) {
1948                                 TRACE_INFO("broadcast by client-manager");
1949                                 CLIENT_MUTEX_LOCK(&slot->mutex);
1950                                 // check all requests
1951                                 __dp_client_stop_all_requests(slot);
1952                                 CLIENT_MUTEX_UNLOCK(&slot->mutex);
1953                                 continue;
1954                         } else {
1955                                 TRACE_ERROR("interrupted by client-manager sock:%d", client_sock);
1956                                 break;
1957                         }
1958                 }
1959                 if (FD_ISSET(client_sock, &imask) > 0) {
1960
1961                         CLIENT_MUTEX_LOCK(&slot->mutex);
1962
1963                         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1964                         client->access_time = (int)time(NULL);
1965
1966                         errorcode = DP_ERROR_NONE;
1967
1968                         // read ipc_fmt first. below func will deal followed packets
1969                         dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(client_sock);
1970                         if (ipc_info == NULL) {
1971                                 TRACE_ERROR("sock:%d maybe closed", client_sock);
1972                                 errorcode = DP_ERROR_IO_ERROR;
1973                         } else {
1974                                 TRACE_DEBUG("sock:%d id:%d section:%s property:%s errorcode:%s size:%d",
1975                                                 client_sock, ipc_info->id,
1976                                                 dp_print_section(ipc_info->section),
1977                                                 dp_print_property(ipc_info->property),
1978                                                 dp_print_errorcode(ipc_info->errorcode),
1979                                                 ipc_info->size);
1980
1981                                 if (client->dbhandle == 0 || dp_db_check_connection(client->dbhandle) < 0) {
1982                                         if (dp_db_open_client(&client->dbhandle, slot->pkgname, &errorcode) < 0) {
1983                                                 TRACE_ERROR("failed to open database for sock:%d errorcode:%s", client_sock, dp_print_errorcode(errorcode));
1984                                                 if (dp_ipc_query(client->channel, ipc_info->id,
1985                                                                         ipc_info->section, ipc_info->property, errorcode, 0) < 0) {
1986                                                         TRACE_ERROR("check ipc sock:%d", client->channel);
1987                                                 }
1988                                         }
1989                                 }
1990
1991                                 if (errorcode == DP_ERROR_NONE) {
1992                                         // JOB
1993                                         errorcode = __dp_client_requests(slot, ipc_info);
1994                                 }
1995
1996                         }
1997                         free(ipc_info);
1998
1999                         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
2000                         CLIENT_MUTEX_UNLOCK(&slot->mutex);
2001
2002                         if (errorcode == DP_ERROR_IO_ERROR ||
2003                                         errorcode == DP_ERROR_OUT_OF_MEMORY ||
2004                                         errorcode == DP_ERROR_INVALID_PARAMETER) {
2005                                 TRACE_ERROR("disconnect client errorcode:%s sock:%d",
2006                                                 dp_print_errorcode(errorcode), client_sock);
2007                                 break;
2008                         }
2009
2010                 } else if (FD_ISSET(client_sock, &emask) > 0) {
2011                         TRACE_ERROR("[EXCEPTION]");
2012                         break;
2013                 } else {
2014
2015                         // timeout
2016                         if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) == 0) {
2017                                 // 1. clear zombie requests. clean requests finished. paused or ready for long time
2018                                 dp_client_clear_requests(slot);
2019
2020                                 if (client->dbhandle != 0) {
2021                                         int sql_errorcode = DP_ERROR_NONE;
2022                                         // 2. maintain only 1000 rows for each client
2023                                         if (dp_db_limit_rows(client->dbhandle, DP_TABLE_LOGGING, DP_LOG_DB_LIMIT_ROWS, &sql_errorcode) < 0)
2024                                                 TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode));
2025                                         // 3. maintain for 48 hours
2026                                         if (dp_db_limit_time(client->dbhandle, DP_TABLE_LOGGING, DP_CARE_CLIENT_INFO_PERIOD, &sql_errorcode) < 0)
2027                                                 TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode));
2028                                 }
2029                                 // 4. if no requests, exit by itself.
2030                                 if (slot->client.requests == NULL) {
2031                                         TRACE_DEBUG("no requests");
2032                                         CLIENT_MUTEX_UNLOCK(&slot->mutex);
2033                                         break;
2034                                 }
2035                                 CLIENT_MUTEX_UNLOCK(&slot->mutex);
2036                         }
2037                 }
2038         }
2039
2040         FD_CLR(client_sock, &imask);
2041         FD_CLR(client_sock, &emask);
2042
2043         // if no requests, clear slot after disconnect with client.
2044         CLIENT_MUTEX_LOCK(&slot->mutex);
2045
2046         TRACE_INFO("thread done slot %p thread:%lu", slot, slot->thread);
2047
2048         slot->thread = 0;// to prevent kill thread twice
2049
2050         int i = 0;
2051         dp_request_fmt *tailp = slot->client.requests;
2052         dp_request_fmt *prevp = NULL;
2053         for (; tailp != NULL; i++) {
2054                 if (tailp->state != DP_STATE_QUEUED &&
2055                                 tailp->state != DP_STATE_CONNECTING &&
2056                                 tailp->state != DP_STATE_DOWNLOADING) {
2057                         dp_request_fmt *removep = tailp;
2058                         if (prevp == NULL) // first request.
2059                                 client->requests = tailp->next;
2060                         else
2061                                 prevp->next = tailp->next;
2062                         tailp = tailp->next;
2063                         TRACE_DEBUG("request %d remove: id:%d state:%s", i, removep->id, dp_print_state(removep->state));
2064                         dp_request_free(removep);
2065                         continue;
2066                 }
2067                 TRACE_DEBUG("request %d remain: id:%d state:%s", i, tailp->id, dp_print_state(tailp->state));
2068                 prevp = tailp;
2069                 tailp = tailp->next;
2070
2071         }
2072         // if no requests after clear finished requests.
2073         if (slot->client.requests == NULL) {
2074                 dp_client_slot_free(slot);
2075         } else {
2076                 if (slot->client.notify >= 0)
2077                         close(slot->client.notify);
2078                 dp_notify_deinit(slot->credential.pid);
2079                 slot->client.notify = -1;
2080                 if (slot->client.channel > 0)
2081                         close(slot->client.channel);
2082                 slot->client.channel = -1;
2083         }
2084         TRACE_INFO("thread done slot %p thread:%lu sock:%d", slot, slot->thread, client_sock);
2085         CLIENT_MUTEX_UNLOCK(&slot->mutex);
2086         return 0;
2087 }
2088