summaryrefslogtreecommitdiff
path: root/provider/download-provider-da-interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'provider/download-provider-da-interface.c')
-rwxr-xr-xprovider/download-provider-da-interface.c903
1 files changed, 903 insertions, 0 deletions
diff --git a/provider/download-provider-da-interface.c b/provider/download-provider-da-interface.c
new file mode 100755
index 0000000..87eb375
--- /dev/null
+++ b/provider/download-provider-da-interface.c
@@ -0,0 +1,903 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <string.h>
+#include <dlfcn.h> // dlopen
+
+#include <sys/smack.h>
+#include "download-provider.h"
+#include "download-provider-log.h"
+#include "download-provider-pthread.h"
+#include "download-provider-socket.h"
+#include "download-provider-db.h"
+#include "download-provider-queue.h"
+#include "download-provider-notification.h"
+#include "download-provider-request.h"
+#include "download-provider-network.h"
+#include "download-provider-da-interface.h"
+
+#include "download-agent-defs.h"
+#include "download-agent-interface.h"
+
+#define DP_SDCARD_MNT_POINT "/opt/storage/sdcard"
+
+static void *g_da_handle = NULL;
+static int (*download_agent_init)(da_client_cb_t *) = NULL; // int da_init(da_client_cb_t *da_client_callback);
+static int (*download_agent_deinit)() = NULL; // int da_deinit();
+static int (*download_agent_is_alive)(int) = NULL; // int da_is_valid_download_id(int download_id);
+static int (*download_agent_suspend)(int) = NULL; // int da_suspend_download(int download_id);
+static int (*download_agent_resume)(int) = NULL; // int da_resume_download(int download_id);
+static int (*download_agent_cancel)(int) = NULL; // int da_cancel_download(int download_id);
+static int (*download_agent_start)(const char *, extension_data_t *, int *) = NULL; // int da_start_download_with_extension(const char *url, extension_data_t *ext_data, int *download_id);
+
+
+int dp_is_file_exist(const char *file_path)
+{
+ struct stat file_state;
+ int stat_ret;
+
+ if (file_path == NULL) {
+ TRACE_ERROR("[NULL-CHECK] file path is NULL");
+ return -1;
+ }
+
+ stat_ret = stat(file_path, &file_state);
+
+ if (stat_ret == 0)
+ if (file_state.st_mode & S_IFREG)
+ return 0;
+
+ return -1;
+}
+
+static int __change_error(int err)
+{
+ int ret = DP_ERROR_NONE;
+ switch (err) {
+ case DA_RESULT_OK:
+ ret = DP_ERROR_NONE;
+ break;
+ case DA_ERR_INVALID_ARGUMENT:
+ ret = DP_ERROR_INVALID_PARAMETER;
+ break;
+ case DA_ERR_FAIL_TO_MEMALLOC:
+ ret = DP_ERROR_OUT_OF_MEMORY;
+ break;
+ case DA_ERR_UNREACHABLE_SERVER:
+ ret = DP_ERROR_NETWORK_UNREACHABLE;
+ break;
+ case DA_ERR_HTTP_TIMEOUT:
+ ret = DP_ERROR_CONNECTION_TIMED_OUT;
+ break;
+ case DA_ERR_DISK_FULL:
+ ret = DP_ERROR_NO_SPACE;
+ break;
+ case DA_ERR_INVALID_STATE:
+ ret = DP_ERROR_INVALID_STATE;
+ break;
+ case DA_ERR_NETWORK_FAIL:
+ ret = DP_ERROR_CONNECTION_FAILED;
+ break;
+ case DA_ERR_INVALID_URL:
+ ret = DP_ERROR_INVALID_URL;
+ break;
+ case DA_ERR_INVALID_INSTALL_PATH:
+ ret = DP_ERROR_INVALID_DESTINATION;
+ break;
+ case DA_ERR_ALREADY_MAX_DOWNLOAD:
+ ret = DP_ERROR_TOO_MANY_DOWNLOADS;
+ break;
+ case DA_ERR_FAIL_TO_CREATE_THREAD:
+ case DA_ERR_FAIL_TO_OBTAIN_MUTEX:
+ case DA_ERR_FAIL_TO_ACCESS_FILE:
+ case DA_ERR_FAIL_TO_GET_CONF_VALUE:
+ case DA_ERR_FAIL_TO_ACCESS_STORAGE:
+ default:
+ ret = DP_ERROR_IO_ERROR;
+ break;
+ }
+ return ret;
+}
+
+static void __download_info_cb(user_download_info_t *info, void *user_data)
+{
+ if (!info) {
+ TRACE_ERROR("[NULL-CHECK] Agent info");
+ return ;
+ }
+ dp_request_slots *request_slot = (dp_request_slots *) user_data;
+ if (request_slot == NULL) {
+ TRACE_ERROR("[NULL-CHECK] request req_id:%d", info->download_id);
+ return ;
+ }
+ CLIENT_MUTEX_LOCK(&request_slot->mutex);
+ if (request_slot->request == NULL) {
+ TRACE_ERROR("[NULL-CHECK] request req_id:%d", info->download_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+ dp_request *request = request_slot->request;
+ if (request->id < 0 || (request->agent_id != info->download_id)) {
+ TRACE_ERROR("[NULL-CHECK] agent_id : %d req_id %d",
+ request->agent_id, info->download_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+
+ int request_id = request->id;
+
+ // update info before sending event
+ if (info->tmp_saved_path != NULL) {
+
+ TRACE_SECURE_DEBUG("[STARTED][%d] [%s]", request_id, info->tmp_saved_path);
+ int conds_count = 6; // id + tmp_saved_path + file_size + content_name + etag
+ int conds_index = 0;
+ db_conds_list_fmt conds_p[conds_count];
+ memset(&conds_p, 0x00, conds_count * sizeof(db_conds_list_fmt));
+
+ conds_p[conds_index].column = DP_DB_COL_TMP_SAVED_PATH;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_TEXT;
+ conds_p[conds_index].value = info->tmp_saved_path;
+ conds_index++;
+ if (info->file_type != NULL) {
+ conds_p[conds_index].column = DP_DB_COL_MIMETYPE;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_TEXT;
+ conds_p[conds_index].value = info->file_type;
+ conds_index++;
+ }
+ if (info->content_name != NULL) {
+ conds_p[conds_index].column = DP_DB_COL_CONTENT_NAME;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_TEXT;
+ conds_p[conds_index].value = info->content_name;
+ conds_index++;
+ }
+ if (info->etag != NULL) {
+ conds_p[conds_index].column = DP_DB_COL_ETAG;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_TEXT;
+ conds_p[conds_index].value = info->etag;
+ conds_index++;
+ }
+ if (info->file_size > 0) {
+ request->file_size = info->file_size;
+ conds_p[conds_index].column = DP_DB_COL_CONTENT_SIZE;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_INT64;
+ conds_p[conds_index].value = &info->file_size;
+ conds_index++;
+ }
+
+ int check_id = dp_db_get_int_column(request_id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_ID);
+ if (check_id == request_id) { // update
+ if (dp_db_update_columns(request_id, DP_DB_TABLE_DOWNLOAD_INFO, conds_index, conds_p) < 0) {
+ if (dp_db_is_full_error() == 0) {
+ request->error = DP_ERROR_NO_SPACE;
+ TRACE_ERROR("[SQLITE_FULL][%d]", request_id);
+ if (dp_cancel_agent_download(request->agent_id) < 0)
+ TRACE_ERROR("[fail][%d]cancel_agent", request_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+ }
+ } else { // insert
+ conds_p[conds_index].column = DP_DB_COL_ID;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_INT;
+ conds_p[conds_index].value = &request_id;
+ conds_index++;
+ if (dp_db_insert_columns(DP_DB_TABLE_DOWNLOAD_INFO, conds_index, conds_p) < 0) {
+ if (dp_db_is_full_error() == 0) {
+ request->error = DP_ERROR_NO_SPACE;
+ TRACE_ERROR("[SQLITE_FULL][%d]", request_id);
+ if (dp_cancel_agent_download(request->agent_id) < 0)
+ TRACE_ERROR("[fail][%d]cancel_agent", request_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+ }
+ }
+
+ }
+
+ request->ip_changed = 0;
+ request->state = DP_STATE_DOWNLOADING;
+ request->error = DP_ERROR_NONE;
+ dp_request_state_response(request);
+
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+}
+
+static void __progress_cb(user_progress_info_t *info, void *user_data)
+{
+ if (!info) {
+ TRACE_ERROR("[NULL-CHECK] Agent info");
+ return ;
+ }
+ dp_request_slots *request_slot = (dp_request_slots *) user_data;
+ if (request_slot == NULL) {
+ TRACE_ERROR("[NULL-CHECK] request req_id:%d", info->download_id);
+ return ;
+ }
+ CLIENT_MUTEX_LOCK(&request_slot->mutex);
+ if (request_slot->request == NULL) {
+ TRACE_ERROR("[NULL-CHECK] request req_id:%d", info->download_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+ dp_request *request = request_slot->request;
+ if (request->id < 0 || (request->agent_id != info->download_id)) {
+ TRACE_ERROR("[NULL-CHECK] agent_id : %d req_id %d",
+ request->agent_id, info->download_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+
+ if (request->state == DP_STATE_DOWNLOADING) {
+ request->received_size = info->received_size;
+ time_t tt = time(NULL);
+ struct tm *localTime = localtime(&tt);
+ // send event every 1 second.
+ if (request->progress_lasttime != localTime->tm_sec) {
+ request->progress_lasttime = localTime->tm_sec;
+ if (request->auto_notification) {
+ dp_update_downloadinginfo_notification
+ (request->noti_priv_id,
+ (double)request->received_size,
+ (double)request->file_size);
+ } else {
+ int noti_type = dp_db_get_int_column(request->id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE);
+ if(noti_type == DP_NOTIFICATION_TYPE_ALL)
+ dp_update_downloadinginfo_notification
+ (request->noti_priv_id,
+ (double)request->received_size,
+ (double)request->file_size);
+ }
+
+ if (request->progress_cb && request->group != NULL &&
+ request->group->event_socket >= 0 &&
+ request->received_size > 0)
+ dp_ipc_send_event(request->group->event_socket,
+ request->id, request->state, request->error,
+ request->received_size);
+ }
+ }
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+}
+
+static int __is_transmute_smack(char *path)
+{
+ char *dir_label = NULL;
+ int ret = -1;
+ if (smack_getlabel(path, &dir_label, SMACK_LABEL_TRANSMUTE) == 0 &&
+ dir_label != NULL) {
+ if (strncmp(dir_label, "TRUE", strlen(dir_label)) == 0)
+ ret = 0;
+ }
+ free(dir_label);
+ return ret;
+}
+
+static dp_error_type __set_dir_smack_label(char *smack_label, char *dir_path, char *saved_path)
+{
+ if (smack_label == NULL || dir_path== NULL || saved_path == NULL)
+ return DP_ERROR_PERMISSION_DENIED;
+
+ int is_setted_dir_label = 0;
+ dp_error_type errorcode = DP_ERROR_NONE;
+
+ TRACE_SECURE_INFO("[PARSE] dir path [%s]", dir_path);
+ if (__is_transmute_smack(dir_path) < 0) {
+ TRACE_DEBUG("[SMACK] no transmute");
+ } else {
+ char *dir_label = NULL;
+ if (smack_getlabel(dir_path, &dir_label,
+ SMACK_LABEL_ACCESS) == 0) {
+ if (smack_have_access(smack_label, dir_label, "t") > 0) {
+ if (smack_setlabel(saved_path, dir_label,
+ SMACK_LABEL_ACCESS) != 0) {
+ TRACE_SECURE_ERROR("[SMACK ERROR] label:%s",
+ dir_label);
+ errorcode = DP_ERROR_PERMISSION_DENIED;
+ } else {
+ is_setted_dir_label = 1;
+ }
+ } else {
+ TRACE_SECURE_ERROR("[SMACK ERROR] access:%s/%s",
+ smack_label, dir_label);
+ errorcode = DP_ERROR_PERMISSION_DENIED;
+ }
+ } else {
+ TRACE_SECURE_ERROR("[SMACK ERROR] no label:", dir_path);
+ errorcode = DP_ERROR_PERMISSION_DENIED;
+ }
+ free(dir_label);
+ }
+ if (is_setted_dir_label == 0 &&
+ smack_setlabel(saved_path, smack_label,
+ SMACK_LABEL_ACCESS) != 0) {
+ TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", smack_label);
+ errorcode = DP_ERROR_PERMISSION_DENIED;
+ // remove file.
+ if (dp_is_file_exist(saved_path) == 0)
+ unlink(saved_path);
+ }
+ return errorcode;
+}
+
+static dp_error_type __set_file_permission_to_client(dp_request *request, char *saved_path)
+{
+ dp_error_type errorcode = DP_ERROR_NONE;
+ char *str = NULL;
+ char *smack_label = NULL;
+ str = strrchr(saved_path, '/');
+ dp_credential cred;
+ if (request->group == NULL) {
+ cred.uid = dp_db_cond_get_int(DP_DB_TABLE_GROUPS,
+ DP_DB_GROUPS_COL_UID,
+ DP_DB_GROUPS_COL_PKG,
+ DP_DB_COL_TYPE_TEXT, request->packagename);
+ cred.gid = dp_db_cond_get_int(DP_DB_TABLE_GROUPS,
+ DP_DB_GROUPS_COL_GID,
+ DP_DB_GROUPS_COL_PKG,
+ DP_DB_COL_TYPE_TEXT, request->packagename);
+ } else {
+ cred = request->group->credential;
+ }
+ TRACE_DEBUG
+ ("[chown][%d] [%d][%d]", request->id, cred.uid, cred.gid);
+ if (chown(saved_path, cred.uid, cred.gid) < 0)
+ TRACE_STRERROR("[ERROR][%d] chown", request->id);
+ if (chmod(saved_path,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0)
+ TRACE_STRERROR("[ERROR][%d] chmod", request->id);
+ if (dp_is_smackfs_mounted() == 1) {
+ if (request->group == NULL) {
+ // get smack_label from sql
+ smack_label =
+ dp_db_cond_get_text(DP_DB_TABLE_GROUPS,
+ DP_DB_GROUPS_COL_SMACK_LABEL,
+ DP_DB_GROUPS_COL_PKG,
+ DP_DB_COL_TYPE_TEXT, request->packagename);
+ } else {
+ smack_label = dp_strdup(request->group->smack_label);
+ }
+ if (smack_label == NULL) {
+ TRACE_SECURE_ERROR("[SMACK][%d] no label", request->id);
+ errorcode = DP_ERROR_PERMISSION_DENIED;
+ } else {
+ size_t len = str - (saved_path);
+ char *dir_path = (char *)calloc(len + 1, sizeof(char));
+ if (dir_path != NULL) {
+ strncpy(dir_path, saved_path, len);
+ errorcode =
+ __set_dir_smack_label(smack_label, dir_path,
+ saved_path);
+ free(dir_path);
+ } else {
+ TRACE_SECURE_ERROR("[ERROR] calloc");
+ errorcode = DP_ERROR_OUT_OF_MEMORY;
+ }
+ free(smack_label);
+ }
+ }
+ return errorcode;
+}
+
+static void __finished_cb(user_finished_info_t *info, void *user_data)
+{
+ if (!info) {
+ TRACE_ERROR("[NULL-CHECK] Agent info");
+ return ;
+ }
+ dp_request_slots *request_slot = (dp_request_slots *) user_data;
+ if (request_slot == NULL) {
+ TRACE_ERROR("[NULL-CHECK] request req_id:%d", info->download_id);
+ return ;
+ }
+ CLIENT_MUTEX_LOCK(&request_slot->mutex);
+ if (request_slot->request == NULL) {
+ TRACE_ERROR("[NULL-CHECK] request req_id:%d", info->download_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+ dp_request *request = request_slot->request;
+ if (request->id < 0 || (request->agent_id != info->download_id)) {
+ TRACE_ERROR("[NULL-CHECK] agent_id : %d req_id %d",
+ request->agent_id, info->download_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+
+ int request_id = request->id;
+ dp_state_type state = DP_STATE_NONE;
+ dp_error_type errorcode = DP_ERROR_NONE;
+
+ if (info->http_status > 0)
+ if (dp_db_replace_column(request_id, DP_DB_TABLE_DOWNLOAD_INFO,
+ DP_DB_COL_HTTP_STATUS,
+ DP_DB_COL_TYPE_INT, &info->http_status) < 0)
+ TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+
+ if (info->err == DA_RESULT_OK) {
+
+ int conds_count = 5; // id + saved_path + content_name + http_status + file_size
+ int conds_index = 0;
+ db_conds_list_fmt conds_p[conds_count];
+ memset(&conds_p, 0x00, conds_count * sizeof(db_conds_list_fmt));
+
+ char *content_name = NULL;
+ if (info->saved_path != NULL) {
+ char *str = NULL;
+ if(!(strncmp(DP_SDCARD_MNT_POINT, info->saved_path,
+ strlen(DP_SDCARD_MNT_POINT)) == 0)) {
+ errorcode = __set_file_permission_to_client(request,
+ info->saved_path);
+ }
+ str = strrchr(info->saved_path, '/');
+ if (str != NULL) {
+ str++;
+ content_name = dp_strdup(str);
+ TRACE_SECURE_DEBUG("[PARSE][%d] content_name [%s]",
+ request_id, content_name);
+ }
+
+ conds_p[conds_index].column = DP_DB_COL_SAVED_PATH;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_TEXT;
+ conds_p[conds_index].value = info->saved_path;
+ conds_index++;
+ if (content_name != NULL) {
+ conds_p[conds_index].column = DP_DB_COL_CONTENT_NAME;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_TEXT;
+ conds_p[conds_index].value = content_name;
+ conds_index++;
+ }
+
+ if (errorcode == DP_ERROR_NONE) {
+ state = DP_STATE_COMPLETED;
+ TRACE_SECURE_INFO("[COMPLETED][%d] saved to [%s]",
+ request_id, info->saved_path);
+ } else {
+ state = DP_STATE_FAILED;
+ TRACE_SECURE_INFO("[FAILED][%d] saved to [%s]",
+ request_id, info->saved_path);
+ }
+ } else {
+ TRACE_ERROR("Cannot enter here");
+ TRACE_ERROR("[ERROR][%d] No SavedPath", request_id);
+ errorcode = DP_ERROR_INVALID_DESTINATION;
+ state = DP_STATE_FAILED;
+ }
+ if (request->file_size == 0) {
+ request->file_size = request->received_size;
+ conds_p[conds_index].column = DP_DB_COL_CONTENT_SIZE;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_INT64;
+ conds_p[conds_index].value = &request->file_size;
+ conds_index++;
+ }
+
+ int check_id = dp_db_get_int_column(request_id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_ID);
+ if (check_id == request_id) { // update
+ if (dp_db_update_columns(request_id, DP_DB_TABLE_DOWNLOAD_INFO, conds_index, conds_p) < 0) {
+ if (dp_db_is_full_error() == 0) {
+ request->error = DP_ERROR_NO_SPACE;
+ TRACE_ERROR("[SQLITE_FULL][%d]", request_id);
+ if (dp_cancel_agent_download(request->agent_id) < 0)
+ TRACE_ERROR("[fail][%d]cancel_agent", request_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+ }
+ } else { // insert
+ conds_p[conds_index].column = DP_DB_COL_ID;
+ conds_p[conds_index].type = DP_DB_COL_TYPE_INT;
+ conds_p[conds_index].value = &request_id;
+ conds_index++;
+ if (dp_db_insert_columns(DP_DB_TABLE_DOWNLOAD_INFO, conds_index, conds_p) < 0) {
+ if (dp_db_is_full_error() == 0) {
+ request->error = DP_ERROR_NO_SPACE;
+ TRACE_ERROR("[SQLITE_FULL][%d]", request_id);
+ if (dp_cancel_agent_download(request->agent_id) < 0)
+ TRACE_ERROR("[fail][%d]cancel_agent", request_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+ }
+ }
+ free(content_name);
+ } else {
+ char *tmp_saved_path =
+ dp_request_get_tmpsavedpath(request_id, request, &errorcode);
+
+ if (tmp_saved_path != NULL) {
+ errorcode = __set_file_permission_to_client(request, tmp_saved_path);
+ free(tmp_saved_path);
+ } else {
+ TRACE_ERROR("Cannot enter here");
+ TRACE_ERROR("[ERROR][%d] No SavedPath", request_id);
+ }
+
+ if (info->err == DA_RESULT_USER_CANCELED) {
+ state = DP_STATE_CANCELED;
+ errorcode = request->error;
+ TRACE_INFO("[CANCELED][%d]", request_id);
+ } else {
+ state = DP_STATE_FAILED;
+ errorcode = __change_error(info->err);
+ TRACE_ERROR("[FAILED][%d][%s]", request_id,
+ dp_print_errorcode(errorcode));
+ }
+ }
+
+ request->state = state;
+ request->error = errorcode;
+
+ // auto resume when failed by ip_changed.
+ if (state == DP_STATE_FAILED && info->err == DA_ERR_NETWORK_FAIL &&
+ request->network_type != DP_NETWORK_TYPE_WIFI_DIRECT) {
+ if (request->ip_changed == 1 &&
+ dp_get_network_connection_instant_status() !=
+ DP_NETWORK_TYPE_OFF) {
+ // resume
+ TRACE_DEBUG("[RESUME][%d] will be queued", request_id);
+ request->state = DP_STATE_QUEUED;
+ request->error = DP_ERROR_NONE;
+ } else {
+ TRACE_DEBUG("[CHECK][%d] check again in timeout", request_id);
+ }
+ } else {
+ // stay on memory till called destroy by client or timeout
+ if (request->group != NULL &&
+ request->group->event_socket >= 0) {
+ /* update the received file size.
+ * The last received file size cannot update
+ * because of reducing update algorithm*/
+ if (request->received_size > 0) {
+ dp_ipc_send_event(request->group->event_socket,
+ request->id, DP_STATE_DOWNLOADING, request->error,
+ request->received_size);
+ }
+ }
+ dp_request_state_response(request);
+ }
+
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+
+ dp_thread_queue_manager_wake_up();
+}
+
+static void __paused_cb(user_paused_info_t *info, void *user_data)
+{
+ dp_request_slots *request_slot = (dp_request_slots *) user_data;
+ if (request_slot == NULL) {
+ TRACE_ERROR("[NULL-CHECK] request req_id:%d", info->download_id);
+ return ;
+ }
+ CLIENT_MUTEX_LOCK(&request_slot->mutex);
+ if (request_slot->request == NULL) {
+ TRACE_ERROR("[NULL-CHECK] request req_id:%d", info->download_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+ dp_request *request = request_slot->request;
+ if (request->id < 0 || (request->agent_id != info->download_id)) {
+ TRACE_ERROR("[NULL-CHECK] agent_id : %d req_id %d",
+ request->agent_id, info->download_id);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+
+ if (request->state != DP_STATE_PAUSE_REQUESTED) {
+ TRACE_ERROR("[CHECK] now status:%d", request->state);
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+ return ;
+ }
+
+ int request_id = request->id;
+
+ if (dp_db_update_date
+ (request_id, DP_DB_TABLE_LOG, DP_DB_COL_ACCESS_TIME) < 0)
+ TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+
+ request->state = DP_STATE_PAUSED;
+ request->error = DP_ERROR_NONE;
+ dp_request_state_response(request);
+
+ CLIENT_MUTEX_UNLOCK(&request_slot->mutex);
+
+ dp_thread_queue_manager_wake_up();
+}
+
+int dp_init_agent()
+{
+
+ g_da_handle = dlopen("libdownloadagent2.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (!g_da_handle) {
+ TRACE_ERROR("[dlopen] %s", dlerror());
+ g_da_handle = NULL;
+ return DP_ERROR_OUT_OF_MEMORY;
+ }
+ dlerror(); /* Clear any existing error */
+
+ *(void **) (&download_agent_init) = dlsym(g_da_handle, "da_init");
+ if (download_agent_init == NULL ) {
+ TRACE_ERROR("[dlsym] da_init:%s", dlerror());
+ dlclose(g_da_handle);
+ g_da_handle = NULL;
+ return DP_ERROR_OUT_OF_MEMORY;
+ }
+
+ *(void **) (&download_agent_deinit) = dlsym(g_da_handle, "da_deinit");
+ if (download_agent_deinit == NULL ) {
+ TRACE_ERROR("[dlsym] da_deinit:%s", dlerror());
+ dlclose(g_da_handle);
+ g_da_handle = NULL;
+ return DP_ERROR_OUT_OF_MEMORY;
+ }
+
+ *(void **) (&download_agent_is_alive) = dlsym(g_da_handle, "da_is_valid_download_id");
+ if (download_agent_is_alive == NULL ) {
+ TRACE_ERROR("[dlsym] da_is_valid_download_id:%s", dlerror());
+ dlclose(g_da_handle);
+ g_da_handle = NULL;
+ return DP_ERROR_OUT_OF_MEMORY;
+ }
+
+ *(void **) (&download_agent_suspend) = dlsym(g_da_handle, "da_suspend_download");
+ if (download_agent_suspend == NULL ) {
+ TRACE_ERROR("[dlsym] da_suspend_download:%s", dlerror());
+ dlclose(g_da_handle);
+ g_da_handle = NULL;
+ return DP_ERROR_OUT_OF_MEMORY;
+ }
+
+ *(void **) (&download_agent_resume) = dlsym(g_da_handle, "da_resume_download");
+ if (download_agent_resume == NULL ) {
+ TRACE_ERROR("[dlsym] da_resume_download:%s", dlerror());
+ dlclose(g_da_handle);
+ g_da_handle = NULL;
+ return DP_ERROR_OUT_OF_MEMORY;
+ }
+
+ *(void **) (&download_agent_cancel) = dlsym(g_da_handle, "da_cancel_download");
+ if (download_agent_cancel == NULL ) {
+ TRACE_ERROR("[dlsym] da_cancel_download:%s", dlerror());
+ dlclose(g_da_handle);
+ g_da_handle = NULL;
+ return DP_ERROR_OUT_OF_MEMORY;
+ }
+
+ *(void **) (&download_agent_start) = dlsym(g_da_handle, "da_start_download_with_extension");
+ if (download_agent_start == NULL ) {
+ TRACE_ERROR("[dlsym] da_start_download_with_extension:%s", dlerror());
+ dlclose(g_da_handle);
+ g_da_handle = NULL;
+ return DP_ERROR_OUT_OF_MEMORY;
+ }
+
+ int da_ret = -1;
+ da_client_cb_t da_cb = {
+ __download_info_cb,
+ __progress_cb,
+ __finished_cb,
+ __paused_cb
+ };
+ da_ret = (*download_agent_init)(&da_cb);
+ if (da_ret != DA_RESULT_OK) {
+ return DP_ERROR_OUT_OF_MEMORY;
+ }
+ return DP_ERROR_NONE;
+}
+
+void dp_deinit_agent()
+{
+ if (g_da_handle != NULL) {
+ if (download_agent_deinit != NULL)
+ (*download_agent_deinit)();
+
+ dlclose(g_da_handle);
+ g_da_handle = NULL;
+ }
+}
+
+// 1 : alive
+// 0 : not alive
+int dp_is_alive_download(int req_id)
+{
+ int da_ret = 0;
+ if (req_id < 0) {
+ TRACE_ERROR("[NULL-CHECK] req_id");
+ return 0;
+ }
+ if (download_agent_is_alive != NULL)
+ da_ret = (*download_agent_is_alive)(req_id);
+ return da_ret;
+}
+
+// 0 : success
+// -1 : failed
+dp_error_type dp_cancel_agent_download(int req_id)
+{
+ if (req_id < 0) {
+ TRACE_ERROR("[NULL-CHECK] req_id");
+ return -1;
+ }
+ if (dp_is_alive_download(req_id) == 0) {
+ TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id);
+ return -1;
+ }
+ if (download_agent_cancel != NULL) {
+ if ((*download_agent_cancel)(req_id) == DA_RESULT_OK)
+ return 0;
+ }
+ return -1;
+}
+
+// 0 : success
+// -1 : failed
+dp_error_type dp_pause_agent_download(int req_id)
+{
+ if (req_id < 0) {
+ TRACE_ERROR("[NULL-CHECK] req_id");
+ return -1;
+ }
+ if (dp_is_alive_download(req_id) == 0) {
+ TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id);
+ return -1;
+ }
+ if (download_agent_suspend != NULL) {
+ if ((*download_agent_suspend)(req_id) == DA_RESULT_OK)
+ return 0;
+ }
+ return -1;
+}
+
+
+// 0 : success
+// -1 : failed
+// -2 : pended
+dp_error_type dp_start_agent_download(dp_request_slots *request_slot)
+{
+ int da_ret = -1;
+ int req_dl_id = -1;
+ dp_error_type errorcode = DP_ERROR_NONE;
+ extension_data_t ext_data = {0,};
+ char *etag = NULL;
+
+ if (request_slot == NULL) {
+ TRACE_ERROR("[NULL-CHECK] download_clientinfo_slot");
+ return DP_ERROR_INVALID_PARAMETER;
+ }
+
+ if (request_slot->request == NULL) {
+ TRACE_ERROR("[NULL-CHECK] download_clientinfo_slot");
+ return DP_ERROR_INVALID_PARAMETER;
+ }
+
+ dp_request *request = request_slot->request;
+
+ char *url = dp_request_get_url(request->id, &errorcode);
+ if (url == NULL) {
+ TRACE_ERROR("[ERROR][%d] URL is NULL", request->id);
+ return DP_ERROR_INVALID_URL;
+ }
+ char *destination =
+ dp_request_get_destination(request->id, request, &errorcode);
+ if (destination != NULL)
+ ext_data.install_path = destination;
+
+ char *filename =
+ dp_request_get_filename(request->id, request, &errorcode);
+ if (filename != NULL)
+ ext_data.file_name = filename;
+
+ // call start_download() of download-agent
+
+ char *tmp_saved_path =
+ dp_request_get_tmpsavedpath(request->id, request, &errorcode);
+ if (tmp_saved_path) {
+ etag = dp_request_get_etag(request->id, request, &errorcode);
+ if (etag) {
+ TRACE_DEBUG("[RESUME][%d]", request->id);
+ ext_data.etag = etag;
+ ext_data.temp_file_path = tmp_saved_path;
+ } else {
+ /* FIXME later : It is better to handle the unlink function in download agaent module
+ * or in upload the request data to memory after the download provider process is restarted */
+ TRACE_SECURE_INFO("[RESTART][%d] try to remove tmp file [%s]",
+ request->id, tmp_saved_path);
+ if (dp_is_file_exist(tmp_saved_path) == 0)
+ if (unlink(tmp_saved_path) != 0)
+ TRACE_STRERROR
+ ("[ERROR][%d] remove file", request->id);
+ }
+ }
+ char *pkg_name = dp_request_get_pkg_name(request->id, request, &errorcode);
+ if (pkg_name != NULL)
+ ext_data.pkg_name = pkg_name;
+ // get headers list from httpheaders table(DB)
+ int headers_count = dp_db_get_cond_rows_count
+ (request->id, DP_DB_TABLE_HTTP_HEADERS, NULL, 0, NULL);
+ if (headers_count > 0) {
+ ext_data.request_header = calloc(headers_count, sizeof(char*));
+ if (ext_data.request_header != NULL) {
+ ext_data.request_header_count = dp_db_get_http_headers_list
+ (request->id, (char**)ext_data.request_header);
+ }
+ }
+
+ ext_data.user_data = (void *)request_slot;
+
+ // call start API of agent lib
+ if (download_agent_start != NULL)
+ da_ret = (*download_agent_start)(url, &ext_data, &req_dl_id);
+ if (ext_data.request_header_count > 0) {
+ int len = 0;
+ int i = 0;
+ len = ext_data.request_header_count;
+ for (i = 0; i < len; i++) {
+ if (ext_data.request_header[i])
+ free((void *)(ext_data.request_header[i]));
+ }
+ free(ext_data.request_header);
+ }
+ free(url);
+ if (destination)
+ free(destination);
+ if (filename)
+ free(filename);
+ if (tmp_saved_path)
+ free(tmp_saved_path);
+ if (etag)
+ free(etag);
+ if (pkg_name)
+ free(pkg_name);
+
+ // if start_download() return error cause of maximun download limitation,
+ // set state to DOWNLOAD_STATE_PENDED.
+ if (da_ret == DA_ERR_ALREADY_MAX_DOWNLOAD) {
+ TRACE_DEBUG("[PENDING][%d] DA_ERR_ALREADY_MAX_DOWNLOAD [%d]",
+ request->id, da_ret);
+ return DP_ERROR_TOO_MANY_DOWNLOADS;
+ } else if (da_ret != DA_RESULT_OK) {
+ TRACE_ERROR("[ERROR][%d] DP_ERROR_CONNECTION_FAILED [%d]",
+ request->id, da_ret);
+ return __change_error(da_ret);
+ }
+ TRACE_DEBUG("[SUCCESS][%d] agent_id [%d]", request->id, req_dl_id);
+ request->agent_id = req_dl_id;
+ return DP_ERROR_NONE;
+}
+
+dp_error_type dp_resume_agent_download(int req_id)
+{
+ int da_ret = -1;
+ if (req_id < 0) {
+ TRACE_ERROR("[NULL-CHECK] req_id");
+ return DP_ERROR_INVALID_PARAMETER;
+ }
+ if (download_agent_resume != NULL)
+ da_ret = (*download_agent_resume)(req_id);
+ if (da_ret == DA_RESULT_OK)
+ return DP_ERROR_NONE;
+ else if (da_ret == DA_ERR_INVALID_STATE)
+ return DP_ERROR_INVALID_STATE;
+ return __change_error(da_ret);
+}
+