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 char *dp_print_state(int state)
52 case DP_STATE_CONNECTING:
54 case DP_STATE_DOWNLOADING:
58 case DP_STATE_COMPLETED:
60 case DP_STATE_CANCELED:
70 char *dp_print_errorcode(int errorcode)
75 case DP_ERROR_INVALID_PARAMETER:
76 return "INVALID_PARAMETER";
77 case DP_ERROR_OUT_OF_MEMORY:
78 return "OUT_OF_MEMORY";
79 case DP_ERROR_IO_ERROR:
81 case DP_ERROR_NETWORK_UNREACHABLE:
82 return "NETWORK_UNREACHABLE";
83 case DP_ERROR_CONNECTION_TIMED_OUT:
84 return "CONNECTION_TIMED_OUT";
85 case DP_ERROR_NO_SPACE:
87 case DP_ERROR_FIELD_NOT_FOUND:
88 return "FIELD_NOT_FOUND";
89 case DP_ERROR_INVALID_STATE:
90 return "INVALID_STATE";
91 case DP_ERROR_CONNECTION_FAILED:
92 return "CONNECTION_FAILED";
93 case DP_ERROR_INVALID_URL:
95 case DP_ERROR_INVALID_DESTINATION:
96 return "INVALID_DESTINATION";
97 case DP_ERROR_QUEUE_FULL:
99 case DP_ERROR_ALREADY_COMPLETED:
100 return "ALREADY_COMPLETED";
101 case DP_ERROR_FILE_ALREADY_EXISTS:
102 return "FILE_ALREADY_EXISTS";
103 case DP_ERROR_TOO_MANY_DOWNLOADS:
104 return "TOO_MANY_DOWNLOADS";
105 case DP_ERROR_NO_DATA:
107 case DP_ERROR_UNHANDLED_HTTP_CODE:
108 return "UNHANDLED_HTTP_CODE";
109 case DP_ERROR_CANNOT_RESUME:
110 return "CANNOT_RESUME";
111 case DP_ERROR_PERMISSION_DENIED:
112 return "PERMISSION_DENIED";
113 case DP_ERROR_RESPONSE_TIMEOUT:
114 return "RESPONSE_TIMEOUT";
115 case DP_ERROR_REQUEST_TIMEOUT:
116 return "REQUEST_TIMEOUT";
117 case DP_ERROR_SYSTEM_DOWN:
118 return "SYSTEM_DOWN";
119 case DP_ERROR_CLIENT_DOWN:
120 return "CLIENT_DOWN";
121 case DP_ERROR_DISK_BUSY:
123 case DP_ERROR_ID_NOT_FOUND:
124 return "ID_NOT_FOUND";
131 char *dp_print_section(short section)
154 char *dp_print_property(unsigned property)
167 case DP_PROP_DESTROY:
171 case DP_PROP_DESTINATION:
172 return "DESTINATION";
173 case DP_PROP_FILENAME:
175 case DP_PROP_STATE_CALLBACK:
177 case DP_PROP_PROGRESS_CALLBACK:
178 return "PROGRESS_CB";
179 case DP_PROP_AUTO_DOWNLOAD:
180 return "AUTO_DOWNLOAD";
181 case DP_PROP_NETWORK_TYPE:
182 return "NETWORK_TYPE";
183 case DP_PROP_NETWORK_BONDING:
184 return "NETWORK_BONDING";
185 case DP_PROP_SAVED_PATH:
187 case DP_PROP_TEMP_SAVED_PATH:
188 return "TEMP_SAVED_PATH";
189 case DP_PROP_MIME_TYPE:
191 case DP_PROP_RECEIVED_SIZE:
192 return "RECEIVED_SIZE";
193 case DP_PROP_TOTAL_FILE_SIZE:
194 return "TOTAL_FILE_SIZE";
195 case DP_PROP_CONTENT_NAME:
196 return "CONTENT_NAME";
197 case DP_PROP_HTTP_STATUS:
198 return "HTTP_STATUS";
205 case DP_PROP_NOTIFICATION_RAW:
206 return "NOTIFICATION_RAW";
207 case DP_PROP_NOTIFICATION_SUBJECT:
208 return "NOTIFICATION_SUBJECT";
209 case DP_PROP_NOTIFICATION_DESCRIPTION:
210 return "NOTIFICATION_DESCRIPTION";
211 case DP_PROP_NOTIFICATION_TYPE:
212 return "NOTIFICATION_TYPE";
213 case DP_PROP_HTTP_HEADERS:
214 return "HTTP_HEADERS";
215 case DP_PROP_HTTP_HEADER:
216 return "HTTP_HEADER";
223 static int __dp_get_download_id(dp_client_fmt *client)
225 int download_id = -1;
226 int check_duplicate = 1;
228 int errorcode = DP_ERROR_NONE;
231 if (dp_db_get_max_download_id(client->dbhandle,
232 DP_TABLE_LOGGING, &download_id, &errorcode) < 0) {
233 TRACE_ERROR("ERROR [%d]", errorcode);
234 // database is empty start with id : 1
235 download_id = DP_FIRST_DOWNLOAD_ID;
237 if (download_id < INT_MAX)
244 if (download_id < INT_MAX) {
245 TRACE_DEBUG("download_id [%d]", download_id);
246 check_duplicate = dp_db_check_duplicated_int(client->dbhandle,
247 DP_TABLE_LOGGING, DP_DB_COL_ID, download_id, &errorcode);
248 if (errorcode == DP_ERROR_NONE) {
249 if (check_duplicate == 0)
252 TRACE_ERROR("ERROR [%d]", errorcode);
254 if (retry_count < 3) {
256 } else if (retry_count < 10) {
257 gettimeofday(&tval, NULL);
258 tval.tv_usec = (tval.tv_usec & 0x0fff);
259 download_id += 1171 * retry_count + tval.tv_usec;
260 } else if (retry_count < 20) {
261 gettimeofday(&tval, NULL);
262 tval.tv_usec = (tval.tv_usec & 0xff33ff) + retry_count;
263 download_id += tval.tv_usec;
265 TRACE_ERROR("failed to generate unique download_id [%d]", download_id);
269 TRACE_ERROR("reached INT_MAX limit");
270 download_id = DP_FIRST_DOWNLOAD_ID;
272 } while (check_duplicate != 0);
276 void dp_request_create(dp_client_fmt *client, dp_request_fmt *request)
279 // find the tail of linked list & check limitation
281 dp_request_fmt *tailp = client->requests;
282 dp_request_fmt *prevp = NULL;
283 for (; i < MAX_DOWNLOAD_HANDLE; i++) {
286 TRACE_DEBUG("link %d info: id:%d access-time:%d", i, tailp->id, tailp->access_time);
290 request->next = NULL;
291 if (prevp == NULL) // it's first link
292 client->requests = request;
294 prevp->next = request; // attach at the tail
296 TRACE_DEBUG("sock:%d download-id:%d", client->channel, request->id);
299 static int __dp_request_create(dp_client_fmt *client, dp_ipc_fmt *ipc_info)
301 int errorcode = DP_ERROR_NONE;
303 int download_id = __dp_get_download_id(client);
305 // allocation new request.
306 dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt));
307 if (request == NULL) {
308 TRACE_ERROR("check memory sock:%d download-id:%d", client->channel, download_id);
309 return DP_ERROR_OUT_OF_MEMORY;
312 if (dp_db_new_logging(client->dbhandle, download_id, DP_STATE_READY, DP_ERROR_NONE, &errorcode) < 0) {
313 TRACE_ERROR("new log sock:%d download-id:%d errorcode:%s", client->channel, download_id, dp_print_errorcode(errorcode));
318 request->id = download_id;
319 request->agent_id = -1;
320 request->state = DP_STATE_READY;
321 request->error = DP_ERROR_NONE;
322 request->network_type = DP_NETWORK_ALL;
323 request->access_time = (int)time(NULL);
324 request->state_cb = 0;
325 request->progress_cb = 0;
326 request->startcount = 0;
327 request->noti_type = DP_NOTIFICATION_TYPE_NONE;
328 request->progress_lasttime = 0;
329 request->received_size = 0;
330 request->content_type = DP_CONTENT_UNKNOWN;
331 request->file_size = 0;
332 request->noti_priv_id = -1;
334 dp_request_create(client, request);
335 ipc_info->id = download_id;
339 void dp_request_free(dp_request_fmt *request)
341 // free notification handle here
342 TRACE_DEBUG("destory id:%d", request->id);
346 void dp_client_clear_requests(void *slotp)
348 dp_client_slots_fmt *slot = (dp_client_slots_fmt *)slotp;
350 TRACE_ERROR("check slot memory");
353 dp_client_fmt *client = &slot->client;
355 int now_time = (int)time(NULL);
357 unsigned queued_count = 0;
358 unsigned ongoing_count = 0;
359 dp_request_fmt *tailp = client->requests;
360 dp_request_fmt *prevp = NULL;
361 for (; tailp != NULL; i++) {
363 unsigned can_unload = 0;
364 if (tailp->id <= 0 || tailp->state == DP_STATE_NONE) {
365 TRACE_ERROR("id:%d unexpected request (%d/%d)", tailp->id, tailp->access_time, now_time);
367 } else if (tailp->access_time > 0 &&
368 (now_time - tailp->access_time) > DP_CARE_CLIENT_CLEAR_INTERVAL) {
369 // check accesstime. if difference is bigger than DP_CARE_CLIENT_CLEAR_INTERVAL, clear.
371 if (tailp->state == DP_STATE_READY ||
372 tailp->state == DP_STATE_COMPLETED ||
373 tailp->state == DP_STATE_CANCELED ||
374 tailp->state == DP_STATE_FAILED) {
376 } else if (tailp->state == DP_STATE_CONNECTING) { // it take 120 sec over to connect. it means zombie.
377 TRACE_ERROR("id:%d connection timeout (%d/%d)", tailp->id, tailp->access_time, now_time);
378 if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0)
379 TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id);
380 tailp->state = DP_STATE_FAILED;
381 tailp->error = DP_ERROR_CONNECTION_TIMED_OUT;
382 if (tailp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
383 tailp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
384 if (dp_notification_manager_push_notification(slot, tailp, DP_NOTIFICATION) < 0)
385 TRACE_ERROR("failed to register notification for id:%d", tailp->id);
388 } else if (tailp->state == DP_STATE_PAUSED &&
389 dp_is_alive_download(tailp->agent_id) == 0) {
390 // paused & agent_id not exist.... unload from memory.
391 TRACE_ERROR("id:%d hanged as paused (%d/%d)", tailp->id, tailp->access_time, now_time);
395 if (can_unload == 1) {
396 dp_request_fmt *removep = tailp;
397 if (prevp == NULL) // first request.
398 client->requests = tailp->next;
400 prevp->next = tailp->next;
402 TRACE_DEBUG("request %d clear: id:%d state:%s", i, removep->id, dp_print_state(removep->state));
403 dp_request_free(removep);
409 if (tailp->state == DP_STATE_QUEUED)
415 TRACE_DEBUG("info requests:%d queued:%d", ongoing_count, queued_count);
416 if (queued_count > 0)
417 dp_queue_manager_wake_up();
420 int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
422 int errorcode = DP_ERROR_NONE;
424 if (requestp != NULL && client->requests != NULL) {
425 if (requestp == client->requests) {
426 // cancel downloading ... after checking status
427 client->requests = requestp->next;
428 dp_request_free(requestp);
431 dp_request_fmt *prevp = client->requests;
432 dp_request_fmt *removep = client->requests->next;
433 for (; i < MAX_DOWNLOAD_HANDLE; i++) {
434 if (removep == NULL) {
435 errorcode = DP_ERROR_ID_NOT_FOUND;
438 if (removep == requestp) {
439 // cancel downloading ... after checking status
440 prevp->next = removep->next;
441 dp_request_free(removep);
445 removep = removep->next;
450 TRACE_DEBUG("sock:%d id:%d errorcode:%s", client->channel,
451 (ipc_info) ? ipc_info->id : -1, dp_print_errorcode(errorcode));
456 static int __dp_request_read_int(int sock, dp_ipc_fmt *ipc_info, int *value)
458 int errorcode = DP_ERROR_NONE;
459 if (ipc_info->size == sizeof(int)) {
460 if (dp_ipc_read(sock, value, ipc_info->size, __FUNCTION__) < 0) {
461 TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size);
462 errorcode = DP_ERROR_IO_ERROR;
465 errorcode = DP_ERROR_IO_ERROR;
470 static int __dp_request_feedback_string(int sock, dp_ipc_fmt *ipc_info, void *string, size_t length, int errorvalue)
472 int errorcode = DP_ERROR_NONE;
474 if (length == 0 && errorvalue == DP_ERROR_NONE)
475 errorvalue = DP_ERROR_NO_DATA;
477 if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, length * sizeof(char)) < 0) {
478 errorcode = DP_ERROR_IO_ERROR;
479 TRACE_ERROR("sock:%d check ipc length:%d", sock, length);
481 if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) {
482 if (dp_ipc_write(sock, string, sizeof(char) * length) < 0) {
483 errorcode = DP_ERROR_IO_ERROR;
484 TRACE_ERROR("sock:%d check ipc length:%d", sock, length);
490 static int __dp_request_read_string(int sock, dp_ipc_fmt *ipc_info, char **string)
492 int errorcode = DP_ERROR_NONE;
493 if (ipc_info->size > 0) {
494 char *recv_str = (char *)calloc((ipc_info->size + (size_t)1), sizeof(char));
495 if (recv_str == NULL) {
496 TRACE_ERROR("sock:%d check memory length:%d", sock, ipc_info->size);
497 errorcode = DP_ERROR_OUT_OF_MEMORY;
499 if (dp_ipc_read(sock, recv_str, ipc_info->size, __FUNCTION__) <= 0) {
500 TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size);
501 errorcode = DP_ERROR_IO_ERROR;
504 recv_str[ipc_info->size] = '\0';
505 TRACE_DEBUG("sock:%d length:%d string:%s", sock, ipc_info->size, recv_str);
510 errorcode = DP_ERROR_IO_ERROR;
515 static int __dp_request_feedback_int(int sock, dp_ipc_fmt *ipc_info, void *value, int errorvalue, size_t extra_size)
517 int errorcode = DP_ERROR_NONE;
518 if (errorvalue != DP_ERROR_NONE)
520 if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, extra_size) < 0) {
521 errorcode = DP_ERROR_IO_ERROR;
522 TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size);
524 if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) {
525 if (dp_ipc_write(sock, value, extra_size) < 0) {
526 errorcode = DP_ERROR_IO_ERROR;
527 TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size);
533 static int __dp_request_get_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
535 int errorcode = DP_ERROR_NONE;
536 switch (ipc_info->property) {
541 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (unsigned char **)&string, &length, &errorcode) < 0) {
542 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
543 errorcode = DP_ERROR_NO_DATA;
545 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
546 if (result == DP_ERROR_IO_ERROR) {
547 errorcode = DP_ERROR_IO_ERROR;
548 TRACE_ERROR("check ipc sock:%d", client->channel);
553 case DP_PROP_DESTINATION:
557 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (unsigned char **)&string, &length, &errorcode) < 0) {
558 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
559 errorcode = DP_ERROR_NO_DATA;
561 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
562 if (result == DP_ERROR_IO_ERROR) {
563 errorcode = DP_ERROR_IO_ERROR;
564 TRACE_ERROR("check ipc sock:%d", client->channel);
569 case DP_PROP_FILENAME:
573 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (unsigned char **)&string, &length, &errorcode) < 0) {
574 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
575 errorcode = DP_ERROR_NO_DATA;
577 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
578 if (result == DP_ERROR_IO_ERROR) {
579 errorcode = DP_ERROR_IO_ERROR;
580 TRACE_ERROR("check ipc sock:%d", client->channel);
585 case DP_PROP_STATE_CALLBACK:
588 if (requestp != NULL) {
589 callback = requestp->state_cb;
591 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, &callback, &errorcode) < 0) {
592 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
593 errorcode = DP_ERROR_NO_DATA;
596 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int));
597 if (result == DP_ERROR_IO_ERROR) {
598 errorcode = DP_ERROR_IO_ERROR;
599 TRACE_ERROR("check ipc sock:%d", client->channel);
603 case DP_PROP_PROGRESS_CALLBACK:
606 if (requestp != NULL) {
607 callback = requestp->progress_cb;
609 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, &callback, &errorcode) < 0) {
610 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
611 errorcode = DP_ERROR_NO_DATA;
614 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int));
615 if (result == DP_ERROR_IO_ERROR) {
616 errorcode = DP_ERROR_IO_ERROR;
617 TRACE_ERROR("check ipc sock:%d", client->channel);
621 case DP_PROP_AUTO_DOWNLOAD:
623 int autodownload = 0;
624 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, &autodownload, &errorcode) < 0) {
625 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
626 errorcode = DP_ERROR_NO_DATA;
628 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&autodownload, errorcode, sizeof(int));
629 if (result == DP_ERROR_IO_ERROR) {
630 errorcode = DP_ERROR_IO_ERROR;
631 TRACE_ERROR("check ipc sock:%d", client->channel);
635 case DP_PROP_NETWORK_TYPE:
638 if (requestp != NULL) {
639 network = requestp->network_type;
641 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, &network, &errorcode) < 0) {
642 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
643 errorcode = DP_ERROR_NO_DATA;
646 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network, errorcode, sizeof(int));
647 if (result == DP_ERROR_IO_ERROR) {
648 errorcode = DP_ERROR_IO_ERROR;
649 TRACE_ERROR("check ipc sock:%d", client->channel);
653 case DP_PROP_NETWORK_BONDING:
655 int network_bonding = 0;
656 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, &network_bonding, &errorcode) < 0) {
657 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
658 errorcode = DP_ERROR_NO_DATA;
660 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network_bonding, errorcode, sizeof(int));
661 if (result == DP_ERROR_IO_ERROR) {
662 errorcode = DP_ERROR_IO_ERROR;
663 TRACE_ERROR("check ipc sock:%d", client->channel);
667 case DP_PROP_SAVED_PATH:
671 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) {
672 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
673 errorcode = DP_ERROR_NO_DATA;
675 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
676 if (result == DP_ERROR_IO_ERROR) {
677 errorcode = DP_ERROR_IO_ERROR;
678 TRACE_ERROR("check ipc sock:%d", client->channel);
683 case DP_PROP_TEMP_SAVED_PATH:
687 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) {
688 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
689 errorcode = DP_ERROR_NO_DATA;
691 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
692 if (result == DP_ERROR_IO_ERROR) {
693 errorcode = DP_ERROR_IO_ERROR;
694 TRACE_ERROR("check ipc sock:%d", client->channel);
699 case DP_PROP_MIME_TYPE:
703 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_MIMETYPE, (unsigned char **)&string, &length, &errorcode) < 0) {
704 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
705 errorcode = DP_ERROR_NO_DATA;
707 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
708 if (result == DP_ERROR_IO_ERROR) {
709 errorcode = DP_ERROR_IO_ERROR;
710 TRACE_ERROR("check ipc sock:%d", client->channel);
715 case DP_PROP_RECEIVED_SIZE:
717 unsigned long long recv_size = 0;
718 if (requestp != NULL)
719 recv_size = requestp->received_size;
721 errorcode = DP_ERROR_INVALID_STATE;
723 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&recv_size, errorcode, sizeof(unsigned long long));
724 if (result == DP_ERROR_IO_ERROR) {
725 errorcode = DP_ERROR_IO_ERROR;
726 TRACE_ERROR("check ipc sock:%d", client->channel);
730 case DP_PROP_TOTAL_FILE_SIZE:
732 unsigned long long file_size = 0;
733 if (requestp != NULL) {
734 file_size = requestp->file_size;
736 // load content_size(INT64) from database;
737 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, &file_size, &errorcode) < 0) {
738 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
739 errorcode = DP_ERROR_NO_DATA;
742 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&file_size, errorcode, sizeof(unsigned long long));
743 if (result == DP_ERROR_IO_ERROR) {
744 errorcode = DP_ERROR_IO_ERROR;
745 TRACE_ERROR("check ipc sock:%d", client->channel);
749 case DP_PROP_CONTENT_NAME:
753 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&string, &length, &errorcode) < 0) {
754 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
755 errorcode = DP_ERROR_NO_DATA;
757 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
758 if (result == DP_ERROR_IO_ERROR) {
759 errorcode = DP_ERROR_IO_ERROR;
760 TRACE_ERROR("check ipc sock:%d", client->channel);
765 case DP_PROP_HTTP_STATUS:
768 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_HTTP_STATUS, &httpstatus, &errorcode) < 0) {
769 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
770 errorcode = DP_ERROR_NO_DATA;
772 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&httpstatus, errorcode, sizeof(int));
773 if (result == DP_ERROR_IO_ERROR) {
774 errorcode = DP_ERROR_IO_ERROR;
775 TRACE_ERROR("check ipc sock:%d", client->channel);
783 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (unsigned char **)&string, &length, &errorcode) < 0) {
784 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
785 errorcode = DP_ERROR_NO_DATA;
787 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
788 if (result == DP_ERROR_IO_ERROR) {
789 errorcode = DP_ERROR_IO_ERROR;
790 TRACE_ERROR("check ipc sock:%d", client->channel);
797 int state = DP_STATE_NONE;
798 if (requestp != NULL) {
799 state = requestp->state;
801 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &state, &errorcode) < 0) {
802 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
803 errorcode = DP_ERROR_ID_NOT_FOUND;
806 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&state, errorcode, sizeof(int));
807 if (result == DP_ERROR_IO_ERROR) {
808 errorcode = DP_ERROR_IO_ERROR;
809 TRACE_ERROR("check ipc sock:%d", client->channel);
815 int errorvalue = DP_ERROR_NONE;
816 if (requestp != NULL) {
817 errorvalue = requestp->error;
819 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_ERRORCODE, &errorvalue, &errorcode) < 0) {
820 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
821 errorcode = DP_ERROR_ID_NOT_FOUND;
824 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&errorvalue, errorcode, sizeof(int));
825 if (result == DP_ERROR_IO_ERROR) {
826 errorcode = DP_ERROR_IO_ERROR;
827 TRACE_ERROR("check ipc sock:%d", client->channel);
831 case DP_PROP_NOTIFICATION_TYPE:
834 if (requestp != NULL) {
835 noti_type = requestp->noti_type;
836 // if already notification, unregister from notification bar.
838 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, ¬i_type, &errorcode) < 0) {
839 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
840 errorcode = DP_ERROR_NO_DATA;
843 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)¬i_type, errorcode, sizeof(int));
844 if (result == DP_ERROR_IO_ERROR) {
845 errorcode = DP_ERROR_IO_ERROR;
846 TRACE_ERROR("check ipc sock:%d", client->channel);
850 case DP_PROP_NOTIFICATION_SUBJECT:
854 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&string, &length, &errorcode) < 0) {
855 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
856 errorcode = DP_ERROR_NO_DATA;
858 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
859 if (result == DP_ERROR_IO_ERROR) {
860 errorcode = DP_ERROR_IO_ERROR;
861 TRACE_ERROR("check ipc sock:%d", client->channel);
866 case DP_PROP_NOTIFICATION_DESCRIPTION:
870 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (unsigned char **)&string, &length, &errorcode) < 0) {
871 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
872 errorcode = DP_ERROR_NO_DATA;
874 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
875 if (result == DP_ERROR_IO_ERROR) {
876 errorcode = DP_ERROR_IO_ERROR;
877 TRACE_ERROR("check ipc sock:%d", client->channel);
882 case DP_PROP_NOTIFICATION_RAW: // read type, send raw binary for type
884 int bundle_type = -1;
885 errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type);
886 TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type);
887 char *raw_column = NULL;
888 if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING)
889 raw_column = DP_DB_COL_NOTI_RAW_ONGOING;
890 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE)
891 raw_column = DP_DB_COL_NOTI_RAW_COMPLETE;
892 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED)
893 raw_column = DP_DB_COL_NOTI_RAW_FAIL;
895 if (raw_column == NULL) {
896 errorcode = DP_ERROR_INVALID_PARAMETER;
897 TRACE_ERROR("invalid type %s type:%d", dp_print_property(ipc_info->property), bundle_type);
898 if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, ipc_info->property, errorcode, 0) < 0) {
899 errorcode = DP_ERROR_IO_ERROR;
900 TRACE_ERROR("check ipc sock:%d", client->channel);
903 if (errorcode == DP_ERROR_NONE) {
904 unsigned char *raws_buffer = NULL;
906 // get blob binary from database by raw_column
907 if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &raws_buffer, &length, &errorcode) < 0) {
908 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
909 errorcode = DP_ERROR_NO_DATA;
911 int result = __dp_request_feedback_string(client->channel, ipc_info, raws_buffer, (size_t)length, errorcode);
912 if (result == DP_ERROR_IO_ERROR) {
913 errorcode = DP_ERROR_IO_ERROR;
914 TRACE_ERROR("check ipc sock:%d", client->channel);
920 case DP_PROP_HTTP_HEADERS:
923 // 2. send the number of header fields by id
924 // 3. send response & field string for each fields
925 int field_count = dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ID, ipc_info->id, &errorcode);
926 if (field_count < 0) {
927 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
928 errorcode = DP_ERROR_DISK_BUSY;
931 int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&field_count, errorcode, sizeof(int));
932 if (result == DP_ERROR_IO_ERROR) {
933 errorcode = DP_ERROR_IO_ERROR;
934 TRACE_ERROR("check ipc sock:%d", client->channel);
935 } else if (field_count > 0) {
936 // get fields from database.
937 int *ids = (int *)calloc(field_count, sizeof(int));
939 TRACE_ERROR("failed to allocate the clients");
940 errorcode = DP_ERROR_OUT_OF_MEMORY;
942 // getting ids of clients
944 int rows_count = dp_db_get_cond_ids(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, DP_DB_COL_ID, ipc_info->id, ids, field_count, &errorcode);
945 for (; i < rows_count; i++) {
948 if (dp_db_get_cond_string(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, ids[i], DP_DB_COL_HEADER_FIELD, (unsigned char **)&string, &length, &errorcode) < 0) {
949 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
950 errorcode = DP_ERROR_NO_DATA;
952 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
954 if (result == DP_ERROR_IO_ERROR) {
955 errorcode = DP_ERROR_IO_ERROR;
956 TRACE_ERROR("check ipc sock:%d", client->channel);
966 case DP_PROP_HTTP_HEADER:
968 // 1. read field string
969 // 2. response with extra size
971 char *header_field = NULL;
974 errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
975 if (errorcode == DP_ERROR_NONE && header_field != NULL) {
976 if (dp_db_get_header_value(client->dbhandle, ipc_info->id, header_field, (unsigned char **)&string, &length, &errorcode) < 0) {
977 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
978 errorcode = DP_ERROR_NO_DATA;
981 if (errorcode != DP_ERROR_NONE)
982 TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
983 if (header_field == NULL) {
984 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
985 errorcode = DP_ERROR_INVALID_PARAMETER;
988 int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode);
989 if (result == DP_ERROR_IO_ERROR) {
990 errorcode = DP_ERROR_IO_ERROR;
991 TRACE_ERROR("check ipc sock:%d", client->channel);
998 errorcode = DP_ERROR_INVALID_PARAMETER;
1004 static int __dp_request_set_info(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1007 TRACE_ERROR("check slot memory");
1008 return DP_ERROR_INVALID_PARAMETER;
1010 dp_client_fmt *client = &slot->client;
1011 if (client == NULL || ipc_info == NULL) {
1012 TRACE_ERROR("check client or ipc info.");
1013 return DP_ERROR_INVALID_PARAMETER;
1016 int errorcode = DP_ERROR_NONE;
1018 // if completed or downloading, invalid state.
1019 int download_state = DP_STATE_NONE;
1020 if (requestp != NULL) {
1021 download_state = requestp->state;
1023 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) {
1024 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
1025 errorcode = DP_ERROR_ID_NOT_FOUND;
1027 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1028 ipc_info->property, errorcode, 0) < 0) {
1029 TRACE_ERROR("check ipc sock:%d", client->channel);
1034 // should the state be checked ?
1035 TRACE_DEBUG("state:%s set property:%s", dp_print_state(download_state), dp_print_property(ipc_info->property));
1037 switch (ipc_info->property) {
1040 char *recv_str = NULL;
1041 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1042 if (errorcode == DP_ERROR_NONE) {
1043 if (recv_str == NULL) {
1044 errorcode = DP_ERROR_INVALID_PARAMETER;
1046 // write to database here
1047 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1048 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1049 errorcode = DP_ERROR_DISK_BUSY;
1056 case DP_PROP_DESTINATION:
1058 char *recv_str = NULL;
1059 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1060 if (errorcode == DP_ERROR_NONE) {
1061 if (recv_str == NULL) {
1062 errorcode = DP_ERROR_INVALID_PARAMETER;
1064 // check here destination is available
1065 errorcode = dp_is_valid_dir(slot->credential, recv_str);
1066 if (errorcode == DP_ERROR_NONE &&
1067 dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1068 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1069 errorcode = DP_ERROR_DISK_BUSY;
1076 case DP_PROP_TEMP_SAVED_PATH:
1078 char *recv_str = NULL;
1079 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1080 if (errorcode == DP_ERROR_NONE) {
1081 if (recv_str == NULL) {
1082 errorcode = DP_ERROR_INVALID_PARAMETER;
1084 errorcode = dp_is_valid_dir(slot->credential, recv_str);
1085 if (errorcode == DP_ERROR_NONE &&
1086 dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_TEMP_FILE_PATH, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1087 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1088 errorcode = DP_ERROR_DISK_BUSY;
1095 case DP_PROP_FILENAME:
1097 char *recv_str = NULL;
1098 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1099 if (errorcode == DP_ERROR_NONE) {
1100 if (recv_str == NULL) {
1101 errorcode = DP_ERROR_INVALID_PARAMETER;
1103 // write to database here
1104 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1105 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1106 errorcode = DP_ERROR_DISK_BUSY;
1113 case DP_PROP_STATE_CALLBACK:
1116 // DP_ERROR_INVALID_STATE if downloading or finished
1117 // update database here
1118 if (requestp != NULL)
1119 requestp->state_cb = 1;
1122 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1123 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1124 errorcode = DP_ERROR_DISK_BUSY;
1128 case DP_PROP_PROGRESS_CALLBACK:
1131 // DP_ERROR_INVALID_STATE if downloading or finished
1132 // update database here
1133 if (requestp != NULL)
1134 requestp->progress_cb = 1;
1137 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1138 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1139 errorcode = DP_ERROR_DISK_BUSY;
1143 case DP_PROP_AUTO_DOWNLOAD:
1145 // update autodownload property as 1 in database
1147 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1148 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1149 errorcode = DP_ERROR_DISK_BUSY;
1153 case DP_PROP_NETWORK_TYPE:
1156 errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1157 if (recv_int <= DP_NETWORK_OFF ||
1158 recv_int > DP_NETWORK_ALL) {
1159 errorcode = DP_ERROR_INVALID_PARAMETER;
1161 // update in database
1162 if (requestp != NULL) {
1163 if (requestp->state == DP_STATE_QUEUED) {
1164 dp_queue_manager_clear_queue(requestp);
1166 requestp->network_type = recv_int;
1167 if (requestp->state == DP_STATE_CONNECTING ||
1168 requestp->state == DP_STATE_DOWNLOADING) {
1169 // pause & push queue
1170 if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) {
1171 TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id);
1173 requestp->state = DP_STATE_PAUSED;
1174 requestp->error = DP_ERROR_NONE;
1175 if (dp_queue_manager_push_queue(slot, requestp) < 0) {
1176 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0)
1177 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1178 requestp->state = DP_STATE_FAILED;
1179 requestp->error = DP_ERROR_QUEUE_FULL;
1180 errorcode = DP_ERROR_QUEUE_FULL;
1186 int enable_cb = recv_int;
1187 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1188 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1189 errorcode = DP_ERROR_DISK_BUSY;
1194 case DP_PROP_NETWORK_BONDING:
1197 errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1198 if (errorcode == DP_ERROR_NONE) {
1199 if (requestp != NULL && requestp->network_type != DP_NETWORK_ALL) {
1200 errorcode = DP_ERROR_INVALID_NETWORK_TYPE;
1201 TRACE_ERROR("[ERROR] wrong network type");
1202 } else if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, (void *)&recv_int, ipc_info->size, 0, &errorcode) < 0) {
1203 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1204 errorcode = DP_ERROR_DISK_BUSY;
1209 case DP_PROP_NOTIFICATION_TYPE:
1212 errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int);
1213 if (recv_int == DP_NOTIFICATION_TYPE_NONE ||
1214 recv_int == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
1215 recv_int == DP_NOTIFICATION_TYPE_ALL) {
1216 // check state request->state == DP_STATE_COMPLETED
1217 // DP_ERROR_INVALID_STATE
1218 // update notificatio type in database
1219 int noti_type = recv_int;
1220 if (requestp != NULL) {
1221 if (recv_int < requestp->noti_type) {
1222 // if already notification, unregister from notification bar.
1223 if (recv_int == DP_NOTIFICATION_TYPE_NONE) {
1224 if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION) < 0)
1225 TRACE_ERROR("failed to clear notification %s", dp_print_property(ipc_info->property));
1227 if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0)
1228 TRACE_ERROR("failed to clear ongoing %s", dp_print_property(ipc_info->property));
1230 requestp->noti_type = recv_int;
1232 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) {
1233 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1234 errorcode = DP_ERROR_DISK_BUSY;
1237 errorcode = DP_ERROR_INVALID_PARAMETER;
1241 case DP_PROP_NOTIFICATION_SUBJECT:
1243 char *recv_str = NULL;
1244 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1245 if (errorcode == DP_ERROR_NONE) {
1246 if (recv_str == NULL) {
1247 errorcode = DP_ERROR_INVALID_PARAMETER;
1249 // write to database here
1250 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1251 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1252 errorcode = DP_ERROR_DISK_BUSY;
1259 case DP_PROP_NOTIFICATION_DESCRIPTION:
1261 char *recv_str = NULL;
1262 errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str);
1263 if (errorcode == DP_ERROR_NONE) {
1264 if (recv_str == NULL) {
1265 errorcode = DP_ERROR_INVALID_PARAMETER;
1267 // write to database here
1268 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) {
1269 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1270 errorcode = DP_ERROR_DISK_BUSY;
1277 case DP_PROP_NOTIFICATION_RAW: // bundle_type(db column) + bundle_binary
1279 int bundle_type = -1;
1280 errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type);
1281 TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1282 char *raw_column = NULL;
1283 if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING)
1284 raw_column = DP_DB_COL_NOTI_RAW_ONGOING;
1285 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE)
1286 raw_column = DP_DB_COL_NOTI_RAW_COMPLETE;
1287 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED)
1288 raw_column = DP_DB_COL_NOTI_RAW_FAIL;
1290 errorcode = DP_ERROR_INVALID_PARAMETER;
1292 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1293 ipc_info->property, errorcode, 0) < 0) {
1294 TRACE_ERROR("check ipc sock:%d", client->channel);
1295 errorcode = DP_ERROR_IO_ERROR;
1297 if (errorcode == DP_ERROR_NONE) {
1298 dp_ipc_fmt *raw_info = dp_ipc_get_fmt(client->channel);
1299 if (raw_info == NULL || raw_info->section != ipc_info->section ||
1300 raw_info->property != ipc_info->property ||
1301 (raw_info->id != ipc_info->id)) {
1302 TRACE_ERROR("there is a confusion waiting raw binary in %s section", dp_print_property(ipc_info->property));
1303 errorcode = DP_ERROR_IO_ERROR;
1305 if (raw_info != NULL && raw_info->size > 0 && raw_info->size < SIZE_MAX) {
1306 unsigned char *recv_raws = (unsigned char *)calloc(raw_info->size, sizeof(unsigned char));
1307 if (recv_raws == NULL) {
1308 TRACE_ERROR("sock:%d check memory length:%d", client->channel, raw_info->size);
1309 errorcode = DP_ERROR_OUT_OF_MEMORY;
1311 if (dp_ipc_read(client->channel, recv_raws, raw_info->size, __FUNCTION__) <= 0) {
1312 TRACE_ERROR("sock:%d check ipc length:%d", client->channel, raw_info->size);
1313 errorcode = DP_ERROR_IO_ERROR;
1315 TRACE_DEBUG("sock:%d length:%d raws", client->channel, raw_info->size);
1317 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, (void *)recv_raws, raw_info->size, 3, &errorcode) < 0) {
1318 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1319 errorcode = DP_ERROR_DISK_BUSY;
1325 errorcode = DP_ERROR_IO_ERROR;
1331 case DP_PROP_HTTP_HEADER: // a request can have one or more fields, a fields can have only one value.
1333 char *header_field = NULL;
1334 char *header_value = NULL;
1335 // 1. read field string
1336 // 2. response after checking sql status
1337 // 3. read query IPC for checking IPC
1338 // 4. read value string
1340 errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
1341 if (errorcode == DP_ERROR_NONE && header_field != NULL) {
1343 int check_field = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode);
1344 if (check_field < 0) {
1345 errorcode = DP_ERROR_DISK_BUSY;
1347 errorcode = DP_ERROR_NONE;
1349 if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section,
1350 ipc_info->property, errorcode, 0) < 0) {
1351 TRACE_ERROR("check ipc sock:%d", client->channel);
1352 errorcode = DP_ERROR_IO_ERROR;
1354 dp_ipc_fmt *header_ipc = dp_ipc_get_fmt(client->channel);
1355 if (header_ipc == NULL || header_ipc->section != ipc_info->section ||
1356 header_ipc->property != ipc_info->property ||
1357 (header_ipc->id != ipc_info->id)) {
1358 TRACE_ERROR("there is a confusion during waiting http string in %s section", dp_print_property(ipc_info->property));
1359 errorcode = DP_ERROR_IO_ERROR;
1361 errorcode = __dp_request_read_string(client->channel, header_ipc, &header_value);
1362 if (errorcode == DP_ERROR_NONE && header_value != NULL) {
1363 if (check_field == 0) { // insert
1364 if (dp_db_new_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) {
1365 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1366 errorcode = DP_ERROR_DISK_BUSY;
1369 if (dp_db_update_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) {
1370 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1371 errorcode = DP_ERROR_DISK_BUSY;
1375 if (errorcode != DP_ERROR_NONE)
1376 TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1377 if (header_value == NULL) {
1378 TRACE_ERROR("failed to set %s, do you want to run as unset?", dp_print_property(ipc_info->property));
1379 errorcode = DP_ERROR_INVALID_PARAMETER;
1387 if (errorcode != DP_ERROR_NONE)
1388 TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1389 if (header_field == NULL) {
1390 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1391 errorcode = DP_ERROR_INVALID_PARAMETER;
1399 errorcode = DP_ERROR_INVALID_PARAMETER;
1403 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1404 ipc_info->property, errorcode, 0) < 0) {
1405 TRACE_ERROR("check ipc sock:%d", client->channel);
1410 static int __dp_request_unset_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1412 if (client == NULL || ipc_info == NULL) {
1413 TRACE_ERROR("check client or ipc info.");
1414 return DP_ERROR_INVALID_PARAMETER;
1417 int errorcode = DP_ERROR_NONE;
1419 switch (ipc_info->property) {
1421 // it would be run like cancel operation
1422 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, &errorcode) < 0)
1423 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1425 case DP_PROP_DESTINATION:
1426 // if downloading, change destination to da_agent
1427 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, &errorcode) < 0)
1428 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1430 case DP_PROP_FILENAME:
1431 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, &errorcode) < 0)
1432 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1434 case DP_PROP_STATE_CALLBACK:
1436 if (requestp != NULL)
1437 requestp->state_cb = 0;
1440 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) {
1441 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1442 errorcode = DP_ERROR_DISK_BUSY;
1446 case DP_PROP_PROGRESS_CALLBACK:
1448 if (requestp != NULL)
1449 requestp->progress_cb = 0;
1452 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) {
1453 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1454 errorcode = DP_ERROR_DISK_BUSY;
1458 case DP_PROP_AUTO_DOWNLOAD:
1460 // update autodownload property as 0 in database
1462 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, 0, 0, &errorcode) < 0) {
1463 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1464 errorcode = DP_ERROR_DISK_BUSY;
1468 case DP_PROP_NETWORK_TYPE:
1471 // update database here
1472 if (requestp != NULL)
1473 requestp->network_type = DP_NETWORK_OFF;
1475 int enable_cb = DP_NETWORK_OFF;
1476 if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) {
1477 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1478 errorcode = DP_ERROR_DISK_BUSY;
1482 case DP_PROP_NOTIFICATION_TYPE:
1484 int noti_type = DP_NOTIFICATION_TYPE_NONE;
1485 if (requestp != NULL)
1486 requestp->noti_type = noti_type;
1488 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) {
1489 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1490 errorcode = DP_ERROR_DISK_BUSY;
1494 case DP_PROP_NOTIFICATION_SUBJECT:
1496 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, &errorcode) < 0)
1497 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1500 case DP_PROP_NOTIFICATION_DESCRIPTION:
1502 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, &errorcode) < 0)
1503 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1506 case DP_PROP_NOTIFICATION_RAW:
1508 int bundle_type = -1;
1509 errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type);
1510 TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1511 char *raw_column = NULL;
1512 if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING)
1513 raw_column = DP_DB_COL_NOTI_RAW_ONGOING;
1514 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE)
1515 raw_column = DP_DB_COL_NOTI_RAW_COMPLETE;
1516 else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED)
1517 raw_column = DP_DB_COL_NOTI_RAW_FAIL;
1518 if (raw_column != NULL) {
1519 if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &errorcode) < 0)
1520 TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property));
1522 TRACE_ERROR("invalid param set: %s type:%d", dp_print_property(ipc_info->property), bundle_type);
1523 errorcode = DP_ERROR_INVALID_PARAMETER;
1527 case DP_PROP_HTTP_HEADER: // unset value by field
1529 char *header_field = NULL;
1530 errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field);
1531 if (errorcode == DP_ERROR_NONE && header_field != NULL) {
1532 int is_present = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode);
1534 errorcode = DP_ERROR_DISK_BUSY;
1535 else if (is_present == 0)
1536 errorcode = DP_ERROR_FIELD_NOT_FOUND;
1537 else if (dp_db_cond_delete(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, header_field, 2, &errorcode) < 0) {
1538 TRACE_ERROR("failed to unset %s for %s", dp_print_property(ipc_info->property), header_field);
1539 errorcode = DP_ERROR_DISK_BUSY;
1542 if (errorcode != DP_ERROR_NONE)
1543 TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode));
1544 if (header_field == NULL) {
1545 TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property));
1546 errorcode = DP_ERROR_INVALID_PARAMETER;
1553 errorcode = DP_ERROR_INVALID_PARAMETER;
1557 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_UNSET,
1558 ipc_info->property, errorcode, 0) < 0) {
1559 TRACE_ERROR("check ipc sock:%d", client->channel);
1564 static int __dp_call_cancel_agent(dp_request_fmt *request)
1567 if (request != NULL) {
1568 if (request->agent_id >= 0) {
1569 TRACE_INFO("cancel download(%d) id: %d state:%s", request->agent_id,
1570 request->id, dp_print_state(request->state));
1571 if (dp_cancel_agent_download_without_update(request->agent_id) == 0)
1574 TRACE_ERROR("invalid agent-id:%d id:%d", request->agent_id, request->id);
1580 static int __dp_request_controls(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp)
1583 TRACE_ERROR("check slot memory");
1584 return DP_ERROR_INVALID_PARAMETER;
1586 dp_client_fmt *client = &slot->client;
1587 if (client == NULL || ipc_info == NULL) {
1588 TRACE_ERROR("check client or ipc info.");
1589 return DP_ERROR_INVALID_PARAMETER;
1592 int errorcode = DP_ERROR_NONE;
1594 if (ipc_info->property == DP_PROP_CREATE) {
1595 // check packets again
1596 if (ipc_info->size != 0 || ipc_info->id != -1)
1597 errorcode = DP_ERROR_IO_ERROR;
1599 errorcode = __dp_request_create(client, ipc_info);
1603 int download_state = DP_STATE_NONE;
1604 if (requestp != NULL) {
1605 download_state = requestp->state;
1607 if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) {
1608 TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property));
1609 errorcode = DP_ERROR_ID_NOT_FOUND;
1611 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET,
1612 ipc_info->property, errorcode, 0) < 0) {
1613 TRACE_ERROR("check ipc sock:%d", client->channel);
1618 TRACE_DEBUG("id:%d state:%s set property:%s", ipc_info->id, dp_print_state(download_state), dp_print_property(ipc_info->property));
1620 if (ipc_info->property == DP_PROP_START) {
1622 if (download_state == DP_STATE_COMPLETED ||
1623 download_state == DP_STATE_DOWNLOADING) {
1624 errorcode = DP_ERROR_INVALID_STATE;
1627 if (requestp == NULL) { // load from databse
1629 // load and add new request to client->requests.
1631 if (requestp == NULL) {
1632 TRACE_ERROR("failed to load id:%d from database sock:%d", ipc_info->id, client->channel);
1633 errorcode = DP_ERROR_DISK_BUSY;
1635 if (errorcode == DP_ERROR_NONE) {
1637 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) {
1638 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1639 errorcode = DP_ERROR_DISK_BUSY;
1641 requestp->state = DP_STATE_QUEUED;
1642 requestp->error = DP_ERROR_NONE;
1643 // if it's the first request for this client-> push a request at the head of queue.
1644 // check count queued, connecting.downloading in requets of client
1645 // else push at the tail of queue.
1647 if (dp_queue_manager_push_queue(slot, requestp) < 0) {
1648 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0)
1649 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1650 requestp->state = DP_STATE_FAILED;
1651 requestp->error = DP_ERROR_QUEUE_FULL;
1652 errorcode = DP_ERROR_QUEUE_FULL;
1654 dp_queue_manager_wake_up();
1656 if (requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
1657 if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0)
1658 TRACE_ERROR("failed to register notification for id:%d", ipc_info->id);
1663 TRACE_DEBUG("id:%d check start error:%s", ipc_info->id, dp_print_errorcode(errorcode));
1666 } else if (ipc_info->property == DP_PROP_PAUSE) {
1668 if (download_state > DP_STATE_DOWNLOADING) {
1669 errorcode = DP_ERROR_INVALID_STATE;
1670 } else { // change state regardless it's on memory or not.
1671 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_PAUSED, DP_ERROR_NONE, &errorcode) < 0) {
1672 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1673 errorcode = DP_ERROR_DISK_BUSY;
1675 // call da_pause API
1676 if (requestp != NULL) {
1677 // pop from queue. if state is queued.
1678 if (requestp->state == DP_STATE_QUEUED) {
1679 dp_queue_manager_clear_queue(requestp);
1680 } else if (requestp->state == DP_STATE_CONNECTING ||
1681 requestp->state == DP_STATE_DOWNLOADING) {
1682 if (dp_pause_agent_download_without_update(requestp->agent_id) < 0)
1683 TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id);
1685 requestp->state = DP_STATE_PAUSED;
1686 requestp->error = DP_ERROR_NONE;
1691 } else if (ipc_info->property == DP_PROP_CANCEL) {
1693 if (download_state > DP_STATE_COMPLETED) {
1694 errorcode = DP_ERROR_INVALID_STATE;
1695 } else { // change state regardless it's on memory or not.
1696 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) {
1697 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1698 errorcode = DP_ERROR_DISK_BUSY;
1700 // call da_cancel API
1701 if (requestp != NULL) {
1702 // pop from queue. if state is queued.
1703 if (requestp->state == DP_STATE_QUEUED) {
1704 dp_queue_manager_clear_queue(requestp);
1705 } else if (requestp->state == DP_STATE_CONNECTING ||
1706 requestp->state == DP_STATE_DOWNLOADING) {
1707 if (__dp_call_cancel_agent(requestp) < 0)
1708 TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id);
1710 requestp->agent_id = -1;
1711 requestp->state = DP_STATE_CANCELED;
1712 requestp->error = DP_ERROR_NONE;
1713 if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
1714 requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
1715 if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0)
1716 TRACE_ERROR("failed to register notification for id:%d", ipc_info->id);
1722 } else if (ipc_info->property == DP_PROP_DESTROY) {
1725 // pop from queue. if state is queued.
1726 if (requestp != NULL) {
1727 if (requestp->state == DP_STATE_QUEUED)
1728 dp_queue_manager_clear_queue(requestp);
1729 if (requestp->state == DP_STATE_CONNECTING ||
1730 requestp->state == DP_STATE_DOWNLOADING) {
1731 // update state property database;
1732 if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) {
1733 TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id);
1735 // call da_cancel API
1736 if (__dp_call_cancel_agent(requestp) < 0)
1737 TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id);
1739 requestp->state = DP_STATE_CANCELED;
1741 if (requestp->state == DP_STATE_QUEUED || requestp->state == DP_STATE_CANCELED) {
1743 if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY ||
1744 requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) {
1745 if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0)
1746 TRACE_ERROR("failed to register notification for id:%d", ipc_info->id);
1749 requestp->agent_id = -1;
1751 errorcode = dp_request_destroy(client, ipc_info, requestp);
1754 errorcode = DP_ERROR_INVALID_PARAMETER;
1755 TRACE_ERROR("invalid param - id:%d set property:%s", ipc_info->id, dp_print_property(ipc_info->property));
1760 if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_CONTROL,
1761 ipc_info->property, errorcode, 0) < 0) {
1762 TRACE_ERROR("check ipc sock:%d", client->channel);
1765 // workaround. client still request the feedback by cancelation
1766 if (ipc_info->property == DP_PROP_CANCEL ||
1767 ipc_info->property == DP_PROP_PAUSE) {
1768 if (requestp != NULL && requestp->state_cb == 1) {
1769 if (slot->client.notify < 0 ||
1770 dp_notify_feedback(slot->client.notify, slot, ipc_info->id, requestp->state, errorcode, 0) < 0) {
1771 TRACE_ERROR("id:%d disable state callback by IO_ERROR", ipc_info->id);
1772 requestp->state_cb = 0;
1780 static int __dp_client_requests(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info)
1783 TRACE_ERROR("check slot memory");
1784 return DP_ERROR_INVALID_PARAMETER;
1786 dp_client_fmt *client = &slot->client;
1787 if (client == NULL || ipc_info == NULL) {
1788 TRACE_ERROR("check client or ipc info.");
1789 return DP_ERROR_INVALID_PARAMETER;
1792 int errorcode = DP_ERROR_NONE;
1794 // check id except create command /////////// DP_ERROR_ID_NOT_FOUND
1795 dp_request_fmt *requestp = NULL;
1796 if (ipc_info->section != DP_SEC_CONTROL ||
1797 ipc_info->property != DP_PROP_CREATE) {
1798 // check on requests
1800 requestp = client->requests;
1801 errorcode = DP_ERROR_ID_NOT_FOUND;
1802 for (; i < MAX_DOWNLOAD_HANDLE; i++) {
1803 if (requestp == NULL)
1805 //TRACE_DEBUG("link %d info: id:%d access-time:%d", i, requestp->id, requestp->access_time);
1806 if (requestp->id == ipc_info->id) {
1807 errorcode = DP_ERROR_NONE;
1810 requestp = requestp->next;
1812 if (errorcode == DP_ERROR_ID_NOT_FOUND) {
1813 // check in database
1814 if (dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_LOGGING, DP_DB_COL_ID, ipc_info->id, &errorcode) > 0) {
1815 //TRACE_DEBUG("found %d from database", ipc_info->id);
1816 errorcode = DP_ERROR_NONE;
1821 if (errorcode != DP_ERROR_NONE) { // prechecking
1822 TRACE_ERROR("precheck errorcode:%s sock:%d id:%d section:%s property:%s",
1823 dp_print_errorcode(errorcode),
1824 client->channel, ipc_info->id,
1825 dp_print_section(ipc_info->section),
1826 dp_print_property(ipc_info->property));
1828 // clear followed packets.
1829 if (ipc_info->size > 0) {
1830 char garbage[ipc_info->size];
1831 if (read(client->channel, &garbage, ipc_info->size) == 0) {
1832 TRACE_ERROR("sock:%d closed peer", client->channel);
1833 errorcode = DP_ERROR_IO_ERROR;
1837 if (dp_ipc_query(client->channel, ipc_info->id,
1838 ipc_info->section, ipc_info->property, errorcode, 0) < 0) {
1839 TRACE_ERROR("check ipc sock:%d", client->channel);
1840 errorcode = DP_ERROR_IO_ERROR;
1845 switch (ipc_info->section) {
1846 case DP_SEC_CONTROL:
1847 errorcode = __dp_request_controls(slot, ipc_info, requestp);
1850 errorcode = __dp_request_get_info(client, ipc_info, requestp);
1853 errorcode = __dp_request_set_info(slot, ipc_info, requestp);
1856 errorcode = __dp_request_unset_info(client, ipc_info, requestp);
1859 errorcode = DP_ERROR_INVALID_PARAMETER;
1865 static void __dp_client_stop_all_requests(dp_client_slots_fmt *slot)
1867 unsigned push_count = 0;
1868 int errorcode = DP_ERROR_NONE;
1870 dp_request_fmt *tailp = slot->client.requests;
1871 for (; tailp != NULL; i++) {
1872 TRACE_DEBUG("request %d stop id:%d state:%s", i, tailp->id, dp_print_state(tailp->state));
1873 int state = tailp->state;
1874 if (state == DP_STATE_CONNECTING) {
1875 if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0)
1876 TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id);
1877 } else if (state == DP_STATE_DOWNLOADING) {
1878 if (dp_pause_agent_download(tailp->agent_id) < 0)
1879 TRACE_ERROR("failed to pause download(%d) id:%d", tailp->agent_id, tailp->id);
1881 if (state == DP_STATE_DOWNLOADING || state == DP_STATE_CONNECTING) {
1882 tailp->state = DP_STATE_QUEUED;
1883 // This is error code for checking the reason when changing ip configuration process
1884 tailp->error = DP_ERROR_IO_EAGAIN;
1885 // push to queue now
1886 // in da callback, check DP_ERROR_IO_EAGAIN, then ignore.
1887 if (dp_db_update_logging(slot->client.dbhandle, tailp->id, tailp->state, DP_ERROR_NONE, &errorcode) < 0)
1888 TRACE_ERROR("update log sock:%d download-id:%d", slot->client.channel, tailp->id);
1889 if (dp_queue_manager_push_queue(slot, tailp) < 0) {
1890 TRACE_ERROR("Fail to push queueg sock:%d download-id:%d", slot->client.channel, tailp->id);
1891 // FIXME later : error case. How can handle this item?
1896 tailp = tailp->next;
1899 dp_queue_manager_wake_up();
1902 void dp_client_sig_handler(int signo)
1904 TRACE_INFO("thread:%lu signal:%d", pthread_self(), signo);
1907 void *dp_client_request_thread(void *arg)
1909 dp_client_slots_fmt *slot = (dp_client_slots_fmt *)arg;
1911 TRACE_ERROR("slot null, can not launch the thread for client");
1915 // wait detaching thread
1916 CLIENT_MUTEX_LOCK(&slot->mutex);
1918 TRACE_INFO("slot %p thread:%lu", slot, slot->thread);
1920 struct sigaction act = {{0},};
1922 sigemptyset(&newmask);
1923 sigaddset(&newmask, SIGUSR1);
1924 act.sa_handler = dp_client_sig_handler;
1925 sigaction(SIGUSR1, &act, NULL);
1927 fd_set imask, emask;
1928 int errorcode = DP_ERROR_NONE;
1929 dp_client_fmt *client = &slot->client;
1930 int client_sock = client->channel;
1931 struct timeval timeout; // for timeout of select
1933 CLIENT_MUTEX_UNLOCK(&slot->mutex);
1935 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
1937 while (slot != NULL && client_sock >= 0 &&
1938 client_sock == slot->client.channel) {
1940 memset(&timeout, 0x00, sizeof(struct timeval));
1941 timeout.tv_sec = DP_CARE_CLIENT_REQUEST_INTERVAL;
1944 FD_SET(client_sock, &imask);
1945 FD_SET(client_sock, &emask);
1946 if (select(client_sock + 1, &imask, 0, &emask, &timeout) < 0) {
1947 if (slot != NULL && slot->client.channel >= 0) {
1948 TRACE_INFO("broadcast by client-manager");
1949 CLIENT_MUTEX_LOCK(&slot->mutex);
1950 // check all requests
1951 __dp_client_stop_all_requests(slot);
1952 CLIENT_MUTEX_UNLOCK(&slot->mutex);
1955 TRACE_ERROR("interrupted by client-manager sock:%d", client_sock);
1959 if (FD_ISSET(client_sock, &imask) > 0) {
1961 CLIENT_MUTEX_LOCK(&slot->mutex);
1963 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1964 client->access_time = (int)time(NULL);
1966 errorcode = DP_ERROR_NONE;
1968 // read ipc_fmt first. below func will deal followed packets
1969 dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(client_sock);
1970 if (ipc_info == NULL) {
1971 TRACE_ERROR("sock:%d maybe closed", client_sock);
1972 errorcode = DP_ERROR_IO_ERROR;
1974 TRACE_DEBUG("sock:%d id:%d section:%s property:%s errorcode:%s size:%d",
1975 client_sock, ipc_info->id,
1976 dp_print_section(ipc_info->section),
1977 dp_print_property(ipc_info->property),
1978 dp_print_errorcode(ipc_info->errorcode),
1981 if (client->dbhandle == 0 || dp_db_check_connection(client->dbhandle) < 0) {
1982 if (dp_db_open_client(&client->dbhandle, slot->pkgname, &errorcode) < 0) {
1983 TRACE_ERROR("failed to open database for sock:%d errorcode:%s", client_sock, dp_print_errorcode(errorcode));
1984 if (dp_ipc_query(client->channel, ipc_info->id,
1985 ipc_info->section, ipc_info->property, errorcode, 0) < 0) {
1986 TRACE_ERROR("check ipc sock:%d", client->channel);
1991 if (errorcode == DP_ERROR_NONE) {
1993 errorcode = __dp_client_requests(slot, ipc_info);
1999 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
2000 CLIENT_MUTEX_UNLOCK(&slot->mutex);
2002 if (errorcode == DP_ERROR_IO_ERROR ||
2003 errorcode == DP_ERROR_OUT_OF_MEMORY ||
2004 errorcode == DP_ERROR_INVALID_PARAMETER) {
2005 TRACE_ERROR("disconnect client errorcode:%s sock:%d",
2006 dp_print_errorcode(errorcode), client_sock);
2010 } else if (FD_ISSET(client_sock, &emask) > 0) {
2011 TRACE_ERROR("[EXCEPTION]");
2016 if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) == 0) {
2017 // 1. clear zombie requests. clean requests finished. paused or ready for long time
2018 dp_client_clear_requests(slot);
2020 if (client->dbhandle != 0) {
2021 int sql_errorcode = DP_ERROR_NONE;
2022 // 2. maintain only 1000 rows for each client
2023 if (dp_db_limit_rows(client->dbhandle, DP_TABLE_LOGGING, DP_LOG_DB_LIMIT_ROWS, &sql_errorcode) < 0)
2024 TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode));
2025 // 3. maintain for 48 hours
2026 if (dp_db_limit_time(client->dbhandle, DP_TABLE_LOGGING, DP_CARE_CLIENT_INFO_PERIOD, &sql_errorcode) < 0)
2027 TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode));
2029 // 4. if no requests, exit by itself.
2030 if (slot->client.requests == NULL) {
2031 TRACE_DEBUG("no requests");
2032 CLIENT_MUTEX_UNLOCK(&slot->mutex);
2035 CLIENT_MUTEX_UNLOCK(&slot->mutex);
2040 FD_CLR(client_sock, &imask);
2041 FD_CLR(client_sock, &emask);
2043 // if no requests, clear slot after disconnect with client.
2044 CLIENT_MUTEX_LOCK(&slot->mutex);
2046 TRACE_INFO("thread done slot %p thread:%lu", slot, slot->thread);
2048 slot->thread = 0;// to prevent kill thread twice
2051 dp_request_fmt *tailp = slot->client.requests;
2052 dp_request_fmt *prevp = NULL;
2053 for (; tailp != NULL; i++) {
2054 if (tailp->state != DP_STATE_QUEUED &&
2055 tailp->state != DP_STATE_CONNECTING &&
2056 tailp->state != DP_STATE_DOWNLOADING) {
2057 dp_request_fmt *removep = tailp;
2058 if (prevp == NULL) // first request.
2059 client->requests = tailp->next;
2061 prevp->next = tailp->next;
2062 tailp = tailp->next;
2063 TRACE_DEBUG("request %d remove: id:%d state:%s", i, removep->id, dp_print_state(removep->state));
2064 dp_request_free(removep);
2067 TRACE_DEBUG("request %d remain: id:%d state:%s", i, tailp->id, dp_print_state(tailp->state));
2069 tailp = tailp->next;
2072 // if no requests after clear finished requests.
2073 if (slot->client.requests == NULL) {
2074 dp_client_slot_free(slot);
2076 if (slot->client.notify >= 0)
2077 close(slot->client.notify);
2078 dp_notify_deinit(slot->credential.pid);
2079 slot->client.notify = -1;
2080 if (slot->client.channel > 0)
2081 close(slot->client.channel);
2082 slot->client.channel = -1;
2084 TRACE_INFO("thread done slot %p thread:%lu sock:%d", slot, slot->thread, client_sock);
2085 CLIENT_MUTEX_UNLOCK(&slot->mutex);