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-smack.h>
39 char *dp_print_state(int state)
48 case DP_STATE_CONNECTING:
50 case DP_STATE_DOWNLOADING:
54 case DP_STATE_COMPLETED:
56 case DP_STATE_CANCELED:
66 char *dp_print_errorcode(int errorcode)
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:
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:
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:
91 case DP_ERROR_INVALID_DESTINATION:
92 return "INVALID_DESTINATION";
93 case DP_ERROR_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:
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:
119 case DP_ERROR_ID_NOT_FOUND:
120 return "ID_NOT_FOUND";
127 char *dp_print_section(short section)
150 char *dp_print_property(unsigned property)
163 case DP_PROP_DESTROY:
167 case DP_PROP_DESTINATION:
168 return "DESTINATION";
169 case DP_PROP_FILENAME:
171 case DP_PROP_STATE_CALLBACK:
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:
183 case DP_PROP_TEMP_SAVED_PATH:
184 return "TEMP_SAVED_PATH";
185 case DP_PROP_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";
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";
219 static int __dp_get_download_id(dp_client_fmt *client)
221 int download_id = -1;
222 int check_duplicate = 1;
224 int errorcode = DP_ERROR_NONE;
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;
233 if (download_id < INT_MAX)
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)
248 TRACE_ERROR("ERROR [%d]", errorcode);
250 if (retry_count < 3) {
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;
261 TRACE_ERROR("failed to generate unique download_id [%d]", download_id);
265 TRACE_ERROR("reached INT_MAX limit");
266 download_id = DP_FIRST_DOWNLOAD_ID;
268 } while (check_duplicate != 0);
272 void dp_request_create(dp_client_fmt *client, dp_request_fmt *request)
275 // find the tail of linked list & check limitation
277 dp_request_fmt *tailp = client->requests;
278 dp_request_fmt *prevp = NULL;
279 for (; i < MAX_DOWNLOAD_HANDLE; i++) {
282 TRACE_DEBUG("link %d info: id:%d access-time:%d", i, tailp->id, tailp->access_time);
286 request->next = NULL;
287 if (prevp == NULL) // it's first link
288 client->requests = request;
290 prevp->next = request; // attach at the tail
292 TRACE_DEBUG("sock:%d download-id:%d", client->channel, request->id);
295 static int __dp_request_create(dp_client_fmt *client, dp_ipc_fmt *ipc_info)
297 int errorcode = DP_ERROR_NONE;
299 int download_id = __dp_get_download_id(client);
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;
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));
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;
330 dp_request_create(client, request);
331 ipc_info->id = download_id;
335 void dp_request_free(dp_request_fmt *request)
337 // free notification handle here
338 TRACE_DEBUG("destory id:%d", request->id);
342 void dp_client_clear_requests(void *slotp)
344 dp_client_slots_fmt *slot = (dp_client_slots_fmt *)slotp;
346 TRACE_ERROR("check slot memory");
349 dp_client_fmt *client = &slot->client;
351 int now_time = (int)time(NULL);
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++) {
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);
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.
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) {
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);
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);
391 if (can_unload == 1) {
392 dp_request_fmt *removep = tailp;
393 if (prevp == NULL) // first request.
394 client->requests = tailp->next;
396 prevp->next = 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);
405 if (tailp->state == DP_STATE_QUEUED)
411 TRACE_DEBUG("info requests:%d queued:%d", ongoing_count, queued_count);
412 if (queued_count > 0)
413 dp_queue_manager_wake_up();
416 int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
418 int errorcode = DP_ERROR_NONE;
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);
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;
434 if (removep == requestp) {
435 // cancel downloading ... after checking status
436 prevp->next = removep->next;
437 dp_request_free(removep);
441 removep = removep->next;
446 TRACE_DEBUG("sock:%d id:%d errorcode:%s", client->channel,
447 (ipc_info) ? ipc_info->id : -1, dp_print_errorcode(errorcode));
452 static int __dp_request_read_int(int sock, dp_ipc_fmt *ipc_info, int *value)
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;
461 errorcode = DP_ERROR_IO_ERROR;
466 static int __dp_request_feedback_string(int sock, dp_ipc_fmt *ipc_info, void *string, size_t length, int errorvalue)
468 int errorcode = DP_ERROR_NONE;
470 if (length == 0 && errorvalue == DP_ERROR_NONE)
471 errorvalue = DP_ERROR_NO_DATA;
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);
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);
486 static int __dp_request_read_string(int sock, dp_ipc_fmt *ipc_info, char **string)
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;
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;
500 recv_str[ipc_info->size] = '\0';
501 TRACE_DEBUG("sock:%d length:%d string:%s", sock, ipc_info->size, recv_str);
506 errorcode = DP_ERROR_IO_ERROR;
511 static int __dp_request_feedback_int(int sock, dp_ipc_fmt *ipc_info, void *value, int errorvalue, size_t extra_size)
513 int errorcode = DP_ERROR_NONE;
514 if (errorvalue != DP_ERROR_NONE)
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);
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);
529 static int __dp_request_get_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
531 int errorcode = DP_ERROR_NONE;
532 switch (ipc_info->property) {
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;
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);
549 case DP_PROP_DESTINATION:
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;
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);
565 case DP_PROP_FILENAME:
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;
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);
581 case DP_PROP_STATE_CALLBACK:
584 if (requestp != NULL) {
585 callback = requestp->state_cb;
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;
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);
599 case DP_PROP_PROGRESS_CALLBACK:
602 if (requestp != NULL) {
603 callback = requestp->progress_cb;
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;
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);
617 case DP_PROP_AUTO_DOWNLOAD:
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;
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);
631 case DP_PROP_NETWORK_TYPE:
634 if (requestp != NULL) {
635 network = requestp->network_type;
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;
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);
649 case DP_PROP_NETWORK_BONDING:
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;
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);
663 case DP_PROP_SAVED_PATH:
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;
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);
679 case DP_PROP_TEMP_SAVED_PATH:
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;
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);
695 case DP_PROP_MIME_TYPE:
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;
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);
711 case DP_PROP_RECEIVED_SIZE:
713 unsigned long long recv_size = 0;
714 if (requestp != NULL)
715 recv_size = requestp->received_size;
717 errorcode = DP_ERROR_INVALID_STATE;
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);
726 case DP_PROP_TOTAL_FILE_SIZE:
728 unsigned long long file_size = 0;
729 if (requestp != NULL) {
730 file_size = requestp->file_size;
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;
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);
745 case DP_PROP_CONTENT_NAME:
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;
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);
761 case DP_PROP_HTTP_STATUS:
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;
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);
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;
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);
793 int state = DP_STATE_NONE;
794 if (requestp != NULL) {
795 state = requestp->state;
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;
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);
811 int errorvalue = DP_ERROR_NONE;
812 if (requestp != NULL) {
813 errorvalue = requestp->error;
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;
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);
827 case DP_PROP_NOTIFICATION_TYPE:
830 if (requestp != NULL) {
831 noti_type = requestp->noti_type;
832 // if already notification, unregister from notification bar.
834 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, ¬i_type, &errorcode) < 0) {
835 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
836 errorcode = DP_ERROR_NO_DATA;
839 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)¬i_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);
846 case DP_PROP_NOTIFICATION_SUBJECT:
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;
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);
862 case DP_PROP_NOTIFICATION_DESCRIPTION:
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;
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);
878 case DP_PROP_NOTIFICATION_RAW: // read type, send raw binary for type
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;
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);
899 if (errorcode == DP_ERROR_NONE) {
900 unsigned char *raws_buffer = NULL;
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;
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);
916 case DP_PROP_HTTP_HEADERS:
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;
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));
935 TRACE_ERROR("failed to allocate the clients");
936 errorcode = DP_ERROR_OUT_OF_MEMORY;
938 // getting ids of clients
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++) {
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;
948 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
950 if (result == DP_ERROR_IO_ERROR) {
951 errorcode = DP_ERROR_IO_ERROR;
952 TRACE_ERROR("check ipc sock:%d", client->channel);
962 case DP_PROP_HTTP_HEADER:
964 // 1. read field string
965 // 2. response with extra size
967 char *header_field = NULL;
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;
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;
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);
994 errorcode = DP_ERROR_INVALID_PARAMETER;
1000 static int __dp_request_set_info(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1003 TRACE_ERROR("check slot memory");
1004 return DP_ERROR_INVALID_PARAMETER;
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;
1012 int errorcode = DP_ERROR_NONE;
1014 // if completed or downloading, invalid state.
1015 int download_state = DP_STATE_NONE;
1016 if (requestp != NULL) {
1017 download_state = requestp->state;
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;
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);
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));
1033 switch (ipc_info->property) {
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;
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;
1052 case DP_PROP_DESTINATION:
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;
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;
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;
1083 case DP_PROP_TEMP_SAVED_PATH:
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;
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;
1100 case DP_PROP_FILENAME:
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;
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;
1118 case DP_PROP_STATE_CALLBACK:
1121 // DP_ERROR_INVALID_STATE if downloading or finished
1122 // update database here
1123 if (requestp != NULL)
1124 requestp->state_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;
1133 case DP_PROP_PROGRESS_CALLBACK:
1136 // DP_ERROR_INVALID_STATE if downloading or finished
1137 // update database here
1138 if (requestp != NULL)
1139 requestp->progress_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;
1148 case DP_PROP_AUTO_DOWNLOAD:
1150 // update autodownload property as 1 in database
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;
1158 case DP_PROP_NETWORK_TYPE:
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;
1166 // update in database
1167 if (requestp != NULL) {
1168 if (requestp->state == DP_STATE_QUEUED) {
1169 dp_queue_manager_clear_queue(requestp);
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);
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;
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;
1199 case DP_PROP_NETWORK_BONDING:
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;
1214 case DP_PROP_NOTIFICATION_TYPE:
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));
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));
1235 requestp->noti_type = recv_int;
1237 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) {
1238 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1239 errorcode = DP_ERROR_DISK_BUSY;
1242 errorcode = DP_ERROR_INVALID_PARAMETER;
1246 case DP_PROP_NOTIFICATION_SUBJECT:
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;
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;
1264 case DP_PROP_NOTIFICATION_DESCRIPTION:
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;
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;
1282 case DP_PROP_NOTIFICATION_RAW: // bundle_type(db column) + bundle_binary
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;
1295 errorcode = DP_ERROR_INVALID_PARAMETER;
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;
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;
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;
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;
1320 TRACE_DEBUG("sock:%d length:%d raws", client->channel, raw_info->size);
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;
1330 errorcode = DP_ERROR_IO_ERROR;
1336 case DP_PROP_HTTP_HEADER: // a request can have one or more fields, a fields can have only one value.
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
1345 errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
1346 if (errorcode == DP_ERROR_NONE && header_field != NULL) {
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;
1352 errorcode = DP_ERROR_NONE;
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;
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;
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;
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;
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;
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;
1404 errorcode = DP_ERROR_INVALID_PARAMETER;
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);
1415 static int __dp_request_unset_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1417 if (client == NULL || ipc_info == NULL) {
1418 TRACE_ERROR("check client or ipc info.");
1419 return DP_ERROR_INVALID_PARAMETER;
1422 int errorcode = DP_ERROR_NONE;
1424 switch (ipc_info->property) {
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));
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));
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));
1439 case DP_PROP_STATE_CALLBACK:
1441 if (requestp != NULL)
1442 requestp->state_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;
1451 case DP_PROP_PROGRESS_CALLBACK:
1453 if (requestp != NULL)
1454 requestp->progress_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;
1463 case DP_PROP_AUTO_DOWNLOAD:
1465 // update autodownload property as 0 in database
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;
1473 case DP_PROP_NETWORK_TYPE:
1476 // update database here
1477 if (requestp != NULL)
1478 requestp->network_type = DP_NETWORK_OFF;
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;
1487 case DP_PROP_NOTIFICATION_TYPE:
1489 int noti_type = DP_NOTIFICATION_TYPE_NONE;
1490 if (requestp != NULL)
1491 requestp->noti_type = noti_type;
1493 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) {
1494 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1495 errorcode = DP_ERROR_DISK_BUSY;
1499 case DP_PROP_NOTIFICATION_SUBJECT:
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));
1505 case DP_PROP_NOTIFICATION_DESCRIPTION:
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));
1511 case DP_PROP_NOTIFICATION_RAW:
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));
1527 TRACE_ERROR("invalid param set: %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1528 errorcode = DP_ERROR_INVALID_PARAMETER;
1532 case DP_PROP_HTTP_HEADER: // unset value by field
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);
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;
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;
1558 errorcode = DP_ERROR_INVALID_PARAMETER;
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);
1569 static int __dp_call_cancel_agent(dp_request_fmt *request)
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)
1579 TRACE_ERROR("invalid agent-id:%d id:%d", request->agent_id, request->id);
1585 static int __dp_request_controls(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1588 TRACE_ERROR("check slot memory");
1589 return DP_ERROR_INVALID_PARAMETER;
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;
1597 int errorcode = DP_ERROR_NONE;
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;
1604 errorcode = __dp_request_create(client, ipc_info);
1608 int download_state = DP_STATE_NONE;
1609 if (requestp != NULL) {
1610 download_state = requestp->state;
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;
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);
1623 TRACE_DEBUG("id:%d state:%s set property:%s", ipc_info->id, dp_print_state(download_state), dp_print_property(ipc_info->property));
1625 if (ipc_info->property == DP_PROP_START) {
1627 if (download_state == DP_STATE_COMPLETED ||
1628 download_state == DP_STATE_DOWNLOADING) {
1629 errorcode = DP_ERROR_INVALID_STATE;
1632 if (requestp == NULL) { // load from databse
1634 // load and add new request to client->requests.
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;
1640 if (errorcode == DP_ERROR_NONE) {
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;
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.
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;
1659 dp_queue_manager_wake_up();
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);
1668 TRACE_DEBUG("id:%d check start error:%s", ipc_info->id, dp_print_errorcode(errorcode));
1671 } else if (ipc_info->property == DP_PROP_PAUSE) {
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;
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);
1690 requestp->state = DP_STATE_PAUSED;
1691 requestp->error = DP_ERROR_NONE;
1696 } else if (ipc_info->property == DP_PROP_CANCEL) {
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;
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);
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);
1727 } else if (ipc_info->property == DP_PROP_DESTROY) {
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);
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);
1744 requestp->state = DP_STATE_CANCELED;
1746 if (requestp->state == DP_STATE_QUEUED || requestp->state == DP_STATE_CANCELED) {
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);
1754 requestp->agent_id = -1;
1756 errorcode = dp_request_destroy(client, ipc_info, requestp);
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));
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);
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;
1785 static int __dp_client_requests(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info)
1788 TRACE_ERROR("check slot memory");
1789 return DP_ERROR_INVALID_PARAMETER;
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;
1797 int errorcode = DP_ERROR_NONE;
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
1805 requestp = client->requests;
1806 errorcode = DP_ERROR_ID_NOT_FOUND;
1807 for (; i < MAX_DOWNLOAD_HANDLE; i++) {
1808 if (requestp == NULL)
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;
1815 requestp = requestp->next;
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;
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));
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;
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;
1850 switch (ipc_info->section) {
1851 case DP_SEC_CONTROL:
1852 errorcode = __dp_request_controls(slot, ipc_info, requestp);
1855 errorcode = __dp_request_get_info(client, ipc_info, requestp);
1858 errorcode = __dp_request_set_info(slot, ipc_info, requestp);
1861 errorcode = __dp_request_unset_info(client, ipc_info, requestp);
1864 errorcode = DP_ERROR_INVALID_PARAMETER;
1870 static void __dp_client_stop_all_requests(dp_client_slots_fmt *slot)
1872 unsigned push_count = 0;
1873 int errorcode = DP_ERROR_NONE;
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);
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?
1901 tailp = tailp->next;
1904 dp_queue_manager_wake_up();
1907 void dp_client_sig_handler(int signo)
1909 TRACE_INFO("thread:%lu signal:%d", pthread_self(), signo);
1912 void *dp_client_request_thread(void *arg)
1914 dp_client_slots_fmt *slot = (dp_client_slots_fmt *)arg;
1916 TRACE_ERROR("slot null, can not launch the thread for client");
1920 // wait detaching thread
1921 CLIENT_MUTEX_LOCK(&slot->mutex);
1923 TRACE_INFO("slot %p thread:%lu", slot, slot->thread);
1925 struct sigaction act = {{0},};
1927 sigemptyset(&newmask);
1928 sigaddset(&newmask, SIGUSR1);
1929 act.sa_handler = dp_client_sig_handler;
1930 sigaction(SIGUSR1, &act, NULL);
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
1938 CLIENT_MUTEX_UNLOCK(&slot->mutex);
1940 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
1942 while (slot != NULL && client_sock >= 0 &&
1943 client_sock == slot->client.channel) {
1945 memset(&timeout, 0x00, sizeof(struct timeval));
1946 timeout.tv_sec = DP_CARE_CLIENT_REQUEST_INTERVAL;
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);
1960 TRACE_ERROR("interrupted by client-manager sock:%d", client_sock);
1964 if (FD_ISSET(client_sock, &imask) > 0) {
1966 CLIENT_MUTEX_LOCK(&slot->mutex);
1968 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1969 client->access_time = (int)time(NULL);
1971 errorcode = DP_ERROR_NONE;
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;
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),
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);
1996 if (errorcode == DP_ERROR_NONE) {
1998 errorcode = __dp_client_requests(slot, ipc_info);
2004 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
2005 CLIENT_MUTEX_UNLOCK(&slot->mutex);
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);
2015 } else if (FD_ISSET(client_sock, &emask) > 0) {
2016 TRACE_ERROR("[EXCEPTION]");
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);
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));
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);
2040 CLIENT_MUTEX_UNLOCK(&slot->mutex);
2045 FD_CLR(client_sock, &imask);
2046 FD_CLR(client_sock, &emask);
2048 // if no requests, clear slot after disconnect with client.
2049 CLIENT_MUTEX_LOCK(&slot->mutex);
2051 TRACE_INFO("thread done slot %p thread:%lu", slot, slot->thread);
2053 slot->thread = 0;// to prevent kill thread twice
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;
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);
2072 TRACE_DEBUG("request %d remain: id:%d state:%s", i, tailp->id, dp_print_state(tailp->state));
2074 tailp = tailp->next;
2077 // if no requests after clear finished requests.
2078 if (slot->client.requests == NULL) {
2079 dp_client_slot_free(slot);
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;
2089 TRACE_INFO("thread done slot %p thread:%lu sock:%d", slot, slot->thread, client_sock);
2090 CLIENT_MUTEX_UNLOCK(&slot->mutex);