2 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <sys/types.h>
24 #include <download-provider-log.h>
25 #include <download-provider-config.h>
26 #include <download-provider-ipc.h>
27 #include <download-provider-network.h>
28 #include <download-provider-client.h>
29 #include <download-provider-pthread.h>
30 #include <download-provider-notify.h>
31 #include <download-provider-notification-manager.h>
32 #include <download-provider-queue-manager.h>
33 #include <download-provider-client-manager.h>
34 #include <download-provider-db-defs.h>
35 #include <download-provider-db.h>
36 #include <download-provider-plugin-download-agent.h>
37 #include <download-provider-security.h>
40 #define SIZE_MAX ((size_t) - 1)
43 static const char *dp_db_column[] = {
44 [DP_PROP_NONE] = NULL,
45 [DP_PROP_URL] = DP_DB_COL_URL,
46 [DP_PROP_PROXY] = DP_DB_COL_PROXY,
47 [DP_PROP_DESTINATION] = DP_DB_COL_DESTINATION,
48 [DP_PROP_FILENAME] = DP_DB_COL_FILENAME,
49 [DP_PROP_STATE_CALLBACK] = DP_DB_COL_STATE_EVENT,
50 [DP_PROP_PROGRESS_CALLBACK] = DP_DB_COL_PROGRESS_EVENT,
51 [DP_PROP_AUTO_DOWNLOAD] = DP_DB_COL_AUTO_DOWNLOAD,
52 [DP_PROP_NETWORK_TYPE] = DP_DB_COL_NETWORK_TYPE,
53 [DP_PROP_NETWORK_BONDING] = DP_DB_COL_NETWORK_BONDING,
54 [DP_PROP_SAVED_PATH] = DP_DB_COL_SAVED_PATH,
55 [DP_PROP_TEMP_SAVED_PATH] = DP_DB_COL_TMP_SAVED_PATH,
56 [DP_PROP_MIME_TYPE] = DP_DB_COL_MIMETYPE,
57 [DP_PROP_RECEIVED_SIZE] = NULL,
58 [DP_PROP_TOTAL_FILE_SIZE] = DP_DB_COL_CONTENT_SIZE,
59 [DP_PROP_CONTENT_NAME] = DP_DB_COL_CONTENT_NAME,
60 [DP_PROP_HTTP_STATUS] = DP_DB_COL_HTTP_STATUS,
61 [DP_PROP_ETAG] = DP_DB_COL_ETAG,
62 [DP_PROP_STATE] = DP_DB_COL_STATE,
63 [DP_PROP_ERROR] = DP_DB_COL_ERRORCODE,
64 [DP_PROP_HTTP_HEADERS] = NULL,
65 [DP_PROP_HTTP_HEADER] = NULL,
66 [DP_PROP_NOTIFICATION_RAW] = NULL,
67 [DP_PROP_NOTIFICATION_SUBJECT] = DP_DB_COL_NOTI_SUBJECT,
68 [DP_PROP_NOTIFICATION_DESCRIPTION] = DP_DB_COL_NOTI_DESCRIPTION,
69 [DP_PROP_NOTIFICATION_TYPE] = DP_DB_COL_NOTI_TYPE,
70 [DP_PROP_CREATE] = NULL,
71 [DP_PROP_START] = NULL,
72 [DP_PROP_PAUSE] = NULL,
73 [DP_PROP_CANCEL] = NULL,
74 [DP_PROP_DESTROY] = NULL,
77 char *dp_print_state(int state)
86 case DP_STATE_CONNECTING:
88 case DP_STATE_DOWNLOADING:
92 case DP_STATE_COMPLETED:
94 case DP_STATE_CANCELED:
104 char *dp_print_errorcode(int errorcode)
109 case DP_ERROR_INVALID_PARAMETER:
110 return "INVALID_PARAMETER";
111 case DP_ERROR_OUT_OF_MEMORY:
112 return "OUT_OF_MEMORY";
113 case DP_ERROR_IO_ERROR:
115 case DP_ERROR_NETWORK_UNREACHABLE:
116 return "NETWORK_UNREACHABLE";
117 case DP_ERROR_CONNECTION_TIMED_OUT:
118 return "CONNECTION_TIMED_OUT";
119 case DP_ERROR_NO_SPACE:
121 case DP_ERROR_FIELD_NOT_FOUND:
122 return "FIELD_NOT_FOUND";
123 case DP_ERROR_INVALID_STATE:
124 return "INVALID_STATE";
125 case DP_ERROR_CONNECTION_FAILED:
126 return "CONNECTION_FAILED";
127 case DP_ERROR_INVALID_URL:
128 return "INVALID_URL";
129 case DP_ERROR_INVALID_DESTINATION:
130 return "INVALID_DESTINATION";
131 case DP_ERROR_QUEUE_FULL:
133 case DP_ERROR_ALREADY_COMPLETED:
134 return "ALREADY_COMPLETED";
135 case DP_ERROR_FILE_ALREADY_EXISTS:
136 return "FILE_ALREADY_EXISTS";
137 case DP_ERROR_TOO_MANY_DOWNLOADS:
138 return "TOO_MANY_DOWNLOADS";
139 case DP_ERROR_NO_DATA:
141 case DP_ERROR_UNHANDLED_HTTP_CODE:
142 return "UNHANDLED_HTTP_CODE";
143 case DP_ERROR_CANNOT_RESUME:
144 return "CANNOT_RESUME";
145 case DP_ERROR_PERMISSION_DENIED:
146 return "PERMISSION_DENIED";
147 case DP_ERROR_RESPONSE_TIMEOUT:
148 return "RESPONSE_TIMEOUT";
149 case DP_ERROR_REQUEST_TIMEOUT:
150 return "REQUEST_TIMEOUT";
151 case DP_ERROR_SYSTEM_DOWN:
152 return "SYSTEM_DOWN";
153 case DP_ERROR_CLIENT_DOWN:
154 return "CLIENT_DOWN";
155 case DP_ERROR_DISK_BUSY:
157 case DP_ERROR_ID_NOT_FOUND:
158 return "ID_NOT_FOUND";
165 char *dp_print_section(short section)
188 char *dp_print_property(unsigned property)
201 case DP_PROP_DESTROY:
207 case DP_PROP_DESTINATION:
208 return "DESTINATION";
209 case DP_PROP_FILENAME:
211 case DP_PROP_STATE_CALLBACK:
213 case DP_PROP_PROGRESS_CALLBACK:
214 return "PROGRESS_CB";
215 case DP_PROP_AUTO_DOWNLOAD:
216 return "AUTO_DOWNLOAD";
217 case DP_PROP_NETWORK_TYPE:
218 return "NETWORK_TYPE";
219 case DP_PROP_NETWORK_BONDING:
220 return "NETWORK_BONDING";
221 case DP_PROP_SAVED_PATH:
223 case DP_PROP_TEMP_SAVED_PATH:
224 return "TEMP_SAVED_PATH";
225 case DP_PROP_MIME_TYPE:
227 case DP_PROP_RECEIVED_SIZE:
228 return "RECEIVED_SIZE";
229 case DP_PROP_TOTAL_FILE_SIZE:
230 return "TOTAL_FILE_SIZE";
231 case DP_PROP_CONTENT_NAME:
232 return "CONTENT_NAME";
233 case DP_PROP_HTTP_STATUS:
234 return "HTTP_STATUS";
241 case DP_PROP_NOTIFICATION_RAW:
242 return "NOTIFICATION_RAW";
243 case DP_PROP_NOTIFICATION_SUBJECT:
244 return "NOTIFICATION_SUBJECT";
245 case DP_PROP_NOTIFICATION_DESCRIPTION:
246 return "NOTIFICATION_DESCRIPTION";
247 case DP_PROP_NOTIFICATION_TYPE:
248 return "NOTIFICATION_TYPE";
249 case DP_PROP_HTTP_HEADERS:
250 return "HTTP_HEADERS";
251 case DP_PROP_HTTP_HEADER:
252 return "HTTP_HEADER";
253 case DP_PROP_VERIFY_HOST:
254 return "VERIFY_HOST";
261 static const char *__dp_get_db_table_name(unsigned property)
266 case DP_PROP_DESTINATION:
267 case DP_PROP_FILENAME:
268 case DP_PROP_STATE_CALLBACK:
269 case DP_PROP_PROGRESS_CALLBACK:
270 case DP_PROP_NETWORK_TYPE:
271 case DP_PROP_NETWORK_BONDING:
272 return DP_TABLE_REQUEST;
273 case DP_PROP_AUTO_DOWNLOAD:
276 return DP_TABLE_LOGGING;
277 case DP_PROP_SAVED_PATH:
278 case DP_PROP_TEMP_SAVED_PATH:
279 case DP_PROP_MIME_TYPE:
280 case DP_PROP_CONTENT_NAME:
282 case DP_PROP_TOTAL_FILE_SIZE:
283 case DP_PROP_HTTP_STATUS:
284 return DP_TABLE_DOWNLOAD;
285 case DP_PROP_NOTIFICATION_RAW:
286 case DP_PROP_NOTIFICATION_SUBJECT:
287 case DP_PROP_NOTIFICATION_DESCRIPTION:
288 case DP_PROP_NOTIFICATION_TYPE:
289 return DP_TABLE_NOTIFICATION;
290 case DP_PROP_HTTP_HEADERS:
291 case DP_PROP_HTTP_HEADER:
292 return DP_TABLE_HEADERS;
293 case DP_PROP_RECEIVED_SIZE:
299 case DP_PROP_DESTROY:
306 static int __dp_get_download_id(dp_client_fmt *client)
308 int download_id = -1;
309 int check_duplicate = 1;
311 int errorcode = DP_ERROR_NONE;
314 if (dp_db_get_max_download_id(client->dbhandle,
315 DP_TABLE_LOGGING, &download_id, &errorcode) < 0) {
316 TRACE_ERROR("ERROR [%d]", errorcode);
317 // database is empty start with id : 1
318 download_id = DP_FIRST_DOWNLOAD_ID;
320 if (download_id < INT_MAX)
327 if (download_id < INT_MAX) {
328 TRACE_INFO("download_id [%d]", download_id);
329 check_duplicate = dp_db_check_duplicated_int(client->dbhandle,
330 DP_TABLE_LOGGING, DP_DB_COL_ID, download_id, &errorcode);
331 if (errorcode == DP_ERROR_NONE) {
332 if (check_duplicate == 0)
335 TRACE_ERROR("ERROR [%d]", errorcode);
337 if (retry_count < 3) {
339 } else if (retry_count < 10) {
340 gettimeofday(&tval, NULL);
341 tval.tv_usec = (tval.tv_usec & 0x0fff);
342 download_id += 1171 * retry_count + tval.tv_usec;
343 } else if (retry_count < 20) {
344 gettimeofday(&tval, NULL);
345 tval.tv_usec = (tval.tv_usec & 0xff33ff) + retry_count;
346 download_id += tval.tv_usec;
348 TRACE_ERROR("failed to generate unique download_id [%d]", download_id);
352 TRACE_ERROR("reached INT_MAX limit");
353 download_id = DP_FIRST_DOWNLOAD_ID;
355 } while (check_duplicate != 0);
359 void dp_request_create(dp_client_fmt *client, dp_request_fmt *request)
362 // find the tail of linked list & check limitation
364 dp_request_fmt *tailp = client->requests;
365 dp_request_fmt *prevp = NULL;
366 for (; i < MAX_DOWNLOAD_HANDLE; i++) {
369 TRACE_DEBUG("link %d info: id:%d access-time:%d", i, tailp->id, tailp->access_time);
373 request->next = NULL;
374 if (prevp == NULL) // it's first link
375 client->requests = request;
377 prevp->next = request; // attach at the tail
379 TRACE_INFO("sock:%d download-id:%d", client->channel, request->id);
382 static int __dp_request_create(dp_client_fmt *client, dp_ipc_fmt *ipc_info)
384 int errorcode = DP_ERROR_NONE;
386 int download_id = __dp_get_download_id(client);
388 // allocation new request.
389 dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt));
390 if (request == NULL) {
391 TRACE_ERROR("check memory sock:%d download-id:%d", client->channel, download_id);
392 return DP_ERROR_OUT_OF_MEMORY;
395 if (dp_db_new_logging(client->dbhandle, download_id, DP_STATE_READY, DP_ERROR_NONE, &errorcode) < 0) {
396 TRACE_ERROR("new log sock:%d download-id:%d errorcode:%s", client->channel, download_id, dp_print_errorcode(errorcode));
401 request->id = download_id;
402 request->agent_id = -1;
403 request->state = DP_STATE_READY;
404 request->error = DP_ERROR_NONE;
405 request->network_type = DP_NETWORK_ALL;
406 request->access_time = (int)time(NULL);
407 request->state_cb = 0;
408 request->progress_cb = 0;
409 request->startcount = 0;
410 request->noti_type = DP_NOTIFICATION_TYPE_NONE;
411 request->progress_lasttime = 0;
412 request->received_size = 0;
413 request->content_type = DP_CONTENT_UNKNOWN;
414 request->file_size = 0;
415 request->noti_priv_id = -1;
417 dp_request_create(client, request);
418 ipc_info->id = download_id;
422 void dp_request_free(dp_request_fmt *request)
424 // free notification handle here
425 TRACE_DEBUG("destory id:%d", request->id);
429 static int _dp_client_can_remove_request(dp_request_fmt *request)
431 if (request->id <= 0 || request->state == DP_STATE_NONE) {
432 TRACE_ERROR("id:%d unexpected request.", request->id);
436 int now_time = (int)time(NULL);
437 if (request->access_time > 0 &&
438 (now_time - request->access_time) > DP_CARE_CLIENT_CLEAR_INTERVAL) {
439 // check accesstime. if difference is bigger than DP_CARE_CLIENT_CLEAR_INTERVAL, clear.
440 if (request->state == DP_STATE_READY || request->state == DP_STATE_COMPLETED ||
441 request->state == DP_STATE_CANCELED || request->state == DP_STATE_FAILED)
445 if (request->state == DP_STATE_PAUSED &&
446 dp_is_alive_download(request->agent_id) == 0) {
447 // paused & agent_id not exist.... unload from memory.
448 TRACE_ERROR("id:%d hanged as paused (%d/%d)",request->id, request->access_time, now_time);
455 static int _dp_client_check_zombie_request(dp_request_fmt *request)
457 int now_time = (int)time(NULL);
460 if (request->access_time > 0)
461 time_diff = now_time - request->access_time;
463 if (time_diff > DP_CARE_CLIENT_CLEAR_INTERVAL && request->state == DP_STATE_CONNECTING) {
464 TRACE_ERROR("id:%d connection timeout (%d/%d)",
465 request->id, request->access_time, now_time);
472 void dp_client_clear_requests(void *slotp)
474 dp_client_slots_fmt *slot = (dp_client_slots_fmt *)slotp;
476 TRACE_ERROR("check slot memory");
480 dp_client_fmt *client = &slot->client;
481 dp_request_fmt *tailp = client->requests;
482 dp_request_fmt *prevp = NULL;
484 unsigned queued_count = 0;
485 unsigned ongoing_count = 0;
487 for (int i = 0; tailp != NULL; i++) {
488 int can_remove = _dp_client_can_remove_request(tailp);
489 int is_zombie = _dp_client_check_zombie_request(tailp);
492 TRACE_ERROR("id:%d is zombie request.", tailp->id);
493 if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0)
494 TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id);
495 tailp->state = DP_STATE_FAILED;
496 tailp->error = DP_ERROR_CONNECTION_TIMED_OUT;
497 if (tailp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
498 tailp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
499 if (dp_notification_manager_push_notification(slot, tailp, DP_NOTIFICATION) < 0)
500 TRACE_ERROR("failed to register notification for id:%d", tailp->id);
505 dp_request_fmt *removep = tailp;
506 if (prevp == NULL) // first request.
507 client->requests = tailp->next;
509 prevp->next = tailp->next;
511 TRACE_DEBUG("request %d clear: id:%d state:%s", i, removep->id, dp_print_state(removep->state));
512 dp_request_free(removep);
518 if (tailp->state == DP_STATE_QUEUED)
524 TRACE_DEBUG("info requests:%d queued:%d", ongoing_count, queued_count);
525 if (queued_count > 0)
526 dp_queue_manager_wake_up();
529 int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
531 int errorcode = DP_ERROR_NONE;
533 if (requestp != NULL && client->requests != NULL) {
534 if (requestp == client->requests) {
535 // cancel downloading ... after checking status
536 client->requests = requestp->next;
537 dp_request_free(requestp);
540 dp_request_fmt *prevp = client->requests;
541 dp_request_fmt *removep = client->requests->next;
542 for (; i < MAX_DOWNLOAD_HANDLE; i++) {
543 if (removep == NULL) {
544 errorcode = DP_ERROR_ID_NOT_FOUND;
547 if (removep == requestp) {
548 // cancel downloading ... after checking status
549 prevp->next = removep->next;
550 dp_request_free(removep);
554 removep = removep->next;
559 TRACE_DEBUG("sock:%d id:%d errorcode:%s", client->channel,
560 (ipc_info) ? ipc_info->id : -1, dp_print_errorcode(errorcode));
565 static void _dp_client_clear_stale_db(dp_client_fmt *client)
567 TRACE_DEBUG("Clear the stale DB data.");
568 int errorcode = DP_ERROR_NONE;
569 if (client && client->dbhandle != 0) {
570 // maintain only 1000 rows for each client
571 if (dp_db_limit_rows(client->dbhandle,
572 DP_TABLE_LOGGING, DP_LOG_DB_LIMIT_ROWS, &errorcode) < 0)
573 TRACE_INFO("limit rows error:%s", dp_print_errorcode(errorcode));
574 // maintain for 48 hours
575 if (dp_db_limit_time(client->dbhandle,
576 DP_TABLE_LOGGING, DP_CARE_CLIENT_INFO_PERIOD, &errorcode) < 0)
577 TRACE_INFO("limit rows error:%s", dp_print_errorcode(errorcode));
581 static int __dp_request_read_int(int sock, dp_ipc_fmt *ipc_info, int *value)
583 int errorcode = DP_ERROR_NONE;
584 if (ipc_info->size == sizeof(int)) {
585 if (dp_ipc_read(sock, value, ipc_info->size, __FUNCTION__) < 0) {
586 TRACE_ERROR("sock:%d check ipc length:%zd", sock, ipc_info->size);
587 errorcode = DP_ERROR_IO_ERROR;
590 errorcode = DP_ERROR_IO_ERROR;
595 static int __dp_request_feedback_string(int sock, dp_ipc_fmt *ipc_info, void *string, size_t length, int errorvalue)
597 int errorcode = DP_ERROR_NONE;
599 if (length == 0 && errorvalue == DP_ERROR_NONE)
600 errorvalue = DP_ERROR_NO_DATA;
602 if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, length * sizeof(char)) < 0) {
603 errorcode = DP_ERROR_IO_ERROR;
604 TRACE_ERROR("sock:%d check ipc length:%zd", sock, length);
606 if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) {
607 if (dp_ipc_write(sock, string, sizeof(char) * length) < 0) {
608 errorcode = DP_ERROR_IO_ERROR;
609 TRACE_ERROR("sock:%d check ipc length:%zd", sock, length);
615 static int __dp_request_read_string(int sock, dp_ipc_fmt *ipc_info, char **string)
617 int errorcode = DP_ERROR_NONE;
618 if (ipc_info->size > 0) {
619 char *recv_str = (char *)calloc((ipc_info->size + (size_t)1), sizeof(char));
620 if (recv_str == NULL) {
621 TRACE_ERROR("sock:%d check memory length:%zd", sock, ipc_info->size);
622 errorcode = DP_ERROR_OUT_OF_MEMORY;
624 if (dp_ipc_read(sock, recv_str, ipc_info->size, __FUNCTION__) <= 0) {
625 TRACE_ERROR("sock:%d check ipc length:%zd", sock, ipc_info->size);
626 errorcode = DP_ERROR_IO_ERROR;
629 recv_str[ipc_info->size] = '\0';
630 TRACE_DEBUG("sock:%d length:%zd string:%s", sock, ipc_info->size, recv_str);
635 errorcode = DP_ERROR_IO_ERROR;
640 static int __dp_request_feedback_int(int sock, dp_ipc_fmt *ipc_info, void *value, int errorvalue, size_t extra_size)
642 int errorcode = DP_ERROR_NONE;
643 if (errorvalue != DP_ERROR_NONE)
645 if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, extra_size) < 0) {
646 errorcode = DP_ERROR_IO_ERROR;
647 TRACE_ERROR("sock:%d check ipc length:%zd", sock, extra_size);
649 if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) {
650 if (dp_ipc_write(sock, value, extra_size) < 0) {
651 errorcode = DP_ERROR_IO_ERROR;
652 TRACE_ERROR("sock:%d check ipc length:%zd", sock, extra_size);
658 static int __dp_request_get_info_string(dp_client_fmt *client, dp_ipc_fmt *ipc_info)
660 int errorcode = DP_ERROR_NONE;
661 int bundle_type = -1; // DP_PROP_NOTIFICATION_RAW
664 const char *table = __dp_get_db_table_name(ipc_info->property);
665 const char *column = dp_db_column[ipc_info->property];
667 if (ipc_info->property == DP_PROP_NOTIFICATION_RAW) {
668 errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type);
669 TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type);
671 if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING)
672 column = DP_DB_COL_NOTI_RAW_ONGOING;
673 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE)
674 column = DP_DB_COL_NOTI_RAW_COMPLETE;
675 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED)
676 column = DP_DB_COL_NOTI_RAW_FAIL;
678 if (column == NULL) {
679 errorcode = DP_ERROR_INVALID_PARAMETER;
680 TRACE_ERROR("invalid type %s type:%d",
681 dp_print_property(ipc_info->property), bundle_type);
682 if (dp_ipc_query(client->channel, ipc_info->id,
683 ipc_info->section, ipc_info->property, errorcode, 0) < 0) {
684 errorcode = DP_ERROR_IO_ERROR;
685 TRACE_ERROR("check ipc sock:%d", client->channel);
691 if (dp_db_get_property_string(client->dbhandle, ipc_info->id,
692 table, column, (unsigned char **)&string, &length, &errorcode) < 0)
693 errorcode = DP_ERROR_NO_DATA;
695 if (__dp_request_feedback_string(client->channel, ipc_info,
696 string, length, errorcode) == DP_ERROR_IO_ERROR) {
697 errorcode = DP_ERROR_IO_ERROR;
698 TRACE_ERROR("check ipc sock:%d", client->channel);
706 static int __dp_request_get_info_int_from_db(dp_client_fmt *client, dp_ipc_fmt *ipc_info)
708 int errorcode = DP_ERROR_NONE;
709 int is_file_size = 0;
711 unsigned long long lval = 0;
712 const char *table = __dp_get_db_table_name(ipc_info->property);
713 size_t size = sizeof(int);
715 if (ipc_info->property == DP_PROP_RECEIVED_SIZE
716 || ipc_info->property == DP_PROP_TOTAL_FILE_SIZE) {
718 size = sizeof(unsigned long long);
721 if (dp_db_get_property_int(client->dbhandle, ipc_info->id,
722 table, dp_db_column[ipc_info->property],
723 (is_file_size ? (void *)&lval : (void *)&ival), &errorcode) < 0) {
724 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
725 errorcode = DP_ERROR_NO_DATA;
728 if (__dp_request_feedback_int(client->channel, ipc_info,
729 (is_file_size ? (void *)&lval : (void *)&ival),
730 errorcode, size) == DP_ERROR_IO_ERROR) {
731 errorcode = DP_ERROR_IO_ERROR;
732 TRACE_ERROR("check ipc sock:%d", client->channel);
738 static int __dp_request_get_info_int_from_request(dp_client_fmt *client,
739 dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
742 int errorcode = DP_ERROR_NONE;
743 size_t size = sizeof(int);
746 switch (ipc_info->property) {
747 case DP_PROP_RECEIVED_SIZE:
748 val = &requestp->received_size;
749 size = sizeof(unsigned long long);
751 case DP_PROP_STATE_CALLBACK:
752 val = &requestp->state_cb;
754 case DP_PROP_PROGRESS_CALLBACK:
755 val = &requestp->progress_cb;
757 case DP_PROP_NETWORK_TYPE:
758 val = &requestp->network_type;
761 val = &requestp->state;
764 val = &requestp->error;
766 case DP_PROP_TOTAL_FILE_SIZE:
767 val = &requestp->file_size;
768 size = sizeof(unsigned long long);
770 case DP_PROP_NOTIFICATION_TYPE:
771 val = &requestp->noti_type;
777 if (ipc_info->property == DP_PROP_RECEIVED_SIZE) {
778 errorcode = DP_ERROR_INVALID_STATE;
781 return __dp_request_get_info_int_from_db(client, ipc_info);
785 if (__dp_request_feedback_int(client->channel, ipc_info,
786 val, errorcode, size) == DP_ERROR_IO_ERROR) {
787 errorcode = DP_ERROR_IO_ERROR;
788 TRACE_ERROR("check ipc sock:%d", client->channel);
793 static int __dp_request_get_http_headers_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info)
795 int errorcode = DP_ERROR_NONE;
796 int field_count = dp_db_check_duplicated_int(client->dbhandle,
797 DP_TABLE_HEADERS, DP_DB_COL_ID, ipc_info->id, &errorcode);
799 if (field_count < 0) {
800 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
801 errorcode = DP_ERROR_DISK_BUSY;
805 int result = __dp_request_feedback_int(client->channel,
806 ipc_info, (void *)&field_count, errorcode, sizeof(int));
807 if (result == DP_ERROR_IO_ERROR) {
808 errorcode = DP_ERROR_IO_ERROR;
809 TRACE_ERROR("check ipc sock:%d", client->channel);
810 } else if (field_count > 0) {
811 // get fields from database.
812 int *ids = (int *)calloc(field_count, sizeof(int));
814 TRACE_ERROR("failed to allocate the clients");
815 errorcode = DP_ERROR_OUT_OF_MEMORY;
817 // getting ids of clients
819 int rows_count = dp_db_get_cond_ids(client->dbhandle,
820 DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, DP_DB_COL_ID,
821 ipc_info->id, ids, field_count, &errorcode);
822 for (; i < rows_count; i++) {
825 if (dp_db_get_cond_string(client->dbhandle,
826 DP_TABLE_HEADERS, DP_DB_COL_ROW_ID,
827 ids[i], DP_DB_COL_HEADER_FIELD,
828 (unsigned char **)&string, &length, &errorcode) < 0) {
829 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
830 errorcode = DP_ERROR_NO_DATA;
832 result = __dp_request_feedback_string(client->channel,
833 ipc_info, string, length, errorcode);
835 if (result == DP_ERROR_IO_ERROR) {
836 errorcode = DP_ERROR_IO_ERROR;
837 TRACE_ERROR("check ipc sock:%d", client->channel);
848 /* 1. read field string
849 * 2. response with extra size
852 static int __dp_request_get_http_header_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info)
854 char *header_field = NULL;
857 int errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
858 if (errorcode == DP_ERROR_NONE && header_field != NULL) {
859 if (dp_db_get_header_value(client->dbhandle, ipc_info->id,
860 header_field, (unsigned char **)&string, &length, &errorcode) < 0)
861 errorcode = DP_ERROR_NO_DATA;
862 } else if (header_field == NULL) {
863 errorcode = DP_ERROR_INVALID_PARAMETER;
866 if (__dp_request_feedback_string(client->channel,
867 ipc_info, string, length, errorcode) == DP_ERROR_IO_ERROR) {
868 errorcode = DP_ERROR_IO_ERROR;
869 TRACE_ERROR("check ipc sock:%d", client->channel);
878 static int __dp_request_get_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
880 int errorcode = DP_ERROR_NONE;
882 switch (ipc_info->property) {
885 case DP_PROP_DESTINATION:
886 case DP_PROP_FILENAME:
887 case DP_PROP_SAVED_PATH:
888 case DP_PROP_TEMP_SAVED_PATH:
889 case DP_PROP_MIME_TYPE:
890 case DP_PROP_CONTENT_NAME:
892 case DP_PROP_NOTIFICATION_SUBJECT:
893 case DP_PROP_NOTIFICATION_DESCRIPTION:
894 case DP_PROP_NOTIFICATION_RAW:
895 errorcode = __dp_request_get_info_string(client, ipc_info);
897 case DP_PROP_RECEIVED_SIZE:
898 case DP_PROP_STATE_CALLBACK:
899 case DP_PROP_PROGRESS_CALLBACK:
900 case DP_PROP_NETWORK_TYPE:
903 case DP_PROP_TOTAL_FILE_SIZE:
904 case DP_PROP_NOTIFICATION_TYPE:
905 errorcode = __dp_request_get_info_int_from_request(client, ipc_info, requestp);
907 case DP_PROP_NETWORK_BONDING:
908 case DP_PROP_AUTO_DOWNLOAD:
909 case DP_PROP_HTTP_STATUS:
910 errorcode = __dp_request_get_info_int_from_db(client, ipc_info);
912 case DP_PROP_HTTP_HEADERS:
913 errorcode = __dp_request_get_http_headers_info(client, ipc_info);
915 case DP_PROP_HTTP_HEADER:
916 errorcode = __dp_request_get_http_header_info(client, ipc_info);
919 errorcode = DP_ERROR_INVALID_PARAMETER;
923 if (errorcode != DP_ERROR_NONE)
924 TRACE_ERROR("failed to get %s, error:%s",
925 dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
930 static int __dp_request_set_info(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
933 TRACE_ERROR("check slot memory");
934 return DP_ERROR_INVALID_PARAMETER;
936 dp_client_fmt *client = &slot->client;
937 if (client == NULL || ipc_info == NULL) {
938 TRACE_ERROR("check client or ipc info.");
939 return DP_ERROR_INVALID_PARAMETER;
942 int errorcode = DP_ERROR_NONE;
944 // if completed or downloading, invalid state.
945 int download_state = DP_STATE_NONE;
946 if (requestp != NULL) {
947 download_state = requestp->state;
949 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) {
950 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
951 errorcode = DP_ERROR_ID_NOT_FOUND;
953 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
954 ipc_info->property, errorcode, 0) < 0) {
955 TRACE_ERROR("check ipc sock:%d", client->channel);
960 // should the state be checked ?
961 TRACE_DEBUG("state:%s set property:%s", dp_print_state(download_state), dp_print_property(ipc_info->property));
963 switch (ipc_info->property) {
966 char *recv_str = NULL;
967 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
968 if (errorcode == DP_ERROR_NONE) {
969 if (recv_str == NULL) {
970 errorcode = DP_ERROR_INVALID_PARAMETER;
972 // write to database here
973 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) {
974 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
975 errorcode = DP_ERROR_DISK_BUSY;
984 char *recv_str = NULL;
985 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
986 if (errorcode == DP_ERROR_NONE) {
987 if (recv_str == NULL) {
988 errorcode = DP_ERROR_INVALID_PARAMETER;
990 // write to database here
991 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROXY, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0)
992 TRACE_ERROR("failed to set %s errorcode:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
998 case DP_PROP_DESTINATION:
1000 char *recv_str = NULL;
1001 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1002 if (errorcode == DP_ERROR_NONE) {
1003 if (recv_str == NULL) {
1004 errorcode = DP_ERROR_INVALID_PARAMETER;
1006 // check here destination is available
1007 errorcode = dp_is_valid_dir(slot->credential, recv_str);
1008 if (errorcode == DP_ERROR_NONE &&
1009 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) {
1010 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1011 errorcode = DP_ERROR_DISK_BUSY;
1018 case DP_PROP_TEMP_SAVED_PATH:
1020 char *recv_str = NULL;
1021 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1022 if (errorcode == DP_ERROR_NONE) {
1023 if (recv_str == NULL) {
1024 errorcode = DP_ERROR_INVALID_PARAMETER;
1026 errorcode = dp_is_valid_dir(slot->credential, recv_str);
1027 if (errorcode == DP_ERROR_NONE &&
1028 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) {
1029 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1030 errorcode = DP_ERROR_DISK_BUSY;
1037 case DP_PROP_FILENAME:
1039 char *recv_str = NULL;
1040 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1041 if (errorcode == DP_ERROR_NONE) {
1042 if (recv_str == NULL) {
1043 errorcode = DP_ERROR_INVALID_PARAMETER;
1045 // write to database here
1046 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) {
1047 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1048 errorcode = DP_ERROR_DISK_BUSY;
1055 case DP_PROP_STATE_CALLBACK:
1058 // DP_ERROR_INVALID_STATE if downloading or finished
1059 // update database here
1060 if (requestp != NULL)
1061 requestp->state_cb = 1;
1064 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) {
1065 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1066 errorcode = DP_ERROR_DISK_BUSY;
1070 case DP_PROP_PROGRESS_CALLBACK:
1073 // DP_ERROR_INVALID_STATE if downloading or finished
1074 // update database here
1075 if (requestp != NULL)
1076 requestp->progress_cb = 1;
1079 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) {
1080 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1081 errorcode = DP_ERROR_DISK_BUSY;
1085 case DP_PROP_AUTO_DOWNLOAD:
1087 // update autodownload property as 1 in database
1089 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) {
1090 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1091 errorcode = DP_ERROR_DISK_BUSY;
1095 case DP_PROP_NETWORK_TYPE:
1098 errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1099 if (recv_int <= DP_NETWORK_OFF ||
1100 recv_int > DP_NETWORK_ALL) {
1101 errorcode = DP_ERROR_INVALID_PARAMETER;
1103 // update in database
1104 if (requestp != NULL) {
1105 if (requestp->state == DP_STATE_QUEUED) {
1106 dp_queue_manager_clear_queue(requestp);
1108 requestp->network_type = recv_int;
1109 if (requestp->state == DP_STATE_CONNECTING ||
1110 requestp->state == DP_STATE_DOWNLOADING) {
1111 // pause & push queue
1112 if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) {
1113 TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id);
1115 requestp->state = DP_STATE_PAUSED;
1116 requestp->error = DP_ERROR_NONE;
1117 if (dp_queue_manager_push_queue(slot, requestp) < 0) {
1118 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0)
1119 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1120 requestp->state = DP_STATE_FAILED;
1121 requestp->error = DP_ERROR_QUEUE_FULL;
1122 errorcode = DP_ERROR_QUEUE_FULL;
1128 int enable_cb = recv_int;
1129 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) {
1130 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1131 errorcode = DP_ERROR_DISK_BUSY;
1136 case DP_PROP_NETWORK_BONDING:
1139 errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1140 if (errorcode == DP_ERROR_NONE) {
1141 if (requestp != NULL && requestp->network_type != DP_NETWORK_ALL) {
1142 errorcode = DP_ERROR_INVALID_NETWORK_TYPE;
1143 TRACE_ERROR("[ERROR] wrong network type");
1144 } 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) {
1145 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1146 errorcode = DP_ERROR_DISK_BUSY;
1151 case DP_PROP_NOTIFICATION_TYPE:
1154 errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1155 if (recv_int == DP_NOTIFICATION_TYPE_NONE ||
1156 recv_int == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
1157 recv_int == DP_NOTIFICATION_TYPE_ALL) {
1158 // check state request->state == DP_STATE_COMPLETED
1159 // DP_ERROR_INVALID_STATE
1160 // update notificatio type in database
1161 int noti_type = recv_int;
1162 if (requestp != NULL) {
1163 if (recv_int < requestp->noti_type) {
1164 // if already notification, unregister from notification bar.
1165 if (recv_int == DP_NOTIFICATION_TYPE_NONE) {
1166 if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION) < 0)
1167 TRACE_ERROR("failed to clear notification %s", dp_print_property(ipc_info->property));
1169 if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0)
1170 TRACE_ERROR("failed to clear ongoing %s", dp_print_property(ipc_info->property));
1172 requestp->noti_type = recv_int;
1174 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)¬i_type, ipc_info->size, 0, &errorcode) < 0) {
1175 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1176 errorcode = DP_ERROR_DISK_BUSY;
1179 errorcode = DP_ERROR_INVALID_PARAMETER;
1183 case DP_PROP_NOTIFICATION_SUBJECT:
1185 char *recv_str = NULL;
1186 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1187 if (errorcode == DP_ERROR_NONE) {
1188 if (recv_str == NULL) {
1189 errorcode = DP_ERROR_INVALID_PARAMETER;
1191 // write to database here
1192 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) {
1193 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1194 errorcode = DP_ERROR_DISK_BUSY;
1201 case DP_PROP_NOTIFICATION_DESCRIPTION:
1203 char *recv_str = NULL;
1204 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1205 if (errorcode == DP_ERROR_NONE) {
1206 if (recv_str == NULL) {
1207 errorcode = DP_ERROR_INVALID_PARAMETER;
1209 // write to database here
1210 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) {
1211 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1212 errorcode = DP_ERROR_DISK_BUSY;
1219 case DP_PROP_NOTIFICATION_RAW: // bundle_type(db column) + bundle_binary
1221 int bundle_type = -1;
1222 errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type);
1223 TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1224 char *raw_column = NULL;
1225 if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING)
1226 raw_column = DP_DB_COL_NOTI_RAW_ONGOING;
1227 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE)
1228 raw_column = DP_DB_COL_NOTI_RAW_COMPLETE;
1229 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED)
1230 raw_column = DP_DB_COL_NOTI_RAW_FAIL;
1232 errorcode = DP_ERROR_INVALID_PARAMETER;
1234 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1235 ipc_info->property, errorcode, 0) < 0) {
1236 TRACE_ERROR("check ipc sock:%d", client->channel);
1237 errorcode = DP_ERROR_IO_ERROR;
1239 if (errorcode == DP_ERROR_NONE) {
1240 dp_ipc_fmt *raw_info = dp_ipc_get_fmt(client->channel);
1241 if (raw_info == NULL || raw_info->section != ipc_info->section ||
1242 raw_info->property != ipc_info->property ||
1243 (raw_info->id != ipc_info->id)) {
1244 TRACE_ERROR("there is a confusion waiting raw binary in %s section", dp_print_property(ipc_info->property));
1245 errorcode = DP_ERROR_IO_ERROR;
1247 if (raw_info != NULL && raw_info->size > 0 && raw_info->size < SIZE_MAX) {
1248 unsigned char *recv_raws = (unsigned char *)calloc(raw_info->size, sizeof(unsigned char));
1249 if (recv_raws == NULL) {
1250 TRACE_ERROR("sock:%d check memory length:%zd", client->channel, raw_info->size);
1251 errorcode = DP_ERROR_OUT_OF_MEMORY;
1253 if (dp_ipc_read(client->channel, recv_raws, raw_info->size, __FUNCTION__) <= 0) {
1254 TRACE_ERROR("sock:%d check ipc length:%zd", client->channel, raw_info->size);
1255 errorcode = DP_ERROR_IO_ERROR;
1257 TRACE_DEBUG("sock:%d length:%zd raws", client->channel, raw_info->size);
1259 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, (void *)recv_raws, raw_info->size, 3, &errorcode) < 0) {
1260 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1261 errorcode = DP_ERROR_DISK_BUSY;
1267 errorcode = DP_ERROR_IO_ERROR;
1273 case DP_PROP_HTTP_HEADER: // a request can have one or more fields, a fields can have only one value.
1275 char *header_field = NULL;
1276 char *header_value = NULL;
1277 // 1. read field string
1278 // 2. response after checking sql status
1279 // 3. read query IPC for checking IPC
1280 // 4. read value string
1282 errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
1283 if (errorcode == DP_ERROR_NONE && header_field != NULL) {
1285 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);
1286 if (check_field < 0) {
1287 errorcode = DP_ERROR_DISK_BUSY;
1289 errorcode = DP_ERROR_NONE;
1291 if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section,
1292 ipc_info->property, errorcode, 0) < 0) {
1293 TRACE_ERROR("check ipc sock:%d", client->channel);
1294 errorcode = DP_ERROR_IO_ERROR;
1296 dp_ipc_fmt *header_ipc = dp_ipc_get_fmt(client->channel);
1297 if (header_ipc == NULL || header_ipc->section != ipc_info->section ||
1298 header_ipc->property != ipc_info->property ||
1299 (header_ipc->id != ipc_info->id)) {
1300 TRACE_ERROR("there is a confusion during waiting http string in %s section", dp_print_property(ipc_info->property));
1301 errorcode = DP_ERROR_IO_ERROR;
1303 errorcode = __dp_request_read_string(client->channel, header_ipc, &header_value);
1304 if (errorcode == DP_ERROR_NONE && header_value != NULL) {
1305 if (check_field == 0) { // insert
1306 if (dp_db_new_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) {
1307 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1308 errorcode = DP_ERROR_DISK_BUSY;
1311 if (dp_db_update_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) {
1312 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1313 errorcode = DP_ERROR_DISK_BUSY;
1317 if (errorcode != DP_ERROR_NONE)
1318 TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1319 if (header_value == NULL) {
1320 TRACE_ERROR("failed to set %s, do you want to run as unset?", dp_print_property(ipc_info->property));
1321 errorcode = DP_ERROR_INVALID_PARAMETER;
1329 if (errorcode != DP_ERROR_NONE)
1330 TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1331 if (header_field == NULL) {
1332 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1333 errorcode = DP_ERROR_INVALID_PARAMETER;
1340 case DP_PROP_VERIFY_HOST:
1343 errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1344 if (errorcode == DP_ERROR_NONE) {
1345 if (requestp != NULL)
1346 requestp->disable_verify_host = recv_int ? 0 : 1;
1351 errorcode = DP_ERROR_INVALID_PARAMETER;
1355 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1356 ipc_info->property, errorcode, 0) < 0)
1357 TRACE_ERROR("check ipc sock:%d", client->channel);
1361 static int __dp_request_unset_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1363 if (client == NULL || ipc_info == NULL) {
1364 TRACE_ERROR("check client or ipc info.");
1365 return DP_ERROR_INVALID_PARAMETER;
1368 int errorcode = DP_ERROR_NONE;
1370 switch (ipc_info->property) {
1372 // it would be run like cancel operation
1373 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, &errorcode) < 0)
1374 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1377 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROXY, &errorcode) < 0)
1378 TRACE_ERROR("failed to unset %s errorcode:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1380 case DP_PROP_DESTINATION:
1381 // if downloading, change destination to da_agent
1382 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, &errorcode) < 0)
1383 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1385 case DP_PROP_FILENAME:
1386 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, &errorcode) < 0)
1387 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1389 case DP_PROP_STATE_CALLBACK:
1391 if (requestp != NULL)
1392 requestp->state_cb = 0;
1395 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) {
1396 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1397 errorcode = DP_ERROR_DISK_BUSY;
1401 case DP_PROP_PROGRESS_CALLBACK:
1403 if (requestp != NULL)
1404 requestp->progress_cb = 0;
1407 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) {
1408 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1409 errorcode = DP_ERROR_DISK_BUSY;
1413 case DP_PROP_AUTO_DOWNLOAD:
1415 // update autodownload property as 0 in database
1417 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) {
1418 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1419 errorcode = DP_ERROR_DISK_BUSY;
1423 case DP_PROP_NETWORK_TYPE:
1426 // update database here
1427 if (requestp != NULL)
1428 requestp->network_type = DP_NETWORK_OFF;
1430 int enable_cb = DP_NETWORK_OFF;
1431 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) {
1432 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1433 errorcode = DP_ERROR_DISK_BUSY;
1437 case DP_PROP_NOTIFICATION_TYPE:
1439 int noti_type = DP_NOTIFICATION_TYPE_NONE;
1440 if (requestp != NULL)
1441 requestp->noti_type = noti_type;
1443 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)¬i_type, ipc_info->size, 0, &errorcode) < 0) {
1444 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1445 errorcode = DP_ERROR_DISK_BUSY;
1449 case DP_PROP_NOTIFICATION_SUBJECT:
1451 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, &errorcode) < 0)
1452 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1455 case DP_PROP_NOTIFICATION_DESCRIPTION:
1457 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, &errorcode) < 0)
1458 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1461 case DP_PROP_NOTIFICATION_RAW:
1463 int bundle_type = -1;
1464 errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type);
1465 TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1466 char *raw_column = NULL;
1467 if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING)
1468 raw_column = DP_DB_COL_NOTI_RAW_ONGOING;
1469 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE)
1470 raw_column = DP_DB_COL_NOTI_RAW_COMPLETE;
1471 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED)
1472 raw_column = DP_DB_COL_NOTI_RAW_FAIL;
1473 if (raw_column != NULL) {
1474 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &errorcode) < 0)
1475 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1477 TRACE_ERROR("invalid param set: %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1478 errorcode = DP_ERROR_INVALID_PARAMETER;
1482 case DP_PROP_HTTP_HEADER: // unset value by field
1484 char *header_field = NULL;
1485 errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
1486 if (errorcode == DP_ERROR_NONE && header_field != NULL) {
1487 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);
1489 errorcode = DP_ERROR_DISK_BUSY;
1490 else if (is_present == 0)
1491 errorcode = DP_ERROR_FIELD_NOT_FOUND;
1492 else if (dp_db_cond_delete(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, header_field, 2, &errorcode) < 0) {
1493 TRACE_ERROR("failed to unset %s for %s", dp_print_property(ipc_info->property), header_field);
1494 errorcode = DP_ERROR_DISK_BUSY;
1497 if (errorcode != DP_ERROR_NONE)
1498 TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1499 if (header_field == NULL) {
1500 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1501 errorcode = DP_ERROR_INVALID_PARAMETER;
1508 errorcode = DP_ERROR_INVALID_PARAMETER;
1512 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_UNSET,
1513 ipc_info->property, errorcode, 0) < 0) {
1514 TRACE_ERROR("check ipc sock:%d", client->channel);
1519 static int __dp_call_cancel_agent(dp_request_fmt *request)
1522 if (request != NULL) {
1523 if (request->agent_id >= 0) {
1524 TRACE_INFO("cancel download(%d) id: %d state:%s", request->agent_id,
1525 request->id, dp_print_state(request->state));
1526 if (dp_cancel_agent_download_without_update(request->agent_id) == 0)
1529 TRACE_ERROR("invalid agent-id:%d id:%d", request->agent_id, request->id);
1535 static int __dp_request_controls(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1538 TRACE_ERROR("check slot memory");
1539 return DP_ERROR_INVALID_PARAMETER;
1541 dp_client_fmt *client = &slot->client;
1542 if (client == NULL || ipc_info == NULL) {
1543 TRACE_ERROR("check client or ipc info.");
1544 return DP_ERROR_INVALID_PARAMETER;
1547 int errorcode = DP_ERROR_NONE;
1549 if (ipc_info->property == DP_PROP_CREATE) {
1550 // check packets again
1551 if (ipc_info->size != 0 || ipc_info->id != -1)
1552 errorcode = DP_ERROR_IO_ERROR;
1554 errorcode = __dp_request_create(client, ipc_info);
1558 int download_state = DP_STATE_NONE;
1559 if (requestp != NULL) {
1560 download_state = requestp->state;
1562 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) {
1563 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
1564 errorcode = DP_ERROR_ID_NOT_FOUND;
1566 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1567 ipc_info->property, errorcode, 0) < 0) {
1568 TRACE_ERROR("check ipc sock:%d", client->channel);
1573 TRACE_DEBUG("id:%d state:%s set property:%s", ipc_info->id, dp_print_state(download_state), dp_print_property(ipc_info->property));
1575 if (ipc_info->property == DP_PROP_START) {
1577 if (download_state == DP_STATE_COMPLETED ||
1578 download_state == DP_STATE_DOWNLOADING) {
1579 errorcode = DP_ERROR_INVALID_STATE;
1582 if (requestp == NULL) { // load from databse
1584 // load and add new request to client->requests.
1586 if (requestp == NULL) {
1587 TRACE_ERROR("failed to load id:%d from database sock:%d", ipc_info->id, client->channel);
1588 errorcode = DP_ERROR_DISK_BUSY;
1590 if (errorcode == DP_ERROR_NONE) {
1592 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) {
1593 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1594 errorcode = DP_ERROR_DISK_BUSY;
1596 requestp->state = DP_STATE_QUEUED;
1597 requestp->error = DP_ERROR_NONE;
1598 // if it's the first request for this client-> push a request at the head of queue.
1599 // check count queued, connecting.downloading in requets of client
1600 // else push at the tail of queue.
1602 if (dp_queue_manager_push_queue(slot, requestp) < 0) {
1603 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0)
1604 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1605 requestp->state = DP_STATE_FAILED;
1606 requestp->error = DP_ERROR_QUEUE_FULL;
1607 errorcode = DP_ERROR_QUEUE_FULL;
1609 dp_queue_manager_wake_up();
1611 if (requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
1612 if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0)
1613 TRACE_ERROR("failed to register notification for id:%d", ipc_info->id);
1618 TRACE_DEBUG("id:%d check start error:%s", ipc_info->id, dp_print_errorcode(errorcode));
1621 } else if (ipc_info->property == DP_PROP_PAUSE) {
1623 if (download_state > DP_STATE_DOWNLOADING) {
1624 errorcode = DP_ERROR_INVALID_STATE;
1625 } else { // change state regardless it's on memory or not.
1626 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_PAUSED, DP_ERROR_NONE, &errorcode) < 0) {
1627 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1628 errorcode = DP_ERROR_DISK_BUSY;
1630 // call da_pause API
1631 if (requestp != NULL) {
1632 // pop from queue. if state is queued.
1633 if (requestp->state == DP_STATE_QUEUED) {
1634 dp_queue_manager_clear_queue(requestp);
1635 } else if (requestp->state == DP_STATE_CONNECTING ||
1636 requestp->state == DP_STATE_DOWNLOADING) {
1637 if (dp_pause_agent_download_without_update(requestp->agent_id) < 0)
1638 TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id);
1640 requestp->state = DP_STATE_PAUSED;
1641 requestp->error = DP_ERROR_NONE;
1646 } else if (ipc_info->property == DP_PROP_CANCEL) {
1648 if (download_state > DP_STATE_COMPLETED) {
1649 errorcode = DP_ERROR_INVALID_STATE;
1650 } else { // change state regardless it's on memory or not.
1651 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) {
1652 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1653 errorcode = DP_ERROR_DISK_BUSY;
1655 // call da_cancel API
1656 if (requestp != NULL) {
1657 // pop from queue. if state is queued.
1658 if (requestp->state == DP_STATE_QUEUED) {
1659 dp_queue_manager_clear_queue(requestp);
1660 } else if (requestp->state == DP_STATE_CONNECTING ||
1661 requestp->state == DP_STATE_DOWNLOADING ||
1662 requestp->state == DP_STATE_PAUSED) {
1663 if (__dp_call_cancel_agent(requestp) < 0)
1664 TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id);
1666 requestp->agent_id = -1;
1667 requestp->state = DP_STATE_CANCELED;
1668 requestp->error = DP_ERROR_NONE;
1669 if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
1670 requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
1671 if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0)
1672 TRACE_ERROR("failed to register notification for id:%d", ipc_info->id);
1678 } else if (ipc_info->property == DP_PROP_DESTROY) {
1681 // pop from queue. if state is queued.
1682 if (requestp != NULL) {
1683 if (requestp->state == DP_STATE_QUEUED)
1684 dp_queue_manager_clear_queue(requestp);
1685 if (requestp->state == DP_STATE_CONNECTING ||
1686 requestp->state == DP_STATE_DOWNLOADING) {
1687 // update state property database;
1688 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) {
1689 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1691 // call da_cancel API
1692 if (__dp_call_cancel_agent(requestp) < 0)
1693 TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id);
1695 requestp->state = DP_STATE_CANCELED;
1697 if (requestp->state == DP_STATE_QUEUED || requestp->state == DP_STATE_CANCELED) {
1699 if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
1700 requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
1701 if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0)
1702 TRACE_ERROR("failed to register notification for id:%d", ipc_info->id);
1705 requestp->agent_id = -1;
1707 errorcode = dp_request_destroy(client, ipc_info, requestp);
1710 errorcode = DP_ERROR_INVALID_PARAMETER;
1711 TRACE_ERROR("invalid param - id:%d set property:%s", ipc_info->id, dp_print_property(ipc_info->property));
1716 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_CONTROL,
1717 ipc_info->property, errorcode, 0) < 0) {
1718 TRACE_ERROR("check ipc sock:%d", client->channel);
1721 // workaround. client still request the feedback by cancelation
1722 if (ipc_info->property == DP_PROP_CANCEL ||
1723 ipc_info->property == DP_PROP_PAUSE) {
1724 if (requestp != NULL && requestp->state_cb == 1) {
1725 if (slot->client.notify < 0 ||
1726 dp_notify_feedback(slot->client.notify, slot, ipc_info->id, requestp->state, errorcode, 0) < 0) {
1727 TRACE_ERROR("id:%d disable state callback by IO_ERROR", ipc_info->id);
1728 requestp->state_cb = 0;
1736 static int __dp_client_requests(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info)
1739 TRACE_ERROR("check slot memory");
1740 return DP_ERROR_INVALID_PARAMETER;
1742 dp_client_fmt *client = &slot->client;
1743 if (client == NULL || ipc_info == NULL) {
1744 TRACE_ERROR("check client or ipc info.");
1745 return DP_ERROR_INVALID_PARAMETER;
1748 int errorcode = DP_ERROR_NONE;
1750 // check id except create command /////////// DP_ERROR_ID_NOT_FOUND
1751 dp_request_fmt *requestp = NULL;
1752 if (ipc_info->section != DP_SEC_CONTROL ||
1753 ipc_info->property != DP_PROP_CREATE) {
1754 // check on requests
1756 requestp = client->requests;
1757 errorcode = DP_ERROR_ID_NOT_FOUND;
1758 for (; i < MAX_DOWNLOAD_HANDLE; i++) {
1759 if (requestp == NULL)
1761 //TRACE_DEBUG("link %d info: id:%d access-time:%d", i, requestp->id, requestp->access_time);
1762 if (requestp->id == ipc_info->id) {
1763 errorcode = DP_ERROR_NONE;
1766 requestp = requestp->next;
1768 if (errorcode == DP_ERROR_ID_NOT_FOUND) {
1769 // check in database
1770 if (dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_LOGGING, DP_DB_COL_ID, ipc_info->id, &errorcode) > 0) {
1771 //TRACE_DEBUG("found %d from database", ipc_info->id);
1772 errorcode = DP_ERROR_NONE;
1777 if (errorcode != DP_ERROR_NONE) { // prechecking
1778 TRACE_ERROR("precheck errorcode:%s sock:%d id:%d section:%s property:%s",
1779 dp_print_errorcode(errorcode),
1780 client->channel, ipc_info->id,
1781 dp_print_section(ipc_info->section),
1782 dp_print_property(ipc_info->property));
1784 // clear followed packets.
1785 if (ipc_info->size > 0) {
1786 char garbage[ipc_info->size];
1787 if (read(client->channel, &garbage, ipc_info->size) == 0) {
1788 TRACE_ERROR("sock:%d closed peer", client->channel);
1789 errorcode = DP_ERROR_IO_ERROR;
1793 if (dp_ipc_query(client->channel, ipc_info->id,
1794 ipc_info->section, ipc_info->property, errorcode, 0) < 0) {
1795 TRACE_ERROR("check ipc sock:%d", client->channel);
1796 errorcode = DP_ERROR_IO_ERROR;
1801 switch (ipc_info->section) {
1802 case DP_SEC_CONTROL:
1803 errorcode = __dp_request_controls(slot, ipc_info, requestp);
1806 errorcode = __dp_request_get_info(client, ipc_info, requestp);
1809 errorcode = __dp_request_set_info(slot, ipc_info, requestp);
1812 errorcode = __dp_request_unset_info(client, ipc_info, requestp);
1815 errorcode = DP_ERROR_INVALID_PARAMETER;
1821 static void __dp_client_stop_all_requests(dp_client_slots_fmt *slot)
1823 unsigned push_count = 0;
1824 int errorcode = DP_ERROR_NONE;
1826 dp_request_fmt *tailp = slot->client.requests;
1827 for (; tailp != NULL; i++) {
1828 TRACE_DEBUG("request %d stop id:%d state:%s", i, tailp->id, dp_print_state(tailp->state));
1829 int state = tailp->state;
1830 if (state == DP_STATE_CONNECTING) {
1831 if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0)
1832 TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id);
1833 } else if (state == DP_STATE_DOWNLOADING) {
1834 if (dp_pause_agent_download(tailp->agent_id) < 0)
1835 TRACE_ERROR("failed to pause download(%d) id:%d", tailp->agent_id, tailp->id);
1837 if (state == DP_STATE_DOWNLOADING || state == DP_STATE_CONNECTING) {
1838 tailp->state = DP_STATE_QUEUED;
1839 // This is error code for checking the reason when changing ip configuration process
1840 tailp->error = DP_ERROR_IO_EAGAIN;
1841 // push to queue now
1842 // in da callback, check DP_ERROR_IO_EAGAIN, then ignore.
1843 if (dp_db_update_logging(slot->client.dbhandle, tailp->id, tailp->state, DP_ERROR_NONE, &errorcode) < 0)
1844 TRACE_ERROR("update log sock:%d download-id:%d", slot->client.channel, tailp->id);
1845 if (dp_queue_manager_push_queue(slot, tailp) < 0) {
1846 TRACE_ERROR("Fail to push queueg sock:%d download-id:%d", slot->client.channel, tailp->id);
1847 // FIXME later : error case. How can handle this item?
1852 tailp = tailp->next;
1855 dp_queue_manager_wake_up();
1858 void dp_client_sig_handler(int signo)
1860 TRACE_INFO("thread:%lu signal:%d", pthread_self(), signo);
1863 void *dp_client_request_thread(void *arg)
1865 dp_client_slots_fmt *slot = (dp_client_slots_fmt *)arg;
1867 TRACE_ERROR("slot null, can not launch the thread for client");
1871 // wait detaching thread
1872 CLIENT_MUTEX_LOCK(&slot->mutex);
1874 TRACE_INFO("slot %p thread:%lu", slot, slot->thread);
1876 struct sigaction act = {{0},};
1878 sigemptyset(&newmask);
1879 sigaddset(&newmask, SIGUSR1);
1880 act.sa_handler = dp_client_sig_handler;
1881 sigaction(SIGUSR1, &act, NULL);
1883 fd_set imask, emask;
1884 int errorcode = DP_ERROR_NONE;
1885 dp_client_fmt *client = &slot->client;
1886 int client_sock = client->channel;
1887 struct timeval timeout; // for timeout of select
1889 CLIENT_MUTEX_UNLOCK(&slot->mutex);
1891 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
1893 while (slot != NULL && client_sock >= 0 &&
1894 client_sock == slot->client.channel) {
1895 memset(&timeout, 0x00, sizeof(struct timeval));
1896 timeout.tv_sec = DP_CARE_CLIENT_REQUEST_INTERVAL;
1899 FD_SET(client_sock, &imask);
1900 FD_SET(client_sock, &emask);
1901 if (select(client_sock + 1, &imask, 0, &emask, &timeout) < 0) {
1902 if (slot != NULL && slot->client.channel >= 0) {
1903 TRACE_INFO("broadcast by client-manager");
1904 CLIENT_MUTEX_LOCK(&slot->mutex);
1905 // check all requests
1906 __dp_client_stop_all_requests(slot);
1907 CLIENT_MUTEX_UNLOCK(&slot->mutex);
1910 TRACE_ERROR("interrupted by client-manager sock:%d", client_sock);
1914 if (FD_ISSET(client_sock, &imask) > 0) {
1916 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1917 CLIENT_MUTEX_LOCK(&slot->mutex);
1919 client->access_time = (int)time(NULL);
1921 errorcode = DP_ERROR_NONE;
1923 // read ipc_fmt first. below func will deal followed packets
1924 dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(client_sock);
1925 if (ipc_info == NULL) {
1926 TRACE_ERROR("sock:%d maybe closed", client_sock);
1927 errorcode = DP_ERROR_IO_ERROR;
1929 TRACE_INFO("sock:%d id:%d section:%s property:%s errorcode:%s size:%zd",
1930 client_sock, ipc_info->id,
1931 dp_print_section(ipc_info->section),
1932 dp_print_property(ipc_info->property),
1933 dp_print_errorcode(ipc_info->errorcode),
1936 if (client->dbhandle == 0 || dp_db_check_connection(client->dbhandle) < 0) {
1937 if (dp_db_open_client(&client->dbhandle, slot->pkgname, &errorcode) < 0) {
1938 TRACE_ERROR("failed to open database for sock:%d errorcode:%s",
1939 client_sock, dp_print_errorcode(errorcode));
1940 if (dp_ipc_query(client->channel, ipc_info->id,
1941 ipc_info->section, ipc_info->property, errorcode, 0) < 0) {
1942 TRACE_ERROR("check ipc sock:%d", client->channel);
1947 if (errorcode == DP_ERROR_NONE) {
1949 errorcode = __dp_client_requests(slot, ipc_info);
1955 CLIENT_MUTEX_UNLOCK(&slot->mutex);
1956 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
1958 if (errorcode == DP_ERROR_IO_ERROR ||
1959 errorcode == DP_ERROR_OUT_OF_MEMORY ||
1960 errorcode == DP_ERROR_INVALID_PARAMETER) {
1961 TRACE_ERROR("disconnect client errorcode:%s sock:%d",
1962 dp_print_errorcode(errorcode), client_sock);
1966 } else if (FD_ISSET(client_sock, &emask) > 0) {
1967 TRACE_ERROR("[EXCEPTION]");
1970 TRACE_ERROR("[TIMEOUT]");
1971 if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) == 0) {
1972 // 1. clear zombie requests. clean requests finished. paused or ready for long time
1973 dp_client_clear_requests(slot);
1975 // 2. if no requests, exit by itself.
1976 if (slot->client.requests == NULL) {
1977 TRACE_DEBUG("no requests");
1978 CLIENT_MUTEX_UNLOCK(&slot->mutex);
1981 CLIENT_MUTEX_UNLOCK(&slot->mutex);
1984 } // while (slot != NULL && client_sock >= 0 && ....)
1986 _dp_client_clear_stale_db(client);
1988 if (client_sock >= 0 && client_sock < FD_SETSIZE) {
1989 FD_CLR(client_sock, &imask);
1990 FD_CLR(client_sock, &emask);
1993 // if no requests, clear slot after disconnect with client.
1994 CLIENT_MUTEX_LOCK(&slot->mutex);
1996 TRACE_INFO("thread done slot %p thread:%lu", slot, slot->thread);
1998 slot->thread = 0;// to prevent kill thread twice
2001 dp_request_fmt *tailp = slot->client.requests;
2002 dp_request_fmt *prevp = NULL;
2003 for (; tailp != NULL; i++) {
2004 if (tailp->state != DP_STATE_QUEUED &&
2005 tailp->state != DP_STATE_CONNECTING &&
2006 tailp->state != DP_STATE_DOWNLOADING) {
2007 dp_request_fmt *removep = tailp;
2008 if (prevp == NULL) // first request.
2009 client->requests = tailp->next;
2011 prevp->next = tailp->next;
2012 tailp = tailp->next;
2013 TRACE_DEBUG("request %d remove: id:%d state:%s", i, removep->id, dp_print_state(removep->state));
2014 dp_request_free(removep);
2017 TRACE_DEBUG("request %d remain: id:%d state:%s", i, tailp->id, dp_print_state(tailp->state));
2019 tailp = tailp->next;
2022 // if no requests after clear finished requests.
2023 if (slot->client.requests == NULL) {
2024 dp_client_slot_free(slot);
2026 if (slot->client.notify >= 0)
2027 close(slot->client.notify);
2028 dp_notify_deinit(slot->credential.pid);
2029 slot->client.notify = -1;
2030 if (slot->client.channel > 0)
2031 close(slot->client.channel);
2032 slot->client.channel = -1;
2034 TRACE_INFO("thread done slot %p thread:%lu sock:%d", slot, slot->thread, client_sock);
2035 CLIENT_MUTEX_UNLOCK(&slot->mutex);