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