diff options
279 files changed, 13817 insertions, 18759 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2511e8e..67d6e27 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,12 +21,36 @@ IF(DEFINED SUPPORT_LOG_MESSAGE) ENDIF(SUPPORT_LOG_MESSAGE) ENDIF(DEFINED SUPPORT_LOG_MESSAGE) -IF(DEFINED SUPPORT_CHECK_IPC) - MESSAGE("SUPPORT_CHECK_IPC: ${SUPPORT_CHECK_IPC}") - IF(SUPPORT_CHECK_IPC) - ADD_DEFINITIONS(-DSUPPORT_CHECK_IPC) - ENDIF(SUPPORT_CHECK_IPC) -ENDIF(DEFINED SUPPORT_CHECK_IPC) +IF(DEFINED IPC_SOCKET) + ADD_DEFINITIONS(-DIPC_SOCKET=\"${IPC_SOCKET}\") +ENDIF(DEFINED IPC_SOCKET) + +IF(DEFINED NOTIFY_DIR) + ADD_DEFINITIONS(-DNOTIFY_DIR=\"${NOTIFY_DIR}\") +ENDIF(DEFINED NOTIFY_DIR) + +IF(DEFINED LOCALE_DIR) + ADD_DEFINITIONS(-DLOCALE_DIR=\"${LOCALE_DIR}\") +ENDIF(DEFINED LOCALE_DIR) + +IF(DEFINED SUPPORT_SECURITY_PRIVILEGE) + MESSAGE("SUPPORT_SECURITY_PRIVILEGE: ${SUPPORT_SECURITY_PRIVILEGE}") + IF(SUPPORT_SECURITY_PRIVILEGE) + ADD_DEFINITIONS(-DSUPPORT_SECURITY_PRIVILEGE) + ENDIF(SUPPORT_SECURITY_PRIVILEGE) +ENDIF(DEFINED SUPPORT_SECURITY_PRIVILEGE) + +IF(DEFINED SUPPORT_COMPANION_MODE) + MESSAGE("SUPPORT_COMPANION_MODE: ${SUPPORT_COMPANION_MODE}") + IF(SUPPORT_COMPANION_MODE) + ADD_DEFINITIONS(-DSUPPORT_COMPANION_MODE) + ENDIF(SUPPORT_COMPANION_MODE) +ENDIF(DEFINED SUPPORT_COMPANION_MODE) + +IF (TIZEN_2_3_UX) + MESSAGE("TIZEN_2_3_UX:On") + ADD_DEFINITIONS("-D_TIZEN_2_3_UX") +ENDIF(TIZEN_2_3_UX) # BUILD @@ -34,7 +58,11 @@ ADD_SUBDIRECTORY(agent) ADD_SUBDIRECTORY(provider-interface) ADD_SUBDIRECTORY(provider) # i18n -ADD_SUBDIRECTORY(po) +IF(TIZEN_2_3_UX) +ADD_SUBDIRECTORY(po/tizen2.3) +ELSE(TIZEN_2_3_UX) +ADD_SUBDIRECTORY(po/redwood) +ENDIF(TIZEN_2_3_UX) # INSTALL @@ -47,21 +75,17 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/download-provider.pc DESTINATION ${LIB INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/systemd/download-provider.service DESTINATION /usr/lib/systemd/system) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/systemd/download-provider.socket DESTINATION /usr/lib/systemd/system) -INSTALL(FILES ${CMAKE_SOURCE_DIR}/download-provider-schema.sql DESTINATION ${DATABASE_SCHEMA_DIR}) - # install images -INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/ DESTINATION ${IMAGE_DIR} - FILES_MATCHING - PATTERN "*.png" - PATTERN "*.gif" - ) +IF(TIZEN_2_3_UX) +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/tizen2.3/ DESTINATION ${IMAGE_DIR}) +ELSE(TIZEN_2_3_UX) +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/redwood/ DESTINATION ${IMAGE_DIR}) +ENDIF(TIZEN_2_3_UX) IF(DEFINED LICENSE_DIR) CONFIGURE_FILE(LICENSE.APLv2 share/license/${PROJECT_NAME}) INSTALL(FILES share/license/${PROJECT_NAME} DESTINATION ${LICENSE_DIR}) ENDIF(DEFINED LICENSE_DIR) -IF(DEFINED SMACK_RULE_DIR) - INSTALL(FILES ${PROJECT_NAME}.rule DESTINATION ${SMACK_RULE_DIR}) -ENDIF(DEFINED SMACK_RULE_DIR) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/dump-download-provider.sh DESTINATION ${CMAKE_LOG_DUMP_SCRIPT_DIR}) diff --git a/agent/CMakeLists.txt b/agent/CMakeLists.txt index 26f2b34..c92fc48 100755 --- a/agent/CMakeLists.txt +++ b/agent/CMakeLists.txt @@ -1,67 +1,27 @@ PROJECT(downloadagent2 C) -IF("${CMAKE_BUILD_TYPE}" STREQUAL "") - SET(CMAKE_BUILD_TYPE "Debug") -ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") -MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") +SET(VERSION "0.1.0") -SET(PREFIX ${CMAKE_INSTALL_PREFIX}) -SET(VERSION "0.0.1") FIND_PROGRAM(UNAME NAMES uname) EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") - -#DA Engine Include Directory -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include) - -INCLUDE(FindPkgConfig) -pkg_check_modules(subpkgs REQUIRED - libsoup-2.4 - xdgmime - vconf - capi-network-connection - glib-2.0 - dlog -) - -FOREACH(flag ${subpkgs_CFLAGS}) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") -ENDFOREACH(flag) - -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") -SET(CMAKE_C_FLAGS_DEBUG "-O0 -Wall") - IF("${ARCH}" MATCHES "^arm.*") ADD_DEFINITIONS("-D_TARGET") SET(CMAKE_C_FLAGS_RELEASE "-mabi=aapcs-linux -msoft-float -O2") ENDIF("${ARCH}" MATCHES "^arm.*") -ADD_DEFINITIONS("-D_EFL_PLATFORM") -#allow to install widget, deb pkg and apk for testing -ADD_DEFINITIONS("-DDA_DEBUG_USING_DLOG") -#This should be removed when release a target -ADD_DEFINITIONS("-D_SAMSUNG_MIME_POLICY") - -############################################################################# -#+++++++++++++++++++++++++DA ENGINE+++++++++++++++++++++++++++++++++++++++++++ -############################################################################# +#DA Engine Include Directory +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include) SET(SRCS_PATH ".") -SET(SRCS_DA_ENGINE - ${SRCS_PATH}/download-agent-debug.c +SET(SRCS_DA ${SRCS_PATH}/download-agent-interface.c ${SRCS_PATH}/download-agent-client-mgr.c ${SRCS_PATH}/download-agent-dl-mgr.c - ${SRCS_PATH}/download-agent-dl-info-util.c - ${SRCS_PATH}/download-agent-http-queue.c - ${SRCS_PATH}/download-agent-http-misc.c + ${SRCS_PATH}/download-agent-dl-info.c ${SRCS_PATH}/download-agent-http-mgr.c ${SRCS_PATH}/download-agent-http-msg-handler.c ${SRCS_PATH}/download-agent-encoding.c - ${SRCS_PATH}/download-agent-utils.c - ${SRCS_PATH}/download-agent-utils-dl-id-history.c - ${SRCS_PATH}/download-agent-basic.c ${SRCS_PATH}/download-agent-file.c - ${SRCS_PATH}/download-agent-plugin-libsoup.c ${SRCS_PATH}/download-agent-plugin-conf.c ${SRCS_PATH}/download-agent-mime-util.c ) @@ -71,14 +31,86 @@ SET(HEADERS include/download-agent-interface.h ) -ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS_DA_ENGINE}) -#TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${subpkgs_LDFLAGS} "-ldl") -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${subpkgs_LDFLAGS}) -SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION 0.0.1) +INCLUDE(FindPkgConfig) + +MESSAGE("SUPPORT_SYS_RESOURCE: ${SUPPORT_SYS_RESOURCE}") +IF (SUPPORT_SYS_RESOURCE) +pkg_check_modules(subpkgs REQUIRED + xdgmime + vconf + capi-network-connection + dlog + system-resource + storage +) +ELSE (SUPPORT_SYS_RESOURCE) +pkg_check_modules(subpkgs REQUIRED + xdgmime + vconf + capi-network-connection + dlog + storage +) +ENDIF (SUPPORT_SYS_RESOURCE) + +IF ("${HTTP_LIB}" MATCHES "libcurl") + MESSAGE("HTTP_LIB: ${HTTP_LIB}") + pkg_check_modules(httppkgs REQUIRED + libcurl + ) + LIST(APPEND SRCS_DA + ${SRCS_PATH}/download-agent-plugin-libcurl.c + ) +ENDIF ("${HTTP_LIB}" MATCHES "libcurl") -############################################################################# -#+++++++++++++++++++++++++INSTALLATION++++++++++++++++++++++++++++++++++++++++ -############################################################################# +IF (SUPPORT_OMA_DRM) + MESSAGE("SUPPORT_OMA_DRM: ${SUPPORT_OMA_DRM}") + ADD_DEFINITIONS("-D_ENABLE_OMA_DRM") + LIST(APPEND SRCS_DA + ${SRCS_PATH}/download-agent-plugin-drm.c + ) + pkg_check_modules(drmpkgs REQUIRED + drm-client + drm-trusted + ) +ENDIF (SUPPORT_OMA_DRM) -INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +IF (SUPPORT_SYS_RESOURCE) + ADD_DEFINITIONS("-D_ENABLE_SYS_RESOURCE") +ENDIF (SUPPORT_SYS_RESOURCE) + +IF (SUPPORT_DOWNLOAD_BOOSTER) + MESSAGE("SUPPORT_DOWNLOAD_BOOSTER:${SUPPORT_DOWNLOAD_BOOSTER}") + ADD_DEFINITIONS("-D_RAF_SUPPORT") + ADD_DEFINITIONS("-D_DOWNLOAD_BOOSTER_SUPPORT") +ENDIF (SUPPORT_DOWNLOAD_BOOSTER) +FOREACH(flag ${subpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +FOREACH(flag ${httppkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +IF (SUPPORT_OMA_DRM) + FOREACH(flag ${drmpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") + ENDFOREACH(flag) + #This is request of DRM Team. + ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64") +ENDIF (SUPPORT_OMA_DRM) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -Wall") + +ADD_DEFINITIONS("-D_ENABLE_DLOG") +#This should be removed when release a target +ADD_DEFINITIONS("-D_SAMSUNG_MIME_POLICY") + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS_DA}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${subpkgs_LDFLAGS} ${httppkgs_LDFLAGS} ${drmpkgs_LDFLAGS}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION}) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) diff --git a/agent/download-agent-basic.c b/agent/download-agent-basic.c deleted file mode 100755 index 73fc892..0000000 --- a/agent/download-agent-basic.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * 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 <stdlib.h> - -#include "download-agent-basic.h" -#include "download-agent-debug.h" -#include "download-agent-client-mgr.h" -#include "download-agent-utils.h" -#include "download-agent-http-mgr.h" -#include "download-agent-http-misc.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-pthread.h" -#include "download-agent-file.h" - -static void* __thread_start_download(void* data); -void __thread_clean_up_handler_for_start_download(void *arg); - -static da_result_t __make_source_info_basic_download( - stage_info *stage, - client_input_t *client_input); -static da_result_t __download_content(stage_info *stage); - -da_result_t start_download(const char *url , int *dl_id) -{ - DA_LOG_FUNC_LOGD(Default); - return start_download_with_extension(url, dl_id, NULL); -} - -da_result_t start_download_with_extension( - const char *url, - int *dl_id, - extension_data_t *extension_data) -{ - da_result_t ret = DA_RESULT_OK; - int slot_id = 0; - const char **request_header = DA_NULL; - const char *install_path = DA_NULL; - const char *file_name = DA_NULL; - const char *etag = DA_NULL; - const char *temp_file_path = DA_NULL; - const char *pkg_name = DA_NULL; - int request_header_count = 0; - void *user_data = DA_NULL; - client_input_t *client_input = DA_NULL; - client_input_basic_t *client_input_basic = DA_NULL; - download_thread_input *thread_info = DA_NULL; - pthread_attr_t thread_attr; - - DA_LOG_FUNC_LOGV(Default); - - if (extension_data) { - request_header = extension_data->request_header; - if (extension_data->request_header_count) - request_header_count = extension_data->request_header_count; - install_path = extension_data->install_path; - file_name = extension_data->file_name; - user_data = extension_data->user_data; - etag = extension_data->etag; - temp_file_path = extension_data->temp_file_path; - pkg_name = extension_data->pkg_name; - } - - ret = get_available_slot_id(&slot_id); - if (DA_RESULT_OK != ret) - return ret; - - *dl_id = GET_DL_ID(slot_id); - - client_input = (client_input_t *)calloc(1, sizeof(client_input_t)); - if (!client_input) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } else { - client_input->user_data = user_data; - if (install_path) { - int install_path_len = strlen(install_path); - if (install_path[install_path_len-1] == '/') - install_path_len--; - - client_input->install_path = (char *)calloc(install_path_len+1, sizeof(char)); - if (client_input->install_path) - strncpy(client_input->install_path, install_path, install_path_len); - } - - if (file_name) { - client_input->file_name = (char *)calloc(strlen(file_name)+1, sizeof(char)); - if (client_input->file_name) - strncpy(client_input->file_name, file_name, strlen(file_name)); - } - - if (etag) { - client_input->etag = (char *)calloc(strlen(etag)+1, sizeof(char)); - if (client_input->etag) - strncpy(client_input->etag, etag, strlen(etag)); - - } - - if (temp_file_path) { - client_input->temp_file_path = (char *)calloc(strlen(temp_file_path)+1, sizeof(char)); - if (client_input->temp_file_path) - strncpy(client_input->temp_file_path, temp_file_path, strlen(temp_file_path)); - } - - if (pkg_name) { - client_input->pkg_name = (char *)calloc(strlen(pkg_name)+1, sizeof(char)); - if (client_input->pkg_name) - strncpy(client_input->pkg_name, pkg_name, strlen(pkg_name)); - } - client_input_basic = &(client_input->client_input_basic); - client_input_basic->req_url = (char *)calloc(strlen(url)+1, sizeof(char)); - if(DA_NULL == client_input_basic->req_url) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - strncpy(client_input_basic->req_url ,url,strlen(url)); - - if (request_header_count > 0) { - int i = 0; - client_input_basic->user_request_header = - (char **)calloc(1, sizeof(char *)*request_header_count); - if(DA_NULL == client_input_basic->user_request_header) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - for (i = 0; i < request_header_count; i++) - { - client_input_basic->user_request_header[i] = strdup(request_header[i]); - } - client_input_basic->user_request_header_count = request_header_count; - } - } - - thread_info = (download_thread_input *)calloc(1, sizeof(download_thread_input)); - if (!thread_info) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } else { - thread_info->slot_id = slot_id; - thread_info->client_input = client_input; - } - if (pthread_attr_init(&thread_attr) != 0) { - ret = DA_ERR_FAIL_TO_CREATE_THREAD; - goto ERR; - } - - if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) != 0) { - ret = DA_ERR_FAIL_TO_CREATE_THREAD; - goto ERR; - } - - if (pthread_create(&GET_DL_THREAD_ID(slot_id), &thread_attr, - __thread_start_download, thread_info) < 0) { - DA_LOG_ERR(Thread, "making thread failed.."); - ret = DA_ERR_FAIL_TO_CREATE_THREAD; - } else { - if (GET_DL_THREAD_ID(slot_id) < 1) { - DA_LOG_ERR(Thread, "The thread start is failed before calling this"); -// When http resource is leaked, the thread ID is initialized at error handling section of thread_start_download() -// Because the thread ID is initialized, the ptrhead_detach should not be called. This is something like timing issue between threads. -// thread info and basic_dl_input is freed at thread_start_download(). And it should not returns error code in this case. - goto ERR; - } - } - DA_LOG_DEBUG(Thread, "download thread create slot_id[%d] thread id[%lu]", - slot_id,GET_DL_THREAD_ID(slot_id)); - -ERR: - if (DA_RESULT_OK != ret) { - if (client_input) { - clean_up_client_input_info(client_input); - free(client_input); - client_input = DA_NULL; - } - if (thread_info) { - free(thread_info); - thread_info = DA_NULL; - } - destroy_download_info(slot_id); - } - return ret; -} - -da_result_t __make_source_info_basic_download( - stage_info *stage, - client_input_t *client_input) -{ - da_result_t ret = DA_RESULT_OK; - client_input_basic_t *client_input_basic = DA_NULL; - source_info_t *source_info = DA_NULL; - source_info_basic_t *source_info_basic = DA_NULL; - - DA_LOG_FUNC_LOGV(Default); - - if (!stage) { - DA_LOG_ERR(Default, "no stage; DA_ERR_INVALID_ARGUMENT"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - client_input_basic = &(client_input->client_input_basic); - if (DA_NULL == client_input_basic->req_url) { - DA_LOG_ERR(Default, "DA_ERR_INVALID_URL"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - source_info_basic = (source_info_basic_t*)calloc(1, sizeof(source_info_basic_t)); - if (DA_NULL == source_info_basic) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - - source_info_basic->url = client_input_basic->req_url; - client_input_basic->req_url = DA_NULL; - - if (client_input_basic->user_request_header) { - source_info_basic->user_request_header = - client_input_basic->user_request_header; - source_info_basic->user_request_header_count = - client_input_basic->user_request_header_count; - client_input_basic->user_request_header = DA_NULL; - client_input_basic->user_request_header_count = 0; - } - - source_info = GET_STAGE_SOURCE_INFO(stage); - memset(source_info, 0, sizeof(source_info_t)); - - source_info->source_info_type.source_info_basic = source_info_basic; - -// DA_SECURE_LOGI("BASIC HTTP STARTED: URL=%s", -// source_info->source_info_type.source_info_basic->url); -ERR: - return ret; -} - -void __thread_clean_up_handler_for_start_download(void *arg) -{ - DA_LOG_CRITICAL(Default, "cleanup for thread id = %d", pthread_self()); -} - -static void *__thread_start_download(void *data) -{ - da_result_t ret = DA_RESULT_OK; - download_thread_input *thread_info = DA_NULL; - client_input_t *client_input = DA_NULL; - stage_info *stage = DA_NULL; - download_state_t download_state = 0; - - int slot_id = DA_INVALID_ID; - - DA_LOG_FUNC_LOGV(Thread); - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL); - - thread_info = (download_thread_input*)data; - if (DA_NULL == thread_info) { - DA_LOG_ERR(Thread, "thread_info is NULL.."); - ret = DA_ERR_INVALID_ARGUMENT; - return DA_NULL; - } else { - slot_id = thread_info->slot_id; - client_input = thread_info->client_input; - - if(thread_info) { - free(thread_info); - thread_info = DA_NULL; - } - } - - pthread_cleanup_push(__thread_clean_up_handler_for_start_download, (void *)NULL); - - if (DA_FALSE == is_valid_slot_id(slot_id)) { - ret = DA_ERR_INVALID_ARGUMENT; - DA_LOG_ERR(Default, "Invalid Download ID"); - goto ERR; - } - - if (!client_input) { - ret = DA_ERR_INVALID_ARGUMENT; - DA_LOG_ERR(Default, "Invalid client_input"); - goto ERR; - } - - stage = Add_new_download_stage(slot_id); - if (!stage) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - DA_LOG_ERR(Default, "STAGE ADDITION FAIL!"); - goto ERR; - } - DA_LOG_VERBOSE(Default, "new added Stage : %p", stage); - - GET_DL_USER_DATA(slot_id) = client_input->user_data; - client_input->user_data = DA_NULL; - GET_DL_USER_INSTALL_PATH(slot_id) = client_input->install_path; - client_input->install_path = DA_NULL; - GET_DL_USER_FILE_NAME(slot_id) = client_input->file_name; - client_input->file_name = DA_NULL; - GET_DL_USER_ETAG(slot_id) = client_input->etag; - client_input->etag = DA_NULL; - GET_DL_USER_TEMP_FILE_PATH(slot_id) = client_input->temp_file_path; - client_input->temp_file_path = DA_NULL; - - ret = __make_source_info_basic_download(stage, client_input); - - if (ret == DA_RESULT_OK) { - /* to save memory */ - if (client_input) { - clean_up_client_input_info(client_input); - free(client_input); - client_input = DA_NULL; - } - - ret = __download_content(stage); - if (stage != GET_DL_CURRENT_STAGE(slot_id)) { - DA_LOG_ERR(Default,"Playready download case. The next stage is present stage"); - stage = GET_DL_CURRENT_STAGE(slot_id); - } - } -ERR: - if (client_input) { - clean_up_client_input_info(client_input); - free(client_input); - client_input = DA_NULL; - } - - if (DA_RESULT_OK == ret) { - char *installed_path = NULL; - char *etag = DA_NULL; - req_dl_info *request_info = NULL; - file_info *file_storage = NULL; - DA_LOG_VERBOSE(Default, "Whole download flow is finished."); - _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - download_state = GET_DL_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - if (download_state == DOWNLOAD_STATE_ABORTED) { - DA_LOG(Default, "Abort case. Do not call client callback"); -#ifdef PAUSE_EXIT - } else if (download_state == DOWNLOAD_STATE_PAUSED) { - DA_LOG(Default, "Finish case from paused state"); - destroy_download_info(slot_id); -#endif - } else { - request_info = GET_STAGE_TRANSACTION_INFO(stage); - etag = GET_REQUEST_HTTP_HDR_ETAG(request_info); - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - installed_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage); - send_user_noti_and_finish_download_flow(slot_id, installed_path, - etag); - } - } else { - char *etag = DA_NULL; - req_dl_info *request_info = NULL; - request_info = GET_STAGE_TRANSACTION_INFO(stage); - DA_LOG_CRITICAL(Default, "Download Failed -Return = %d", ret); - if (request_info) { - etag = GET_REQUEST_HTTP_HDR_ETAG(request_info); - send_client_finished_info(slot_id, GET_DL_ID(slot_id), - DA_NULL, etag, ret, get_http_status(slot_id)); - } - destroy_download_info(slot_id); - } - - pthread_cleanup_pop(0); - DA_LOG_CRITICAL(Thread, "==thread_start_download - EXIT=="); - pthread_exit((void *)NULL); - return DA_NULL; -} - -da_result_t __download_content(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - download_state_t download_state = 0; - da_bool_t isDownloadComplete = DA_FALSE; - int slot_id = DA_INVALID_ID; - - DA_LOG_FUNC_LOGV(Default); - - slot_id = GET_STAGE_DL_ID(stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD, stage); - - do { - stage = GET_DL_CURRENT_STAGE(slot_id); - _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - download_state = GET_DL_STATE_ON_STAGE(stage); - DA_LOG_VERBOSE(Default, "download_state to - [%d] ", download_state); - _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - - switch(download_state) { - case DOWNLOAD_STATE_NEW_DOWNLOAD: - ret = requesting_download(stage); - - _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - download_state = GET_DL_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - if (download_state == DOWNLOAD_STATE_CANCELED || - download_state == DOWNLOAD_STATE_ABORTED || - download_state == DOWNLOAD_STATE_PAUSED) { - break; - } else { - if (DA_RESULT_OK == ret) { - ret = handle_after_download(stage); - } - } - break; - default: - isDownloadComplete = DA_TRUE; - break; - } - }while ((DA_RESULT_OK == ret) && (DA_FALSE == isDownloadComplete)); - - return ret; -} diff --git a/agent/download-agent-client-mgr.c b/agent/download-agent-client-mgr.c index b27a2d4..82dd516 100755 --- a/agent/download-agent-client-mgr.c +++ b/agent/download-agent-client-mgr.c @@ -14,618 +14,132 @@ * limitations under the License. */ -#include <unistd.h> +#include <stdlib.h> #include "download-agent-client-mgr.h" -#include "download-agent-debug.h" -#include "download-agent-utils.h" -#include "download-agent-file.h" -#define IS_CLIENT_Q_HAVING_DATA(QUEUE) (QUEUE->having_data) - -static client_app_mgr_t client_app_mgr; - -static da_result_t __launch_client_thread(void); -static void *__thread_for_client_noti(void *data); -void __thread_clean_up_handler_for_client_thread(void *arg); -static void __pop_client_noti(client_noti_t **out_client_noti); - -void __client_q_goto_sleep_without_lock(void); -void __client_q_wake_up_without_lock(void); -void destroy_client_noti(client_noti_t *client_noti); - -da_result_t init_client_app_mgr() -{ - DA_LOG_FUNC_LOGV(ClientNoti); - - if(client_app_mgr.is_init) - return DA_RESULT_OK; - - client_app_mgr.is_init = DA_TRUE; - client_app_mgr.client_app_info.client_user_agent = DA_NULL; - client_app_mgr.is_thread_init = DA_FALSE; - client_app_mgr.thread_id = 0; - - return DA_RESULT_OK; -} - -da_bool_t is_client_app_mgr_init(void) -{ - return client_app_mgr.is_init; -} - -da_result_t reg_client_app( - da_client_cb_t *da_client_callback) -{ - da_result_t ret = DA_RESULT_OK; - client_queue_t *queue = DA_NULL; - client_noti_t *client_noti = DA_NULL; - - DA_LOG_FUNC_LOGD(ClientNoti); - - memset(&(client_app_mgr.client_app_info.client_callback), - 0, sizeof(da_client_cb_t)); - memcpy(&(client_app_mgr.client_app_info.client_callback), - da_client_callback, sizeof(da_client_cb_t)); - - _da_thread_mutex_init(&(client_app_mgr.mutex_client_mgr), DA_NULL); - - /* If some noti is existed at queue, delete all */ - do { - __pop_client_noti(&client_noti); - destroy_client_noti(client_noti); - } while(client_noti != DA_NULL); - - queue = &(client_app_mgr.client_queue); - DA_LOG_VERBOSE(ClientNoti, "client queue = %p", queue); - _da_thread_mutex_init(&(queue->mutex_client_queue), DA_NULL); - _da_thread_cond_init(&(queue->cond_client_queue), DA_NULL); - - ret = __launch_client_thread(); - - return ret; -} - -da_result_t dereg_client_app(void) +da_ret_t send_client_paused_info(da_info_t *da_info) { - client_noti_t *client_noti = DA_NULL; - - DA_LOG_FUNC_LOGV(ClientNoti); - - client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); - if (!client_noti) { - DA_LOG_ERR(ClientNoti, "calloc fail"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - client_noti->slot_id = DA_INVALID_ID; - client_noti->noti_type = Q_CLIENT_NOTI_TYPE_TERMINATE; - client_noti->next = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); - _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr)); - if (client_app_mgr.is_thread_init != DA_TRUE) { - DA_LOG_CRITICAL(ClientNoti, "try to cancel client mgr thread id[%lu]", - client_app_mgr.thread_id); - if (client_app_mgr.thread_id && - pthread_cancel(client_app_mgr.thread_id) < 0) { - DA_LOG_ERR(ClientNoti, "cancel thread is failed!!!"); - } - free(client_noti); + if (da_info->is_cb_update && da_info->cb_info.paused_cb) { + da_info->cb_info.paused_cb(da_info->da_id, + req_info->user_req_data, req_info->user_client_data); + DA_LOGV("id[%d]", da_info->da_id); } else { - void *t_return = NULL; - DA_LOG_VERBOSE(ClientNoti, "pushing Q_CLIENT_NOTI_TYPE_TERMINATE"); - push_client_noti(client_noti); - DA_LOG_DEBUG(Thread, "===try to join client mgr thread id[%lu]===", - client_app_mgr.thread_id); - if (client_app_mgr.thread_id && - pthread_join(client_app_mgr.thread_id, &t_return) < 0) { - DA_LOG_ERR(Thread, "join client thread is failed!!!"); - } - DA_LOG_DEBUG(Thread, "===thread join return[%d]===", (char*)t_return); + DA_LOGV("No CB:id[%d]", da_info->da_id); } - _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr)); - /* ToDo: This clean up should be done at the end of client_thread. */ - if(client_app_mgr.client_app_info.client_user_agent) { - free(client_app_mgr.client_app_info.client_user_agent); - client_app_mgr.client_app_info.client_user_agent = DA_NULL; - } - _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr)); - client_app_mgr.is_thread_init = DA_FALSE; - _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr)); - _da_thread_mutex_destroy(&(client_app_mgr.mutex_client_mgr)); return DA_RESULT_OK; } -da_result_t send_client_paused_info(int slot_id) +da_ret_t send_client_update_dl_info(da_info_t *da_info) { - client_noti_t *client_noti = DA_NULL; - user_paused_info_t *paused_info = DA_NULL; - download_state_t state = GET_DL_STATE_ON_ID(slot_id); - - DA_LOG_FUNC_LOGD(ClientNoti); - - if (!GET_DL_ENABLE_PAUSE_UPDATE(slot_id)) { - DA_LOG(ClientNoti, "Do not call pause cb"); - return DA_RESULT_OK; - } - if (!is_valid_slot_id(slot_id)) { - DA_LOG_ERR(ClientNoti, "Download ID is not valid"); - return DA_RESULT_OK; - } + download_info_t *info = DA_NULL; + file_info_t *file_info = DA_NULL; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); - DA_LOG_VERBOSE(ClientNoti, "slot_id[%d]", slot_id); - if ((DOWNLOAD_STATE_PAUSED != state)) { - DA_LOG(ClientNoti, "The state is not paused. state:%d", state); - return DA_ERR_INVALID_STATE; - } - - client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); - if (!client_noti) { - DA_LOG_ERR(ClientNoti, "calloc fail"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - client_noti->slot_id = slot_id; - client_noti->user_data = GET_DL_USER_DATA(slot_id); - client_noti->noti_type = Q_CLIENT_NOTI_TYPE_PAUSED_INFO; - client_noti->next = DA_NULL; - - paused_info = (user_paused_info_t *)&(client_noti->type.paused_info); - paused_info->download_id= GET_DL_ID(slot_id); - DA_LOG(ClientNoti, "pushing paused info. slot_id=%d, dl_id=%d", - slot_id, GET_DL_ID(slot_id)); - - push_client_noti(client_noti); - - return DA_RESULT_OK; -} - -da_result_t send_client_update_progress_info ( - int slot_id, - int dl_id, - unsigned long int received_size - ) -{ - client_noti_t *client_noti = DA_NULL; - user_progress_info_t *progress_info = DA_NULL; - - DA_LOG_FUNC_LOGV(ClientNoti); - - if (!is_valid_slot_id(slot_id)) { - DA_LOG_ERR(ClientNoti, "Download ID is not valid"); - return DA_ERR_INVALID_DL_REQ_ID; - } - - client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); - if (!client_noti) { - DA_LOG_ERR(ClientNoti, "calloc fail"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - client_noti->slot_id = slot_id; - client_noti->user_data = GET_DL_USER_DATA(slot_id); - client_noti->noti_type = Q_CLIENT_NOTI_TYPE_PROGRESS_INFO; - client_noti->next = DA_NULL; - - progress_info = (user_progress_info_t *)&(client_noti->type.update_progress_info); - progress_info->download_id= dl_id; - progress_info->received_size = received_size; - - DA_LOG_VERBOSE(ClientNoti, "pushing received_size=%lu, slot_id=%d, dl_id=%d", - received_size, slot_id, dl_id); - - push_client_noti(client_noti); - - return DA_RESULT_OK; -} - -da_result_t send_client_update_dl_info ( - int slot_id, - int dl_id, - char *file_type, - unsigned long int file_size, - char *tmp_saved_path, - char *pure_file_name, - char *etag, - char *extension) -{ - client_noti_t *client_noti = DA_NULL; - user_download_info_t *update_dl_info = DA_NULL; - int len = 0; - - DA_LOG_FUNC_LOGV(ClientNoti); - - if (!is_valid_slot_id(slot_id)) { - DA_LOG_ERR(ClientNoti, "Download ID is not valid"); - return DA_ERR_INVALID_DL_REQ_ID; - } - - client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); - if (!client_noti) { - DA_LOG_ERR(ClientNoti, "calloc fail"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - client_noti->slot_id = slot_id; - client_noti->user_data = GET_DL_USER_DATA(slot_id); - client_noti->noti_type = Q_CLIENT_NOTI_TYPE_STARTED_INFO; - client_noti->next = DA_NULL; - - update_dl_info = (user_download_info_t *)&(client_noti->type.update_dl_info); - update_dl_info->download_id = dl_id; - update_dl_info->file_size = file_size; - if (pure_file_name && extension) { - len = strlen(pure_file_name) + strlen(extension) + 1; - update_dl_info->content_name = (char *)calloc(len + 1, sizeof(char)); - if (!update_dl_info->content_name) { - free(client_noti); + if (da_info->is_cb_update && da_info->cb_info.download_info_cb) { + info = (download_info_t *)calloc(1, sizeof(download_info_t)); + if (!info) return DA_ERR_FAIL_TO_MEMALLOC; + info->download_id = da_info->da_id; + info->file_size = http_info->content_len_from_header; + if (http_info->content_type_from_header) + info->file_type = strdup(http_info->content_type_from_header); + if (file_info->file_path) + info->tmp_saved_path = strdup(file_info->file_path); + if (file_info->pure_file_name) + info->content_name = strdup(file_info->pure_file_name); + if (http_info->etag_from_header) { + info->etag = strdup(http_info->etag_from_header); + //DA_SECURE_LOGI("etag[%s]", info->etag); } - snprintf(update_dl_info->content_name, len + 1, "%s.%s", - pure_file_name, extension); - } - - /* These strings MUST be copied to detach __thread_for_client_noti from download_info */ - if (file_type) - update_dl_info->file_type = strdup(file_type); - - if (tmp_saved_path) - update_dl_info->tmp_saved_path = strdup(tmp_saved_path); - - if (etag) - update_dl_info->etag = strdup(etag); - DA_LOG_DEBUG(ClientNoti, "pushing slot_id=%d, dl_id=%d", slot_id, dl_id); - - push_client_noti(client_noti); - - return DA_RESULT_OK; -} - -da_result_t send_client_finished_info ( - int slot_id, - int dl_id, - char *saved_path, - char *etag, - int error, - int http_status - ) -{ - client_noti_t *client_noti = DA_NULL; - user_finished_info_t *finished_info = DA_NULL; - - DA_LOG_FUNC_LOGV(ClientNoti); - - if (!is_valid_slot_id(slot_id)) { - DA_LOG_ERR(ClientNoti, "Download ID is not valid"); - return DA_ERR_INVALID_DL_REQ_ID; - } - - client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); - if (!client_noti) { - DA_LOG_ERR(ClientNoti, "calloc fail"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - client_noti->slot_id = slot_id; - client_noti->user_data = GET_DL_USER_DATA(slot_id); - client_noti->noti_type = Q_CLIENT_NOTI_TYPE_FINISHED_INFO; - client_noti->next = DA_NULL; - - finished_info = (user_finished_info_t *)&(client_noti->type.finished_info); - finished_info->download_id = dl_id; - finished_info->err = error; - finished_info->http_status = http_status; - - if (saved_path) { - finished_info->saved_path = strdup(saved_path); - DA_SECURE_LOGD("saved path=%s", saved_path); - } - if (etag) { - finished_info->etag = strdup(etag); - DA_SECURE_LOGD("pushing finished info. etag[%s]", etag); - } - DA_LOG_VERBOSE(ClientNoti, "user_data=%p", client_noti->user_data); - DA_LOG_VERBOSE(ClientNoti, "http_status=%d", http_status); - DA_LOG(ClientNoti, "pushing slot_id=%d, dl_id=%d err=%d", slot_id, dl_id, error); - - push_client_noti(client_noti); - - return DA_RESULT_OK; -} - -da_result_t __launch_client_thread(void) -{ - pthread_t thread_id = 0; - - DA_LOG_FUNC_LOGV(Thread); - - if (pthread_create(&thread_id, DA_NULL, - __thread_for_client_noti,DA_NULL) < 0) { - DA_LOG_ERR(Thread, "making thread failed.."); - return DA_ERR_FAIL_TO_CREATE_THREAD; + da_info->cb_info.download_info_cb(info, + req_info->user_req_data, req_info->user_client_data); + DA_LOGD("id[%d]", info->download_id); + //DA_LOGI("id[%d]total_size[%lu]", info->download_id, info->file_size); + //if (http_info->content_type_from_header) + //DA_SECURE_LOGI("mime_type[%s]", http_info->content_type_from_header); + } else { + DA_LOGI("No CB:id[%d]", da_info->da_id); } - DA_LOG_VERBOSE(Thread, "client mgr thread id[%d]", thread_id); - client_app_mgr.thread_id = thread_id; return DA_RESULT_OK; } -void destroy_client_noti(client_noti_t *client_noti) -{ - if (client_noti) { - if (client_noti->noti_type == Q_CLIENT_NOTI_TYPE_STARTED_INFO) { - user_download_info_t *update_dl_info = DA_NULL; - update_dl_info = (user_download_info_t*)&(client_noti->type.update_dl_info); - if (update_dl_info->file_type) { - free(update_dl_info->file_type); - update_dl_info->file_type = DA_NULL; - } - if (update_dl_info->tmp_saved_path) { - free(update_dl_info->tmp_saved_path); - update_dl_info->tmp_saved_path = DA_NULL; - } - if (update_dl_info->etag) { - free(update_dl_info->etag); - update_dl_info->etag = DA_NULL; - } - } else if (client_noti->noti_type == - Q_CLIENT_NOTI_TYPE_FINISHED_INFO) { - user_finished_info_t *finished_info = DA_NULL; - finished_info = (user_finished_info_t*) - &(client_noti->type.finished_info); - if (finished_info->saved_path) { - free(finished_info->saved_path); - finished_info->saved_path = DA_NULL; - } - if (finished_info->etag) { - free(finished_info->etag); - finished_info->etag = DA_NULL; - } - } - free(client_noti); - } -} - - -void push_client_noti(client_noti_t *client_noti) +da_ret_t send_client_update_progress_info(da_info_t *da_info) { - client_queue_t *queue = DA_NULL; - client_noti_t *head = DA_NULL; - client_noti_t *pre = DA_NULL; - client_noti_t *cur = DA_NULL; - - queue = &(client_app_mgr.client_queue); - _da_thread_mutex_lock (&(queue->mutex_client_queue)); + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); - head = queue->client_q_head; - if (!head) { - queue->client_q_head = client_noti; - } else { - cur = head; - while (cur->next) { - pre = cur; - cur = pre->next; - } -#if 0 - if (cur->noti_type == Q_CLIENT_NOTI_TYPE_PROGRESS_INFO) { - /* For UI performance. If the update noti info is existed at queue, - replace it with new update noti info */ - if (cur->slot_id == client_noti->slot_id) { - /* DA_LOG(ClientNoti, "exchange queue's tail and pushing item"); */ - if (pre == DA_NULL) - queue->client_q_head = client_noti; - else - pre->next = client_noti; - destroy_client_noti(cur); - } else { - cur->next = client_noti; - } - } else { - cur->next = client_noti; - } -#else - cur->next = client_noti; -#endif - } - - queue->having_data = DA_TRUE; + if (!file_info->is_updated) + return DA_RESULT_OK; - __client_q_wake_up_without_lock(); - if (queue->client_q_head->next) { - DA_LOG_VERBOSE(ClientNoti, "client noti[%p] next noti[%p]", - queue->client_q_head, queue->client_q_head->next); + if (da_info->is_cb_update && da_info->cb_info.progress_cb) { + da_info->cb_info.progress_cb(da_info->da_id, + file_info->bytes_written_to_file, + req_info->user_req_data, req_info->user_client_data); + DA_LOGV("id[%d],size[%llu]", da_info->da_id, + file_info->bytes_written_to_file); } else { - DA_LOG_VERBOSE(ClientNoti, "client noti[%p] next noti is NULL", - queue->client_q_head); + DA_LOGI("No CB:id[%d]", da_info->da_id); } - - _da_thread_mutex_unlock (&(queue->mutex_client_queue)); + file_info->is_updated = DA_FALSE; + return DA_RESULT_OK; } -void __pop_client_noti(client_noti_t **out_client_noti) +da_ret_t send_client_finished_info(da_info_t *da_info, int err) { - client_queue_t *queue = DA_NULL; - - queue = &(client_app_mgr.client_queue); + finished_info_t *info = DA_NULL; + file_info_t *file_info = DA_NULL; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); - _da_thread_mutex_lock (&(queue->mutex_client_queue)); - - if (queue->client_q_head) { - *out_client_noti = queue->client_q_head; - queue->client_q_head = queue->client_q_head->next; - if (queue->client_q_head) { - DA_LOG_VERBOSE(ClientNoti, "client noti[%p] next noti[%p]", - *out_client_noti, queue->client_q_head); - } else { - DA_LOG_VERBOSE(ClientNoti, "client noti[%p] next noti is NULL", - *out_client_noti); - } + if (da_info->is_cb_update && da_info->cb_info.finished_cb) { + info = (finished_info_t *)calloc(1, sizeof(finished_info_t)); + if (!info) + return DA_ERR_FAIL_TO_MEMALLOC; + info->download_id = da_info->da_id; + if (http_info->http_msg_response) + info->http_status = http_info->http_msg_response->status_code; + else + DA_LOGE("http_msg_response is NULL"); + if (file_info->file_path) + info->saved_path = strdup(file_info->file_path); + if (http_info->etag_from_header) + info->etag = strdup(http_info->etag_from_header); + info->err = err; + da_info->cb_info.finished_cb(info, + req_info->user_req_data, req_info->user_client_data); + DA_LOGD("id[%d]", info->download_id); + //DA_LOGI("id[%d],err[%d], http_status[%d]", info->download_id, + //info->err, info->http_status); } else { - *out_client_noti = DA_NULL; - } - - if (queue->client_q_head == DA_NULL) { - queue->having_data = DA_FALSE; + DA_LOGI("No CB:id[%d]", da_info->da_id); } - - _da_thread_mutex_unlock (&(queue->mutex_client_queue)); -} - -void __client_q_goto_sleep_without_lock(void) -{ - client_queue_t *queue = DA_NULL; - queue = &(client_app_mgr.client_queue); - _da_thread_cond_wait(&(queue->cond_client_queue), &(queue->mutex_client_queue)); -} - -void __client_q_wake_up_without_lock(void) -{ - client_queue_t *queue = DA_NULL; - queue = &(client_app_mgr.client_queue); - _da_thread_cond_signal(&(queue->cond_client_queue)); -} - -void __thread_clean_up_handler_for_client_thread(void *arg) -{ - DA_LOG_CRITICAL(Thread, "cleanup for thread id = %d", pthread_self()); -} - -static void *__thread_for_client_noti(void *data) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t need_wait = DA_TRUE; - client_queue_t *queue = DA_NULL; - client_noti_t *client_noti = DA_NULL; - - DA_LOG_FUNC_LOGV(Thread); - - _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr)); - client_app_mgr.is_thread_init = DA_TRUE; - _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr)); - - queue = &(client_app_mgr.client_queue); - DA_LOG_VERBOSE(ClientNoti, "client queue = %p", queue); - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL); - pthread_cleanup_push(__thread_clean_up_handler_for_client_thread, (void *)DA_NULL); - - do { - _da_thread_mutex_lock(&(queue->mutex_client_queue)); - if (DA_FALSE == IS_CLIENT_Q_HAVING_DATA(queue)) { - DA_LOG_VERBOSE(Thread, "Sleep @ thread_for_client_noti!"); - __client_q_goto_sleep_without_lock(); - DA_LOG_VERBOSE(Thread, "Woke up @ thread_for_client_noti"); - } - _da_thread_mutex_unlock(&(queue->mutex_client_queue)); - - do { - __pop_client_noti(&client_noti); - if (client_noti == DA_NULL) { - DA_LOG_ERR(ClientNoti, "There is no data on client queue!"); - ret = DA_ERR_INVALID_STATE; - need_wait = DA_FALSE; - } else { - DA_LOG_VERBOSE(ClientNoti, "noti type[%d]", - client_noti->noti_type); - switch (client_noti->noti_type) { - case Q_CLIENT_NOTI_TYPE_STARTED_INFO: - { - user_download_info_t *update_dl_info = DA_NULL;; - update_dl_info = (user_download_info_t*)(&(client_noti->type.update_dl_info)); - if (client_app_mgr.client_app_info.client_callback.update_dl_info_cb) { - client_app_mgr.client_app_info.client_callback.update_dl_info_cb(update_dl_info, client_noti->user_data); - if (update_dl_info->etag) - DA_SECURE_LOGD("Etag:[%s]", update_dl_info->etag); - DA_SECURE_LOGD("file size=%lu", update_dl_info->file_size); - DA_LOG(ClientNoti, "Update download info for slot_id=%d, dl_id=%d- DONE", - client_noti->slot_id, - update_dl_info->download_id - ); - } - } - break; - case Q_CLIENT_NOTI_TYPE_PROGRESS_INFO: - { - user_progress_info_t *progress_info = DA_NULL;; - progress_info = (user_progress_info_t*)(&(client_noti->type.update_progress_info)); - if (client_app_mgr.client_app_info.client_callback.update_progress_info_cb) { - client_app_mgr.client_app_info.client_callback.update_progress_info_cb(progress_info, client_noti->user_data); - DA_LOG_VERBOSE(ClientNoti, "Update downloading info for slot_id=%d, dl_id=%d, received size=%lu - DONE", - client_noti->slot_id, - progress_info->download_id, - progress_info->received_size); - } - } - break; - case Q_CLIENT_NOTI_TYPE_FINISHED_INFO: - { - user_finished_info_t *finished_info = DA_NULL;; - finished_info = (user_finished_info_t*)(&(client_noti->type.finished_info)); - if (client_app_mgr.client_app_info.client_callback.finished_info_cb) { - client_app_mgr.client_app_info.client_callback.finished_info_cb( - finished_info, client_noti->user_data); - DA_LOG(ClientNoti, "Completed info for slot_id=%d, dl_id=%d, err=%d http_state=%d user_data=%p- DONE", - client_noti->slot_id, - finished_info->download_id, - finished_info->err, - finished_info->http_status, - client_noti->user_data); - if (finished_info->etag) - DA_SECURE_LOGD("Completed info for etag=%s - DONE", - finished_info->etag); - - } - } - break; - case Q_CLIENT_NOTI_TYPE_PAUSED_INFO: - { - user_paused_info_t *da_paused_info = DA_NULL; - da_paused_info = (user_paused_info_t *)(&(client_noti->type.paused_info)); - - if (client_app_mgr.client_app_info.client_callback.paused_info_cb) { - DA_LOG(ClientNoti, "User Paused info for slot_id=%d, dl_id=%d - Done", - client_noti->slot_id, - da_paused_info->download_id); - client_app_mgr.client_app_info.client_callback.paused_info_cb( - da_paused_info, client_noti->user_data); - } - } - break; - case Q_CLIENT_NOTI_TYPE_TERMINATE: - DA_LOG_VERBOSE(ClientNoti, "Q_CLIENT_NOTI_TYPE_TERMINATE"); - need_wait = DA_FALSE; - break; - } - destroy_client_noti(client_noti); - } - - if(DA_TRUE == need_wait) { - _da_thread_mutex_lock(&(queue->mutex_client_queue)); - if (DA_FALSE == IS_CLIENT_Q_HAVING_DATA(queue)) { - _da_thread_mutex_unlock (&(queue->mutex_client_queue)); - break; - } else { - _da_thread_mutex_unlock (&(queue->mutex_client_queue)); - } - } else { - break; - } - } while (1); - } while (DA_TRUE == need_wait); - - _da_thread_mutex_destroy(&(queue->mutex_client_queue)); - _da_thread_cond_destroy(&(queue->cond_client_queue)); - - pthread_cleanup_pop(0); - DA_LOG_DEBUG(Thread, "=====thread_for_client_noti- EXIT====="); - pthread_exit((void *)NULL); - return DA_NULL; + return DA_RESULT_OK; } -char *get_client_user_agent_string(void) -{ - if (!client_app_mgr.is_init) - return DA_NULL; - - return client_app_mgr.client_app_info.client_user_agent; -} diff --git a/agent/download-agent-debug.c b/agent/download-agent-debug.c deleted file mode 100755 index 07078b3..0000000 --- a/agent/download-agent-debug.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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 <stdlib.h> -#include <string.h> - -#include "download-agent-debug.h" -#include "download-agent-utils.h" - -#define STRING_IT(x) #x -#define TURN_ON_LOG(channel) (DALogBitMap |= (0x1<<(channel))) - -int DALogBitMap; - -char *__get_log_env(void); -char **__parsing_log_env(char *in_log_env); -char *__copying_str(char *source, int length); -char *__get_channel_name_from_enum(da_log_channel channel_enum); - -da_result_t init_log_mgr(void) { - da_result_t ret = DA_RESULT_OK; - static da_bool_t did_log_mgr_init = DA_FALSE; - char *log_env = DA_NULL; - char **parsed_log_env = DA_NULL; - char **cur_parsed_log_env = DA_NULL; - int i = 0; - - if (did_log_mgr_init) - return ret; - - did_log_mgr_init = DA_TRUE; - - log_env = __get_log_env(); - if (!log_env) { - /* If no environment values are found, do behave like all logs are turned on except for Soup log */ - DALogBitMap = ~(0x1 << Soup); - return ret; - } - - TURN_ON_LOG(Default); - - parsed_log_env = __parsing_log_env(log_env); - if (parsed_log_env) { - char *channel_keyward = DA_NULL; - for (cur_parsed_log_env = parsed_log_env; *cur_parsed_log_env; cur_parsed_log_env++) { - if (!*cur_parsed_log_env) - break; - for (i = 0; i < DA_LOG_CHANNEL_MAX; i++) { - channel_keyward = __get_channel_name_from_enum(i); - if (channel_keyward && !strcmp(*cur_parsed_log_env, - channel_keyward)) { - TURN_ON_LOG(i); - break; - } - } - free(*cur_parsed_log_env); - } - free(parsed_log_env); - } - - if (log_env) - free(log_env); - - return ret; -} - -char *__get_log_env(void) { - char *log_env = DA_NULL; - - /* environment value has higher priority than configure file */ - log_env = getenv(DA_DEBUG_ENV_KEY); - if (log_env && strlen(log_env)) - return strdup(log_env); - - if (read_data_from_file(DA_DEBUG_CONFIG_FILE_PATH, &log_env)) - return log_env; - - return DA_NULL; -} - -char **__parsing_log_env(char *in_log_env) { - char **out_parsed_result = DA_NULL; - - char **temp_result_array = DA_NULL; - char **cur_temp_result_array = DA_NULL; - int how_many_item = 0; - int how_many_delimeter = 0; - - char delimiter = ','; - - char *org_str = in_log_env; - char *cur_char = org_str; - char *start = org_str; - char *end = org_str; - int target_len = 0; - - if (!org_str) - return DA_NULL; - - /* counting delimiter to know how many items should be memory allocated. - * This causes two round of loop (counting delimiter and real operation). - * But I think it is tolerable, because input parameter is from console. - * And it is also a reason why we should not use fixed length array. - * Users are hard to input very long environment, but it is possible. */ - for (cur_char = org_str; *cur_char; cur_char++) { - if (*cur_char == delimiter) - how_many_delimeter++; - } - how_many_item = how_many_delimeter + 1; - temp_result_array = (char**) calloc(1, how_many_item + 1); - if (!(temp_result_array)) - goto ERR; - - cur_temp_result_array = temp_result_array; - cur_char = org_str; - while (1) { - if (*cur_char == delimiter) { - end = cur_char; - target_len = (int) (end - start); - *cur_temp_result_array++ = __copying_str(start, - target_len); - start = ++cur_char; - continue; - } else if (!(*cur_char)) { - end = cur_char; - target_len = (int) (end - start); - *cur_temp_result_array++ = __copying_str(start, - target_len); - *cur_temp_result_array = DA_NULL; - break; - } else { - cur_char++; - } - } - out_parsed_result = temp_result_array; -ERR: - return out_parsed_result; -} - -char *__copying_str(char *source, int length) { - char *copied_str = DA_NULL; - char *cur_pos = DA_NULL; - char white_space = ' '; - char end_of_line = 10; /* ASCII for LF */ - int i = 0; - - if (!source || !(length > 0)) - return DA_NULL; - - copied_str = (char*) calloc(1, length + 1); - if (copied_str) { - cur_pos = copied_str; - for (i = 0; i < length; i++) { - if ((source[i] != white_space) && (source[i] - != end_of_line)) - *cur_pos++ = source[i]; - } - } - - return copied_str; -} - -char *__get_channel_name_from_enum(da_log_channel channel_enum) { - switch (channel_enum) { - case Soup: - return STRING_IT(Soup); - case HTTPManager: - return STRING_IT(HTTPManager); - case FileManager: - return STRING_IT(FileManager); - case DRMManager: - return STRING_IT(DRMManager); - case DownloadManager: - return STRING_IT(DownloadManager); - case ClientNoti: - return STRING_IT(ClientNoti); - case HTTPMessageHandler: - return STRING_IT(HTTPMessageHandler); - case Encoding: - return STRING_IT(Encoding); - case QueueManager: - return STRING_IT(QueueManager); - case Parsing: - return STRING_IT(Parsing); - case Thread: - return STRING_IT(Thread); - case Default: - return STRING_IT(Default); - default: - return DA_NULL; - } -} diff --git a/agent/download-agent-dl-info-util.c b/agent/download-agent-dl-info-util.c deleted file mode 100755 index 2b66357..0000000 --- a/agent/download-agent-dl-info-util.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * 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 <string.h> - -#include "download-agent-client-mgr.h" -#include "download-agent-dl-info-util.h" -#include "download-agent-debug.h" -#include "download-agent-utils.h" -#include "download-agent-file.h" -#include "download-agent-http-mgr.h" -#include "download-agent-plugin-conf.h" - -pthread_mutex_t mutex_download_state[DA_MAX_DOWNLOAD_ID]; -static pthread_mutex_t mutex_download_mgr = PTHREAD_MUTEX_INITIALIZER; -download_mgr_t download_mgr; - -void cleanup_source_info_basic_download(source_info_basic_t *source_info_basic); -void cleanup_req_dl_info_http(req_dl_info *http_download); -void destroy_file_info(file_info *file); - -da_result_t init_download_mgr() { - da_result_t ret = DA_RESULT_OK; - int i = 0; - - DA_LOG_FUNC_LOGV(Default); - - _da_thread_mutex_lock(&mutex_download_mgr); - - if (download_mgr.is_init == DA_FALSE) { - download_mgr.is_init = DA_TRUE; - - for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) { - _da_thread_mutex_init(&mutex_download_state[i], DA_NULL); - init_download_info(i); - } - init_dl_id_history(&(download_mgr.dl_id_history)); - } - - _da_thread_mutex_unlock(&mutex_download_mgr); - - return ret; -} - -da_result_t deinit_download_mgr(void) { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_LOGV(Default); - - _da_thread_mutex_lock(&mutex_download_mgr); - if (download_mgr.is_init == DA_TRUE) { - int i = 0; - dl_info_t *dl_info = DA_NULL; - void *t_return = NULL; - for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) { - dl_info = &(download_mgr.dl_info[i]); - if (dl_info && dl_info->is_using) { - request_to_abort_http_download(GET_DL_CURRENT_STAGE(i)); - DA_LOG_CRITICAL(Thread, "===download id[%d] thread id[%lu] join===",i, GET_DL_THREAD_ID(i)); -/* Because the download daemon can call the deinit function, the resources of pthread are not freed - FIXME later : It is needed to change the termination flow again. - if (pthread_join(GET_DL_THREAD_ID(i), &t_return) < 0) { - DA_LOG_ERR(Thread, "join client thread is failed!!!"); - } -*/ - DA_LOG_CRITICAL(Thread, "===download id[%d] thread join return[%d]===",i, (char*)t_return); - } - } - download_mgr.is_init = DA_FALSE; - deinit_dl_id_history(&(download_mgr.dl_id_history)); - } - _da_thread_mutex_unlock(&mutex_download_mgr); - return ret; -} - -void init_download_info(int slot_id) -{ - dl_info_t *dl_info = DA_NULL; - - DA_LOG_FUNC_LOGV(Default); - - _da_thread_mutex_lock(&mutex_download_state[slot_id]); - dl_info = &(download_mgr.dl_info[slot_id]); - dl_info->is_using = DA_FALSE; - dl_info->state = DOWNLOAD_STATE_IDLE; - dl_info->download_stage_data = DA_NULL; - dl_info->dl_id = 0; - dl_info->http_status = 0; - dl_info->enable_pause_update = DA_FALSE; - dl_info->user_install_path = DA_NULL; - dl_info->user_file_name = DA_NULL; - dl_info->user_etag = DA_NULL; - dl_info->user_temp_file_path = DA_NULL; - dl_info->user_data = DA_NULL; - - Q_init_queue(&(dl_info->queue)); - - DA_LOG_VERBOSE(Default, "Init slot_id [%d] Info END", slot_id); - _da_thread_mutex_unlock(&mutex_download_state[slot_id]); - - return; -} - -void destroy_download_info(int slot_id) -{ - dl_info_t *dl_info = DA_NULL; - - DA_LOG_VERBOSE(Default, "Destroying slot_id [%d] Info", slot_id); - - if (slot_id == DA_INVALID_ID) { - DA_LOG_ERR(Default, "invalid slot_id"); - return; - } - - dl_info = &(download_mgr.dl_info[slot_id]); - if (DA_FALSE == dl_info->is_using) { - return; - } - - _da_thread_mutex_lock (&mutex_download_state[slot_id]); - dl_info->state = DOWNLOAD_STATE_IDLE; - dl_info->active_dl_thread_id = 0; - - if (dl_info->download_stage_data != DA_NULL) { - remove_download_stage(slot_id, dl_info->download_stage_data); - dl_info->download_stage_data = DA_NULL; - } - dl_info->dl_id = 0; - dl_info->enable_pause_update = DA_FALSE; - if (dl_info->user_install_path) { - free(dl_info->user_install_path); - dl_info->user_install_path = DA_NULL; - } - - if (dl_info->user_file_name) { - free(dl_info->user_file_name); - dl_info->user_file_name = DA_NULL; - } - - if (dl_info->user_etag) { - free(dl_info->user_etag); - dl_info->user_etag = DA_NULL; - } - - if (dl_info->user_temp_file_path) { - free(dl_info->user_temp_file_path); - dl_info->user_temp_file_path = DA_NULL; - } - - dl_info->user_data = DA_NULL; - - Q_destroy_queue(&(dl_info->queue)); - dl_info->http_status = 0; - - dl_info->is_using = DA_FALSE; - - DA_LOG_DEBUG(Default, "Destroying slot_id [%d] Info END", slot_id); - _da_thread_mutex_unlock (&mutex_download_state[slot_id]); - return; -} - -void *Add_new_download_stage(int slot_id) -{ - stage_info *download_stage_data = NULL; - stage_info *new_download_stage_data = NULL; - - DA_LOG_FUNC_LOGV(Default); - - new_download_stage_data = (stage_info*)calloc(1, sizeof(stage_info)); - if (!new_download_stage_data) - goto ERR; - - new_download_stage_data->dl_id = slot_id; - download_stage_data = GET_DL_CURRENT_STAGE(slot_id); - if (download_stage_data) { - while (download_stage_data->next_stage_info) { - download_stage_data - = download_stage_data->next_stage_info; - }; - download_stage_data->next_stage_info = new_download_stage_data; - } else { - GET_DL_CURRENT_STAGE(slot_id) = new_download_stage_data; - } - DA_LOG_VERBOSE(Default, "NEW STAGE ADDED FOR DOWNLOAD ID[%d] new_stage[%p]", slot_id,new_download_stage_data); - -ERR: - return new_download_stage_data; -} - -void remove_download_stage(int slot_id, stage_info *in_stage) -{ - stage_info *stage = DA_NULL; - - DA_LOG_FUNC_LOGV(Default); - - stage = GET_DL_CURRENT_STAGE(slot_id); - if (DA_NULL == stage) { - DA_LOG_VERBOSE(Default, "There is no stage field on slot_id = %d", slot_id); - goto ERR; - } - - if (DA_NULL == in_stage) { - DA_LOG_VERBOSE(Default, "There is no in_stage to remove."); - goto ERR; - } - - if (in_stage == stage) { - DA_LOG_VERBOSE(Default, "Base stage will be removed. in_stage[%p]",in_stage); - DA_LOG_VERBOSE(Default, "next stage[%p]",stage->next_stage_info); - GET_DL_CURRENT_STAGE(slot_id) = stage->next_stage_info; - empty_stage_info(in_stage); - free(in_stage); - in_stage = DA_NULL; - } else { - while (in_stage != stage->next_stage_info) { - stage = stage->next_stage_info; - } - if (in_stage == stage->next_stage_info) { - stage->next_stage_info - = stage->next_stage_info->next_stage_info; - DA_LOG_VERBOSE(Default, "Stage will be removed. in_stage[%p]",in_stage); - DA_LOG_VERBOSE(Default, "next stage[%p]",stage->next_stage_info); - empty_stage_info(in_stage); - free(in_stage); - in_stage = DA_NULL; - } - } - -ERR: - return; -} - -void empty_stage_info(stage_info *in_stage) -{ - source_info_t *source_information = NULL; - req_dl_info *request_download_info = NULL; - file_info *file_information = NULL; - - DA_LOG_VERBOSE(Default, "Stage to Remove:[%p]", in_stage); - source_information = GET_STAGE_SOURCE_INFO(in_stage); - - cleanup_source_info_basic_download( - GET_SOURCE_BASIC(source_information)); - - request_download_info = GET_STAGE_TRANSACTION_INFO(in_stage); - - cleanup_req_dl_info_http(request_download_info); - - file_information = GET_STAGE_CONTENT_STORE_INFO(in_stage); - destroy_file_info(file_information); -} - -void cleanup_source_info_basic_download(source_info_basic_t *source_info_basic) -{ - if (NULL == source_info_basic) - goto ERR; - - DA_LOG_FUNC_LOGV(Default); - - if (NULL != source_info_basic->url) { - free(source_info_basic->url); - source_info_basic->url = DA_NULL; - } - -ERR: - return; - -} - -void cleanup_req_dl_info_http(req_dl_info *http_download) -{ - DA_LOG_FUNC_LOGV(Default); - - if (http_download->http_info.http_msg_request) { - http_msg_request_destroy( - &(http_download->http_info.http_msg_request)); - http_download->http_info.http_msg_request = DA_NULL; - } - - if (http_download->http_info.http_msg_response) { - http_msg_response_destroy( - &(http_download->http_info.http_msg_response)); - http_download->http_info.http_msg_response = DA_NULL; - } - - if (DA_NULL != http_download->location_url) { - free(http_download->location_url); - http_download->location_url = DA_NULL; - } - if (DA_NULL != http_download->content_type_from_header) { - free(http_download->content_type_from_header); - http_download->content_type_from_header = DA_NULL; - } - - if (DA_NULL != http_download->etag_from_header) { - free(http_download->etag_from_header); - http_download->etag_from_header = DA_NULL; - } - - http_download->invloved_transaction_id = DA_INVALID_ID; - http_download->content_len_from_header = 0; - http_download->downloaded_data_size = 0; - - _da_thread_mutex_destroy(&(http_download->mutex_http_state)); - - return; -} - -void destroy_file_info(file_info *file_information) -{ - DA_LOG_FUNC_LOGV(Default); - - if (!file_information) - return; - - if (file_information->file_name_final) { - free(file_information->file_name_final); - file_information->file_name_final = NULL; - } - - if (file_information->content_type) { - free(file_information->content_type); - file_information->content_type = NULL; - } - - if (file_information->pure_file_name) { - free(file_information->pure_file_name); - file_information->pure_file_name = NULL; - } - - if (file_information->extension) { - free(file_information->extension); - file_information->extension = NULL; - } - return; -} - -void clean_up_client_input_info(client_input_t *client_input) -{ - DA_LOG_FUNC_LOGV(Default); - - if (client_input) { - client_input->user_data = NULL; - - if (client_input->install_path) { - free(client_input->install_path); - client_input->install_path = DA_NULL; - } - - if (client_input->file_name) { - free(client_input->file_name); - client_input->file_name = DA_NULL; - } - - if (client_input->etag) { - free(client_input->etag); - client_input->etag = DA_NULL; - } - - if (client_input->temp_file_path) { - free(client_input->temp_file_path); - client_input->temp_file_path = DA_NULL; - } - - if (client_input->pkg_name) { - free(client_input->pkg_name); - client_input->pkg_name = DA_NULL; - } - - client_input_basic_t *client_input_basic = - &(client_input->client_input_basic); - - if (client_input_basic && client_input_basic->req_url) { - free(client_input_basic->req_url); - client_input_basic->req_url = DA_NULL; - } - - if (client_input_basic && client_input_basic->user_request_header) { - int i = 0; - int count = client_input_basic->user_request_header_count; - for (i = 0; i < count; i++) - { - if (client_input_basic->user_request_header[i]) { - free(client_input_basic->user_request_header[i]); - client_input_basic->user_request_header[i] = DA_NULL; - } - } - - free(client_input_basic->user_request_header); - client_input_basic->user_request_header = DA_NULL; - client_input_basic->user_request_header_count = 0; - } - } else { - DA_LOG_ERR(Default, "client_input is NULL."); - } - - return; -} - -da_result_t get_slot_id_for_dl_id( - int dl_id, - int* slot_id) -{ - da_result_t ret = DA_ERR_INVALID_DL_REQ_ID; - int iter = 0; - - if (dl_id < 0) { - DA_LOG_ERR(Default, "dl_id is less than 0 - %d", dl_id); - return DA_ERR_INVALID_DL_REQ_ID; - } - - _da_thread_mutex_lock(&mutex_download_mgr); - for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) { - if (download_mgr.dl_info[iter].is_using == DA_TRUE) { - if (download_mgr.dl_info[iter].dl_id == - dl_id) { - *slot_id = iter; - ret = DA_RESULT_OK; - break; - } - } - } - _da_thread_mutex_unlock(&mutex_download_mgr); - - return ret; -} - - -da_result_t get_available_slot_id(int *available_id) -{ - da_result_t ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - int i; - - _da_thread_mutex_lock(&mutex_download_mgr); - for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) { - if (download_mgr.dl_info[i].is_using == DA_FALSE) { - init_download_info(i); - - download_mgr.dl_info[i].is_using = DA_TRUE; - - download_mgr.dl_info[i].dl_id - = get_available_dl_id(&(download_mgr.dl_id_history)); - - *available_id = i; - DA_LOG_VERBOSE(Default, "available download id = %d", *available_id); - ret = DA_RESULT_OK; - - break; - } - } - _da_thread_mutex_unlock(&mutex_download_mgr); - - return ret; -} - -da_bool_t is_valid_slot_id(int slot_id) -{ - da_bool_t ret = DA_FALSE; - - if (slot_id >= 0 && slot_id < DA_MAX_DOWNLOAD_ID) { - if (download_mgr.dl_info[slot_id].is_using == DA_TRUE) - ret = DA_TRUE; - } - - return ret; -} - -void store_http_status(int dl_id, int status) -{ - if (status < 100 || status > 599) { - DA_LOG_ERR(Default, "Invalid status code [%d]", status); - return; - } - DA_LOG_VERBOSE(Default, "store_http_status id[%d]status[%d] ",dl_id, status); - download_mgr.dl_info[dl_id].http_status = status; -} - -int get_http_status(int slot_id) -{ - if (!download_mgr.dl_info[slot_id].is_using) { - DA_LOG_ERR(Default, "Invalid slot_id [%d]", slot_id); - return 0; - } - return download_mgr.dl_info[slot_id].http_status; -} diff --git a/agent/download-agent-dl-info.c b/agent/download-agent-dl-info.c new file mode 100644 index 0000000..6e49145 --- /dev/null +++ b/agent/download-agent-dl-info.c @@ -0,0 +1,462 @@ +/* + * 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 <string.h> +#include <stdlib.h> + +#include "download-agent-dl-info.h" +#include "download-agent-http-mgr.h" +#include "download-agent-http-msg-handler.h" + +static pthread_mutex_t mutex_da_info_list = PTHREAD_MUTEX_INITIALIZER; + +static void __init_da_info(int id) +{ + da_info_t *da_info = DA_NULL; + file_info_t *file_info = DA_NULL; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + + da_info = (da_info_t *)calloc(1, sizeof(da_info_t)); + if (!da_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + da_info_list[id] = DA_NULL; + return; + } + file_info = (file_info_t *)calloc(1, sizeof(file_info_t)); + if (!file_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + free(da_info); + da_info_list[id] = DA_NULL; + return; + } + http_info = (http_info_t *)calloc(1, sizeof(http_info_t)); + if (!http_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + free(da_info); + free(file_info); + da_info_list[id] = DA_NULL; + return; + } + req_info = (req_info_t *)calloc(1, sizeof(req_info_t)); + if (!req_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + free(da_info); + free(file_info); + free(http_info); + da_info_list[id] = DA_NULL; + return; + } + + da_info->da_id = DA_INVALID_ID; + da_info->tid = DA_INVALID_ID; + memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t)); + da_info->is_cb_update = DA_FALSE; + da_info->http_info = http_info; + da_info->file_info = file_info; + da_info->req_info = req_info; + da_info->update_time = 0; + da_info_list[id] = da_info; +} + +da_ret_t init_http_msg_t(http_msg_t **http_msg) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *temp = DA_NULL; + temp = (http_msg_t *)calloc(1, sizeof(http_msg_t)); + if (!temp) { + DA_LOGE("Fail to calloc. id"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + *http_msg = temp; + return ret; +} + +void destroy_http_msg_t(http_msg_t *http_msg) +{ + if (http_msg) + free(http_msg); + http_msg = DA_NULL; + return; +} + +da_ret_t get_available_da_id(int *available_id) +{ + da_ret_t ret = DA_ERR_ALREADY_MAX_DOWNLOAD; + int i = 0; + + DA_MUTEX_LOCK(&mutex_da_info_list); + for (i = 0; i < DA_MAX_ID; i++) { + if (da_info_list[i] == DA_NULL) { + *available_id = i; + DA_LOGV("available download id[%d]", *available_id); + __init_da_info(i); + ret = DA_RESULT_OK; + break; + } + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); + + return ret; +} + +da_ret_t get_da_info_with_da_id(int id, da_info_t **out_info) +{ + da_ret_t ret = DA_ERR_INVALID_ARGUMENT; + int i = 0; + + DA_MUTEX_LOCK(&mutex_da_info_list); + for (i = 0; i < DA_MAX_ID; i++) { + if (DA_NULL != da_info_list[i] && da_info_list[i]->da_id == id) { + *out_info = da_info_list[i]; + ret = DA_RESULT_OK; + break; + } + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); + + return ret; +} + +da_ret_t __is_supporting_protocol(const char *url) +{ + da_ret_t ret = DA_RESULT_OK; + int wanted_str_len = 0; + char *protocol = NULL; + char *wanted_str_start = NULL; + char *wanted_str_end = NULL; + + if (DA_NULL == url || strlen(url) < 1) + return DA_ERR_INVALID_URL; + + wanted_str_start = (char*)url; + wanted_str_end = strstr(url, "://"); + if (!wanted_str_end) { + DA_LOGE("No protocol on this url"); + return DA_ERR_INVALID_URL; + } + + wanted_str_len = wanted_str_end - wanted_str_start; + protocol = (char*)calloc(1, wanted_str_len + 1); + if (!protocol) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + strncpy(protocol, wanted_str_start, wanted_str_len); + + if (strlen(protocol) < 1) + ret = DA_ERR_UNSUPPORTED_PROTOCAL; + else if (strcasecmp(protocol, "http") != 0 && + strcasecmp(protocol, "https") != 0) + ret = DA_ERR_UNSUPPORTED_PROTOCAL; + + free(protocol); + return ret; +} + +da_ret_t copy_user_input_data(da_info_t *da_info, const char *url, + req_data_t *ext_data, da_cb_t *da_cb_data) +{ + da_ret_t ret = DA_RESULT_OK; + + if (!url || !da_info) { + DA_LOGE("Invalid Param"); + return DA_ERR_INVALID_ARGUMENT; + } + + ret = __is_supporting_protocol(url); + if (ret != DA_RESULT_OK) { + DA_SECURE_LOGE("url[%s]", url); + return ret; + } + + if (ext_data) { + req_info_t *req_info = da_info->req_info; + + if (ext_data->request_header_count > 0) { + int i = 0; + int count = ext_data->request_header_count; + req_info->req_header = (char **)calloc(count, sizeof(char *)); + if(DA_NULL == req_info->req_header) { + DA_LOGE("Fail to calloc"); + free(req_info); + da_info->req_info = DA_NULL; + return DA_ERR_FAIL_TO_MEMALLOC; + } + for (i = 0; i < count; i++) { + if (ext_data->request_header[i]) + req_info->req_header[i] = + strdup(ext_data->request_header[i]); + } + req_info->req_header_count = count; + } + + if (url) + req_info->url = strdup(url); + if (ext_data->install_path) + req_info->install_path = strdup(ext_data->install_path); + if (ext_data->file_name) + req_info->file_name = strdup(ext_data->file_name); + if (ext_data->etag) + req_info->etag = strdup(ext_data->etag); + if (ext_data->temp_file_path) + req_info->temp_file_path = strdup(ext_data->temp_file_path); + if (ext_data->pkg_name) + req_info->pkg_name = strdup(ext_data->pkg_name); + req_info->network_bonding = ext_data->network_bonding; + if (ext_data->user_req_data) + req_info->user_req_data = ext_data->user_req_data; + if (ext_data->user_client_data) + req_info->user_client_data = ext_data->user_client_data; + da_info->req_info = req_info; + } + if (da_cb_data) { + da_info->is_cb_update = DA_TRUE; + memcpy(&(da_info->cb_info), da_cb_data, sizeof(da_cb_t)); + } + return ret; +} + +static void __destroy_http_msg(http_msg_t *msg) +{ + msg->curl = DA_NULL; + free(msg); +} + +static void __destroy_http_msg_request(http_msg_request_t *msg) +{ + if (msg) { + http_msg_request_destroy(&msg); + free(msg); + } +} + +static void __destroy_http_msg_response(http_msg_response_t *msg) +{ + if (msg) { + http_msg_response_destroy(&msg); + free(msg); + } +} + +static void __destroy_req_info(req_info_t *req_info) +{ + if (req_info) { + free(req_info->url); + if (req_info->req_header && req_info->req_header_count > 0) { + int i = 0; + int count = req_info->req_header_count; + for (i = 0; i < count; i++) { + free(req_info->req_header[i]); + req_info->req_header[i] = DA_NULL; + } + free(req_info->req_header); + req_info->req_header = DA_NULL; + req_info->req_header_count = 0; + } + free(req_info->install_path); + free(req_info->file_name); + free(req_info->etag); + free(req_info->temp_file_path); + free(req_info->pkg_name); + req_info->user_req_data = DA_NULL; + req_info->user_client_data = DA_NULL; + free(req_info); + } +} + +void destroy_http_info(http_info_t *http_info) +{ + if (http_info) { + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + free(http_info->location_url); + free(http_info->proxy_addr); + free(http_info->content_type_from_header); + free(http_info->etag_from_header); + free(http_info->file_name_from_header); + if (http_info->http_msg_request) { + __destroy_http_msg_request(http_info->http_msg_request); + http_info->http_msg_request = DA_NULL; + } + if (http_info->http_msg_response) { + __destroy_http_msg_response(http_info->http_msg_response); + http_info->http_msg_response = DA_NULL; + } + if (http_info->http_msg) { + __destroy_http_msg(http_info->http_msg); + http_info->http_msg = DA_NULL; + } + DA_MUTEX_DESTROY(&(http_info->mutex_state)); + DA_MUTEX_DESTROY(&(http_info->mutex_http)); + DA_COND_DESTROY(&(http_info->cond_http)); + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + http_info->http_method = HTTP_METHOD_GET; + http_info->content_len_from_header = 0; + http_info->total_size = 0; + http_info->error_code = 0; + free(http_info); + } +} + +void destroy_file_info(file_info_t *file_info) +{ + if (file_info) { + file_info->file_handle = DA_NULL; + free(file_info->pure_file_name); + free(file_info->extension); + free(file_info->file_path); + free(file_info->mime_type); + free(file_info->buffer); + file_info->buffer_len = 0; + file_info->file_size = 0; +#ifdef _RAF_SUPPORT + file_info->file_size_of_temp_file = 0; +#endif + file_info->bytes_written_to_file = 0; + file_info->is_updated = DA_FALSE; + free(file_info); + } +} + +// For pause and resume case +void reset_http_info_for_resume(http_info_t *http_info) +{ + if (http_info) { + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + free(http_info->location_url); + http_info->location_url = DA_NULL; + free(http_info->proxy_addr); + http_info->proxy_addr = DA_NULL; + free(http_info->content_type_from_header); + http_info->content_type_from_header = DA_NULL; + if (http_info->http_msg_response) { + __destroy_http_msg_response(http_info->http_msg_response); + http_info->http_msg_response = DA_NULL; + } + if (http_info->http_msg) { + __destroy_http_msg(http_info->http_msg); + http_info->http_msg = DA_NULL; + } + http_info->http_method = HTTP_METHOD_GET; + http_info->content_len_from_header = 0; + http_info->total_size = 0; + } +} + +void reset_http_info(http_info_t *http_info) +{ + if (http_info) { + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + free(http_info->location_url); + http_info->location_url = DA_NULL; + free(http_info->proxy_addr); + http_info->proxy_addr = DA_NULL; + free(http_info->content_type_from_header); + http_info->content_type_from_header = DA_NULL; + if (http_info->http_msg_request) { + __destroy_http_msg_request(http_info->http_msg_request); + http_info->http_msg_request = DA_NULL; + } + if (http_info->http_msg_response) { + __destroy_http_msg_response(http_info->http_msg_response); + http_info->http_msg_response = DA_NULL; + } + if (http_info->http_msg) { + __destroy_http_msg(http_info->http_msg); + http_info->http_msg = DA_NULL; + } + http_info->http_method = HTTP_METHOD_GET; + http_info->content_len_from_header = 0; + http_info->total_size = 0; + } +} + +da_bool_t is_valid_download_id(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + DA_MUTEX_LOCK(&mutex_da_info_list); + if (DA_NULL == da_info_list[download_id]) { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_FALSE; + } + if (is_stopped_state(da_info_list[download_id])) { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_TRUE; + } + if (da_info_list[download_id]->da_id != DA_INVALID_ID) { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_TRUE; + } else { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_FALSE; + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return ret; +} + +void destroy_da_info_list() +{ + int i = 0; + DA_MUTEX_LOCK(&mutex_da_info_list); + for (i = 0; i < DA_MAX_ID; i++) { + if(DA_NULL != da_info_list[i]) { + if (da_info_list[i]->req_info) { + __destroy_req_info(da_info_list[i]->req_info); + da_info_list[i]->req_info = DA_NULL; + } + if (da_info_list[i]->http_info) { + destroy_http_info(da_info_list[i]->http_info); + da_info_list[i]->http_info = DA_NULL; + } + if (da_info_list[i]->file_info) { + destroy_file_info(da_info_list[i]->file_info); + da_info_list[i]->file_info = DA_NULL; + } + free(da_info_list[i]); + da_info_list[i] = DA_NULL; + } + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); +} + +void destroy_da_info(int id) +{ + da_info_t *da_info = DA_NULL; + DA_MUTEX_LOCK(&mutex_da_info_list); + da_info = da_info_list[id]; + if (da_info) { + if (da_info->req_info) { + __destroy_req_info(da_info->req_info); + da_info->req_info = DA_NULL; + } + if (da_info->http_info) { + destroy_http_info(da_info->http_info); + da_info->http_info = DA_NULL; + } + if (da_info->file_info) { + destroy_file_info(da_info->file_info); + da_info->file_info = DA_NULL; + } + da_info->da_id = DA_INVALID_ID; + da_info->tid = DA_INVALID_ID; + memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t)); + free(da_info); + da_info_list[id] = DA_NULL; + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); +} diff --git a/agent/download-agent-dl-mgr.c b/agent/download-agent-dl-mgr.c index 7a2ce0d..e57f3f3 100755 --- a/agent/download-agent-dl-mgr.c +++ b/agent/download-agent-dl-mgr.c @@ -14,301 +14,173 @@ * limitations under the License. */ -#include "download-agent-client-mgr.h" -#include "download-agent-debug.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-utils.h" -#include "download-agent-http-mgr.h" -#include "download-agent-file.h" -#include "download-agent-plugin-conf.h" +#include <stdlib.h> +#include <sys/syscall.h> +#include <signal.h> +#ifdef _ENABLE_SYS_RESOURCE +#include "resourced.h" +#endif -static da_result_t __cancel_download_with_slot_id(int slot_id); -static da_result_t __suspend_download_with_slot_id(int slot_id); - +#include "download-agent-dl-mgr.h" +#include "download-agent-dl-info.h" +#include "download-agent-http-mgr.h" -da_result_t requesting_download(stage_info *stage) +void __thread_clean_up_handler_for_start_download(void *arg) { - da_result_t ret = DA_RESULT_OK; - req_dl_info *request_session = DA_NULL; + DA_LOGI("cleanup for thread id[%lu]", pthread_self()); +} - DA_LOG_FUNC_LOGV(Default); +da_ret_t __download_content(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; - if (!stage) { - DA_LOG_ERR(Default, "stage is null.."); + DA_LOGV(""); + if (!da_info) { + DA_LOGE("NULL CHECK!: da_info"); ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; + return ret; } - ret = make_req_dl_info_http(stage, GET_STAGE_TRANSACTION_INFO(stage)); - if (ret != DA_RESULT_OK) - goto ERR; - - request_session = GET_STAGE_TRANSACTION_INFO(stage); - ret = request_http_download(stage); - if (DA_RESULT_OK == ret) { - DA_LOG_VERBOSE(Default, "Http download is complete."); - } else { - DA_LOG_ERR(Default, "Http download is failed. ret = %d", ret); - goto ERR; - } -ERR: + ret = request_http_download(da_info); return ret; } -da_result_t handle_after_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - da_mime_type_id_t mime_type = DA_MIME_TYPE_NONE; - - DA_LOG_FUNC_LOGV(Default); - mime_type = get_mime_type_id( - GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage))); - - switch (mime_type) { - case DA_MIME_TYPE_NONE: - DA_LOG(Default, "DA_MIME_TYPE_NONE"); - ret = DA_ERR_MISMATCH_CONTENT_TYPE; - break; - default: - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_FINISH, stage); - break; - } /* end of switch */ - - return ret; -} - -static da_result_t __cancel_download_with_slot_id(int slot_id) +static void *__thread_start_download(void *data) { - da_result_t ret = DA_RESULT_OK; - download_state_t download_state; - stage_info *stage = DA_NULL; - - DA_LOG_FUNC_LOGD(Default); - - _da_thread_mutex_lock (&mutex_download_state[slot_id]); - download_state = GET_DL_STATE_ON_ID(slot_id); - DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(slot_id)); - - if (download_state == DOWNLOAD_STATE_FINISH || - download_state == DOWNLOAD_STATE_CANCELED) { - DA_LOG_CRITICAL(Default, "Already download is finished. Do not send cancel request"); - _da_thread_mutex_unlock (&mutex_download_state[slot_id]); - return ret; + da_info_t *da_info = DA_NULL; + req_info_t *req_info = DA_NULL; + int da_id = DA_INVALID_ID; + +// DA_LOGV(""); + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL); + + da_info = (da_info_t *)data; + NULL_CHECK_RET_OPT(da_info, DA_NULL); + req_info = da_info->req_info; + NULL_CHECK_RET_OPT(req_info, DA_NULL); + + da_id = da_info->da_id; + pthread_cleanup_push(__thread_clean_up_handler_for_start_download, DA_NULL); +#ifdef _ENABLE_SYS_RESOURCE + if (req_info->pkg_name) { + pid_t tid = (pid_t) syscall(SYS_gettid); + da_info->tid = (pid_t) syscall(SYS_gettid); + DA_SECURE_LOGI("pkg_name[%s] threadid[%lu]", + req_info->pkg_name,pthread_self()); + if (join_app_performance(req_info->pkg_name, tid) != + RESOURCED_ERROR_OK) { + DA_LOGE("Can not put app to network performance id[%d]", da_id); + } } - _da_thread_mutex_unlock (&mutex_download_state[slot_id]); - - stage = GET_DL_CURRENT_STAGE(slot_id); - if (!stage) - return DA_RESULT_OK; - - ret = request_to_cancel_http_download(stage); - if (ret != DA_RESULT_OK) - goto ERR; - DA_LOG(Default, "Download cancel Successful for download id - %d", slot_id); -ERR: - return ret; +#endif + __download_content(da_info); + destroy_da_info(da_id); + pthread_cleanup_pop(0); + DA_LOGI("=====EXIT thread : da_id[%d]=====", da_id); + pthread_exit((void *)DA_NULL); + return DA_NULL; } -da_result_t cancel_download(int dl_id) +da_ret_t start_download(da_info_t *da_info) { - da_result_t ret = DA_RESULT_OK; - - int slot_id = DA_INVALID_ID; - - DA_LOG_FUNC_LOGD(Default); - - ret = get_slot_id_for_dl_id(dl_id, &slot_id); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(Default, "dl req ID is not Valid"); + da_ret_t ret = DA_RESULT_OK; + pthread_attr_t thread_attr; + pthread_t tid; + if (pthread_attr_init(&thread_attr) != 0) { + ret = DA_ERR_FAIL_TO_CREATE_THREAD; goto ERR; } - if (DA_FALSE == is_valid_slot_id(slot_id)) { - DA_LOG_ERR(Default, "Download ID is not Valid"); - ret = DA_ERR_INVALID_ARGUMENT; + if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) != 0) { + ret = DA_ERR_FAIL_TO_CREATE_THREAD; goto ERR; } - ret = __cancel_download_with_slot_id(slot_id); - -ERR: - return ret; - -} - -static da_result_t __suspend_download_with_slot_id(int slot_id) -{ - da_result_t ret = DA_RESULT_OK; - download_state_t download_state; - stage_info *stage = DA_NULL; - - DA_LOG_FUNC_LOGD(Default); - - _da_thread_mutex_lock (&mutex_download_state[slot_id]); - download_state = GET_DL_STATE_ON_ID(slot_id); - DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(slot_id)); - _da_thread_mutex_unlock (&mutex_download_state[slot_id]); - - stage = GET_DL_CURRENT_STAGE(slot_id); - if (!stage) - return DA_ERR_CANNOT_SUSPEND; - - ret = request_to_suspend_http_download(stage); - if (ret != DA_RESULT_OK) - goto ERR; - DA_LOG(Default, "Download Suspend Successful for download id-%d", slot_id); -ERR: - return ret; -} - -da_result_t suspend_download(int dl_id, da_bool_t is_enable_cb) -{ - da_result_t ret = DA_RESULT_OK; - int slot_id = DA_INVALID_ID; - - DA_LOG_FUNC_LOGD(Default); - - ret = get_slot_id_for_dl_id(dl_id, &slot_id); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(Default, "dl req ID is not Valid"); - goto ERR; - } - GET_DL_ENABLE_PAUSE_UPDATE(slot_id) = is_enable_cb; - if (DA_FALSE == is_valid_slot_id(slot_id)) { - DA_LOG_ERR(Default, "Download ID is not Valid"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; + if (pthread_create(&(tid), &thread_attr, + __thread_start_download, da_info) < 0) { + DA_LOGE("Fail to make thread:id[%d]", da_info->da_id); + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + } else { + if (tid < 1) { + DA_LOGE("The thread start is failed before calling this"); +// When http resource is leaked, the thread ID is initialized at error handling section of thread_start_download() +// Because the thread ID is initialized, the ptrhead_detach should not be called. This is something like timing issue between threads. +// thread info and basic_dl_input is freed at thread_start_download(). And it should not returns error code in this case. + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + goto ERR; + } } - - ret = __suspend_download_with_slot_id(slot_id); - + da_info->thread_id = tid; + DA_LOGI("Thread create:thread id[%lu]", da_info->thread_id); ERR: + if (DA_RESULT_OK != ret) { + destroy_da_info(da_info->da_id); + } return ret; - } -static da_result_t __resume_download_with_slot_id(int slot_id) +da_ret_t cancel_download(int dl_id, da_bool_t is_enable_cb) { - da_result_t ret = DA_RESULT_OK; - download_state_t download_state; - stage_info *stage = DA_NULL; - - DA_LOG_FUNC_LOGD(Default); + da_ret_t ret = DA_RESULT_OK; + da_info_t *da_info = DA_NULL; - _da_thread_mutex_lock (&mutex_download_state[slot_id]); - download_state = GET_DL_STATE_ON_ID(slot_id); - DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(slot_id)); - _da_thread_mutex_unlock (&mutex_download_state[slot_id]); + DA_LOGV(""); - stage = GET_DL_CURRENT_STAGE(slot_id); - - ret = request_to_resume_http_download(stage); + ret = get_da_info_with_da_id(dl_id, &da_info); + if (ret != DA_RESULT_OK || !da_info) { + return DA_ERR_INVALID_ARGUMENT; + } + da_info->is_cb_update = is_enable_cb; + ret = request_to_cancel_http_download(da_info); if (ret != DA_RESULT_OK) goto ERR; - DA_LOG(Default, "Download Resume Successful for download id-%d", slot_id); + DA_LOGI("Download cancel Successful for download id[%d]", da_info->da_id); + ERR: return ret; } -da_result_t resume_download(int dl_id) +da_ret_t suspend_download(int dl_id, da_bool_t is_enable_cb) { - da_result_t ret = DA_RESULT_OK; - int slot_id = DA_INVALID_ID; + da_ret_t ret = DA_RESULT_OK; + da_info_t *da_info = DA_NULL; - DA_LOG_FUNC_LOGD(Default); + DA_LOGV(""); - ret = get_slot_id_for_dl_id(dl_id, &slot_id); + ret = get_da_info_with_da_id(dl_id, &da_info); + if (ret != DA_RESULT_OK || !da_info) { + return DA_ERR_INVALID_ARGUMENT; + } + da_info->is_cb_update = is_enable_cb; + ret = request_to_suspend_http_download(da_info); if (ret != DA_RESULT_OK) goto ERR; - - if (DA_FALSE == is_valid_slot_id(slot_id)) { - DA_LOG_ERR(Default, "Download ID is not Valid"); - ret = DA_ERR_INVALID_DL_REQ_ID; - goto ERR; - } - - ret = __resume_download_with_slot_id(slot_id); - + DA_LOGV("Download Suspend Successful for download id[%d]", da_info->da_id); ERR: return ret; -} - -da_result_t send_user_noti_and_finish_download_flow( - int slot_id, char *installed_path, char *etag) -{ - da_result_t ret = DA_RESULT_OK; - download_state_t download_state = HTTP_STATE_READY_TO_DOWNLOAD; - da_bool_t need_destroy_download_info = DA_FALSE; - - DA_LOG_FUNC_LOGV(Default); - _da_thread_mutex_lock (&mutex_download_state[slot_id]); - download_state = GET_DL_STATE_ON_ID(slot_id); - DA_LOG_DEBUG(Default, "state = %d", download_state); - _da_thread_mutex_unlock (&mutex_download_state[slot_id]); - - switch (download_state) { - case DOWNLOAD_STATE_FINISH: - send_client_finished_info(slot_id, GET_DL_ID(slot_id), - installed_path, DA_NULL, DA_RESULT_OK, - get_http_status(slot_id)); - need_destroy_download_info = DA_TRUE; - break; - case DOWNLOAD_STATE_CANCELED: - send_client_finished_info(slot_id, GET_DL_ID(slot_id), - installed_path, etag, DA_RESULT_USER_CANCELED, - get_http_status(slot_id)); - need_destroy_download_info = DA_TRUE; - break; -#ifdef PAUSE_EXIT - case DOWNLOAD_STATE_PAUSED: - need_destroy_download_info = DA_TRUE; - break; -#endif - default: - DA_LOG(Default, "download state = %d", download_state); - break; - } - - if (need_destroy_download_info == DA_TRUE) { - destroy_download_info(slot_id); - } else { - DA_LOG_CRITICAL(Default, "download info is not destroyed"); - } - - return ret; } -da_bool_t is_valid_download_id(int dl_id) +da_ret_t resume_download(int dl_id) { + da_ret_t ret = DA_RESULT_OK; + da_info_t *da_info = DA_NULL; - da_bool_t ret = DA_TRUE; - int slot_id = DA_INVALID_ID; - - DA_LOG_VERBOSE(Default, "[is_valid_download_id]download_id : %d", dl_id); - - ret = get_slot_id_for_dl_id(dl_id, &slot_id); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(Default, "dl req ID is not Valid"); - ret = DA_FALSE; - goto ERR; - } else { - ret = DA_TRUE; - } + DA_LOGV(""); - if (DA_FALSE == is_valid_slot_id(slot_id)) { - DA_LOG_ERR(Default, "Download ID is not Valid"); - ret = DA_FALSE; - goto ERR; + ret = get_da_info_with_da_id(dl_id, &da_info); + if (ret != DA_RESULT_OK || !da_info) { + return DA_ERR_INVALID_ARGUMENT; } - if (GET_DL_THREAD_ID(slot_id) < 1) { - DA_LOG_ERR(Default, "Download thread is not alive"); - ret = DA_FALSE; + da_info->is_cb_update = DA_TRUE; + ret = request_to_resume_http_download(da_info); + if (ret != DA_RESULT_OK) goto ERR; - } - + DA_LOGV("Download Resume Successful for download id[%d]", da_info->da_id); ERR: return ret; } + diff --git a/agent/download-agent-encoding.c b/agent/download-agent-encoding.c index 1955fcd..3f14fca 100755 --- a/agent/download-agent-encoding.c +++ b/agent/download-agent-encoding.c @@ -16,12 +16,12 @@ #include <string.h> #include <stdlib.h> -#include <glib.h> +#include "glib.h" -#include "download-agent-encoding.h" #include "download-agent-debug.h" +#include "download-agent-encoding.h" -da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, +da_ret_t _parsing_base64_encoded_str(const char *in_encoded_str, char **out_charset_type, char *out_encoding_type, char **out_raw_encoded_str); @@ -34,7 +34,7 @@ da_bool_t is_base64_encoded_word(const char *in_str) char *found_str = DA_NULL; if (!in_str) { - DA_LOG_ERR(Default, "input string is NULL"); + DA_LOGE("input string is NULL"); return DA_FALSE; } @@ -47,14 +47,10 @@ da_bool_t is_base64_encoded_word(const char *in_str) snprintf(second_needle, sizeof(second_needle), "%s", "?="); // ?= } -// DA_SECURE_LOGD("needle = [%s], haystack = [%s]", first_needle, haystack); - found_str = strstr(haystack, first_needle); if (found_str) { if (found_str == haystack) { -// DA_SECURE_LOGD("Input string is starting with %s", needle); haystack = haystack + strlen(haystack) - strlen(second_needle); -// DA_SECURE_LOGD("second haystack is [%s]", haystack); if(!strcmp(haystack, second_needle)) return DA_TRUE; } @@ -62,11 +58,10 @@ da_bool_t is_base64_encoded_word(const char *in_str) return DA_FALSE; } -da_result_t decode_base64_encoded_str(const char *in_encoded_str, +da_ret_t decode_base64_encoded_str(const char *in_encoded_str, char **out_decoded_ascii_str) { - da_result_t ret = DA_RESULT_OK; - + da_ret_t ret = DA_RESULT_OK; const char *org_str = DA_NULL; char *charset_type = NULL; char encoding_type = '\0'; @@ -80,7 +75,7 @@ da_result_t decode_base64_encoded_str(const char *in_encoded_str, org_str = in_encoded_str; if(!org_str) { - DA_LOG_ERR(Default, "Input string is NULL"); + DA_LOGE("Input string is NULL"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } @@ -91,10 +86,8 @@ da_result_t decode_base64_encoded_str(const char *in_encoded_str, goto ERR; } -// DA_SECURE_LOGD("charset = [%s], encoding = [%c], raw = [%s]", charset_type, encoding_type, raw_encoded_str); - if(encoding_type != 'B') { - DA_LOG_ERR(Default, "Encoded Word is not encoded with Base64, but %c. We can only handle Base64.", encoding_type); + DA_LOGE("Encoded Word is not encoded with Base64, but %c. We can only handle Base64.", encoding_type); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } @@ -112,7 +105,7 @@ da_result_t decode_base64_encoded_str(const char *in_encoded_str, DA_SECURE_LOGD("g_decoded_text = [%s]", g_decoded_text); decoded_str = (char*)calloc(1, g_decoded_text_len+1); if(!decoded_str) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); ret = DA_ERR_FAIL_TO_MEMALLOC; goto ERR; } else { @@ -123,40 +116,32 @@ da_result_t decode_base64_encoded_str(const char *in_encoded_str, ERR: *out_decoded_ascii_str = decoded_str; - if(charset_type) { free(charset_type); charset_type = NULL; } - if(raw_encoded_str) { free(raw_encoded_str); raw_encoded_str = NULL; } - if(g_decoded_text) { g_free(g_decoded_text); } - return ret; } - -da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, +da_ret_t _parsing_base64_encoded_str(const char *in_encoded_str, char **out_charset_type, char *out_encoding_type, char **out_raw_encoded_str) { - da_result_t ret = DA_RESULT_OK; - + da_ret_t ret = DA_RESULT_OK; const char *org_str = DA_NULL; // e.g. =?UTF-8?B?7Jew7JWE7JmA7IKs7J6QLmpwZw==?= char *charset_type = NULL; // e.g. UTF-8 char encoding_type = '\0'; // e.g. B (means Base64) char *raw_encoded_str = NULL; // e.g. 7Jew7JWE7JmA7IKs7J6QLmpwZw== - char *haystack = DA_NULL; char needle[8] = {0,}; - char *wanted_str = DA_NULL; int wanted_str_len = 0; char *wanted_str_start = DA_NULL; @@ -164,7 +149,7 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, org_str = in_encoded_str; if (!org_str) { - DA_LOG_ERR(Default, "Input string is NULL"); + DA_LOGE("Input string is NULL"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } @@ -174,12 +159,11 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, snprintf(needle, sizeof(needle), "=?"); wanted_str_end = strstr(haystack, needle); if (!wanted_str_end) { - DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } else { wanted_str = wanted_str_end + strlen(needle); - DA_SECURE_LOGD("strip [%s]", wanted_str); } // for charset @@ -187,14 +171,14 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, needle[0] = '?'; wanted_str_end = strchr(haystack, needle[0]); if (!wanted_str_end) { - DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } else { wanted_str_len = wanted_str_end - wanted_str_start + 1; wanted_str = (char*)calloc(1, wanted_str_len+1); if (!wanted_str) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); ret = DA_ERR_FAIL_TO_MEMALLOC; goto ERR; } else { @@ -203,27 +187,26 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, wanted_str = DA_NULL; } - DA_LOG(Default, "charset [%s]", charset_type); + DA_LOGV("charset [%s]", charset_type); } - // for encoding encoding_type = *(++wanted_str_end); - DA_LOG(Default, "encoding [%c]", encoding_type); + DA_LOGV("encoding [%c]", encoding_type); // for raw encoded str haystack = wanted_str_start = wanted_str_end + 1; snprintf(needle, sizeof(needle), "?="); wanted_str_end = strstr(haystack, needle); if (!wanted_str_end) { - DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } else { wanted_str_len = wanted_str_end - wanted_str_start + 1; wanted_str = (char*)calloc(1, wanted_str_len+1); if (!wanted_str) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); ret = DA_ERR_FAIL_TO_MEMALLOC; goto ERR; } else { @@ -234,7 +217,6 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, DA_SECURE_LOGD("raw encoded str [%s]", raw_encoded_str); } - ERR: if (ret != DA_RESULT_OK) { if (charset_type) { @@ -242,17 +224,15 @@ ERR: charset_type = NULL; } } - *out_charset_type = charset_type; *out_encoding_type = encoding_type; *out_raw_encoded_str = raw_encoded_str; - return ret; } void decode_url_encoded_str(const char *in_encoded_str, char **out_str) { - char *in = NULL; + char *in = NULL; char *out = NULL; *out_str = calloc(1, strlen(in_encoded_str) + 1); if (*out_str == NULL) @@ -279,4 +259,3 @@ void decode_url_encoded_str(const char *in_encoded_str, char **out_str) out++; } } - diff --git a/agent/download-agent-file.c b/agent/download-agent-file.c index 0da5445..ea901e2 100755 --- a/agent/download-agent-file.c +++ b/agent/download-agent-file.c @@ -14,593 +14,69 @@ * limitations under the License. */ -#include <stdio.h> +#include <stdlib.h> #include <dirent.h> #include <unistd.h> +#include <string.h> +#include <sys/vfs.h> #include <math.h> #include <errno.h> -#include "download-agent-client-mgr.h" + #include "download-agent-debug.h" -#include "download-agent-utils.h" -#include "download-agent-dl-mgr.h" #include "download-agent-file.h" #include "download-agent-mime-util.h" -#include "download-agent-http-mgr.h" +/* FIXME Later */ +#include "download-agent-http-msg-handler.h" +#include "download-agent-plugin-drm.h" #include "download-agent-plugin-conf.h" +#include <storage.h> -#define NO_NAME_TEMP_STR "No name" - -static da_result_t __set_file_size(stage_info *stage); -static da_result_t __saved_file_open(stage_info *stage); - -static char *__derive_extension(stage_info *stage); -static da_result_t __divide_file_name_into_pure_name_N_extesion( - const char *in_file_name, - char **out_pure_file_name, - char **out_extension); -static da_result_t __get_candidate_file_name(stage_info *stage, - char **out_pure_file_name, char **out_extension); - -static da_result_t __file_write_buf_make_buf(file_info *file_storage); -static da_result_t __file_write_buf_destroy_buf(file_info *file_storage); -static da_result_t __file_write_buf_flush_buf(stage_info *stage, - file_info *file_storage); -static da_result_t __file_write_buf_copy_to_buf(file_info *file_storage, - char *body, int body_len); -static da_result_t __file_write_buf_directly_write(stage_info *stage, - file_info *file_storage, char *body, int body_len); - -da_result_t clean_files_from_dir(char *dir_path) -{ - da_result_t ret = DA_RESULT_OK; - struct dirent *d = DA_NULL; - DIR *dir; - char file_path[DA_MAX_FULL_PATH_LEN] = { 0, }; - - DA_LOG_FUNC_LOGD(FileManager); - - if (dir_path == DA_NULL) - return DA_ERR_INVALID_ARGUMENT; - - if (is_dir_exist(dir_path)) { - dir = opendir(dir_path); - if (DA_NULL == dir) { - DA_LOG_ERR(FileManager, "opendir() is failed."); - ret = DA_ERR_INVALID_INSTALL_PATH; - } else { - while (DA_NULL != (d = readdir(dir))) { - DA_SECURE_LOGD("%s",d->d_name); - if (0 == strncmp(d->d_name, ".", strlen(".")) - || 0 == strncmp(d->d_name, - "..", - strlen(".."))) { - continue; - } - - memset(file_path, 0x00, DA_MAX_FULL_PATH_LEN); - snprintf(file_path, DA_MAX_FULL_PATH_LEN, - "%s/%s", dir_path, d->d_name); - if (remove(file_path) < 0) { - DA_LOG_ERR(FileManager, "fail to remove file"); - } - } - - closedir(dir); - if (remove(dir_path) < 0) { - DA_LOG_ERR(FileManager, "fail to remove dir"); - } - } - } - return ret; -} - -/* Priority to obtain MIME Type - * 1. HTTP response header's <Content-Type> field - * 2. from OMA descriptor file's <content-type> attribute (mandatory field) - * 3. Otherwise, leave blank for MIME Type - */ -da_result_t get_mime_type(stage_info *stage, char **out_mime_type) -{ - char *mime_type = DA_NULL; - - if (!GET_STAGE_SOURCE_INFO(stage)) - return DA_ERR_INVALID_ARGUMENT; - - /* Priority 1 */ - if (GET_REQUEST_HTTP_HDR_CONT_TYPE(GET_STAGE_TRANSACTION_INFO(stage))) { - mime_type = GET_REQUEST_HTTP_HDR_CONT_TYPE(GET_STAGE_TRANSACTION_INFO(stage)); -// DA_SECURE_LOGI("content type from HTTP response header [%s]", mime_type); - } - - if (!mime_type) { - DA_LOG(FileManager, "no content type derived"); - return DA_RESULT_OK; - } - - /* FIXME really need memory allocation? */ - *out_mime_type = (char *)calloc(1, strlen(mime_type) + 1); - if (*out_mime_type) { - strncpy(*out_mime_type, mime_type, strlen(mime_type)); -// DA_SECURE_LOGD("out_mime_type str[%s] ptr[%p] len[%d]", -// *out_mime_type,*out_mime_type,strlen(*out_mime_type)); - } else { - DA_LOG_ERR(FileManager, "fail to allocate memory"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - -// DA_SECURE_LOGD("mime type = %s", *out_mime_type); - return DA_RESULT_OK; -} - -da_bool_t is_file_exist(const char *file_path) -{ - struct stat dir_state; - int stat_ret; - - if (file_path == DA_NULL) { - DA_LOG_ERR(FileManager, "file path is DA_NULL"); - return DA_FALSE; - } - - stat_ret = stat(file_path, &dir_state); - - if (stat_ret == 0) { - if (dir_state.st_mode & S_IFREG) { - DA_SECURE_LOGD("Exist! %s is a regular file & its size = %lu", file_path, dir_state.st_size); - return DA_TRUE; - } - - return DA_FALSE; - } - return DA_FALSE; - -} - -da_bool_t is_dir_exist(const char *file_path) -{ - struct stat dir_state; - int stat_ret; - - if (file_path == DA_NULL) { - DA_LOG_ERR(FileManager, "file path is DA_NULL"); - return DA_FALSE; - } - - stat_ret = stat(file_path, &dir_state); - - if (stat_ret == 0) { - if (dir_state.st_mode & S_IFDIR) { - DA_LOG_VERBOSE(FileManager, "Existed directory."); - return DA_TRUE; - } - - return DA_FALSE; - } - return DA_FALSE; -} - -void get_file_size(char *file_path, unsigned long long *out_file_size) -{ - struct stat dir_state; - int stat_ret; - - *out_file_size = -1; - - if (file_path == DA_NULL) { - DA_LOG_ERR(FileManager, "file path is DA_NULL"); - return; - } - /* Please do not use ftell() to obtain file size, use stat instead. - * This is a guide from www.securecoding.cert.org - * : FIO19-C. Do not use fseek() and ftell() to compute the size of a file - */ - stat_ret = stat(file_path, &dir_state); - if (stat_ret == 0) { - if (dir_state.st_mode & S_IFREG) { - DA_LOG(FileManager, "size = %lu", dir_state.st_size); - *out_file_size = dir_state.st_size; - } - } - return; -} +#define NO_NAME_TEMP_STR "No name" +#define MAX_SUFFIX_COUNT 1000000000 -da_result_t __saved_file_open(stage_info *stage) +da_ret_t __saved_file_open(file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; - file_info *file_storage = DA_NULL; + da_ret_t ret = DA_RESULT_OK; char *actual_file_path = DA_NULL; void *fd = DA_NULL; - DA_LOG_FUNC_LOGV(FileManager); - - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) - return DA_ERR_INVALID_ARGUMENT; + DA_LOGV(""); - actual_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage); + actual_file_path = file_info->file_path; if (!actual_file_path) return DA_ERR_INVALID_ARGUMENT; fd = fopen(actual_file_path, "a+"); // for resume if (fd == DA_NULL) { - DA_LOG_ERR(FileManager, "File open failed"); + DA_LOGE("File open failed"); if (errno == ENOSPC) ret = DA_ERR_DISK_FULL; else ret = DA_ERR_FAIL_TO_ACCESS_FILE; goto ERR; } - GET_CONTENT_STORE_FILE_HANDLE(file_storage) = fd; -// DA_SECURE_LOGD("file path for saving = %s", -// GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage)); + file_info->file_handle = fd; + //DA_SECURE_LOGD("file path for saving[%s]", file_info->file_path); ERR: if (DA_RESULT_OK != ret) { - GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL; + file_info->file_handle = DA_NULL; } return ret; } -da_result_t __set_file_size(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - req_dl_info *stage_req_info = DA_NULL; - file_info *file_storage = DA_NULL; - - DA_LOG_FUNC_LOGV(FileManager); - - if (!stage) { - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - stage_req_info = GET_STAGE_TRANSACTION_INFO(stage); - - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) - goto ERR; - - if (GET_REQUEST_HTTP_HDR_CONT_LEN(stage_req_info) != 0) { - GET_CONTENT_STORE_FILE_SIZE(file_storage) - = GET_REQUEST_HTTP_HDR_CONT_LEN(stage_req_info); - } else { - GET_CONTENT_STORE_FILE_SIZE(file_storage) = 0; - } - DA_LOG_VERBOSE(FileManager, "file size = %d", GET_CONTENT_STORE_FILE_SIZE(file_storage)); -ERR: - return ret; - -} - -/* Priority to derive extension - * 1. according to MIME-Type - * 2. if MIME-Type is ambiguous or blank, - * 2-1. derived from <Content-Disposition> field's "filename" attribute - * 2-2. derived from url - * 3. if url does not have extension, leave blank for extension - */ -char *__derive_extension(stage_info *stage) -{ - if (!stage) - return DA_NULL; - - source_info_t *source_info = GET_STAGE_SOURCE_INFO(stage); - req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage); - file_info *file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - char *extension = DA_NULL; - char *url = DA_NULL; - - /* Priority 1 */ - char *mime_type = DA_NULL; - mime_type = GET_CONTENT_STORE_CONTENT_TYPE(file_info_data); - if (mime_type && !is_ambiguous_MIME_Type(mime_type)) { - char *extension = DA_NULL; - da_result_t ret = get_extension_from_mime_type(mime_type, &extension); - if (ret == DA_RESULT_OK && extension) - return extension; - } - - /* Priority 2-1 */ - http_msg_response_t *http_msg_response = DA_NULL; - http_msg_response = request_info->http_info.http_msg_response; - if (http_msg_response) { - char *file_name = DA_NULL; - da_bool_t b_ret = http_msg_response_get_content_disposition(http_msg_response, - DA_NULL, &file_name); - if (b_ret && file_name) { - char *extension = DA_NULL; - DA_SECURE_LOGD("Name from Content-Disposition :[%s]", file_name); - __divide_file_name_into_pure_name_N_extesion(file_name, DA_NULL, &extension); - if (file_name) { - free(file_name); - file_name = DA_NULL; - } - if (extension) - return extension; - } - } - /* Priority 2-2 */ - /* If there is location url from response header in case of redirection, - * it try to parse the extention name from the location url */ - if (GET_REQUEST_HTTP_REQ_LOCATION(request_info)) - url = GET_REQUEST_HTTP_REQ_LOCATION(request_info); - else - url = GET_SOURCE_BASIC_URL(source_info); - if (url) { - DA_SECURE_LOGD("url:[%s]", url); - da_bool_t b_ret = da_get_extension_name_from_url(url, &extension); - if (b_ret && extension) - return extension; - } - - return DA_NULL; -} - -/** Priority for deciding file name - * 1. what client wants, which is conveyed by DA_FEATURE_FILE_NAME - * 2. 'filename' option on HTTP response header's Content-Disposition field - * 3. requesting URL - * 4. Otherwise, define it as "No name" - */ -da_result_t __get_candidate_file_name(stage_info *stage, char **out_pure_file_name, char **out_extension) -{ - da_result_t ret = DA_RESULT_OK; - source_info_t *source_info = DA_NULL; - char *pure_file_name = DA_NULL; - char *extension = DA_NULL; - - DA_LOG_FUNC_LOGV(FileManager); - - if (!stage || !out_pure_file_name) - return DA_ERR_INVALID_ARGUMENT; - - source_info = GET_STAGE_SOURCE_INFO(stage); - if (!source_info) - return DA_ERR_INVALID_ARGUMENT; - - /* Priority 1 */ - if (!pure_file_name && GET_DL_USER_FILE_NAME(GET_STAGE_DL_ID(stage))) { - __divide_file_name_into_pure_name_N_extesion( - GET_DL_USER_FILE_NAME(GET_STAGE_DL_ID(stage)), - &pure_file_name, &extension); - } - - /* Priority 2 */ - if (!pure_file_name) { - req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage); - http_msg_response_t *http_msg_response = DA_NULL; - http_msg_response = request_info->http_info.http_msg_response; - if (http_msg_response) { - char *file_name = DA_NULL; - da_bool_t b_ret = http_msg_response_get_content_disposition(http_msg_response, - DA_NULL, &file_name); - if (b_ret && file_name) { - DA_SECURE_LOGD("Name from Content-Disposition :[%s]", file_name); - __divide_file_name_into_pure_name_N_extesion(file_name, &pure_file_name, &extension); - if (file_name) { - free(file_name); - file_name = DA_NULL; - } - } - } - } - - /* Priority 3 */ - if (!pure_file_name) { - char *url = DA_NULL; - req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage); - /* If there is location url from response header in case of redirection, - * it try to parse the file name from the location url */ - if (GET_REQUEST_HTTP_REQ_LOCATION(request_info)) - url = GET_REQUEST_HTTP_REQ_LOCATION(request_info); - else - url = GET_SOURCE_BASIC_URL(source_info); - if (url) { - DA_SECURE_LOGD("url: [%s]", url); - da_get_file_name_from_url(url, &pure_file_name); - } - } - - /* Priority 4 */ - if (!pure_file_name) { - pure_file_name = strdup(NO_NAME_TEMP_STR); - if (!pure_file_name) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - } - - *out_pure_file_name = pure_file_name; - pure_file_name = DA_NULL; - DA_SECURE_LOGD("candidate file name [%s]", *out_pure_file_name); - - if (out_extension) { - if (extension) { - *out_extension = extension; - extension = DA_NULL; - } else { - *out_extension = __derive_extension(stage); - DA_SECURE_LOGD("candidate extension [%s]", *out_extension); - } - } - - if (extension) - free(extension); - - return DA_RESULT_OK; - -ERR: - if (extension) - free(extension); - - return ret; -} - -da_result_t __decide_file_path(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - char *temp_dir = DA_NULL; - char *extension = DA_NULL; - char *file_name_without_extension = DA_NULL; - char *tmp_file_path = DA_NULL; - char *user_install_path = DA_NULL; - file_info *file_info_data = DA_NULL; - int len = 0; - DA_LOG_FUNC_LOGV(FileManager); - - file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_info_data) - return DA_ERR_INVALID_ARGUMENT; - - - /* If the installed path which user want is set, the temporary directory is same to the installation directory. - * Otherwise, the default temporary directory is used. - */ - user_install_path = GET_DL_USER_INSTALL_PATH(GET_STAGE_DL_ID(stage)); - if (user_install_path) { - len = strlen(user_install_path); - temp_dir = (char *)calloc(len + 1, sizeof(char)); - if (!temp_dir) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - memcpy(temp_dir, user_install_path, len); - temp_dir[len] = '\0'; - - } else { - ret = get_default_install_dir(&temp_dir); - if (DA_RESULT_OK != ret || DA_NULL == temp_dir) { - goto ERR; - } - } - - ret = __get_candidate_file_name(stage, &file_name_without_extension, &extension); - if (ret != DA_RESULT_OK) - goto ERR; - - // for resume - tmp_file_path = get_full_path_avoided_duplication(temp_dir, file_name_without_extension, extension); - if (tmp_file_path) { - GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)) - = tmp_file_path; - tmp_file_path = DA_NULL; - } else { - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; - } - - if (file_name_without_extension && !GET_CONTENT_STORE_PURE_FILE_NAME(file_info_data)) { - GET_CONTENT_STORE_PURE_FILE_NAME(file_info_data) = file_name_without_extension; - file_name_without_extension = DA_NULL; - } - - if (extension && !GET_CONTENT_STORE_EXTENSION(file_info_data)) { - GET_CONTENT_STORE_EXTENSION(file_info_data) = extension; - extension = DA_NULL; - } - -ERR: - DA_SECURE_LOGI("decided file path = %s", GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data)); - if (temp_dir) { - free(temp_dir); - temp_dir = DA_NULL; - } - if (file_name_without_extension) { - free(file_name_without_extension); - file_name_without_extension = DA_NULL; - } - if (extension) { - free(extension); - extension = DA_NULL; - } - return ret; -} - -char *get_full_path_avoided_duplication(char *in_dir, char *in_candidate_file_name, char *in_extension) -{ - char *dir = in_dir; - char *file_name = in_candidate_file_name; - char *extension = in_extension; - char *final_path = DA_NULL; - - int final_path_len = 0; - int extension_len = 0; - - int suffix_count = 0; /* means suffix on file name. up to "_1000000000" */ - const int max_suffix_count = 1000000000; - int suffix_len = (int)log10(max_suffix_count+1) + 1; /* 1 means "_" */ - - if (!in_dir || !in_candidate_file_name) - return DA_NULL; - -// DA_SECURE_LOGD("in_candidate_file_name=[%s], in_extension=[%s]", in_candidate_file_name, in_extension); - - if (extension) - extension_len = strlen(extension); - - /* first 1 for "/", second 1 for ".", last 1 for DA_NULL */ - final_path_len = strlen(dir) + 1 + strlen(file_name) + 1 - + suffix_len + extension_len + 1; - - final_path = (char*)calloc(1, final_path_len); - if (!final_path) { - DA_LOG_ERR(FileManager, "DA_ERR_FAIL_TO_MEMALLOC"); - return DA_NULL; - } - - do { - /* e.g) /tmp/abc.jpg - * if there is no extension name, just make a file name without extension */ - if (0 == extension_len) { - if (suffix_count == 0) { - snprintf(final_path, final_path_len, - "%s/%s", dir, file_name); - } else { - snprintf(final_path, final_path_len, - "%s/%s_%d", dir, file_name, suffix_count); - } - } else { - if (suffix_count == 0) { - snprintf(final_path, final_path_len, - "%s/%s.%s", dir, file_name, extension); - } else { - snprintf(final_path, final_path_len, - "%s/%s_%d.%s", - dir, file_name, suffix_count, extension); - } - } - - if (is_file_exist(final_path)) { - suffix_count++; - if (suffix_count > max_suffix_count) { - free(final_path); - final_path = DA_NULL; - break; - } else { - memset(final_path, 0x00, final_path_len); - continue; - } - } - - break; - } while (1); - -// DA_SECURE_LOGD("decided path = [%s]", final_path); - return final_path; -} - -da_result_t __divide_file_name_into_pure_name_N_extesion(const char *in_file_name, char **out_pure_file_name, char **out_extension) +da_ret_t __divide_file_name_into_pure_name_N_extesion(const char *in_file_name, char **out_pure_file_name, char **out_extension) { char *file_name = DA_NULL; char *tmp_ptr = DA_NULL; char temp_file[DA_MAX_FILE_PATH_LEN] = {0,}; char tmp_ext[DA_MAX_STR_LEN] = {0,}; int len = 0; - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; - DA_LOG_FUNC_LOGD(FileManager); + DA_LOGV(""); if (!in_file_name) return DA_ERR_INVALID_ARGUMENT; @@ -639,553 +115,794 @@ da_result_t __divide_file_name_into_pure_name_N_extesion(const char *in_file_nam (const char*) temp_file); } - DA_SECURE_LOGD("pure file name [%s]", *out_pure_file_name); + DA_LOGV( "pure file name [%s]", *out_pure_file_name); return ret; } -da_result_t __file_write_buf_make_buf(file_info *file_storage) +da_ret_t __file_write_buf_make_buf(file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; char *buffer = DA_NULL; - DA_LOG_FUNC_LOGV(FileManager); + DA_LOGV(""); - buffer = (char*) calloc(DOWNLOAD_NOTIFY_LIMIT, 1); + buffer = (char*) calloc(1, DA_FILE_BUF_SIZE); if (DA_NULL == buffer) { - DA_LOG_ERR(FileManager, "Calloc failure "); + DA_LOGE("Calloc failure "); ret = DA_ERR_FAIL_TO_MEMALLOC; } else { - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; - GET_CONTENT_STORE_FILE_BUFFER(file_storage) = buffer; + file_info->buffer_len = 0; + file_info->buffer = buffer; } return ret; } -da_result_t __file_write_buf_destroy_buf(file_info *file_storage) +da_ret_t __file_write_buf_destroy_buf(file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_LOGV(FileManager); + da_ret_t ret = DA_RESULT_OK; - if (GET_CONTENT_STORE_FILE_BUFFER(file_storage)) - free(GET_CONTENT_STORE_FILE_BUFFER(file_storage)); + DA_LOGV(""); + NULL_CHECK_RET(file_info); - GET_CONTENT_STORE_FILE_BUFFER(file_storage) = DA_NULL; - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; + free(file_info->buffer); + file_info->buffer = DA_NULL; + file_info->buffer_len = 0; return ret; } -da_result_t __file_write_buf_flush_buf(stage_info *stage, file_info *file_storage) +da_ret_t __file_write_buf_flush_buf(file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; char *buffer = DA_NULL; int buffer_size = 0; int write_success_len = 0; void *fd = DA_NULL; - DA_LOG_FUNC_LOGV(FileManager); + // DA_LOGV(""); - buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); - buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; if (buffer_size == 0) { - DA_LOG_ERR(FileManager, "no data on buffer.."); + DA_LOGE("no data on buffer.."); return ret; } - fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage); + fd = file_info->file_handle; if (DA_NULL == fd) { - DA_LOG_ERR(FileManager, "There is no file handle."); + DA_LOGE("There is no file handle."); ret = DA_ERR_FAIL_TO_ACCESS_FILE; goto ERR; } + write_success_len = fwrite(buffer, sizeof(char), buffer_size, (FILE *) fd); /* FIXME : This can be necessary later due to progressive download. * The solution for reducing fflush is needed */ //fflush((FILE *) fd); if (write_success_len != buffer_size) { - DA_LOG_ERR(FileManager, "write fails "); + DA_LOGE("write fails "); if (errno == ENOSPC) ret = DA_ERR_DISK_FULL; else ret = DA_ERR_FAIL_TO_ACCESS_FILE; goto ERR; } - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - += write_success_len; - DA_LOG_VERBOSE(FileManager, "write %d bytes", write_success_len); - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_TRUE; - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; - + file_info->bytes_written_to_file += write_success_len; + file_info->is_updated = DA_TRUE; + file_info->buffer_len = 0; ERR: return ret; } -da_result_t __file_write_buf_copy_to_buf(file_info *file_storage, char *body, +da_ret_t __file_write_buf_copy_to_buf(file_info_t *file_info, char *body, int body_len) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; char *buffer = DA_NULL; int buffer_size = 0; - DA_LOG_FUNC_LOGV(FileManager); + DA_LOGV(""); - buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); - buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); + NULL_CHECK_RET(file_info->buffer); + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; memcpy(buffer + buffer_size, body, body_len); - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) += body_len; + file_info->buffer_len += body_len; return ret; } -da_result_t __file_write_buf_directly_write(stage_info *stage, - file_info *file_storage, char *body, int body_len) +da_ret_t __file_write_buf_directly_write(file_info_t *file_info, + char *body, int body_len) { - da_result_t ret = DA_RESULT_OK; - int write_success_len = 0; + da_ret_t ret = DA_RESULT_OK; + size_t write_success_len = 0; void *fd = DA_NULL; - DA_LOG_FUNC_LOGV(FileManager); + // DA_LOGV(""); - fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage); + fd = file_info->file_handle; if (DA_NULL == fd) { - DA_LOG_ERR(FileManager, "There is no file handle."); - + DA_LOGE("There is no file handle."); ret = DA_ERR_FAIL_TO_ACCESS_FILE; goto ERR; } - write_success_len = fwrite(body, sizeof(char), body_len, + + write_success_len = fwrite(body, sizeof(char), (size_t)body_len, (FILE *) fd); /* FIXME : This can be necessary later due to progressive download. * The solution for reducing fflush is needed */ //fflush((FILE *) fd); - if (write_success_len != body_len) { - DA_LOG_ERR(FileManager, "write fails "); + if (write_success_len != (size_t)body_len) { + DA_LOGE("write fails "); if (errno == ENOSPC) ret = DA_ERR_DISK_FULL; else ret = DA_ERR_FAIL_TO_ACCESS_FILE; goto ERR; } - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - += write_success_len; - DA_LOG(FileManager, "write %d bytes", write_success_len); - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_TRUE; + file_info->bytes_written_to_file += write_success_len; + DA_LOGV( "write %llu bytes", write_success_len); + file_info->is_updated = DA_TRUE; ERR: return ret; } -da_result_t file_write_ongoing(stage_info *stage, char *body, int body_len) +/* Priority to derive extension + * 1. extension name which client set + * 2. according to MIME-Type + * 3. if MIME-Type is ambiguous or blank, + * 3-1. derived from <Content-Disposition> field's "filename" attribute + * 3-2. derived from url + * 4. if url does not have extension, leave blank for extension + */ +char *__get_extension_name(char *mime_type, + char *file_name_from_header, char *url) { - da_result_t ret = DA_RESULT_OK; - file_info *file_storage = DA_NULL; - int buffer_size = 0; - char *buffer = DA_NULL; - - DA_LOG_FUNC_LOGV(FileManager); + char *extension = DA_NULL; - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) { - DA_LOG_ERR(FileManager, "file_info is empty."); - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; + /* Priority 1 */ + if (mime_type && !is_ambiguous_MIME_Type(mime_type)) { + char *extension = DA_NULL; + da_ret_t ret = get_extension_from_mime_type(mime_type, &extension); + if (ret == DA_RESULT_OK && extension) + return extension; } + /* Priority 2-1 */ + if (file_name_from_header) { + char *extension = DA_NULL; + DA_SECURE_LOGI("Content-Disposition :[%s]", file_name_from_header); + __divide_file_name_into_pure_name_N_extesion(file_name_from_header, + DA_NULL, &extension); + if (extension) + return extension; + } + /* Priority 2-2 */ + if (url) { + DA_LOGV("Get extension from url"); + da_bool_t b_ret = da_get_extension_name_from_url(url, &extension); + if (b_ret && extension) + return extension; + } + return DA_NULL; +} - buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); - buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_FALSE; - - if (DA_NULL == buffer) { - if (body_len < DOWNLOAD_NOTIFY_LIMIT) { - ret = __file_write_buf_make_buf(file_storage); - if (ret != DA_RESULT_OK) - goto ERR; - - __file_write_buf_copy_to_buf(file_storage, body, body_len); - } else { - ret = __file_write_buf_directly_write(stage, - file_storage, body, body_len); - if (ret != DA_RESULT_OK) - goto ERR; - } - } else { - if (DOWNLOAD_NOTIFY_LIMIT <= body_len) { - ret = __file_write_buf_flush_buf(stage, file_storage); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = __file_write_buf_directly_write(stage, - file_storage, body, body_len); - if (ret != DA_RESULT_OK) - goto ERR; +/** Priority for deciding file name + * 1. file name which client set + * 2. 'filename' option on HTTP response header's Content-Disposition field + * 3. requesting URL + * 4. Otherwise, define it as "No name" + */ +da_ret_t __get_candidate_file_name(char *user_file_name, char *url, + char *file_name_from_header, + char **out_pure_file_name, char **out_extension) +{ + da_ret_t ret = DA_RESULT_OK; - } else if ((DOWNLOAD_NOTIFY_LIMIT - buffer_size) <= body_len) { - ret = __file_write_buf_flush_buf(stage, file_storage); - if (ret != DA_RESULT_OK) - goto ERR; + DA_LOGV(""); - __file_write_buf_copy_to_buf(file_storage, body, body_len); - } else { - __file_write_buf_copy_to_buf(file_storage, body, body_len); - } + /* Priority 1 */ + if (user_file_name) { + __divide_file_name_into_pure_name_N_extesion( + user_file_name, out_pure_file_name, out_extension); } - -ERR: - if (ret != DA_RESULT_OK) { - if (file_storage) { - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; - if (GET_CONTENT_STORE_FILE_BUFFER(file_storage)) { - free( - GET_CONTENT_STORE_FILE_BUFFER(file_storage)); - GET_CONTENT_STORE_FILE_BUFFER(file_storage) - = DA_NULL; - } - } + if (*out_pure_file_name) + return ret; + /* Priority 2 */ + if (file_name_from_header) { + DA_SECURE_LOGI("Content-Disposition:[%s]", file_name_from_header); + __divide_file_name_into_pure_name_N_extesion(file_name_from_header, + out_pure_file_name, DA_NULL); } + if (*out_pure_file_name) + return ret ; + /* Priority 3 */ + if (url) { + DA_LOGV("Get file name from url"); + da_get_file_name_from_url(url, out_pure_file_name); + } + if (*out_pure_file_name) + return ret ; + /* Priority 4 */ + *out_pure_file_name = strdup(NO_NAME_TEMP_STR); + if (*out_pure_file_name == DA_NULL) + ret = DA_ERR_FAIL_TO_MEMALLOC; return ret; } -da_result_t file_write_complete(stage_info *stage) +da_ret_t __decide_file_path(da_info_t *da_info) { - da_result_t ret = DA_RESULT_OK; - file_info*file_storage = DA_NULL; - char *buffer = DA_NULL; - unsigned int buffer_size = 0; - void *fd = DA_NULL; + da_ret_t ret = DA_RESULT_OK; + char *extension = DA_NULL; + char *file_name = DA_NULL; + char *tmp_file_path = DA_NULL; + char *install_dir = DA_DEFAULT_INSTALL_PATH_FOR_PHONE; + char *user_file_name = DA_NULL; + char *file_name_from_header = DA_NULL; + char *url = DA_NULL; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + http_info_t *http_info = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + if (req_info->install_path) + install_dir = req_info->install_path; + user_file_name = req_info->file_name; + /* If there is location url from response header in case of redirection, + * it try to parse the file name from the location url */ + if (http_info->location_url) { + url = http_info->location_url; + DA_LOGI("[TEST] location_url[%s][%p]",http_info->location_url, http_info->location_url); + } else + url = req_info->url; + + file_name_from_header = http_info->file_name_from_header; + + /* extension is extracted only if User set specific name */ + ret = __get_candidate_file_name(user_file_name, url, file_name_from_header, + &file_name, &extension); + if (ret != DA_RESULT_OK) + goto ERR; - DA_LOG_FUNC_LOGV(FileManager); + if (file_name && strpbrk(file_name, DA_INVALID_PATH_STRING) != NULL) { + DA_LOGI("Invalid string at file name"); + free(file_name); + file_name = strdup(NO_NAME_TEMP_STR); + if (!file_name) { + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) { - DA_LOG_ERR(FileManager, "file_info is DA_NULL."); - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; } - buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); - buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); + DA_SECURE_LOGI("candidate file name [%s]", file_name); - if (DA_NULL == buffer) { - DA_LOG_ERR(FileManager, "file buffer is DA_NULL"); - } else { - if (buffer_size != 0) { - ret = __file_write_buf_flush_buf(stage, file_storage); - if (ret != DA_RESULT_OK) - goto ERR; - } - __file_write_buf_destroy_buf(file_storage); + if (!extension) { + extension = __get_extension_name(file_info->mime_type, + file_name_from_header, url); + } + if (file_name && !file_info->pure_file_name) { + file_info->pure_file_name = file_name; + file_name = DA_NULL; + } + if (extension && !file_info->extension) { + DA_LOGV("candidate extension [%s]", extension); + file_info->extension = extension; + extension = DA_NULL; } - fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage); - if (fd) { - fclose(fd); - fd = DA_NULL; + // for resume + tmp_file_path = get_full_path_avoided_duplication(install_dir, + file_info->pure_file_name, file_info->extension); + if (tmp_file_path) { + file_info->file_path = tmp_file_path; + tmp_file_path = DA_NULL; + } else { + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; } - GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL; + ERR: + DA_SECURE_LOGI("decided file path [%s]", file_info->file_path); + free(file_name); + free(extension); return ret; } -da_result_t start_file_writing(stage_info *stage) +// for resume with new download request +da_ret_t __decide_file_path_for_resume(file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; - file_info *file_info_data = DA_NULL; + da_ret_t ret = DA_RESULT_OK; + char *extension = DA_NULL; + char *file_name = DA_NULL; + char *file_path = DA_NULL; + char *ptr = DA_NULL; + char *ptr2 = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(file_info); + + file_path = file_info->file_path; + ptr = strrchr(file_path, '/'); + if (ptr) { + ptr++; + ptr2 = strrchr(ptr, '.'); + if (ptr2) { + int len = 0; + len = ptr2 - ptr; + ptr2++; + extension = strdup(ptr2); + file_name = calloc(1, len + 1); + if (file_name) + snprintf(file_name, len + 1, "%s", ptr); + } else { + file_name = strdup(ptr); + } + } - DA_LOG_FUNC_LOGV(FileManager); + if (file_name && !file_info->pure_file_name) { + file_info->pure_file_name = file_name; + file_name = DA_NULL; + } else { + free(file_name); + } + if (extension && !file_info->extension) { + DA_LOGV( "candidate extension [%s]", extension); + file_info->extension = extension; + extension = DA_NULL; + } else { + free(extension); + } + return ret; +} - file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - ret = get_mime_type(stage, - &GET_CONTENT_STORE_CONTENT_TYPE(file_info_data)); - if (ret != DA_RESULT_OK) - goto ERR; +da_ret_t start_file_writing(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + /* resume case */ + if (req_info->etag || req_info->temp_file_path) { + char *file_path = DA_NULL; + char *origin_path = DA_NULL; + file_path = req_info->temp_file_path; + if (!file_path) + return DA_ERR_INVALID_ARGUMENT; + origin_path = file_info->file_path; + file_info->file_path = strdup(file_path); + free(origin_path); + ret = __decide_file_path_for_resume(file_info); + } else { + ret = __decide_file_path(da_info); + } - ret = __decide_file_path(stage); if (ret != DA_RESULT_OK) goto ERR; - ret = __set_file_size(stage); - if (DA_RESULT_OK != ret) - goto ERR; - - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - = 0; - - ret = __saved_file_open(stage); - + if (req_info->etag || req_info->temp_file_path) { + da_size_t file_size = 0; + get_file_size(req_info->temp_file_path, &file_size); + if (file_size < 1) + goto ERR; +#ifdef _RAF_SUPPORT + file_info->file_size_of_temp_file = file_size; +#endif + file_info->bytes_written_to_file = file_size; + } else { + file_info->bytes_written_to_file = 0; + } + ret = __saved_file_open(file_info); ERR: return ret; } - -da_result_t start_file_writing_append(stage_info *stage) +da_ret_t start_file_append(file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; - DA_LOG_FUNC_LOGD(FileManager); + DA_LOGV(""); - ret = __saved_file_open(stage); + NULL_CHECK_RET(file_info); + ret = __saved_file_open(file_info); return ret; } -// for resume with new download request -da_result_t start_file_writing_append_with_new_download(stage_info *stage) +da_ret_t file_write_ongoing(file_info_t *file_info, char *body, int body_len) { - da_result_t ret = DA_RESULT_OK; - file_info *file_storage = DA_NULL; - char *original_file_path = DA_NULL; - char *temp_file_path = DA_NULL; - char *extension = DA_NULL; - char *file_name_without_extension = DA_NULL; - req_dl_info *request_info = DA_NULL; - unsigned long long temp_file_size = 0; - - DA_LOG_FUNC_LOGD(FileManager); - - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) - return DA_ERR_INVALID_ARGUMENT; - request_info = GET_STAGE_TRANSACTION_INFO(stage); - if (!request_info) - return DA_ERR_INVALID_ARGUMENT; - temp_file_path = GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(request_info); - if (!temp_file_path) - return DA_ERR_INVALID_ARGUMENT; - original_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage); - - GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage) = strdup(temp_file_path); - - if (original_file_path) - free(original_file_path); + da_ret_t ret = DA_RESULT_OK; + int buffer_size = 0; + char *buffer = DA_NULL; - ret = get_mime_type(stage, - &GET_CONTENT_STORE_CONTENT_TYPE(file_storage)); - if (ret != DA_RESULT_OK) - goto ERR; + DA_LOGV(""); - ret = __get_candidate_file_name(stage, &file_name_without_extension, &extension); - if (ret != DA_RESULT_OK) - goto ERR; + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; - if (file_name_without_extension) { - if (!GET_CONTENT_STORE_PURE_FILE_NAME(file_storage)) { - GET_CONTENT_STORE_PURE_FILE_NAME(file_storage) = file_name_without_extension; - file_name_without_extension = DA_NULL; + if (DA_NULL == buffer) { + if (body_len < DA_FILE_BUF_SIZE) { + ret = __file_write_buf_make_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + __file_write_buf_copy_to_buf(file_info, body, body_len); + } else { + ret = __file_write_buf_directly_write(file_info, + body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + } + } else { + if (DA_FILE_BUF_SIZE <= body_len) { + ret = __file_write_buf_flush_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + ret = __file_write_buf_directly_write(file_info, + body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + } else if ((DA_FILE_BUF_SIZE - buffer_size) <= body_len) { + ret = __file_write_buf_flush_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + __file_write_buf_copy_to_buf(file_info, body, body_len); } else { - free(file_name_without_extension); - file_name_without_extension = DA_NULL; + __file_write_buf_copy_to_buf(file_info, body, body_len); } } +ERR: + if (ret != DA_RESULT_OK) { + file_info->buffer_len = 0; + free(file_info->buffer); + file_info->buffer = DA_NULL; + } + return ret; +} - if (extension) { - if (!GET_CONTENT_STORE_EXTENSION(file_storage)) { - GET_CONTENT_STORE_EXTENSION(file_storage) = extension; - extension = DA_NULL; - } else { - free(extension); - extension = DA_NULL; +#ifdef _RAF_SUPPORT +da_ret_t file_write_complete_for_raf(file_info_t *file_info) { + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + da_size_t wrriten_size = 0; + da_size_t file_size = 0; + void *fd = DA_NULL; + + DA_LOGV(""); + fd = file_info->file_handle; + + wrriten_size = file_info->bytes_written_to_file; + // test code + get_file_size(file_info->file_path, &file_size); + DA_LOGI("wrriten_size:%llu file_size:%llu file[%s]", + wrriten_size, file_size, file_info->file_path); + if (fd) { + fclose(fd); + fd = DA_NULL; + } + file_info->file_handle = DA_NULL; + if (wrriten_size < file_size) { + DA_LOGD("Try truncate"); + if (truncate(file_info->file_path, wrriten_size) < 0) { + DA_LOGE("Fail to ftruncate: errno[%d,%s]", errno, strerror(errno)); } + DA_LOGD("Try truncate done"); } - ret = __set_file_size(stage); - if (DA_RESULT_OK != ret) - goto ERR; - get_file_size(temp_file_path, &temp_file_size); - if (temp_file_size < 1) - goto ERR; + ERR: + return ret; +} +#endif - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - = temp_file_size; +da_ret_t file_write_complete(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + unsigned int buffer_size = 0; + void *fd = DA_NULL; - ret = __saved_file_open(stage); - return ret; -ERR: - if (file_name_without_extension) { - free(file_name_without_extension); - file_name_without_extension = DA_NULL; + DA_LOGV(""); + + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; + + if (DA_NULL == buffer) { + DA_LOGE("file buffer is NULL"); + } else { + if (buffer_size != 0) { + ret = __file_write_buf_flush_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + } + __file_write_buf_destroy_buf(file_info); } + fd = file_info->file_handle; - if (extension) { - free(extension); - extension = DA_NULL; + if (fd) { + fclose(fd); + fd = DA_NULL; } + file_info->file_handle = DA_NULL; +ERR: return ret; } -da_result_t discard_download(stage_info *stage) +da_ret_t discard_download(file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; - file_info *file_storage = DA_NULL; + da_ret_t ret = DA_RESULT_OK; FILE *f_handle = DA_NULL; - DA_LOG_FUNC_LOGD(FileManager); - - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); + DA_LOGV(""); - f_handle = GET_CONTENT_STORE_FILE_HANDLE(file_storage); + f_handle = file_info->file_handle; if (f_handle) { fclose(f_handle); - GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL; + file_info->file_handle = DA_NULL; } return ret; } -void clean_paused_file(stage_info *stage) +void clean_paused_file(file_info_t *file_info) { - file_info *file_info_data = DA_NULL; char *paused_file_path = DA_NULL; FILE *fd = DA_NULL; - DA_LOG_FUNC_LOGD(FileManager); + DA_LOGV(""); - file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - - fd = GET_CONTENT_STORE_FILE_HANDLE(file_info_data); + fd = file_info->file_handle; if (fd) { fclose(fd); - GET_CONTENT_STORE_FILE_HANDLE(file_info_data) = DA_NULL; + file_info->file_handle = DA_NULL; } - paused_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data); + paused_file_path = file_info->file_path; + file_info->bytes_written_to_file = 0; // Ignore resume flow after failed or cancled. remove_file((const char*) paused_file_path); return; } -da_result_t replace_content_file_in_stage(stage_info *stage, - const char *dest_dd_file_path) +da_bool_t is_file_exist(const char *file_path) { - da_result_t ret = DA_RESULT_OK; - char *dd_file_path = DA_NULL; - int len; + struct stat dir_state; + int stat_ret; - DA_LOG_FUNC_LOGD(FileManager); + if (file_path == DA_NULL) { + DA_LOGE("file path is DA_NULL"); + return DA_FALSE; + } + stat_ret = stat(file_path, &dir_state); + if (stat_ret == 0) { + if (dir_state.st_mode & S_IFREG) { + //DA_SECURE_LOGD("Exist! %s is a regular file & its size = %lu", file_path, dir_state.st_size); + return DA_TRUE; + } - if (!dest_dd_file_path - && (DA_FALSE == is_file_exist(dest_dd_file_path))) { - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; + return DA_FALSE; } + return DA_FALSE; - dd_file_path - =GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)); +} - if (DA_NULL != dd_file_path) { - remove_file((const char*) dd_file_path); - free(dd_file_path); - } - len = strlen(dest_dd_file_path); - dd_file_path = calloc(1, len + 1); - if (!dd_file_path) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - strncpy(dd_file_path, dest_dd_file_path, len); - GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)) - = dd_file_path; +void get_file_size(char *file_path, da_size_t *out_file_size) +{ + struct stat dir_state; + int stat_ret; -ERR: - return ret; + *out_file_size = -1; + if (file_path == DA_NULL) { + DA_LOGE("file path is DA_NULL"); + return; + } + /* Please do not use ftell() to obtain file size, use stat instead. + * This is a guide from www.securecoding.cert.org + * : FIO19-C. Do not use fseek() and ftell() to compute the size of a file + */ + stat_ret = stat(file_path, &dir_state); + if (stat_ret == 0) { + if (dir_state.st_mode & S_IFREG) { + DA_LOGV( "size = %lu", dir_state.st_size); + *out_file_size = dir_state.st_size; + } + } + return; } -da_result_t copy_file(const char *src, const char *dest) +char *get_full_path_avoided_duplication(char *in_dir, + char *in_candidate_file_name, char *in_extension) { - FILE *fs = DA_NULL; - FILE *fd = DA_NULL; - int freadnum = 0; - int fwritenum = 0; - char buff[4096] = { 0, }; + char *dir = in_dir; + char *file_name = in_candidate_file_name; + char *extension = in_extension; + char *final_path = DA_NULL; + + int dir_path_len = 0; + int final_path_len = 0; + int extension_len = 0; - DA_LOG_FUNC_LOGD(FileManager); + int suffix_count = 0; /* means suffix on file name. up to "_99" */ + int suffix_len = (int)log10(MAX_SUFFIX_COUNT + 1) + 1; /* 1 means "_" */ - /* open files to copy */ - fs = fopen(src, "rb"); - if (!fs) { - DA_LOG_ERR(FileManager, "Fail to open src file"); - return DA_ERR_FAIL_TO_ACCESS_FILE; + if (!in_dir || !in_candidate_file_name) + return DA_NULL; + + //DA_SECURE_LOGI("in_candidate_file_name=[%s],in_extension=[%s]", + //in_candidate_file_name, in_extension); + + if (extension) + extension_len = strlen(extension); + + // to remove trailing slash from dir path + dir_path_len = strlen(dir); + if (dir[dir_path_len - 1] == '/') { + dir[dir_path_len - 1] = '\0'; + --dir_path_len; } - fd = fopen(dest, "wb"); - if (!fd) { - DA_LOG_ERR(FileManager, "Fail to open dest file"); + /* first 1 for "/", second 1 for ".", last 1 for DA_NULL */ + final_path_len = dir_path_len + 1 + strlen(file_name) + 1 + + suffix_len + extension_len + 1; - fclose(fs); - return DA_ERR_FAIL_TO_ACCESS_FILE; + final_path = (char*)calloc(1, final_path_len); + if (!final_path) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_NULL; } - /* actual copy */ - while (!feof(fs)) { - memset(buff, 0x00, 4096); - freadnum = fread(buff, sizeof(char), sizeof(buff), fs); - if (freadnum > 0) { - fwritenum = fwrite(buff, sizeof(char), freadnum, fd); - if (fwritenum <= 0) { - DA_LOG(FileManager, "written = %d",fwritenum); - break; + do { + /* e.g) /tmp/abc.jpg + * if there is no extension name, just make a file name without extension */ + if (0 == extension_len) { + if (suffix_count == 0) { + snprintf(final_path, final_path_len, + "%s/%s", dir, file_name); + } else { + snprintf(final_path, final_path_len, + "%s/%s_%d", dir, file_name, suffix_count); } } else { - DA_LOG(FileManager, "read = %d",freadnum); - break; + if (suffix_count == 0) { + snprintf(final_path, final_path_len, + "%s/%s.%s", dir, file_name, extension); + } else { + snprintf(final_path, final_path_len, + "%s/%s_%d.%s", + dir, file_name, suffix_count, extension); + } } - } - - fclose(fd); - fclose(fs); + if (is_file_exist(final_path)) { + suffix_count++; + if (suffix_count > MAX_SUFFIX_COUNT) { + free(final_path); + final_path = DA_NULL; + break; + } else { + memset(final_path, 0x00, final_path_len); + continue; + } + } + break; + } while (1); - return DA_RESULT_OK; + //DA_SECURE_LOGD("decided path = [%s]", final_path); + return final_path; } -da_result_t create_dir(const char *install_dir) + +da_ret_t check_drm_convert(file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; - /* read/write/search permissions for owner and group, - * and with read/search permissions for others. */ - if (mkdir(install_dir, S_IRWXU | S_IRWXG | S_IRWXO)) { - DA_LOG_ERR(FileManager, "Fail to creaate directory"); - ret = DA_ERR_FAIL_TO_ACCESS_STORAGE; + da_ret_t ret = DA_RESULT_OK; + da_bool_t ret_b = DA_TRUE; + + DA_LOGD(""); + + NULL_CHECK_RET(file_info); + +#ifdef _ENABLE_OMA_DRM + + /* In case of OMA DRM 1.0 SD, it is not necessary to call DRM convert API. + * Because it is already converted itself. + * And, the case will return fail because The SD is not supported now. + */ + if (is_content_drm_dcf(file_info->mime_type)) { + DA_LOGI("DRM SD case"); + unlink(file_info->file_path); + free(file_info->file_path); + file_info->file_path = DA_NULL; + return DA_ERR_DRM_FAIL; + } + if (is_content_drm_dm(file_info->mime_type)) { + char *actual_file_path = DA_NULL; + char *out_file_path = DA_NULL; + + actual_file_path = file_info->file_path; + DA_SECURE_LOGD("actual_file_path = %s", actual_file_path); + if (!actual_file_path) + return DA_ERR_INVALID_ARGUMENT; + ret_b = EDRM_convert(actual_file_path, &out_file_path); + unlink(actual_file_path); + free(actual_file_path); + if (!ret_b) + ret = DA_ERR_DRM_FAIL; + file_info->file_path = out_file_path; } else { - DA_SECURE_LOGD("[%s] is created!", install_dir); - if (chown(install_dir, 5000, 5000) < 0) { - DA_LOG_ERR(FileManager, "Fail to chown"); - ret = DA_ERR_FAIL_TO_ACCESS_STORAGE; - } + return ret; } +#endif + return ret; } -da_result_t get_default_install_dir(char **out_path) +void remove_file(const char *file_path) { - char *default_path = DA_NULL; - da_result_t ret = DA_RESULT_OK; - int len = 0; + DA_LOGV(""); - if (!out_path) { - DA_LOG_ERR(ClientNoti, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; + if (file_path && is_file_exist(file_path)) { + DA_SECURE_LOGD("remove file [%s]", file_path); + if (unlink(file_path) < 0) { + DA_LOGE("file removing failed."); + } } +} - len = strlen(DA_DEFAULT_INSTALL_PATH_FOR_PHONE); +da_ret_t get_available_memory(char *dir_path, da_size_t len) +{ + da_ret_t ret = DA_RESULT_OK; + int fs_ret = 0; + //struct statfs filesys_info = {0, }; + struct statvfs filesys_info; - default_path = calloc(len + 1, sizeof(char)); - if (!default_path) { - return DA_ERR_FAIL_TO_MEMALLOC; - } + DA_LOGV(""); - memcpy(default_path, DA_DEFAULT_INSTALL_PATH_FOR_PHONE, len); - default_path[len] = '\0'; + if (!dir_path) + return DA_ERR_INVALID_INSTALL_PATH; - *out_path = default_path; + //fs_ret = statfs(dir_path, &filesys_info); + // Using this as it considers FOTA memory while returning available memory + fs_ret = storage_get_internal_memory_size(&filesys_info); - if (!is_dir_exist(default_path)) { - ret = create_dir(default_path); + if (fs_ret != 0) { + // DA_LOGE("statfs error[%s]", strerror(errno)); + return DA_ERR_INVALID_ARGUMENT; + // return DA_ERR_INVALID_INSTALL_PATH; } - DA_SECURE_LOGD("default temp path = [%s]", *out_path); - return DA_RESULT_OK; + + double available_size = (double)filesys_info.f_bsize * filesys_info.f_bavail; + double total_size = (double)filesys_info.f_frsize * filesys_info.f_blocks; + DA_SECURE_LOGI(" total = %lf ", total_size); + DA_SECURE_LOGI(" available = %lf ",available_size); + + DA_LOGV("Available Memory(f_bavail) : %lu", filesys_info.f_bavail); + DA_LOGV("Available Memory(f_bsize) : %d", filesys_info.f_bsize); + DA_LOGD("Available Memory(kbytes) : %d", (filesys_info.f_bavail/1024)*filesys_info.f_bsize); + DA_LOGV("Content: %llu", len); + if (available_size < (len + + SAVE_FILE_BUFFERING_SIZE_50KB)) /* 50KB buffering */ + ret = DA_ERR_DISK_FULL; + + return ret; } diff --git a/agent/download-agent-http-mgr.c b/agent/download-agent-http-mgr.c index bbc69f0..3a2feb9 100755 --- a/agent/download-agent-http-mgr.c +++ b/agent/download-agent-http-mgr.c @@ -14,376 +14,200 @@ * limitations under the License. */ -#include "download-agent-utils.h" -#include "download-agent-debug.h" +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <time.h> + +#include "download-agent-dl-info.h" +#include "download-agent-file.h" +#include "download-agent-mime-util.h" #include "download-agent-client-mgr.h" -#include "download-agent-http-mgr.h" -#include "download-agent-http-misc.h" #include "download-agent-http-msg-handler.h" -#include "download-agent-file.h" #include "download-agent-plugin-conf.h" -#include "download-agent-plugin-http-interface.h" - -da_result_t make_default_http_request_hdr(const char *url, - char **user_request_header, - int user_request_heaer_count, - http_msg_request_t **out_http_msg_request, - char *user_request_etag, - char *user_request_temp_file_path); -da_result_t create_resume_http_request_hdr(stage_info *stage, - http_msg_request_t **out_resume_request); - -da_result_t start_new_transaction(stage_info *stage); -da_result_t set_http_request_hdr(stage_info *stage); -da_result_t make_transaction_info_and_start_transaction(stage_info *stage); - -da_result_t pause_for_flow_control(stage_info *stage); -da_result_t unpause_for_flow_control(stage_info *stage); - -da_result_t handle_any_input(stage_info *stage); -da_result_t handle_event_control(stage_info *stage, q_event_t *event); -da_result_t handle_event_http(stage_info *stage, q_event_t *event); -da_result_t handle_event_http_packet(stage_info *stage, q_event_t *event); -da_result_t handle_event_http_final(stage_info *stage, q_event_t *event); -da_result_t handle_event_http_abort(stage_info *stage, q_event_t *event); - -da_result_t exchange_url_from_header_for_redirection(stage_info *stage, - http_msg_response_t *http_msg_response); - -da_result_t handle_event_abort(stage_info *stage); -da_result_t handle_event_cancel(stage_info *stage); -da_result_t handle_event_suspend(stage_info *stage); -da_result_t handle_event_resume(stage_info *stage); -da_result_t handle_http_hdr(stage_info *stage, - http_msg_response_t *http_msg_response, int http_status); -da_result_t handle_http_status_code(stage_info *stage, - http_msg_response_t *http_msg_response, int http_status); -da_result_t handle_http_body(stage_info *stage, char *body, int body_len); - -da_result_t set_hdr_fields_on_download_info(stage_info *stage); - -da_result_t _check_content_type_is_matched(stage_info *stage); -da_result_t _check_enough_memory_for_this_download(stage_info *stage); -da_result_t _check_downloaded_file_size_is_same_with_header_content_size( - stage_info *stage); - -da_result_t _check_resume_download_is_available(stage_info *stage, - http_msg_response_t *new_http_msg_response); -da_result_t _check_this_partial_download_is_available(stage_info *stage, - http_msg_response_t *new_http_msg_response); - -da_result_t _cancel_transaction(stage_info *stage); -da_result_t _disconnect_transaction(stage_info *stage); - -void __parsing_user_request_header(char *user_request_header, - char **out_field, char **out_value); - -http_mgr_t http_mgr; - -da_result_t init_http_mgr(void) -{ - da_result_t ret = DA_RESULT_OK; +#include "download-agent-plugin-drm.h" +#include "download-agent-plugin-libcurl.h" - DA_LOG_FUNC_LOGV(HTTPManager); +void __http_update_cb(http_raw_data_t *data, void *user_param); - if (http_mgr.is_http_init == DA_FALSE) { - http_mgr.is_http_init = DA_TRUE; - ret = PI_http_init(); - } - - return ret; -} +#define CONVERT_STR(NAME) (#NAME) - -da_result_t request_to_abort_http_download(stage_info *stage) +static const char *__get_state_str(http_state_t state) { - da_result_t ret = DA_RESULT_OK; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_LOGD(HTTPManager); - if (!stage) { - DA_LOG_ERR(HTTPManager, "Stage is NULL. download info is already destroyed"); - return DA_ERR_INVALID_ARGUMENT; - } - - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_ABORT"); - ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_ABORT, &q_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); - goto ERR; - } else { - DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); - Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), q_event); + char *str = NULL; + switch(state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + str = CONVERT_STR(HTTP_STATE_READY_TO_DOWNLOAD); + break; + case HTTP_STATE_REDIRECTED: + str = CONVERT_STR(HTTP_STATE_REDIRECTED); + break; + case HTTP_STATE_DOWNLOAD_REQUESTED: + str = CONVERT_STR(HTTP_STATE_DOWNLOAD_REQUESTED); + break; + case HTTP_STATE_DOWNLOAD_STARTED: + str = CONVERT_STR(HTTP_STATE_DOWNLOAD_STARTED); + break; + case HTTP_STATE_DOWNLOADING: + str = CONVERT_STR(HTTP_STATE_DOWNLOADING); + break; + case HTTP_STATE_DOWNLOAD_FINISH: + str = CONVERT_STR(HTTP_STATE_DOWNLOAD_FINISH); + break; + case HTTP_STATE_REQUEST_CANCEL: + str = CONVERT_STR(HTTP_STATE_REQUEST_CANCEL); + break; + case HTTP_STATE_REQUEST_PAUSE: + str = CONVERT_STR(HTTP_STATE_REQUEST_PAUSE); + break; + case HTTP_STATE_REQUEST_RESUME: + str = CONVERT_STR(HTTP_STATE_REQUEST_RESUME); + break; + case HTTP_STATE_CANCELED: + str = CONVERT_STR(HTTP_STATE_CANCELED); + break; + case HTTP_STATE_FAILED: + str = CONVERT_STR(HTTP_STATE_FAILED); + break; + case HTTP_STATE_PAUSED: + str = CONVERT_STR(HTTP_STATE_PAUSED); + break; + case HTTP_STATE_RESUMED: + str = CONVERT_STR(HTTP_STATE_RESUMED); + break; + case HTTP_STATE_ABORTED: + str = CONVERT_STR(HTTP_STATE_ABORTED); + break; + case HTTP_STATE_WAIT_FOR_NET_ERR: + str = CONVERT_STR(HTTP_STATE_WAIT_FOR_NET_ERR); + break; + default: + str = "Unknown State"; + break; } - -ERR: - return ret; + return str; } -void deinit_http_mgr(void) +void __init_http_info(http_info_t *http_info) { - DA_LOG_FUNC_LOGV(HTTPManager); - - if (http_mgr.is_http_init == DA_TRUE) { - http_mgr.is_http_init = DA_FALSE; - PI_http_deinit(); - } + DA_LOGV(""); - return; + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + http_info->update_cb = __http_update_cb; + DA_MUTEX_INIT(&(http_info->mutex_state), DA_NULL); + DA_MUTEX_INIT(&(http_info->mutex_http), DA_NULL); + DA_COND_INIT(&(http_info->cond_http), DA_NULL); } -da_result_t request_http_download(stage_info *stage) +void __parsing_user_request_header(char *user_request_header, + char **out_field, char **out_value) { - da_result_t ret = DA_RESULT_OK; - - int slot_id = DA_INVALID_ID; - http_state_t http_state = 0; - da_bool_t need_wait = DA_TRUE; - - queue_t *queue = DA_NULL; - req_dl_info *req_info = DA_NULL; - - slot_id = GET_STAGE_DL_ID(stage); - queue = GET_DL_QUEUE(slot_id); - req_info = GET_STAGE_TRANSACTION_INFO(stage); - - DA_LOG_VERBOSE(HTTPManager, "queue = %p", GET_DL_QUEUE(slot_id)); - - CHANGE_HTTP_STATE(HTTP_STATE_READY_TO_DOWNLOAD, stage); - - do { - ret = handle_any_input(stage); - if (ret != DA_RESULT_OK) { - if (DA_RESULT_OK == GET_REQUEST_HTTP_RESULT(req_info)) { - GET_REQUEST_HTTP_RESULT(req_info) = ret; - DA_LOG_CRITICAL(HTTPManager, "setting internal error [%d]", ret); - } - _cancel_transaction(stage); - } - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG_VERBOSE(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_READY_TO_DOWNLOAD: - ret = start_new_transaction(stage); - if (ret != DA_RESULT_OK) { - if (DA_RESULT_OK == GET_REQUEST_HTTP_RESULT(req_info)) { - GET_REQUEST_HTTP_RESULT(req_info) = ret; - DA_LOG_CRITICAL(HTTPManager, "setting internal error [%d]", ret); - } - DA_LOG(HTTPManager, "exiting with error..."); - need_wait = DA_FALSE; - break; - } + int len = 0; + char *pos = NULL; + char *temp_pos = NULL; + char *field = NULL; + char *value = NULL; - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_REQUESTED, stage); - break; + DA_LOGV(""); - case HTTP_STATE_CANCELED: - case HTTP_STATE_DOWNLOAD_FINISH: - case HTTP_STATE_ABORTED: -#ifdef PAUSE_EXIT - case HTTP_STATE_PAUSED: -#endif - DA_LOG_VERBOSE(HTTPManager, "exiting..."); - need_wait = DA_FALSE; - break; + if (!user_request_header) { + DA_LOGE("NULL CHECK!: user_request_header"); + goto ERR; + } - default: + pos = strchr(user_request_header, ':'); + if (!pos) { + DA_LOGE("Fail to parse"); + goto ERR; + } + temp_pos = (char *)user_request_header; + while (*temp_pos) + { + if (temp_pos == pos || *temp_pos == ' ') { + len = temp_pos - user_request_header; break; } - - if (need_wait == DA_TRUE) { - _da_thread_mutex_lock(&(queue->mutex_queue)); - if (DA_FALSE == GET_IS_Q_HAVING_DATA(queue)) { - unpause_for_flow_control(stage); - -// DA_LOG_VERBOSE(HTTPManager, "Waiting for input"); - Q_goto_sleep(queue); -// DA_LOG_VERBOSE(HTTPManager, "Woke up to receive new packet or control event"); - } - _da_thread_mutex_unlock (&(queue->mutex_queue)); - - } - - } while (need_wait == DA_TRUE); - - ret = GET_REQUEST_HTTP_RESULT(req_info); - DA_LOG_DEBUG(HTTPManager, "Exit request_http_download! ret[%d]slot_id[%d]", - ret, slot_id); - return ret; -} - -da_result_t request_to_cancel_http_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_LOGD(HTTPManager); - - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_CANCEL"); - ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_CANCEL, &q_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); + temp_pos++; + } + if (len < 1) { + DA_LOGE("Wrong field name"); goto ERR; - } else { - DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); - Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), q_event); } - -ERR: - return ret; -} - -da_result_t request_to_suspend_http_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t http_state = 0; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_LOGD(HTTPManager); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_PAUSED: - case HTTP_STATE_REQUEST_PAUSE: - DA_LOG_CRITICAL(HTTPManager, "Already paused. http_state = %d", http_state); - ret = DA_ERR_ALREADY_SUSPENDED; - break; - - default: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_SUSPEND"); - ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_SUSPEND, - &q_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); - goto ERR; - } else { - DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); - Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), - q_event); - } - - break; + field = (char *)calloc(1, len + 1); + if (!field) { + DA_LOGE("Fail to calloc"); + goto ERR; } - -ERR: - return ret; -} - -da_result_t request_to_resume_http_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t http_state = 0; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_LOGD(HTTPManager); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "[%d] http_state = %d", GET_STAGE_DL_ID(stage), http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_PAUSED: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_RESUME"); - ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_RESUME, - &q_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); - goto ERR; - } else { - DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); - Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), - q_event); - } - - break; - - case HTTP_STATE_REQUEST_PAUSE: - DA_LOG_ERR(HTTPManager, "[%d] Fail to resume. Previous pause is not finished. http_state = %d", GET_STAGE_DL_ID(stage), http_state); - ret = DA_ERR_INVALID_STATE; - - break; - - case HTTP_STATE_RESUMED: - ret = DA_ERR_ALREADY_RESUMED; - - break; - - default: - DA_LOG_ERR(HTTPManager, "[%d] Fail to resume. This is not a paused ID. http_state = %d", GET_STAGE_DL_ID(stage), http_state); - ret = DA_ERR_INVALID_STATE; - - break; + strncpy(field, user_request_header, len); + pos++; + while (*pos) + { + if (*pos != ' ') + break; + pos++; + } + len = strlen(pos) + 1; + value = (char *)calloc(1, len + 1); + if (!value) { + DA_LOGE("Fail to calloc"); + goto ERR; } + strncpy(value, pos, len); + *out_field = field; + *out_value = value; + DA_SECURE_LOGD("field[%s], value[%s]", field, value); + return; ERR: - return ret; + if (field) { + free(field); + field = NULL; + } + return; } -da_result_t start_new_transaction(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - ret = set_http_request_hdr(stage); - if (ret != DA_RESULT_OK) - return ret; - ret = make_transaction_info_and_start_transaction(stage); - return ret; -} - -da_result_t make_default_http_request_hdr(const char *url, - char **user_request_header, - int user_request_header_count, - http_msg_request_t **out_http_msg_request, - char *user_request_etag, - char *user_request_temp_file_path) +da_ret_t __set_http_request_hdr(req_info_t *req_info, http_info_t *http_info, file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; - + da_ret_t ret = DA_RESULT_OK; http_msg_request_t *http_msg_request = NULL; char *user_agent = NULL; + int count = 0; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); - if (!url) { - DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } + NULL_CHECK_RET(req_info); + NULL_CHECK_RET(http_info); + NULL_CHECK_RET(file_info); + NULL_CHECK_RET_OPT(req_info->url, DA_ERR_INVALID_URL); + count = req_info->req_header_count; ret = http_msg_request_create(&http_msg_request); if (ret != DA_RESULT_OK) goto ERR; - ret = http_msg_request_set_url(http_msg_request, url); + ret = http_msg_request_set_url(http_msg_request, req_info->url); if (ret != DA_RESULT_OK) goto ERR; - user_agent = get_user_agent(); - if (user_agent) - http_msg_request_add_field(http_msg_request, HTTP_FIELD_UAGENT, - user_agent); + ret = get_user_agent_string(&user_agent); + if (user_agent && ret == DA_RESULT_OK) + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_UAGENT, user_agent); + - http_msg_request_add_field(http_msg_request, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); - http_msg_request_add_field(http_msg_request, HTTP_FIELD_ACCEPT_CHARSET, "utf-8"); + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_ACCEPT_LANGUAGE, "en"); + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_ACCEPT_CHARSET, "utf-8"); - if (user_request_header && user_request_header_count > 0) { + if (req_info->req_header && count > 0) { int i = 0; - for (i = 0; i < user_request_header_count; i++) - { + for (i = 0; i < count; i++) { char *field = NULL; char *value = NULL; - __parsing_user_request_header(user_request_header[i], - &field, &value); + __parsing_user_request_header(req_info->req_header[i], + &field, &value); if (field && value) { http_msg_request_add_field(http_msg_request, field, value); if (field) { @@ -403,204 +227,348 @@ da_result_t make_default_http_request_hdr(const char *url, free(value); value= NULL; } - DA_LOG_ERR(HTTPManager, "Fail to parse user request header"); + DA_LOGE("Fail to parse user request header"); } } - } else - DA_LOG(HTTPManager, "no user reqeust header inserted"); - - if (user_request_etag) { + } + if (req_info->etag) { char buff[64] = {0,}; - unsigned long long size = 0; + da_size_t size = 0; http_msg_request_add_field(http_msg_request, - HTTP_FIELD_IF_RANGE, user_request_etag); - get_file_size(user_request_temp_file_path, &size); + HTTP_FIELD_IF_RANGE, req_info->etag); + get_file_size(req_info->temp_file_path, &size); +#ifdef _RAF_SUPPORT + file_info->file_size_of_temp_file = size; +#endif snprintf(buff, sizeof(buff)-1, "bytes=%llu-", size); http_msg_request_add_field(http_msg_request, - HTTP_FIELD_RANGE, buff); + HTTP_FIELD_RANGE, buff); } - *out_http_msg_request = http_msg_request; - + http_info->http_msg_request = http_msg_request; + free(user_agent); + return ret; ERR: - if (ret != DA_RESULT_OK) + if (http_msg_request) http_msg_request_destroy(&http_msg_request); - if (user_agent) - free(user_agent); + return ret; + } -da_result_t set_http_request_hdr(stage_info *stage) +da_ret_t __create_http_resume_hdr(req_info_t *req_info, http_info_t *http_info, + file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; - req_dl_info *request_info = DA_NULL; - - char *url = DA_NULL; - char **user_request_header = DA_NULL; - int user_request_header_count = 0; - char *user_request_etag = DA_NULL; - char *user_request_temp_file_path = DA_NULL; - http_msg_request_t* http_msg_request = NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); + da_ret_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + char *value = NULL; + char temp_size_str[32] = { 0, }; + char *etag_from_response = NULL; + char *date_from_response = NULL; + http_msg_response_t *first_response = NULL; + http_msg_request_t *resume_request = NULL; + http_msg_request_t *old_request = NULL; - request_info = GET_STAGE_TRANSACTION_INFO(stage); + DA_LOGV(""); - if (DA_NULL == - (url = GET_REQUEST_HTTP_REQ_URL(request_info))) { - DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); - ret = DA_ERR_INVALID_URL; + first_response = http_info->http_msg_response; + if (first_response) { + b_ret = http_msg_response_get_ETag(first_response, &value); + if (b_ret) { + etag_from_response = value; + value = NULL; + DA_SECURE_LOGD("[ETag][%s]", etag_from_response); + } + b_ret = http_msg_response_get_date(first_response, &value); + if (b_ret) { + date_from_response = value; + value = NULL; + DA_LOGV("[Date][%s]", date_from_response); + } + DA_SECURE_LOGD("downloaded_size[%u]", file_info->bytes_written_to_file); + snprintf(temp_size_str, sizeof(temp_size_str), "bytes=%llu-", + file_info->bytes_written_to_file); + DA_SECURE_LOGD("size str[%s]", temp_size_str); + free(first_response); + http_info->http_msg_response = DA_NULL; + } + old_request = http_info->http_msg_request; + free(old_request); + http_info->http_msg_request = DA_NULL; + + ret = __set_http_request_hdr(req_info, http_info, file_info); + if (ret != DA_RESULT_OK) goto ERR; - } - user_request_header = GET_REQUEST_HTTP_USER_REQUEST_HEADER( - request_info); - user_request_header_count = GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT( - request_info); - user_request_etag = GET_REQUEST_HTTP_USER_REQUEST_ETAG( - request_info); - user_request_temp_file_path = GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH( - request_info); - if (user_request_etag) { - DA_SECURE_LOGD("user_request_etag[%s]",user_request_etag); + resume_request = http_info->http_msg_request; + if (etag_from_response) { + http_msg_request_add_field(resume_request, HTTP_FIELD_IF_RANGE, + etag_from_response); } else { - DA_LOG_VERBOSE(HTTPManager, "user_request_etag is NULL"); + if (date_from_response) { + http_msg_request_add_field(resume_request, + HTTP_FIELD_IF_RANGE, date_from_response); + } } - ret = make_default_http_request_hdr(url, user_request_header, - user_request_header_count, &http_msg_request, - user_request_etag, user_request_temp_file_path); - if (ret == DA_RESULT_OK) - request_info->http_info.http_msg_request = http_msg_request; + + if (strlen(temp_size_str) > 0) + http_msg_request_add_field(resume_request, HTTP_FIELD_RANGE, + temp_size_str); ERR: + if (etag_from_response) { + free(etag_from_response); + etag_from_response = NULL; + } + if (date_from_response) { + free(date_from_response); + date_from_response = NULL; + } return ret; - } -da_result_t make_transaction_info_and_start_transaction(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - int slot_id = DA_INVALID_ID; - req_dl_info *request_info = DA_NULL; +da_ret_t __start_transaction(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info; + DA_LOGV(""); - input_for_tranx_t *input_for_tranx = DA_NULL; + if (!da_info) { + DA_LOGE("NULL CHECK!: da_info"); + return DA_ERR_INVALID_ARGUMENT; + } + http_info = da_info->http_info; + if (!http_info) { + DA_LOGE("NULL CHECK!: http_info"); + return DA_ERR_INVALID_ARGUMENT; + } + http_info->http_method = HTTP_METHOD_GET; + http_info->proxy_addr = get_proxy_address(); - DA_LOG_FUNC_LOGV(HTTPManager); + ret = PI_http_start(da_info); - slot_id = GET_STAGE_DL_ID(stage); + return ret; +} - request_info = GET_STAGE_TRANSACTION_INFO(stage); +da_ret_t __start_resume_transaction(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + ret = __create_http_resume_hdr(req_info, http_info, + file_info); + if (ret != DA_RESULT_OK) + return ret; - if (GET_REQUEST_HTTP_REQ_URL(request_info) == DA_NULL) { - DA_LOG_ERR(HTTPManager, "url is NULL"); - ret = DA_ERR_INVALID_URL; - goto ERR; + reset_http_info_for_resume(http_info); + if (file_info->file_path) { + req_info->temp_file_path = strdup(file_info->file_path); + } else { + DA_LOGE("file_path cannot be NULL in resume case"); + return DA_ERR_INVALID_ARGUMENT; } + ret = __start_transaction(da_info); + return ret; +} - input_for_tranx = (input_for_tranx_t*) calloc(1, - sizeof(input_for_tranx_t)); - if (input_for_tranx == DA_NULL) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } else { - input_for_tranx->proxy_addr = get_proxy_address(); - input_for_tranx->queue = GET_DL_QUEUE(slot_id); - input_for_tranx->http_method = PI_HTTP_METHOD_GET; - input_for_tranx->http_msg_request - = request_info->http_info.http_msg_request; +da_ret_t __start_new_transaction(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + + if (!da_info) { + DA_LOGE("NULL CHECK!: da_info"); + return DA_ERR_INVALID_ARGUMENT; } - ret = PI_http_start_transaction(input_for_tranx, - &(GET_REQUEST_HTTP_TRANS_ID(request_info))); + ret = __set_http_request_hdr(da_info->req_info, da_info->http_info, da_info->file_info); if (ret != DA_RESULT_OK) - goto ERR; - -ERR: - if (input_for_tranx) { - free(input_for_tranx); - input_for_tranx = DA_NULL; - } + return ret; + ret = __start_transaction(da_info); return ret; } -da_result_t make_req_dl_info_http(stage_info *stage, req_dl_info *out_info) +int __check_wait_for_auto_retry(http_info_t *http_info) { - char *url = DA_NULL; - char **user_request_header = DA_NULL; - int user_request_header_count = 0; - char *user_request_etag = DA_NULL; - char *user_request_temp_file_path = DA_NULL; - int dl_id = -1; - source_info_t *source_info = DA_NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if (!stage) { - DA_LOG_ERR(HTTPManager, "stage is NULL"); - return DA_ERR_INVALID_ARGUMENT; - } - - source_info = GET_STAGE_SOURCE_INFO(stage); - - url = source_info->source_info_type.source_info_basic->url; - user_request_header = - source_info->source_info_type.source_info_basic->user_request_header; - user_request_header_count = - source_info->source_info_type.source_info_basic->user_request_header_count; - dl_id = source_info->source_info_type.source_info_basic->dl_id; - user_request_etag = GET_DL_USER_ETAG(GET_STAGE_DL_ID(stage)); - user_request_temp_file_path = GET_DL_USER_TEMP_FILE_PATH(GET_STAGE_DL_ID(stage)); - - DA_SECURE_LOGD("url [%s]", url); - - if (url) { - GET_REQUEST_HTTP_REQ_URL(out_info) = url; - GET_REQUEST_HTTP_USER_REQUEST_HEADER(out_info) = user_request_header; - GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT(out_info) = - user_request_header_count; - GET_REQUEST_HTTP_USER_REQUEST_ETAG(out_info) = - user_request_etag; - GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(out_info) = - user_request_temp_file_path; + da_ret_t ret = DA_RESULT_OK; + struct timespec ts; + struct timeval tp; + NULL_CHECK_RET_OPT(http_info, 0); + gettimeofday(&tp, NULL); + ts.tv_sec = tp.tv_sec + DA_MAX_TIME_OUT; + ts.tv_nsec = tp.tv_usec * 1000; + DA_LOGI("Network Fail case, wait for a while"); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_WAIT_FOR_NET_ERR; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + ret = pthread_cond_timedwait(&(http_info->cond_http), + &(http_info->mutex_http), &ts); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + if (ret == ETIMEDOUT) { + DA_LOGI("Waiting is done by timeout"); + } else if (ret != 0) { + DA_LOGE("fail to pthread_cond_waittime[%d][%s]",ret, strerror(ret)); } else { - DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); - return DA_ERR_INVALID_URL; + DA_LOGI("Waiting is done by control"); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + DA_LOGI("http_state[%s]", __get_state_str(http_info->state)); + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + return 1; } - _da_thread_mutex_init(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)), NULL); - - return DA_RESULT_OK; + return 0; } -da_result_t pause_for_flow_control(stage_info *stage) +// In download thread +da_ret_t request_http_download(da_info_t *da_info) { - return DA_RESULT_OK; -} + da_ret_t ret = DA_RESULT_OK; + req_info_t *req_info = DA_NULL; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + da_bool_t need_wait = DA_TRUE; -da_result_t unpause_for_flow_control(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + __init_http_info(http_info); - DA_LOG_FUNC_LOGV(HTTPManager); + do { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s][%d]",__get_state_str(http_info->state), da_info->da_id); + switch (http_state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_REQUESTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = __start_new_transaction(da_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_LOGD("http_state[%s][%d]",__get_state_str(http_info->state), da_info->da_id); + http_info->error_code = ret; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (ret == DA_ERR_NETWORK_FAIL && http_state != HTTP_STATE_PAUSED) { + DA_LOGE("Network failed"); + if (__check_wait_for_auto_retry(http_info) == 1) + need_wait = DA_TRUE; + else + need_wait = DA_FALSE; + } + break; + case HTTP_STATE_REDIRECTED: + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_DOWNLOAD_STARTED: + case HTTP_STATE_DOWNLOADING: + case HTTP_STATE_REQUEST_PAUSE: + DA_LOGE("Cannot enter here:[%s][id]", + __get_state_str(http_info->state), da_info->da_id); + break; + case HTTP_STATE_REQUEST_CANCEL: + break; + case HTTP_STATE_REQUEST_RESUME: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + need_wait = DA_TRUE; + break; + case HTTP_STATE_CANCELED: + need_wait = DA_FALSE; + ret = DA_RESULT_USER_CANCELED; + break; + case HTTP_STATE_PAUSED: + DA_LOGD("error_code[%d]", http_info->error_code); + send_client_paused_info(da_info); + DA_LOGD("Waiting thread for paused state"); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + pthread_cond_wait(&(http_info->cond_http),&(http_info->mutex_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + DA_LOGD("Wake up thread due to resume"); + break; + case HTTP_STATE_RESUMED: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_REQUESTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = __start_resume_transaction(da_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (ret == DA_ERR_NETWORK_FAIL && http_state != HTTP_STATE_PAUSED) { + DA_LOGE("Network failed"); + if (__check_wait_for_auto_retry(http_info) == 1) + need_wait = DA_TRUE; + else + need_wait = DA_FALSE; + } + break; + case HTTP_STATE_DOWNLOAD_FINISH: + need_wait = DA_FALSE; + if (ret == DA_RESULT_OK) + ret = check_drm_convert(da_info->file_info); + break; + case HTTP_STATE_FAILED: + if (ret == DA_ERR_NETWORK_FAIL) { + if (__check_wait_for_auto_retry(http_info) == 1) + need_wait = DA_TRUE; + else + need_wait = DA_FALSE; + } else { + need_wait = DA_FALSE; + } + break; + case HTTP_STATE_ABORTED: + need_wait = DA_FALSE; + break; + default: + break; + } + } while (need_wait == DA_TRUE); + DA_LOGD("Final http_state[%s][%d] err[%d]",__get_state_str(http_info->state), da_info->da_id, ret); + if (http_info->state != HTTP_STATE_PAUSED) + send_client_finished_info(da_info ,ret); + DA_LOGI("=== Exiting http_download ret[%d] ===", ret); + return ret; +} - PI_http_unpause_transaction( - GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage))); +da_ret_t __disconnect_transaction(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGD(""); + ret = PI_http_disconnect(http_info); return ret; } -da_result_t handle_event_abort(stage_info *stage) + +da_ret_t __handle_event_abort(http_info_t *http_info) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; http_state_t state = 0; - DA_LOG_FUNC_LOGD(HTTPManager); + DA_LOGD(""); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGV("http_state[%s]", __get_state_str(state)); - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); switch (state) { case HTTP_STATE_READY_TO_DOWNLOAD: case HTTP_STATE_REDIRECTED: @@ -614,632 +582,406 @@ da_result_t handle_event_abort(stage_info *stage) case HTTP_STATE_PAUSED: case HTTP_STATE_RESUMED: case HTTP_STATE_ABORTED: + case HTTP_STATE_WAIT_FOR_NET_ERR: /* IF the network session is terminated due to some error, * the state can be aborted.(data aborted case) */ - CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_ABORTED, stage); - _disconnect_transaction(stage); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_ABORTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + __disconnect_transaction(http_info); break; case HTTP_STATE_DOWNLOAD_FINISH: break; default: - DA_LOG_ERR(HTTPManager, "have to check the flow for this case"); + DA_LOGE("Cannot enter here"); break; } return ret; } -da_result_t handle_event_cancel(stage_info *stage) +da_ret_t __check_enough_memory(http_info_t *http_info, char *user_install_path) { - da_result_t ret = DA_RESULT_OK; - http_state_t state = 0; + da_ret_t ret = DA_RESULT_OK; + da_size_t cont_len = 0; + char *dir_path = DA_DEFAULT_INSTALL_PATH_FOR_PHONE; + + DA_LOGV(""); + NULL_CHECK_RET(http_info); + cont_len = http_info->content_len_from_header; + if (cont_len > 0) { + if (user_install_path) + dir_path = user_install_path; + ret = get_available_memory(dir_path, cont_len); + } + return ret; +} - DA_LOG_FUNC_LOGD(HTTPManager); +da_ret_t request_to_abort_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + ret = __handle_event_abort(da_info->http_info); + return ret; +} - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - switch (state) { +da_ret_t request_to_cancel_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + switch (http_state) { case HTTP_STATE_READY_TO_DOWNLOAD: - CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); + ret = PI_http_cancel(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (da_info->thread_id > 0) { + if (pthread_cancel(da_info->thread_id) != 0) { + DA_LOGE("Fail to cancel thread id[%d] err[%s]", + da_info->thread_id, strerror(errno)); + } else { + DA_LOGI("====Exit thread with cancel:da_id[%d]===", + da_info->da_id); + } + } + break; + case HTTP_STATE_WAIT_FOR_NET_ERR: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + DA_COND_SIGNAL(&(http_info->cond_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); break; - case HTTP_STATE_PAUSED: - discard_download(stage); - CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); + reset_http_info(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); break; - case HTTP_STATE_DOWNLOAD_REQUESTED: case HTTP_STATE_DOWNLOAD_STARTED: case HTTP_STATE_DOWNLOADING: case HTTP_STATE_REQUEST_RESUME: case HTTP_STATE_RESUMED: - _cancel_transaction(stage); - CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_CANCEL, stage); + ret = PI_http_cancel(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_REQUEST_CANCEL; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); break; - case HTTP_STATE_DOWNLOAD_FINISH: + ret = DA_ERR_INVALID_STATE; break; - case HTTP_STATE_REQUEST_CANCEL: - DA_LOG(HTTPManager, "HTTP_STATE_REQUEST_CANCEL : cancel is already in progress... "); + DA_LOGV("cancel is already in progress... "); + ret = DA_ERR_INVALID_STATE; break; - default: - DA_LOG_ERR(HTTPManager, "have to check the flow for this case"); + ret = DA_ERR_INVALID_STATE; + DA_LOGE("Cannot enter here"); break; } - return ret; } -da_result_t handle_event_suspend(stage_info *stage) +da_ret_t request_to_suspend_http_download(da_info_t *da_info) { - da_result_t ret = DA_RESULT_OK; + + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; http_state_t http_state = 0; - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); switch (http_state) { + case HTTP_STATE_PAUSED: case HTTP_STATE_REQUEST_PAUSE: - DA_LOG(HTTPManager, "already requested to pause! do nothing"); + DA_LOGI("Already paused. http_state[%s]", __get_state_str(http_state)); + ret = DA_ERR_ALREADY_SUSPENDED; break; - case HTTP_STATE_READY_TO_DOWNLOAD: - CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage); - send_client_paused_info(GET_STAGE_DL_ID(stage)); + DA_LOGE("Download has not been started yet"); + ret = DA_ERR_INVALID_STATE; + break; + case HTTP_STATE_WAIT_FOR_NET_ERR: + DA_LOGD("error_code[%d]", http_info->error_code); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_PAUSED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + DA_COND_SIGNAL(&(http_info->cond_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); break; - default: - //send_client_paused_info(GET_STAGE_DL_ID(stage)); - _cancel_transaction(stage); - GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) = DA_RESULT_OK; - DA_LOG_CRITICAL(HTTPManager, "[%d] cleanup internal error", GET_STAGE_DL_ID(stage)); - CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_PAUSE,stage); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_REQUEST_PAUSE; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("error_code[%d]", http_info->error_code); + if (http_info->error_code != DA_ERR_NETWORK_FAIL) + ret = PI_http_pause(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_PAUSED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; } - return ret; } -da_result_t handle_event_resume(stage_info *stage) +da_ret_t request_to_resume_http_download(da_info_t *da_info) { - da_result_t ret = DA_RESULT_OK; - http_msg_request_t *resume_request = NULL; - + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; http_state_t http_state = 0; + int retry_count = 0; - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + DA_LOGV(""); - if (http_state != HTTP_STATE_PAUSED) { - DA_LOG_ERR(HTTPManager, "Not HTTP_STATE_PAUSED! http_state = %d", http_state); - ret = DA_ERR_INVALID_STATE; - goto ERR; - } - - GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) = DA_RESULT_OK; - DA_LOG_CRITICAL(HTTPManager, "[%d] cleanup internal error", GET_STAGE_DL_ID(stage)); - - CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_RESUME,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); - - ret = create_resume_http_request_hdr(stage, &resume_request); - if (ret != DA_RESULT_OK) - goto ERR; - - if (GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request) - free(GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request); - - GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request - = resume_request; - - make_transaction_info_and_start_transaction(stage); - -ERR: - return ret; - -} - -da_result_t create_resume_http_request_hdr(stage_info *stage, - http_msg_request_t **out_resume_request) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - - req_dl_info *request_info = NULL; - - http_msg_response_t *first_response = NULL; - http_msg_request_t *resume_request = NULL; - - char *value = NULL; - char *url = NULL; - unsigned int downloaded_data_size = 0; - char downloaded_data_size_to_str[32] = { 0, }; - - char *etag_from_response = NULL; - char *date_from_response = NULL; - - DA_LOG_FUNC_LOGD(HTTPManager); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - - if (!(url = GET_REQUEST_HTTP_REQ_URL(GET_STAGE_TRANSACTION_INFO(stage)))) { - DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - first_response = request_info->http_info.http_msg_response; - if (first_response) { - b_ret = http_msg_response_get_ETag(first_response, &value); - if (b_ret) { - etag_from_response = value; - value = NULL; - DA_SECURE_LOGD("[ETag][%s]", etag_from_response); - } + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); - b_ret = http_msg_response_get_date(first_response, &value); - if (b_ret) { - date_from_response = value; - value = NULL; - DA_SECURE_LOGD("[Date][%s]", date_from_response); - } + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); - downloaded_data_size - = GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)); - DA_LOG(HTTPManager, "downloaded_data_size = %u", downloaded_data_size); - snprintf(downloaded_data_size_to_str, sizeof(downloaded_data_size_to_str), "bytes=%u-", - downloaded_data_size); - DA_LOG(HTTPManager, "downloaded_data_size_to_str = %s", downloaded_data_size_to_str); - } - - ret = make_default_http_request_hdr(url, NULL, 0, &resume_request, NULL, NULL); - if (ret != DA_RESULT_OK) - goto ERR; + switch (http_state) { + case HTTP_STATE_PAUSED: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_RESUMED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("Wake up thread for paused state"); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + DA_COND_SIGNAL(&(http_info->cond_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + DA_LOGD("error_code[%d]", http_info->error_code); + if (http_info->error_code != DA_ERR_NETWORK_FAIL) { + ret = PI_http_unpause(http_info); + if (ret != DA_RESULT_OK) + PI_http_cancel(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOADING; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); - if (etag_from_response) { - http_msg_request_add_field(resume_request, HTTP_FIELD_IF_RANGE, - etag_from_response); - } else { - if (date_from_response) { - http_msg_request_add_field(resume_request, - HTTP_FIELD_IF_RANGE, date_from_response); } - } - - if (strlen(downloaded_data_size_to_str) > 0) - http_msg_request_add_field(resume_request, HTTP_FIELD_RANGE, - downloaded_data_size_to_str); - - *out_resume_request = resume_request; - -ERR: - if (etag_from_response) { - free(etag_from_response); - etag_from_response = NULL; - } - - if (date_from_response) { - free(date_from_response); - date_from_response = NULL; - } - - return ret; -} - -da_result_t handle_any_input(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - int slot_id = GET_STAGE_DL_ID(stage); - - queue_t *queue = DA_NULL; - q_event_t *event = DA_NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); - - queue = GET_DL_QUEUE(slot_id); - - Q_pop_event(queue, &event); - if (event == DA_NULL) { - DA_LOG_DEBUG(HTTPManager, "There is no data on the queue!"); - return DA_RESULT_OK; - } - - switch (event->event_type) { - case Q_EVENT_TYPE_CONTROL: - ret = handle_event_control(stage, event); break; - - case Q_EVENT_TYPE_DATA_HTTP: - ret = handle_event_http(stage, event); + case HTTP_STATE_REQUEST_PAUSE: + DA_LOGD("Waiting to handle pause request"); + do { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (http_state == HTTP_STATE_PAUSED) { + DA_LOGD("Change to paused state"); + ret = PI_http_unpause(http_info); + break; + } + retry_count++; + } while(retry_count < 10000); + if (ret != DA_RESULT_OK || retry_count >= 10000) + PI_http_cancel(http_info); break; - - case Q_EVENT_TYPE_DATA_DRM: + case HTTP_STATE_RESUMED: + ret = DA_ERR_ALREADY_RESUMED; break; - default: + DA_LOGE("Fail to resume. Invalid state check. http_state[%s]", + __get_state_str(http_state)); + ret = DA_ERR_INVALID_STATE; + // If resume is failed due to invalid state, the previous pause should be canceled. + PI_http_cancel(http_info); break; } - Q_destroy_q_event(&event); - return ret; } -da_result_t handle_event_control(stage_info *stage, q_event_t *event) +da_ret_t __check_resume_download_is_available( + req_info_t *req_info, http_info_t *http_info, file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_LOGD(HTTPManager); - - if (event->event_type == Q_EVENT_TYPE_CONTROL) { - switch (event->type.q_event_control.control_type) { - case Q_EVENT_TYPE_CONTROL_CANCEL: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_CANCEL"); - ret = handle_event_cancel(stage); - break; - - case Q_EVENT_TYPE_CONTROL_SUSPEND: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_SUSPEND"); - ret = handle_event_suspend(stage); - break; - - case Q_EVENT_TYPE_CONTROL_RESUME: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_RESUME"); - ret = handle_event_resume(stage); - break; - case Q_EVENT_TYPE_CONTROL_ABORT: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_ABORT"); - ret = handle_event_abort(stage); - break; - /* Fixme: need to think how we use this type. For now, this type is not used. */ - case Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED"); - break; - case Q_EVENT_TYPE_CONTROL_NONE: - default: - DA_LOG_ERR(HTTPManager, "Cannot enter here"); - break; - } - } - - return ret; -} + da_ret_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + char *origin_ETag = NULL; + char *new_ETag = NULL; + da_size_t remained_content_len = 0; + char *value = NULL; + da_size_t size = 0; + char *temp_file_path = DA_NULL; + char *dir_path = DA_DEFAULT_INSTALL_PATH_FOR_PHONE; -da_result_t handle_event_http(stage_info *stage, q_event_t *event) -{ - da_result_t ret = DA_RESULT_OK; - q_event_data_http_t *q_event_data_http = DA_NULL; + DA_LOGV(""); - DA_LOG_FUNC_LOGV(HTTPManager); + origin_ETag = req_info->etag; - if (event->event_type == Q_EVENT_TYPE_DATA_HTTP) { - q_event_data_http = &(event->type.q_event_data_http); - switch (q_event_data_http->data_type) { - case Q_EVENT_TYPE_DATA_PACKET: - ret = handle_event_http_packet(stage, event); - break; - case Q_EVENT_TYPE_DATA_FINAL: - DA_LOG_VERBOSE(HTTPManager, "Q_EVENT_TYPE_DATA_FINAL"); - ret = handle_event_http_final(stage, event); - break; - case Q_EVENT_TYPE_DATA_ABORT: - DA_LOG_VERBOSE(HTTPManager, "Q_EVENT_TYPE_DATA_ABORT"); - ret = handle_event_http_abort(stage, event); - break; - } + b_ret = http_msg_response_get_content_length(http_info->http_msg_response, + &size); + if (b_ret) { + remained_content_len = size; + size = 0; + DA_SECURE_LOGD("remained_content_len[%llu]", remained_content_len); } - return ret; -} - -da_result_t handle_event_http_packet(stage_info *stage, q_event_t *event) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t is_handle_hdr_success = DA_TRUE; - q_event_data_http_t *received_data = DA_NULL; - DA_LOG_FUNC_LOGV(HTTPManager); - - received_data = &(event->type.q_event_data_http); - - if (received_data->http_response_msg) { - ret = handle_http_hdr(stage, received_data->http_response_msg, - received_data->http_response_msg->status_code); - if (DA_RESULT_OK != ret) { - is_handle_hdr_success = DA_FALSE; - } - - received_data->http_response_msg = NULL; + b_ret = http_msg_response_get_ETag(http_info->http_msg_response, &value); + if (b_ret) { + new_ETag = value; + value = NULL; + DA_SECURE_LOGD("new ETag[%s]", new_ETag); + } else { + goto ERR; } - if (received_data->body_len > 0) { - if (is_handle_hdr_success == DA_TRUE) { - ret = handle_http_body(stage, received_data->body_data, - received_data->body_len); - } - /*For all cases body_data should be deleted*/ - free(received_data->body_data); - received_data->body_data = DA_NULL; + if (origin_ETag && new_ETag && + 0 != strncmp(origin_ETag, new_ETag, strlen(new_ETag))) { + DA_LOGE("ETag is not identical! revoke!"); + /* FIXME Later : Need to detail error exception handling */ + ret = DA_ERR_NETWORK_FAIL; + /*ret = DA_ERR_MISMATCH_HTTP_HEADER; */ + goto ERR; } - return ret; -} - -da_result_t handle_event_http_final(stage_info *stage, q_event_t *event) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t http_state = 0; - int slot_id = DA_INVALID_ID; - int http_status = 0; - q_event_data_http_t *received_data = DA_NULL; - - - DA_LOG_FUNC_LOGV(HTTPManager); - - slot_id = GET_STAGE_DL_ID(stage); - _disconnect_transaction(stage); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_REDIRECTED: - CHANGE_HTTP_STATE(HTTP_STATE_READY_TO_DOWNLOAD,stage); - break; - - case HTTP_STATE_DOWNLOAD_REQUESTED: - DA_LOG(HTTPManager, "case HTTP_STATE_DOWNLOAD_REQUESTED"); - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage); - /* Most of http status is decided when got headers. - * But it is ignored for credential url when got headers in case of 401 status code. - * So, when the download is finished, it means unauthorized error if the status code has still 401. - */ - received_data = &(event->type.q_event_data_http); - http_status = received_data->status_code; - if (http_status == 401) { - store_http_status(slot_id, http_status); - ret = DA_ERR_NETWORK_FAIL; - } - break; - - case HTTP_STATE_DOWNLOADING: - DA_LOG_VERBOSE(HTTPManager, "case HTTP_STATE_DOWNLOADING"); - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) { - discard_download(stage); - goto ERR; - } - /* Sometimes, the server can send "0" byte package data although whole data are not sent. - * At that case, the libsoup call finished callback function with 200 Ok. - * Only if the DA know content size form response header, it can check the error or not - */ - ret = _check_downloaded_file_size_is_same_with_header_content_size(stage); - if(ret != DA_RESULT_OK) { - discard_download(stage) ; - goto ERR; - } - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage); - send_client_update_progress_info( - slot_id, - GET_DL_ID(slot_id), - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - ); - break; - - case HTTP_STATE_REQUEST_PAUSE: - if (GET_CONTENT_STORE_FILE_HANDLE(GET_STAGE_CONTENT_STORE_INFO(stage))) { - ret = file_write_complete(stage); - - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)) - = DA_FALSE; - - send_client_update_progress_info( - slot_id, - GET_DL_ID(slot_id), - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - ); - - } - CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage); - send_client_paused_info(GET_STAGE_DL_ID(stage)); - DA_LOG(HTTPManager, "Server Notification code is set to NULL"); - break; - - case HTTP_STATE_ABORTED: - case HTTP_STATE_CANCELED: - discard_download(stage); - break; - case HTTP_STATE_REQUEST_CANCEL: - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) - goto ERR; - discard_download(stage); - CHANGE_HTTP_STATE(HTTP_STATE_CANCELED, stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); - break; - - default: - ret = file_write_complete(stage); + if (remained_content_len > 0) { + if (req_info->install_path) + dir_path = req_info->install_path; + ret = get_available_memory(dir_path, remained_content_len); if (ret != DA_RESULT_OK) goto ERR; - discard_download(stage); - CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage); - break; } -ERR: - /* When file complete is failed */ - if (DA_RESULT_OK != ret) { - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage); + if (!http_info->content_type_from_header) { + b_ret = http_msg_response_get_content_type(http_info->http_msg_response, + &value); + if (b_ret) { + http_info->content_type_from_header = value; + value = NULL; + DA_SECURE_LOGD("Content-Type[%s]", + http_info->content_type_from_header); + } } - return ret; -} - -da_result_t handle_event_http_abort(stage_info *stage, q_event_t *event) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t http_state = 0; - DA_LOG_FUNC_LOGD(HTTPManager); - - GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) - = event->type.q_event_data_http.error_type; - DA_LOG_CRITICAL(HTTPManager, "set internal error code : [%d]", GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))); - _disconnect_transaction(stage); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_REQUEST_PAUSE: - CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage); - send_client_paused_info(GET_STAGE_DL_ID(stage)); - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) - goto ERR; - break; - - case HTTP_STATE_REQUEST_CANCEL: - CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) - goto ERR; - discard_download(stage); - break; - - default: - CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage); - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) - goto ERR; - discard_download(stage); - break; + temp_file_path = req_info->temp_file_path; + if (!temp_file_path) { + DA_LOGE("Temporary file path cannot be NULL"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; } + get_file_size(temp_file_path, &size); + http_info->content_len_from_header = remained_content_len + size; + DA_SECURE_LOGD("Content-Length[%llu]", http_info->content_len_from_header); ERR: + if (new_ETag) { + free(new_ETag); + new_ETag = DA_NULL; + } return ret; } -da_result_t handle_http_hdr(stage_info *stage, - http_msg_response_t *http_msg_response, int http_status) -{ - da_result_t ret = DA_RESULT_OK; - int slot_id = DA_INVALID_ID; - http_state_t http_state = 0; - - DA_LOG_FUNC_LOGV(HTTPManager); - - slot_id = GET_STAGE_DL_ID(stage); - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG_DEBUG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_DOWNLOAD_REQUESTED: - case HTTP_STATE_REQUEST_PAUSE: - case HTTP_STATE_REQUEST_RESUME: - case HTTP_STATE_REDIRECTED: - ret = handle_http_status_code(stage, http_msg_response, - http_status); - if (ret != DA_RESULT_OK) - goto ERR; - break; +da_ret_t __check_content_type_is_matched(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *content_type_from_server = DA_NULL; - case HTTP_STATE_REQUEST_CANCEL: - DA_LOG(HTTPManager, "Cancel is in progress.. http_state = %d", http_state); - break; + DA_LOGV(""); - default: - DA_LOG_ERR(HTTPManager, "http_state = %d", http_state); - goto ERR; + content_type_from_server = http_info->content_type_from_header; + if (content_type_from_server == DA_NULL) { + DA_LOGV("http header has no Content-Type field, no need to compare"); + return DA_RESULT_OK; } - -ERR: return ret; } -da_result_t handle_http_status_code(stage_info *stage, - http_msg_response_t *http_msg_response, int http_status) +da_ret_t __handle_http_status_code(http_info_t *http_info, + file_info_t *file_info, req_info_t *req_info) { - da_result_t ret = DA_RESULT_OK; - - int slot_id = DA_INVALID_ID; - req_dl_info *request_info = DA_NULL; + da_ret_t ret = DA_RESULT_OK; http_state_t http_state = 0; + http_msg_response_t *http_msg_response = DA_NULL; + char *location = DA_NULL; + char *if_range_str = DA_NULL; + char *range_str = DA_NULL; + int http_status = 0; - DA_LOG_FUNC_LOGV(HTTPManager); - - slot_id = GET_STAGE_DL_ID(stage); - request_info = GET_STAGE_TRANSACTION_INFO(stage); - - GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_response - = http_msg_response; - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG_VERBOSE(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - store_http_status(slot_id, http_status); - + NULL_CHECK_RET(http_info); + NULL_CHECK_RET(file_info); + NULL_CHECK_RET(req_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + http_msg_response = http_info->http_msg_response; + NULL_CHECK_RET(http_msg_response); + http_status = http_msg_response->status_code; switch (http_status) { case 200: case 201: case 202: case 203: +// Although expecting 206, 200 response is received. Remove temporary file and reset file info + if (http_info->http_msg_request && + http_msg_request_get_if_range(http_info->http_msg_request, &if_range_str) == DA_TRUE && + http_msg_request_get_range(http_info->http_msg_request, &range_str) == DA_TRUE) { + DA_LOGI("Server do not support if-range option"); + clean_paused_file(file_info); + } + free(if_range_str); + free(range_str); if (http_state == HTTP_STATE_REQUEST_RESUME) - clean_paused_file(stage); - ret = set_hdr_fields_on_download_info(stage); - if (ret != DA_RESULT_OK) - goto ERR; - ret = _check_content_type_is_matched(stage); + clean_paused_file(file_info); + ret = __check_content_type_is_matched(http_info); if (ret != DA_RESULT_OK) goto ERR; - ret = _check_enough_memory_for_this_download(stage); + ret = __check_enough_memory(http_info, req_info->install_path); if (ret != DA_RESULT_OK) goto ERR; - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_STARTED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); // ? + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_STARTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); break; case 206: - DA_LOG(HTTPManager, "HTTP Status is %d - Partial download for resume!",http_status); + DA_LOGV("HTTP Status is %d - Partial download for resume!", http_status); /* The resume can be started with start API. * So the state should be not HTTP_STATE_RESUME_REQUESTED but HTTP_STATE_DOWNLOAD_REQUESTED*/ if (http_state == HTTP_STATE_DOWNLOAD_REQUESTED) { - ret = _check_resume_download_is_available(stage, - http_msg_response); + ret = __check_resume_download_is_available(req_info, http_info, file_info); if (ret != DA_RESULT_OK) goto ERR; - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_STARTED,stage); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_STARTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); } else if (http_state == HTTP_STATE_REQUEST_RESUME) { - ret = _check_this_partial_download_is_available(stage, - http_msg_response); - if (ret != DA_RESULT_OK) - goto ERR; - CHANGE_HTTP_STATE(HTTP_STATE_RESUMED,stage); + ///FIXME later : how get previous response header + ///ret = __check_this_partial_download_is_available(http_info, + /// previous_ http_msg_response); + //if (ret != DA_RESULT_OK) + //goto ERR; + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_RESUMED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); } else { - DA_LOG_ERR(HTTPManager, "This download is not resumed, revoke"); + DA_LOGE("This download is not resumed, revoke"); ret = DA_ERR_INVALID_STATE; goto ERR; } - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); break; case 300: @@ -1249,13 +991,17 @@ da_result_t handle_http_status_code(stage_info *stage, case 305: case 306: case 307: - DA_LOG(HTTPManager, "HTTP Status is %d - redirection!",http_status); - ret = exchange_url_from_header_for_redirection(stage, http_msg_response); - if (ret != DA_RESULT_OK) - goto ERR; - CHANGE_HTTP_STATE(HTTP_STATE_REDIRECTED,stage); + DA_LOGV("HTTP Status is %d - redirection!",http_status); + if (http_msg_response_get_location(http_msg_response, &location)) { + DA_SECURE_LOGD("location = %s\n", location); + http_info->location_url = location; + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + } + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_REDIRECTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); http_msg_response_destroy(&http_msg_response); - request_info->http_info.http_msg_response = DA_NULL; + http_info->http_msg_response = DA_NULL; break; case 100: @@ -1263,7 +1009,9 @@ da_result_t handle_http_status_code(stage_info *stage, case 102: case 204: case 304: - DA_LOG(HTTPManager, "HTTP Status is %d - 204 means server got the request, but no content to reply back, 304 means not modified!",http_status); + DA_LOGV("HTTP Status is %d - 204 server got the request, \ + but no content to reply back, \ + 304 means not modified!", http_status); ret = DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT; break; @@ -1271,9 +1019,9 @@ da_result_t handle_http_status_code(stage_info *stage, case 503: case 504: default: - GET_REQUEST_HTTP_RESULT(request_info) - = DA_ERR_UNREACHABLE_SERVER; - DA_LOG_CRITICAL(HTTPManager, "set internal error code : DA_ERR_UNREACHABLE_SERVER [%d]", DA_ERR_UNREACHABLE_SERVER); +/// GET_REQUEST_HTTP_RESULT(request_info) +/// = DA_ERR_UNREACHABLE_SERVER; + DA_LOGI("set internal error code : DA_ERR_UNREACHABLE_SERVER"); break; } @@ -1281,533 +1029,491 @@ ERR: return ret; } -da_result_t exchange_url_from_header_for_redirection(stage_info *stage, - http_msg_response_t *http_msg_response) +da_ret_t __check_before_downloading(da_info_t *da_info, http_state_t state) { - da_result_t ret = DA_RESULT_OK; - char *location = DA_NULL; - - DA_LOG_FUNC_LOGD(HTTPManager); - - if (http_msg_response_get_location(http_msg_response, &location)) { - DA_SECURE_LOGD("location = %s\n", location); - GET_REQUEST_HTTP_REQ_LOCATION(GET_STAGE_TRANSACTION_INFO(stage)) = location; + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + file_info_t *file_info = DA_NULL; + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + DA_LOGD("state:%s",__get_state_str(state)); + // resume case + if (req_info->temp_file_path && file_info->bytes_written_to_file > 0) { + ret = start_file_append(file_info); + } else if (state == HTTP_STATE_DOWNLOAD_STARTED) { + ret = start_file_writing(da_info); + } else { + DA_LOGE("Cannot enter here!"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; } + if (DA_RESULT_OK != ret) + goto ERR; + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOADING; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = send_client_update_dl_info(da_info); +ERR: return ret; } -da_result_t handle_http_body(stage_info *stage, char *body, int body_len) +da_ret_t __handle_event_http_header(http_raw_data_t *raw_data, da_info_t *da_info) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; http_state_t http_state = 0; - int slot_id = DA_INVALID_ID; - - DA_LOG_FUNC_LOGV(HTTPManager); - - slot_id = GET_STAGE_DL_ID(stage); - - if (DA_RESULT_OK - != GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))) { - DA_LOG_CRITICAL(HTTPManager, "ignore because internal error code is set with [%d]", - GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))); - return ret; - } - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - if (http_state == HTTP_STATE_DOWNLOAD_STARTED) { - // resume case - if (GET_REQUEST_HTTP_USER_REQUEST_ETAG(GET_STAGE_TRANSACTION_INFO(stage))) - ret = start_file_writing_append_with_new_download(stage); - else - ret = start_file_writing(stage); - if (DA_RESULT_OK != ret) - goto ERR; - - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOADING, stage); - send_client_update_dl_info( - slot_id, - GET_DL_ID(slot_id), - GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_PURE_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage)), - GET_CONTENT_STORE_EXTENSION(GET_STAGE_CONTENT_STORE_INFO(stage)) - ); - } else if (http_state == HTTP_STATE_RESUMED) { - ret = start_file_writing_append(stage); - if (DA_RESULT_OK != ret) + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + http_msg_response_t *http_msg_response = DA_NULL; + da_size_t size = 0; + char *mime_type = DA_NULL; + char *etag = DA_NULL; + char *file_name = DA_NULL; + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + NULL_CHECK_RET(raw_data); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGV("http_state[%s]", __get_state_str(http_state)); + http_msg_response = http_info->http_msg_response; + switch (http_state) { + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_REQUEST_PAUSE: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_REDIRECTED: + http_msg_response_get_content_length(http_msg_response, &size); + http_info->content_len_from_header = size; + http_msg_response_get_content_type(http_msg_response, &mime_type); + http_info->content_type_from_header = mime_type; + if (mime_type) + file_info->mime_type = strdup(mime_type); + http_msg_response_get_ETag(http_msg_response, &etag); + http_info->etag_from_header = etag; + http_msg_response_get_content_disposition( + http_msg_response, DA_NULL, &file_name); + http_info->file_name_from_header = file_name; + ret = __handle_http_status_code(http_info, file_info, req_info); + if (ret != DA_RESULT_OK) { + DA_LOGE("Fail to handle http status code"); goto ERR; + } +#ifdef _RAF_SUPPORT + char *val = NULL; + http_msg_response_get_RAF_mode(http_msg_response, &val); + if (!val) { + DA_LOGE("Fail to raf mode value from response header"); + } else { + DA_LOGI("[RAF] val[%s:%s]", HTTP_FIELD_RAF_MODE, val); + if (strncmp(val, "yes", strlen("yes")) == 0) { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_STARTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = __check_before_downloading(da_info, http_info->state); + if (ret != DA_RESULT_OK) { + free(val); + goto ERR; + } + http_info->is_raf_mode_confirmed = DA_TRUE; + ret = PI_http_set_file_name_to_curl(http_info->http_msg, file_info->file_path); + if (ret != DA_RESULT_OK) { + DA_LOGE("Fail to set file name to curl"); + free(val); + goto ERR; + } + } + free(val); + } +#endif + break; + case HTTP_STATE_REQUEST_CANCEL: + DA_LOGV("Cancel is in progress.. http_state[%s]", + __get_state_str(http_state)); + break; - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOADING,stage); - send_client_update_dl_info( - slot_id, - GET_DL_ID(slot_id), - GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_PURE_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage)), - GET_CONTENT_STORE_EXTENSION(GET_STAGE_CONTENT_STORE_INFO(stage)) - ); + default: + DA_LOGE("http_state[%s]", __get_state_str(http_state)); + goto ERR; } - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); +ERR: + if (ret != DA_RESULT_OK) { + DA_LOGE("Request to cancel due to error[%d]", ret); + PI_http_cancel(http_info); + http_info->error_code = ret; + discard_download(file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_FAILED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } + free(raw_data); + return ret; +} + +da_ret_t __handle_event_http_packet(http_raw_data_t *raw_data, da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + time_t t; + struct tm *lc_time; + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + NULL_CHECK_RET(raw_data); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); switch (http_state) { + case HTTP_STATE_DOWNLOAD_STARTED: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + ret = __check_before_downloading(da_info, http_state); + if (ret != DA_RESULT_OK) + goto ERR; + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + ret = send_client_update_progress_info(da_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = HTTP_STATE_DOWNLOADING; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_RESUMED: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + __check_before_downloading(da_info, http_state); + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + ret = send_client_update_progress_info(da_info); + break; case HTTP_STATE_REDIRECTED: - DA_LOG(HTTPManager, "Just ignore http body, because this body is not for redirection one."); + DA_LOGV("http_state[%s]", __get_state_str(http_state)); break; - case HTTP_STATE_DOWNLOADING: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif /* Should this function before updating download info * Because it extract mime type at once only if first download updating at client */ - ret = file_write_ongoing(stage, body, body_len); + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); if (ret != DA_RESULT_OK) goto ERR; - if ((DA_TRUE == - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)))) { - - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)) - = DA_FALSE; - send_client_update_progress_info( - slot_id, - GET_DL_ID(slot_id), - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - ); - +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + // send event every 1 second. + if ((t = time(DA_NULL)) > 0) { + if ((lc_time = localtime(&t)) != DA_NULL) { + if (da_info->update_time != lc_time->tm_sec) { + da_info->update_time = lc_time->tm_sec; + ret = send_client_update_progress_info(da_info); + } + } else { + DA_LOGE("Fail to call localtime[%s]",strerror(errno)); + ret = send_client_update_progress_info(da_info); + } + } else { + DA_LOGE("Fail to call time[%s]",strerror(errno)); + ret = send_client_update_progress_info(da_info); } break; - case HTTP_STATE_REQUEST_PAUSE: - ret = file_write_ongoing(stage, body, body_len); +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + DA_LOGV("http_state[%s]", __get_state_str(http_state)); + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); if (ret != DA_RESULT_OK) goto ERR; - break; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + break; default: - DA_LOG(HTTPManager, "Do nothing! http_state is in case %d", http_state); - + DA_LOGE("Do nothing! http_state is in case[%s]", + __get_state_str(http_state)); goto ERR; } - -ERR: - return ret; -} - -/* Function should be renamed , as it is actually not setting the header fields in download info */ -da_result_t set_hdr_fields_on_download_info(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - - req_dl_info *request_info = DA_NULL; - http_msg_response_t *http_msg_response = NULL; - - char *value = NULL; - unsigned long long size = 0; - - DA_LOG_FUNC_LOGV(HTTPManager); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - - http_msg_response - = request_info->http_info.http_msg_response; - if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "There is no header data!!"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - b_ret = http_msg_response_get_content_type(http_msg_response, &value); - if (b_ret) { - GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info) = value; - value = NULL; -// DA_SECURE_LOGD("[Content-Type][%s] - stored", GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info)); - } - - b_ret = http_msg_response_get_content_length(http_msg_response, - &size); - if (b_ret) { - GET_REQUEST_HTTP_HDR_CONT_LEN(request_info) = size; - size = 0; - } - - b_ret = http_msg_response_get_ETag(http_msg_response, &value); - if (b_ret) { - GET_REQUEST_HTTP_HDR_ETAG(request_info) = value; - value = NULL; - DA_SECURE_LOGD("[ETag][%s] - stored ", GET_REQUEST_HTTP_HDR_ETAG(request_info)); - } - ERR: + if (ret != DA_RESULT_OK) { + DA_LOGE("Request to cancel due to error[%d]", ret); + PI_http_cancel(http_info); + http_info->error_code = ret; + discard_download(da_info->file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_FAILED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } + if (raw_data->body) + free(raw_data->body); + free(raw_data); return ret; } -da_result_t _check_content_type_is_matched(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - req_dl_info *request_info = DA_NULL; - source_info_t *source_info = DA_NULL; - char *content_type_from_server = DA_NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - source_info = GET_STAGE_SOURCE_INFO(stage); - - content_type_from_server = GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info); - if (content_type_from_server == DA_NULL) { - DA_LOG(HTTPManager, "http header has no Content-Type field, no need to compare"); - return DA_RESULT_OK; - } - - return ret; -} - -da_result_t _check_enough_memory_for_this_download(stage_info *stage) +da_ret_t __check_file_size_with_header_content_size(file_info_t *file_info) { - da_result_t ret = DA_RESULT_OK; - - req_dl_info *request_info = DA_NULL; - - unsigned long long cont_len = 0; - da_storage_size_t memory; + da_ret_t ret = DA_RESULT_OK; + unsigned long long tmp_file_size = 0; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); - memset(&memory, 0x00, sizeof(da_storage_size_t)); - request_info = GET_STAGE_TRANSACTION_INFO(stage); + if (file_info->file_size > 0) { - cont_len = (unsigned long long) GET_REQUEST_HTTP_HDR_CONT_LEN(request_info); - if (cont_len) { - ret = get_available_memory(&memory); - if (DA_RESULT_OK == ret) { - DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %llu", - memory.b_available,memory.b_size, cont_len); - if (memory.b_available < ((cont_len - + (unsigned long long)SAVE_FILE_BUFFERING_SIZE_50KB) - / (unsigned long long)memory.b_size)) /* 50KB buffering */ - { - ret = DA_ERR_DISK_FULL; - goto ERR; - } +#ifdef _ENABLE_OMA_DRM + if (is_content_drm_dm(file_info->mime_type)) { + /* FIXME Later : How can get the file size of DRM file. */ + return ret; } - } - -ERR: - return ret; -} - -da_result_t _check_this_partial_download_is_available(stage_info *stage, - http_msg_response_t *new_http_msg_response) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - char *origin_ETag = NULL; - char *new_ETag = NULL; - unsigned long long remained_content_len = 0; - da_storage_size_t memory; - char *value = NULL; - unsigned long long size = 0; - - DA_LOG_FUNC_LOGD(HTTPManager); - - origin_ETag - = GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage)); - - b_ret = http_msg_response_get_content_length(new_http_msg_response, - &size); - if (b_ret) { - remained_content_len = size; - size = 0; - DA_LOG(HTTPManager, "[remained_content_len][%lu]", remained_content_len); - } - - b_ret = http_msg_response_get_ETag(new_http_msg_response, &value); - if (b_ret) { - new_ETag = value; - value = NULL; - DA_SECURE_LOGD("[new ETag][%s]", new_ETag); - } else { - goto ERR; - } +#endif - if (origin_ETag && new_ETag && - 0 != strncmp(origin_ETag, new_ETag, strlen(new_ETag))) { - DA_LOG_ERR(HTTPManager, "ETag is not identical! revoke!"); - /* FIXME Later : Need to detail error exception handling */ - ret = DA_ERR_NETWORK_FAIL; - /*ret = DA_ERR_MISMATCH_HTTP_HEADER; */ - goto ERR; - } + get_file_size(file_info->file_path, &tmp_file_size); - if (remained_content_len) { - ret = get_available_memory(&memory); - if (DA_RESULT_OK == ret) { - DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %llu", - memory.b_available,memory.b_size, remained_content_len); - if (memory.b_available < ((remained_content_len - + SAVE_FILE_BUFFERING_SIZE_50KB) - / memory.b_size)) /* 50KB buffering */ - { - ret = DA_ERR_DISK_FULL; - goto ERR; - } + if (tmp_file_size != file_info->file_size) { + DA_SECURE_LOGE("Real file size[%llu], MISMATCH CONTENT SIZE", + tmp_file_size); + ret = DA_ERR_MISMATCH_CONTENT_SIZE; } } - -ERR: - if (new_ETag) { - free(new_ETag); - new_ETag = DA_NULL; - } - return ret; } -da_result_t _check_resume_download_is_available(stage_info *stage, - http_msg_response_t *new_http_msg_response) +da_ret_t __handle_event_http_final(http_raw_data_t *raw_data, da_info_t *da_info) { - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - char *origin_ETag = NULL; - char *new_ETag = NULL; - unsigned long long remained_content_len = 0; - da_storage_size_t memory; - char *value = NULL; - unsigned long long size = 0; - char *temp_file_path = DA_NULL; - req_dl_info *request_info = DA_NULL; + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; - DA_LOG_FUNC_LOGD(HTTPManager); + DA_LOGV(""); - request_info = GET_STAGE_TRANSACTION_INFO(stage); - origin_ETag - = GET_REQUEST_HTTP_USER_REQUEST_ETAG(request_info); + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + NULL_CHECK_RET(raw_data); - b_ret = http_msg_response_get_content_length(new_http_msg_response, - &size); - if (b_ret) { - remained_content_len = size; - size = 0; - DA_LOG(HTTPManager, "[remained_content_len][%lu]", remained_content_len); - } + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); - b_ret = http_msg_response_get_ETag(new_http_msg_response, &value); - if (b_ret) { - new_ETag = value; - value = NULL; - DA_SECURE_LOGD("[new ETag][%s]", new_ETag); - } else { - goto ERR; - } - - if (origin_ETag && new_ETag && - 0 != strncmp(origin_ETag, new_ETag, strlen(new_ETag))) { - DA_LOG_ERR(HTTPManager, "ETag is not identical! revoke!"); - /* FIXME Later : Need to detail error exception handling */ - ret = DA_ERR_NETWORK_FAIL; - /*ret = DA_ERR_MISMATCH_HTTP_HEADER; */ - goto ERR; - } - - if (remained_content_len) { - ret = get_available_memory(&memory); - if (DA_RESULT_OK == ret) { - DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %llu", - memory.b_available,memory.b_size, remained_content_len); - if (memory.b_available < ((remained_content_len - + SAVE_FILE_BUFFERING_SIZE_50KB) - / memory.b_size)) /* 50KB buffering */ - { - ret = DA_ERR_DISK_FULL; - goto ERR; - } + switch (http_state) { + case HTTP_STATE_REDIRECTED: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOAD_REQUESTED: + DA_LOGV("case HTTP_STATE_DOWNLOAD_REQUESTED"); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_FINISH; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOADING: + DA_LOGD("case HTTP_STATE_DOWNLOADING"); +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); } - } - b_ret = http_msg_response_get_content_type(new_http_msg_response, &value); - if (b_ret) { - GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info) = value; - value = NULL; - DA_SECURE_LOGD("[Content-Type][%s]", - GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info)); - } - temp_file_path = GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(request_info); - get_file_size(temp_file_path, &size); - GET_REQUEST_HTTP_HDR_CONT_LEN(request_info) = remained_content_len + size; - DA_SECURE_LOGD("[Content-Length][%llu]", - GET_REQUEST_HTTP_HDR_CONT_LEN(request_info)); - - -ERR: - if (new_ETag) { - free(new_ETag); - new_ETag = DA_NULL; - } - - return ret; -} - - -da_result_t _check_downloaded_file_size_is_same_with_header_content_size( - stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - req_dl_info *request_info = DA_NULL; - file_info *file_info_data = DA_NULL; - - char *real_file_path = DA_NULL; - unsigned long long content_size_from_real_file = 0; - unsigned long long content_size_from_http_header = 0; - - DA_LOG_FUNC_LOGD(HTTPManager); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - - content_size_from_http_header - = GET_CONTENT_STORE_FILE_SIZE(file_info_data); - - if (content_size_from_http_header > 0) { - real_file_path - = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data); - - get_file_size(real_file_path, - &content_size_from_real_file); - - if (content_size_from_real_file - != content_size_from_http_header) { - DA_SECURE_LOGE("size from header = %llu, real size = %llu,\ - DA_ERR_MISMATCH_CONTENT_SIZE", - content_size_from_http_header, content_size_from_real_file); - ret = DA_ERR_MISMATCH_CONTENT_SIZE; +#else + ret = file_write_complete(file_info); +#endif + if (ret != DA_RESULT_OK) { + discard_download(file_info); + goto ERR; + } + ret = __check_file_size_with_header_content_size(file_info); + if(ret != DA_RESULT_OK) { + discard_download(file_info) ; + goto ERR; + } + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_FINISH; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = send_client_update_progress_info(da_info); + break; + case HTTP_STATE_REQUEST_PAUSE: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + if (file_info->file_handle) + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + if (file_info->file_handle) { + ret = file_write_complete(file_info); +// send_client_update_progress_info(da_info); + } +#endif + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_PAUSED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGV("Server Notification code is set to NULL"); + break; + case HTTP_STATE_ABORTED: + case HTTP_STATE_CANCELED: + discard_download(file_info); + break; + case HTTP_STATE_REQUEST_CANCEL: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + ret = file_write_complete(file_info); +#endif + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_PAUSED: + DA_LOGD("Remain paused stated"); + break; + default: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); } +#else + ret = file_write_complete(file_info); +#endif + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_FAILED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; } - return ret; -} - -da_result_t _disconnect_transaction(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - int transaction_id = DA_INVALID_ID; - - DA_LOG_FUNC_LOGV(HTTPManager); - - transaction_id - = GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)); - - DA_LOG(HTTPManager, "transaction_id = %d slot_id = %d", transaction_id, GET_STAGE_DL_ID(stage)); - - if (transaction_id != DA_INVALID_ID) { - ret = PI_http_disconnect_transaction(transaction_id); - GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)) - = DA_INVALID_ID; +ERR: + /* When file complete is failed */ + if (DA_RESULT_OK != ret) { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_FINISH; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); } - + if (raw_data->body) + free(raw_data->body); + free(raw_data); return ret; } -da_result_t _cancel_transaction(stage_info *stage) +void __http_update_cb(http_raw_data_t *data, void *user_param) { - da_result_t ret = DA_RESULT_OK; - int transaction_id = DA_INVALID_ID; - - DA_LOG_FUNC_LOGD(HTTPManager); - - transaction_id - = GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)); - - DA_LOG(HTTPManager, "transaction_id = %d", transaction_id); - - if (transaction_id != DA_INVALID_ID) { - http_state_t state = 0; - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - state = GET_HTTP_STATE_ON_STAGE(stage); - if (state <= HTTP_STATE_DOWNLOAD_REQUESTED) { - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - ret = PI_http_cancel_transaction(transaction_id, DA_TRUE); - } else { - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - ret = PI_http_cancel_transaction(transaction_id, DA_FALSE); - } - + http_raw_data_t *raw_data = DA_NULL; + da_info_t *da_info = DA_NULL; + if (!data || !user_param) { + DA_LOGE("NULL CHECK!: data, user_param"); + return; + } + DA_LOGV(""); + raw_data = data; + da_info = (da_info_t *)user_param; + + switch(data->type) { + case HTTP_EVENT_GOT_HEADER: + __handle_event_http_header(raw_data, da_info); + break; + case HTTP_EVENT_GOT_PACKET: + __handle_event_http_packet(raw_data, da_info); + break; + case HTTP_EVENT_FINAL: + __handle_event_http_final(raw_data, da_info); + break; +/* + case HTTP_EVENT_ABORT: + ret = __handle_event_http_abort(raw_data, da_info); + break; +*/ } - return ret; } -void __parsing_user_request_header(char *user_request_header, - char **out_field, char **out_value) +da_bool_t is_stopped_state(da_info_t *da_info) { - int len = 0; - char *pos = NULL; - char *temp_pos = NULL; - char *field = NULL; - char *value = NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if (!user_request_header) { - DA_LOG_ERR(HTTPManager, "user_request_header is NULL"); - goto ERR; - } - - pos = strchr(user_request_header, ':'); - if (!pos) { - DA_LOG_ERR(HTTPManager, "Fail to parse"); - goto ERR; - } - temp_pos = (char *)user_request_header; - while (*temp_pos) - { - if (temp_pos == pos || *temp_pos == ' ') { - len = temp_pos - user_request_header; - break; - } - temp_pos++; - } - if (len < 1) { - DA_LOG_ERR(HTTPManager, "Wrong field name"); - goto ERR; - } - field = (char *)calloc(1, len + 1); - if (!field) { - DA_LOG_ERR(HTTPManager, "Fail to calloc"); - goto ERR; - } - strncpy(field, user_request_header, len); - pos++; - while (*pos) - { - if (*pos != ' ') - break; - pos++; - } - len = strlen(pos) + 1; - value = (char *)calloc(1, len + 1); - if (!value) { - DA_LOG_ERR(HTTPManager, "Fail to calloc"); - goto ERR; - } - strncpy(value, pos, len); - *out_field = field; - *out_value = value; - DA_SECURE_LOGD("field[%s], value[%s]", field, value); - - return; -ERR: - if (field) { - free(field); - field = NULL; + http_info_t *http_info = DA_NULL; + http_state_t http_state; + NULL_CHECK_RET_OPT(da_info, DA_FALSE); + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, DA_FALSE); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + switch (http_state) { + case HTTP_STATE_REQUEST_CANCEL: + case HTTP_STATE_CANCELED: + case HTTP_STATE_FAILED: + case HTTP_STATE_ABORTED: + //case HTTP_STATE_REQUEST_PAUSE: + //case HTTP_STATE_REQUEST_RESUME: + //case HTTP_STATE_WAIT_FOR_NET_ERR: + return DA_TRUE; + default: + return DA_FALSE; } - return; + return DA_FALSE; } - diff --git a/agent/download-agent-http-misc.c b/agent/download-agent-http-misc.c deleted file mode 100755 index 08cd8ec..0000000 --- a/agent/download-agent-http-misc.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 "download-agent-http-misc.h" -#include "download-agent-debug.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-plugin-conf.h" -#include "download-agent-client-mgr.h" - -#define DEFAULT_HTTP_ACCEPT_HEADERS \ - "Accept-Language: en\r\n" \ - "Accept-Charset: utf-8\r\n" \ - - -char *get_user_agent() -{ - char *uagent_str = DA_NULL; - - DA_LOG_FUNC_LOGV(Default); - - uagent_str = get_client_user_agent_string(); - if (!uagent_str) { - da_result_t ret = DA_RESULT_OK; - ret = get_user_agent_string(&uagent_str); - if (ret != DA_RESULT_OK) - return NULL; - } - return uagent_str; -} - -da_bool_t is_supporting_protocol(const char *protocol) -{ - if((protocol == NULL) || (1 > strlen(protocol))) - { - return DA_FALSE; - } - - if(!strcasecmp(protocol, "http")) - { - return DA_TRUE; - } - else if(!strcasecmp(protocol, "https")) - { - return DA_TRUE; - } - else - { - return DA_FALSE; - } - -} diff --git a/agent/download-agent-http-msg-handler.c b/agent/download-agent-http-msg-handler.c index 6064c37..231a61d 100755 --- a/agent/download-agent-http-msg-handler.c +++ b/agent/download-agent-http-msg-handler.c @@ -20,20 +20,19 @@ #include "download-agent-http-msg-handler.h" #include "download-agent-debug.h" -#include "download-agent-http-misc.h" #include "download-agent-encoding.h" // '.' and ';' are request from Vodafone -#define IS_TERMINATING_CHAR(c) ( ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) -#define IS_TERMINATING_CHAR_EX(c) ( ((c) == '"') || ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) -#define IS_URI_TERMINATING_CHAR(c) ( ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) +#define IS_TERMINATING_CHAR(c) ( ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) +#define IS_TERMINATING_CHAR_EX(c) ( ((c) == '"') || ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) +#define IS_URI_TERMINATING_CHAR(c) ( ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) enum parsing_type { WITH_PARSING_OPTION, WITHOUT_PARSING_OPTION }; -static da_result_t __http_header_add_field(http_header_t **head, +static da_ret_t __http_header_add_field(http_header_t **head, const char *field, const char *value, enum parsing_type type); static void __http_header_destroy_all_field(http_header_t **head); static da_bool_t __get_http_header_for_field( @@ -41,29 +40,27 @@ static da_bool_t __get_http_header_for_field( http_header_t **out_header); static void __exchange_header_value(http_header_t *header, const char *in_raw_value); - static http_header_options_t *__create_http_header_option(const char *field, const char *value); static void __http_header_destroy_all_option(http_header_options_t **head); static da_bool_t __get_http_header_option_for_field( http_header_options_t *header_option, const char *in_field, char **out_value); - static http_header_options_t *__parsing_N_create_option_str(char *org_str); static http_header_options_t *__parsing_options(char *org_str); static void __parsing_raw_value(http_header_t *http_header); -da_result_t http_msg_request_create(http_msg_request_t **http_msg_request) +da_ret_t http_msg_request_create(http_msg_request_t **http_msg_request) { http_msg_request_t *temp_http_msg_request = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); +// DA_LOGV(""); temp_http_msg_request = (http_msg_request_t *)calloc(1, sizeof(http_msg_request_t)); if (!temp_http_msg_request) { *http_msg_request = NULL; - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return DA_ERR_FAIL_TO_MEMALLOC; } @@ -73,7 +70,7 @@ da_result_t http_msg_request_create(http_msg_request_t **http_msg_request) temp_http_msg_request->http_body = NULL; *http_msg_request = temp_http_msg_request; - DA_LOG_DEBUG(HTTPManager, "http_msg_request: %x", (unsigned int)(*http_msg_request)); + DA_LOGV( "http_msg_request: %x", (unsigned int)(*http_msg_request)); return DA_RESULT_OK; } @@ -82,99 +79,54 @@ void http_msg_request_destroy(http_msg_request_t **http_msg_request) { http_msg_request_t *temp_http_msg_request = *http_msg_request; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); if (temp_http_msg_request) { if (temp_http_msg_request->http_method) { free(temp_http_msg_request->http_method); temp_http_msg_request->http_method = NULL; } - if (temp_http_msg_request->url) { free(temp_http_msg_request->url); temp_http_msg_request->url = NULL; } - if (temp_http_msg_request->http_body) { free(temp_http_msg_request->http_body); temp_http_msg_request->http_body = NULL; } - __http_header_destroy_all_field(&(temp_http_msg_request->head)); - free(temp_http_msg_request); *http_msg_request = NULL; } - -} - -da_result_t http_msg_request_set_method(http_msg_request_t *http_msg_request, - const char *method) -{ - DA_LOG_FUNC_LOGD(HTTPManager); - - if (!http_msg_request || !method) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - // ToDo: check method is valid - - http_msg_request->http_method = strdup(method); - - DA_LOG(HTTPManager, "http method : %s", http_msg_request->http_method); - - return DA_RESULT_OK; -} - -da_result_t http_msg_request_get_method(http_msg_request_t *http_msg_request, - const char **method) -{ - DA_LOG_FUNC_LOGV(HTTPManager); - - if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - if (http_msg_request->http_method) { - *method = http_msg_request->http_method; - return DA_RESULT_OK; - } else { - *method = DA_NULL; - return DA_ERR_INVALID_ARGUMENT; - } } -da_result_t http_msg_request_set_url(http_msg_request_t *http_msg_request, +da_ret_t http_msg_request_set_url(http_msg_request_t *http_msg_request, const char *url) { - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } if (!url) { - DA_LOG_ERR(HTTPManager, "url is NULL; DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("url is NULL; DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_URL; } http_msg_request->url = strdup(url); - - //DA_SECURE_LOGD("http url : %s", http_msg_request->url); - + DA_SECURE_LOGI("http url[%s]", http_msg_request->url); return DA_RESULT_OK; } -da_result_t http_msg_request_get_url(http_msg_request_t *http_msg_request, +da_ret_t http_msg_request_get_url(http_msg_request_t *http_msg_request, const char **url) { - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } @@ -187,76 +139,34 @@ da_result_t http_msg_request_get_url(http_msg_request_t *http_msg_request, } } -da_result_t http_msg_request_set_body(http_msg_request_t *http_msg_request, - const char *body) -{ - DA_LOG_FUNC_LOGV(HTTPManager); - - if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - if (!body) - return DA_RESULT_OK; - - http_msg_request->http_body = strdup(body); - - DA_SECURE_LOGD("http body : %s", http_msg_request->http_body); - - return DA_RESULT_OK; -} - -da_result_t http_msg_request_get_body(http_msg_request_t *http_msg_request, - const char **body) -{ - DA_LOG_FUNC_LOGV(HTTPManager); - - if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - if (http_msg_request->http_body) { - *body = http_msg_request->http_body; - return DA_RESULT_OK; - } else { - *body = DA_NULL; - return DA_ERR_INVALID_ARGUMENT; - } -} - -/* FIXME later : check to free filed and value after this API is called */ -da_result_t http_msg_request_add_field(http_msg_request_t *http_msg_request, +da_ret_t http_msg_request_add_field(http_msg_request_t *http_msg_request, const char *field, const char *value) { - DA_LOG_FUNC_LOGV(HTTPManager); + // DA_LOGV(""); if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("Check NULL! : http_msg_request"); return DA_ERR_INVALID_ARGUMENT; } return __http_header_add_field(&(http_msg_request->head), field, value, WITHOUT_PARSING_OPTION); } -da_result_t http_msg_response_create(http_msg_response_t **http_msg_response) +da_ret_t http_msg_response_create(http_msg_response_t **http_msg_response) { http_msg_response_t *temp_http_msg_response = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); temp_http_msg_response = (http_msg_response_t *)calloc(1, sizeof(http_msg_response_t)); if (!temp_http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return DA_ERR_FAIL_TO_MEMALLOC; } else { temp_http_msg_response->status_code = 0; temp_http_msg_response->head = NULL; - *http_msg_response = temp_http_msg_response; - return DA_RESULT_OK; } } @@ -265,59 +175,27 @@ void http_msg_response_destroy(http_msg_response_t **http_msg_response) { http_msg_response_t *temp_http_msg_response = *http_msg_response; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); if (temp_http_msg_response) { __http_header_destroy_all_field(&(temp_http_msg_response->head)); - free(temp_http_msg_response); *http_msg_response = DA_NULL; } } -da_result_t http_msg_response_set_status_code( - http_msg_response_t *http_msg_response, int status_code) -{ - DA_LOG_FUNC_LOGV(HTTPManager); - - if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - http_msg_response->status_code = status_code; - - return DA_RESULT_OK; -} - -da_result_t http_msg_response_get_status_code( - http_msg_response_t *http_msg_response, int *status_code) -{ - DA_LOG_FUNC_LOGD(HTTPManager); - - if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - *status_code = http_msg_response->status_code; - - return DA_RESULT_OK; -} - -da_result_t http_msg_response_add_field(http_msg_response_t *http_msg_response, +da_ret_t http_msg_response_add_field(http_msg_response_t *http_msg_response, const char *field, const char *value) { - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } - return __http_header_add_field(&(http_msg_response->head), field, value, WITH_PARSING_OPTION); } -da_result_t __http_header_add_field(http_header_t **head, +da_ret_t __http_header_add_field(http_header_t **head, const char *field, const char *value, enum parsing_type type) { http_header_t *pre = NULL; @@ -365,7 +243,7 @@ da_result_t __http_header_add_field(http_header_t **head, else *head = cur; } else { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return DA_ERR_FAIL_TO_MEMALLOC; } @@ -377,8 +255,6 @@ void __http_header_destroy_all_field(http_header_t **head) http_header_t *pre = NULL; http_header_t *cur = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); - cur = *head; while (cur) { @@ -386,25 +262,21 @@ void __http_header_destroy_all_field(http_header_t **head) free(cur->field); cur->field = DA_NULL; } - if (cur->value) { free(cur->value); cur->value = DA_NULL; } - if (cur->raw_value) { free(cur->raw_value); cur->raw_value = DA_NULL; } - __http_header_destroy_all_option(&(cur->options)); - + free(cur->options); + cur->options = DA_NULL; pre = cur; cur = cur->next; - free(pre); } - *head = DA_NULL; } @@ -418,13 +290,10 @@ http_header_options_t *__create_http_header_option(const char *field, if (option) { if (field) option->field = strdup(field); - if (value) option->value = strdup(value); - option->next = NULL; } - return option; } @@ -433,38 +302,34 @@ void __http_header_destroy_all_option(http_header_options_t **head) http_header_options_t *pre = NULL; http_header_options_t *cur = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + // DA_LOGV(""); cur = *head; while (cur) { if (cur->field) { - DA_LOG_VERBOSE("field= %s", cur->field); + DA_SECURE_LOGD("field= %s", cur->field); free(cur->field); cur->field = DA_NULL; } - if (cur->value) { free(cur->value); cur->value = DA_NULL; } - pre = cur; cur = cur->next; - free(pre); } - *head = DA_NULL; } -da_result_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, +da_ret_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, http_msg_iter_t *http_msg_iter) { - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } @@ -473,17 +338,15 @@ da_result_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, return DA_RESULT_OK; } -da_result_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, +da_ret_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, http_msg_iter_t *http_msg_iter) { if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } *http_msg_iter = http_msg_response->head; - // DA_LOG_VERBOSE(HTTPManager, "retrieve iter = 0x%x", (unsigned int)http_msg_iter); - return DA_RESULT_OK; } @@ -492,16 +355,12 @@ da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter, { http_header_t *cur = *http_msg_iter; - // DA_LOG_VERBOSE(HTTPManager, "getting iter = 0x%x", (unsigned int)cur); - if (cur) { *out_field = cur->field; *out_value = cur->value; *http_msg_iter = cur->next; - return DA_TRUE; } else { - // DA_LOG_VERBOSE(HTTPManager, "end of iter"); return DA_FALSE; } } @@ -511,16 +370,12 @@ da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter, { http_header_t *cur = *http_msg_iter; - // DA_LOG_VERBOSE(HTTPManager, "getting iter = 0x%x", (unsigned int)cur); - if (cur) { *out_field = cur->field; *out_header = cur; *http_msg_iter = cur->next; - return DA_TRUE; } else { - // DA_LOG_VERBOSE(HTTPManager, "end of iter"); return DA_FALSE; } } @@ -531,21 +386,18 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) char *option_value = NULL; int option_field_len = 0; int option_value_len = 0; - char *org_pos = NULL; int org_str_len = 0; - char *working_str = NULL; char *working_pos = NULL; char *working_pos_field_start = NULL; char *working_pos_value_start = NULL; - da_bool_t is_inside_quotation = DA_FALSE; da_bool_t is_working_for_field = DA_TRUE; int i = 0; http_header_options_t *option = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + // DA_LOGV(""); if (!org_str) return NULL; @@ -564,7 +416,6 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) for (i = 0; i < org_str_len; i++) { if (*org_pos == '"') is_inside_quotation = !is_inside_quotation; - if (is_inside_quotation) { // Leave anything including blank if it is inside of double quotation mark. *working_pos = *org_pos; @@ -580,7 +431,6 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) is_working_for_field = DA_FALSE; working_pos_value_start = working_pos; } - org_pos++; } else { *working_pos = *org_pos; @@ -598,21 +448,19 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) strncpy(option_field, working_pos_field_start, option_field_len); } - if (option_value_len > 0 && working_pos_value_start) { option_value = (char *)calloc(1, option_value_len + 1); if (option_value) strncpy(option_value, working_pos_value_start, option_value_len); } - if (working_str) { free(working_str); working_pos = working_str = NULL; } -// DA_SECURE_LOGD("option_field = [%s], option_value = [%s]", -// option_field, option_value); + DA_SECURE_LOGD("option_field = [%s], option_value = [%s]", + option_field, option_value); if (option_field || option_value) { option = __create_http_header_option( @@ -621,7 +469,6 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) free(option_field); option_field = NULL; } - if (option_value) { free(option_value); option_value = NULL; @@ -632,7 +479,7 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) http_header_options_t *__parsing_options(char *org_str) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; http_header_options_t *head = NULL; http_header_options_t *pre = NULL; http_header_options_t *cur = NULL; @@ -643,7 +490,7 @@ http_header_options_t *__parsing_options(char *org_str) char *wanted_str_end = NULL; char *cur_pos = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); if (!org_str) return NULL; @@ -662,11 +509,10 @@ http_header_options_t *__parsing_options(char *org_str) wanted_str_end = org_str + strlen(org_str); cur_pos = NULL; } - wanted_str_len = wanted_str_end - wanted_str_start; wanted_str = (char *)calloc(1, wanted_str_len + 1); if (!wanted_str) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); ret = DA_ERR_FAIL_TO_MEMALLOC; goto ERR; } @@ -688,7 +534,6 @@ http_header_options_t *__parsing_options(char *org_str) ERR: if (ret != DA_RESULT_OK) __http_header_destroy_all_option(&head); - return head; } @@ -696,10 +541,8 @@ void __parsing_raw_value(http_header_t *http_header_field) { char *raw_value = NULL; char *option_str_start = NULL; - char *trimed_value = NULL; int trimed_value_len = 0; - char *trimed_value_start = NULL; char *trimed_value_end = NULL; @@ -710,7 +553,6 @@ void __parsing_raw_value(http_header_t *http_header_field) return; trimed_value_start = raw_value; - trimed_value_end = strchr(raw_value, ';'); if (!trimed_value_end) { // No options @@ -722,10 +564,9 @@ void __parsing_raw_value(http_header_t *http_header_field) // for trimed value trimed_value_len = trimed_value_end - trimed_value_start; - trimed_value = (char *)calloc(1, trimed_value_len + 1); if (!trimed_value) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return; } strncpy(trimed_value, trimed_value_start, trimed_value_len); @@ -733,18 +574,15 @@ void __parsing_raw_value(http_header_t *http_header_field) // for option parsing option_str_start = trimed_value_end + 1; - http_header_field->options = __parsing_options(option_str_start); /////////////// show http_header_options_t *cur = NULL; - cur = http_header_field->options; while (cur) { // DA_SECURE_LOGD("field = [%s], value = [%s]", cur->field, cur->value); cur = cur->next; } - } da_bool_t __get_http_header_option_for_field( @@ -753,10 +591,10 @@ da_bool_t __get_http_header_option_for_field( { http_header_options_t *cur = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + // DA_LOGV(""); if (!header_option) { - DA_LOG_ERR(HTTPManager, "input header_option is NULL."); + DA_LOGE("input header_option is NULL."); return DA_FALSE; } @@ -773,7 +611,6 @@ da_bool_t __get_http_header_option_for_field( } cur = cur->next; } - return DA_FALSE; } @@ -784,12 +621,33 @@ da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response, http_header_t *header = NULL; char *field = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + //DA_LOGV(""); http_msg_response_get_iter(http_msg_response, &http_msg_iter); while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) { if (field && header && !strncasecmp(field, in_field, strlen(field))) { -// DA_SECURE_LOGD("[%s][%s]", field, header->value); + //DA_SECURE_LOGD("[%s][%s]", field, header->value); + *out_header = header; + return DA_TRUE; + } + } + + return DA_FALSE; +} + +da_bool_t __get_http_req_header_for_field(http_msg_request_t *http_msg_request, + const char *in_field, http_header_t **out_header) +{ + http_msg_iter_t http_msg_iter; + http_header_t *header = NULL; + char *field = NULL; + + //DA_LOGV(""); + + http_msg_request_get_iter(http_msg_request, &http_msg_iter); + while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) { + if (field && header && !strncasecmp(field, in_field, strlen(field))) { + //DA_SECURE_LOGD("[%s][%s]", field, header->value); *out_header = header; return DA_TRUE; } @@ -800,7 +658,7 @@ da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response, void __exchange_header_value(http_header_t *header, const char *in_raw_value) { - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); if (!header || !in_raw_value) return; @@ -811,7 +669,6 @@ void __exchange_header_value(http_header_t *header, const char *in_raw_value) free(header->value); header->value = DA_NULL; } - if (header->raw_value) free(header->raw_value); header->raw_value = strdup(in_raw_value); @@ -825,15 +682,14 @@ da_bool_t http_msg_response_get_content_type( da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); - b_ret = __get_http_header_for_field(http_msg_response, "Content-Type", - &header); + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_CONTENT_TYPE, &header); if (!b_ret) { - DA_LOG(HTTPManager, "no Content-Type"); + DA_LOGV("no Content-Type"); return DA_FALSE; } - if (out_type) *out_type = strdup(header->value); @@ -846,13 +702,13 @@ void http_msg_response_set_content_type(http_msg_response_t *http_msg_response, da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); if (!http_msg_response || !in_type) return; - b_ret = __get_http_header_for_field(http_msg_response, "Content-Type", - &header); + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_CONTENT_TYPE, &header); if (b_ret) { if (header->raw_value && (!strncmp(header->raw_value, in_type, strlen(header->raw_value)))) @@ -862,22 +718,22 @@ void http_msg_response_set_content_type(http_msg_response_t *http_msg_response, __exchange_header_value(header, in_type); } else { __http_header_add_field(&(http_msg_response->head), - "Content-Type", in_type, WITH_PARSING_OPTION); + HTTP_FIELD_CONTENT_TYPE, in_type, WITH_PARSING_OPTION); } } da_bool_t http_msg_response_get_content_length( - http_msg_response_t *http_msg_response, unsigned long long *out_length) + http_msg_response_t *http_msg_response, da_size_t *out_length) { da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); b_ret = __get_http_header_for_field(http_msg_response, - "Content-Length", &header); + HTTP_FIELD_CONTENT_LENGTH, &header); if (!b_ret) { - DA_LOG(HTTPManager, "no Content-Length"); + DA_LOGV( "no Content-Length"); return DA_FALSE; } @@ -894,32 +750,29 @@ da_bool_t http_msg_response_get_content_disposition( da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; char *file_name = NULL; - char *wanted_str = NULL; char *wanted_str_start = NULL; char *wanted_str_end = NULL; char *decoded_str = NULL; int wanted_str_len = 0; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); b_ret = __get_http_header_for_field(http_msg_response, - "Content-Disposition", &header); + HTTP_FIELD_CONTENT_DISPOSITION, &header); if (!b_ret) { - DA_LOG_VERBOSE(HTTPManager, "no Content-Disposition"); + DA_LOGV( "no Content-Disposition"); return DA_FALSE; } - if (out_disposition) *out_disposition = strdup(header->value); - if (!out_file_name) return DA_FALSE; b_ret = __get_http_header_option_for_field(header->options, "filename", &file_name); if (!b_ret) { - DA_LOG(HTTPManager, "no option"); + DA_LOGV( "no option"); return DA_FALSE; } @@ -936,14 +789,14 @@ da_bool_t http_msg_response_get_content_disposition( wanted_str_len = wanted_str_end - wanted_str_start; wanted_str = (char*)calloc(1, wanted_str_len + 1); if (!wanted_str) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return DA_FALSE; } strncpy(wanted_str, wanted_str_start, wanted_str_len); b_ret = is_base64_encoded_word(wanted_str); if (b_ret) { - DA_LOG(HTTPManager, "It's base64 encoded-word string"); + DA_LOGV("It's base64 encoded-word string"); if (DA_RESULT_OK == decode_base64_encoded_str( wanted_str, &decoded_str)) { DA_SECURE_LOGD("base64 decoded str = [%s]", decoded_str); @@ -951,10 +804,10 @@ da_bool_t http_msg_response_get_content_disposition( wanted_str = decoded_str; decoded_str = NULL; } else { - DA_LOG(HTTPManager, "Fail to base64 decode. Just use un-decoded string."); + DA_LOGV("Fail to base64 decode. Just use un-decoded string."); } } else { - DA_LOG(HTTPManager, "It's NOT base64 encoded-word string"); + DA_LOGV("It's NOT base64 encoded-word string"); } decode_url_encoded_str(wanted_str, &decoded_str); /* If it is url encoded string */ @@ -964,14 +817,11 @@ da_bool_t http_msg_response_get_content_disposition( wanted_str = decoded_str; decoded_str = NULL; } - *out_file_name = wanted_str; - - DA_SECURE_LOGD("out_file_name = [%s]", *out_file_name); - + DA_SECURE_LOGI("out_file_name = [%s]", *out_file_name); return DA_TRUE; } else { - DA_LOG_ERR(HTTPManager, "Not matched \" !"); + DA_LOGE("Not matched \" !"); return DA_FALSE; } } @@ -983,51 +833,54 @@ da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response, da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); - b_ret = __get_http_header_for_field(http_msg_response, "ETag", &header); + b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_ETAG, + &header); if (!b_ret) { - DA_LOG_VERBOSE(HTTPManager, "no ETag"); + DA_LOGV( "no ETag"); return DA_FALSE; } - if (out_value) *out_value = strdup(header->value); return DA_TRUE; } -da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response, +#ifdef _RAF_SUPPORT +da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response, char **out_value) { da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); - b_ret = __get_http_header_for_field(http_msg_response, "Date", &header); + b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_RAF_MODE, + &header); if (!b_ret) { - DA_LOG(HTTPManager, "no Date"); + DA_LOGV( "no RAF mode"); return DA_FALSE; } - if (out_value) *out_value = strdup(header->value); return DA_TRUE; } +#endif -da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, +da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response, char **out_value) { da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); - b_ret = __get_http_header_for_field(http_msg_response, "Location", &header); + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_DATA, &header); if (!b_ret) { - DA_LOG(HTTPManager, "no Location"); + DA_LOGV( "no Date"); return DA_FALSE; } if (out_value) @@ -1036,120 +889,27 @@ da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, return DA_TRUE; } -da_result_t http_msg_response_get_boundary( - http_msg_response_t *http_msg_response, char **out_val) -{ - da_result_t ret = DA_RESULT_OK; - - http_msg_iter_t http_msg_iter; - char *field = NULL; - char *value = NULL; - char *boundary = NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - http_msg_response_get_iter(http_msg_response, &http_msg_iter); - while (http_msg_get_field_with_iter(&http_msg_iter, &field, &value)) { - if ((field != DA_NULL) && (value != DA_NULL)) { - if (!strncasecmp(field, "Content-Type", - strlen("Content-Type"))) { - char *org_str = NULL; - char *boundary_str_start = NULL; - char *boundary_value_start = NULL; - char *boundary_value_end = NULL; - int boundary_value_len = 0; - - org_str = value; - - boundary_str_start - = strstr(org_str, "boundary"); - if (boundary_str_start) { - DA_LOG(HTTPManager, "boundary_str_start = %s", boundary_str_start); - // this "Content-Type" value has "boundary" in it, so get the value - boundary_value_start = strchr( - boundary_str_start, '"'); - boundary_value_start += 1; // start without " - - boundary_value_end = strchr( - boundary_value_start, '"'); - boundary_value_len = boundary_value_end - - boundary_value_start; - - DA_LOG(HTTPManager, "boundary_value_start = %s", boundary_value_start); - DA_LOG(HTTPManager, "boundary_value_end = %s", boundary_value_end); - DA_LOG(HTTPManager, "boundary_value_len = %d", boundary_value_len); - - } else { - // no "boundary" field on this "Content-Type" value - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - // end of clear - - boundary = (char *)calloc(1, - boundary_value_len + 1); - if (!boundary) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - - goto ERR; - } - strncpy(boundary, boundary_value_start, - boundary_value_len); - DA_SECURE_LOGD("[boundary][%s]", boundary); - break; - } - } - } - - *out_val = boundary; - -ERR: - return ret; -} - -char *get_http_response_header_raw(http_msg_response_t *http_msg_response) +da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, + char **out_value) { - http_msg_iter_t http_msg_iter; + da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - char *field = NULL; - char tmp_buf[1024*4] = {0,}; - char line_buf[1024] = {0,}; - int len = 0; - char *buff = NULL; - DA_LOG_FUNC_LOGV(HTTPManager); + DA_LOGV(""); - http_msg_response_get_iter(http_msg_response, &http_msg_iter); - while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) { - if (field && header) { - // FIXME later :: buffer length is more than total length. think about getting header's conent length from libsoup - len = strlen(field) + strlen(header->value) + 2; - snprintf(line_buf, len,"%s:%s", field, header->value); - strncat(tmp_buf, line_buf, len); - strcat(tmp_buf, "\n"); - } - } - if (strlen(tmp_buf) > 0) { - buff = (char *)calloc(1, strlen(tmp_buf) + 1); - if (buff == DA_NULL) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); - return DA_NULL; - } - memcpy(buff, tmp_buf, strlen(tmp_buf)); - DA_SECURE_LOGD("\n---raw response header---\n%s\n------\n",buff); - return buff; - } else { - return DA_NULL; + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_LOCATION, &header); + if (!b_ret) { + DA_LOGV( "no Location"); + return DA_FALSE; } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; } -char *_stristr(const char *long_str, const char *find_str) +char *__stristr(const char *long_str, const char *find_str) { int i = 0; int length_long = 0; @@ -1159,7 +919,7 @@ char *_stristr(const char *long_str, const char *find_str) char *look_ptr = NULL; if (long_str == NULL || find_str == NULL) { - DA_LOG_ERR(Default,"INVALID ARGUMENT"); + DA_LOGE("INVALID ARGUMENT"); return NULL; } @@ -1169,14 +929,14 @@ char *_stristr(const char *long_str, const char *find_str) org_ptr = (char*)calloc(1, length_long + 1); if (org_ptr == NULL) { - DA_LOG_ERR(Default,"INVALID ARGUMENT"); + DA_LOGE("INVALID ARGUMENT"); return NULL; } look_ptr = (char*)calloc(1, length_find + 1); if (look_ptr == NULL) { - DA_LOG_ERR(Default,"INVALID ARGUMENT"); + DA_LOGE("INVALID ARGUMENT"); free(org_ptr); return NULL; } @@ -1191,7 +951,6 @@ char *_stristr(const char *long_str, const char *find_str) } else { org_ptr[i] = long_str[i]; } - i++; } @@ -1207,7 +966,6 @@ char *_stristr(const char *long_str, const char *find_str) } else { look_ptr[i] = find_str[i]; } - i++; } @@ -1233,7 +991,6 @@ da_bool_t extract_attribute_from_header( const char *szFindStr, char **ppRtnValue) { - char *pValuePos = NULL; int index = 0; int startPos = 0; @@ -1241,21 +998,19 @@ da_bool_t extract_attribute_from_header( int need_to_end_quataion_mark = 0; if (szHeadStr == DA_NULL || szFindStr == DA_NULL) { - DA_LOG_ERR(Default,"INVALID ARGUMENT"); + DA_LOGE("INVALID ARGUMENT"); return DA_FALSE; } - if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) { - DA_LOG_ERR(Default,"INVALID ARGUMENT");; + DA_LOGE("INVALID ARGUMENT");; return DA_FALSE; } - if (ppRtnValue == NULL) { return DA_FALSE; } - pValuePos = _stristr(szHeadStr, (char*)szFindStr); + pValuePos = __stristr(szHeadStr, (char*)szFindStr); if (pValuePos == NULL) { *ppRtnValue = NULL; goto ERR; @@ -1287,7 +1042,8 @@ da_bool_t extract_attribute_from_header( startPos = index; /* Find the end of data. */ - if (0 == strncasecmp(szFindStr, "Location", strlen("Location")))//terminate character list does not contain ';' in case of URI + if (0 == strncasecmp(szFindStr, HTTP_FIELD_LOCATION, + strlen(HTTP_FIELD_LOCATION)))//terminate character list does not contain ';' in case of URI { while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index])) { index++; @@ -1305,14 +1061,14 @@ da_bool_t extract_attribute_from_header( strLen = index - startPos; if (strLen < 1) { - DA_LOG_ERR(Default," strLen is < 1"); + DA_LOGE(" strLen is < 1"); goto ERR; } *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1)); if (*ppRtnValue == NULL) { - DA_LOG_ERR(Default," *ppRtnValue is NULL"); + DA_LOGE(" *ppRtnValue is NULL"); goto ERR; } @@ -1320,14 +1076,50 @@ da_bool_t extract_attribute_from_header( *(*ppRtnValue + strLen) = '\0'; return DA_TRUE; - ERR: - if (*ppRtnValue) { free(*ppRtnValue); *ppRtnValue = NULL; } - return DA_FALSE; } +da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_IF_RANGE, + &header); + if (!b_ret) { + DA_LOGV( "no If Range"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} + +da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_RANGE, + &header); + if (!b_ret) { + DA_LOGV( "no Range"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} diff --git a/agent/download-agent-http-queue.c b/agent/download-agent-http-queue.c deleted file mode 100755 index 06fe084..0000000 --- a/agent/download-agent-http-queue.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * 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 "download-agent-http-queue.h" -#include "download-agent-http-mgr.h" -#include "download-agent-debug.h" -#include "download-agent-pthread.h" - -void init_q_event_data_http(q_event_t *q_event); -void init_q_event_control(q_event_t *q_event); - -void Q_init_queue(queue_t *queue) -{ - queue->having_data = DA_FALSE; - queue->control_head = DA_NULL; - queue->data_head = DA_NULL; - queue->queue_size = 0; - - _da_thread_mutex_init(&(queue->mutex_queue), DA_NULL); - _da_thread_cond_init(&(queue->cond_queue), DA_NULL); -} - -void Q_destroy_queue(queue_t *queue) -{ - q_event_t *event = DA_NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); - - do { - Q_pop_event(queue, &event); - Q_destroy_q_event(&event); - } while(event); - - queue->having_data = DA_FALSE; - queue->control_head = DA_NULL; - queue->data_head = DA_NULL; - queue->queue_size = 0; - - _da_thread_mutex_destroy(&(queue->mutex_queue)); - _da_thread_cond_destroy(&(queue->cond_queue)); -} - -void Q_init_q_event(q_event_t *q_event) -{ - switch(q_event->event_type) { - case Q_EVENT_TYPE_DATA_HTTP: - init_q_event_data_http(q_event); - break; - - case Q_EVENT_TYPE_DATA_DRM: - break; - - case Q_EVENT_TYPE_CONTROL: - init_q_event_control(q_event); - break; - } - - q_event->size = 0; - q_event->next = DA_NULL; -} - -void Q_destroy_q_event(q_event_t **in_q_event) -{ - q_event_t *q_event = DA_NULL; - q_event = *in_q_event; - - if(q_event == DA_NULL) - return; - - switch(q_event->event_type) { - case Q_EVENT_TYPE_DATA_HTTP: - init_q_event_data_http(q_event); - q_event->size = 0; - q_event->next = DA_NULL; - free(q_event); - break; - - case Q_EVENT_TYPE_DATA_DRM: - q_event->size = 0; - q_event->next = DA_NULL; - free(q_event); - break; - - case Q_EVENT_TYPE_CONTROL: - init_q_event_control(q_event); - q_event->size = 0; - q_event->next = DA_NULL; - free(q_event); - break; - } -} - -da_result_t Q_make_control_event(q_event_type_control control_type, q_event_t **out_event) -{ - da_result_t ret = DA_RESULT_OK; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_LOGD(HTTPManager); - - q_event = (q_event_t *)calloc(1, sizeof(q_event_t)); - if(q_event == DA_NULL) { - DA_LOG_ERR(HTTPManager, "calloc fail for q_event"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - - *out_event = DA_NULL; - } else { - q_event->event_type = Q_EVENT_TYPE_CONTROL; - q_event->type.q_event_control.control_type = control_type; - q_event->next = DA_NULL; - - *out_event = q_event; - } - - return ret; -} - -da_result_t Q_make_http_data_event(q_event_type_data data_type, q_event_t **out_event) -{ - da_result_t ret = DA_RESULT_OK; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); - - q_event = (q_event_t *)calloc(1, sizeof(q_event_t)); - if(q_event == DA_NULL) { - DA_LOG_ERR(HTTPManager, "calloc fail for q_event"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - *out_event = DA_NULL; - } else { - q_event->event_type = Q_EVENT_TYPE_DATA_HTTP; - q_event->type.q_event_data_http.data_type = data_type; - q_event->next = DA_NULL; - - *out_event = q_event; - -// DA_LOG_VERBOSE(HTTPManager, "made event = %x", *out_event); - } - - return ret; - -} - -da_result_t Q_set_status_code_on_http_data_event(q_event_t *q_event, int status_code) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if(q_event->event_type != Q_EVENT_TYPE_DATA_HTTP) { - DA_LOG_ERR(HTTPManager, "status_code can be set only for Q_EVENT_TYPE_DATA_HTTP."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - q_event->type.q_event_data_http.status_code = status_code; - -// DA_LOG_VERBOSE(HTTPManager, "status_code = %d, q_event = %x", q_event->type.q_event_data_http.status_code, q_event); - -ERR: - return ret; - -} - -da_result_t Q_set_http_body_on_http_data_event(q_event_t *q_event, int body_len, char *body_data) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if(q_event->event_type != Q_EVENT_TYPE_DATA_HTTP) { - DA_LOG_ERR(HTTPManager, "http body can be set only for Q_EVENT_TYPE_DATA_HTTP."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - q_event->type.q_event_data_http.body_len = body_len; - q_event->type.q_event_data_http.body_data = body_data; - q_event->size = body_len; - -// DA_LOG_VERBOSE(HTTPManager, "body_len = %d, body_data = %x, q_event = %x", q_event->type.q_event_data_http.body_len, q_event->type.q_event_data_http.body_data, q_event); - -ERR: - return ret; - -} - -da_result_t Q_set_error_type_on_http_data_event(q_event_t *q_event, int error_type) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if(q_event->event_type != Q_EVENT_TYPE_DATA_HTTP) { - DA_LOG_ERR(HTTPManager, "error_type can be set only for Q_EVENT_TYPE_DATA_HTTP."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - q_event->type.q_event_data_http.error_type = error_type; - - DA_LOG_VERBOSE(HTTPManager, "error_type = %d, q_event = %p", q_event->type.q_event_data_http.error_type, q_event); - -ERR: - return ret; - -} - -da_bool_t Q_push_event(const queue_t *in_queue, const q_event_t *in_event) -{ - da_bool_t b_ret = DA_FALSE; - queue_t *queue = (queue_t *)in_queue; - - _da_thread_mutex_lock (&(queue->mutex_queue)); - b_ret = Q_push_event_without_lock(in_queue, in_event); - _da_thread_mutex_unlock (&(queue->mutex_queue)); - - return b_ret; -} - -da_bool_t Q_push_event_without_lock(const queue_t *in_queue, const q_event_t *in_event) -{ - da_bool_t b_ret = DA_FALSE; - queue_t *queue = (queue_t *)in_queue; - q_event_t *event = (q_event_t *)in_event; - q_event_type event_type; - q_event_t *head = DA_NULL; - q_event_t *cur = DA_NULL; - -// DA_LOG_VERBOSE(HTTPManager, "queue = %x", in_queue); - - event_type = event->event_type; - -// _da_thread_mutex_lock (&(queue->mutex_queue)); - - if(event_type == Q_EVENT_TYPE_CONTROL) { - head = queue->control_head; - if(head == DA_NULL) { - queue->control_head = event; - } else { - cur = head; - - while(cur->next != DA_NULL) { - cur = cur->next; - } - cur->next= event; - } - b_ret = DA_TRUE; - } else { - if((event->size == 0) || (queue->queue_size < MAX_QUEUE_SIZE)) { - head = queue->data_head; - if(head == DA_NULL) { - queue->data_head = event; - } else { - cur = head; - while(cur->next != DA_NULL) { - cur = cur->next; - } - cur->next= event ; - } - - queue->queue_size += event->size; -// DA_LOG_VERBOSE(HTTPManager, "queue size is %d", queue->queue_size); - - b_ret = DA_TRUE; - } else { - DA_LOG_CRITICAL(HTTPManager, "rejected event's size is %d queue_size %d", event->size, queue->queue_size); - b_ret = DA_FALSE; - } - } - - queue->having_data = DA_TRUE; - Q_wake_up(queue); -// _da_thread_mutex_unlock (&(queue->mutex_queue)); - return b_ret; -} - -void Q_pop_event(const queue_t *in_queue, q_event_t **out_event) -{ - queue_t *queue = (queue_t*)in_queue; - -// DA_LOG_VERBOSE(HTTPManager, "queue = %x", in_queue); - - /** Pop Priority - * 1. If there are control event, control event should pop first - * 2. If there is no control event, data event should pop - * 3. If there is no control and data event on queue, pop NULL - */ - - _da_thread_mutex_lock (&(queue->mutex_queue)); - - if(queue->control_head != DA_NULL) {/* Priority 1 */ - *out_event = queue->control_head; - queue->control_head = queue->control_head->next; - } else { - if(queue->data_head != DA_NULL) {/* Priority 2 */ - *out_event = queue->data_head; - queue->data_head = queue->data_head->next; - queue->queue_size -= (*out_event)->size; - DA_LOG_VERBOSE(HTTPManager, "queue size is %d", queue->queue_size); - } else {/* Priority 3 */ - *out_event = DA_NULL; - } - } - - if((queue->control_head == DA_NULL) && (queue->data_head == DA_NULL)) { - queue->having_data = DA_FALSE; - } else { - queue->having_data = DA_TRUE; - } - - _da_thread_mutex_unlock (&(queue->mutex_queue)); - -} - -void Q_goto_sleep(const queue_t *in_queue) -{ - DA_LOG_VERBOSE(HTTPManager, "sleep for %p", in_queue); - -//** SHOULD NOT use mutex **// - -// _da_thread_mutex_lock (&(in_queue->mutex_queue)); - _da_thread_cond_wait((pthread_cond_t*)(&(in_queue->cond_queue)),(pthread_mutex_t*) (&(in_queue->mutex_queue))); -// _da_thread_mutex_unlock (&(in_queue->mutex_queue)); -} - -void Q_wake_up(const queue_t *in_queue) -{ - DA_LOG_VERBOSE(HTTPManager, "wake up for %p", in_queue); - -//** SHOULD NOT use mutex **// - -// _da_thread_mutex_lock (&(in_queue->mutex_queue)); - _da_thread_cond_signal((pthread_cond_t*)(&(in_queue->cond_queue))); -// _da_thread_mutex_unlock (&(in_queue->mutex_queue)); -} - -void init_q_event_data_http(q_event_t *q_event) -{ - q_event_data_http_t *q_event_data_http; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if(q_event->event_type == Q_EVENT_TYPE_DATA_HTTP) { - q_event_data_http = &(q_event->type.q_event_data_http); - - if(q_event_data_http) { - q_event_data_http->status_code = 0; - if(q_event_data_http->http_response_msg) { - http_msg_response_destroy(&(q_event_data_http->http_response_msg)); - q_event_data_http->http_response_msg = DA_NULL; - } - - if(q_event_data_http->body_len > 0 ) { - if (q_event_data_http->body_data) { - free(q_event_data_http->body_data); - q_event_data_http->body_data = DA_NULL; - } - } - q_event_data_http->error_type = 0; - } - } -} - -void init_q_event_control(q_event_t *q_event) -{ - q_event_control_t *q_event_control; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if(q_event->event_type == Q_EVENT_TYPE_CONTROL) { - q_event_control = &(q_event->type.q_event_control); - if(q_event_control) { - q_event_control->control_type = Q_EVENT_TYPE_CONTROL_NONE; - } - } - -} diff --git a/agent/download-agent-interface.c b/agent/download-agent-interface.c index 7d994e6..0b19813 100755 --- a/agent/download-agent-interface.c +++ b/agent/download-agent-interface.c @@ -15,214 +15,131 @@ */ #include "download-agent-interface.h" -#include "download-agent-debug.h" -#include "download-agent-utils.h" -#include "download-agent-http-mgr.h" -#include "download-agent-http-misc.h" -#include "download-agent-client-mgr.h" #include "download-agent-dl-mgr.h" -#include "download-agent-basic.h" -#include "download-agent-file.h" -int da_init( - da_client_cb_t *da_client_callback) +int da_init() { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_LOGD(Default); - - if (!da_client_callback) { - ret = DA_ERR_INVALID_ARGUMENT; - return ret; - } - - ret = init_log_mgr(); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = init_client_app_mgr(); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = reg_client_app(da_client_callback); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = init_http_mgr(); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = init_download_mgr(); - if (ret != DA_RESULT_OK) - goto ERR; - -ERR: - if (DA_RESULT_OK != ret) - da_deinit(); - - DA_LOG_CRITICAL(Default, "Return ret = %d", ret); - + DA_LOGV(""); + da_ret_t ret = DA_RESULT_OK; + DA_LOGI("Return ret = %d", ret); return ret; } -/* TODO:: deinit should clean up all the clients... */ int da_deinit() { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_LOGV(Default); - - deinit_http_mgr(); - deinit_download_mgr(); - /* Do not clean temporary download path - * The client can resume or restart download with temporary file in case of failed download. - */ - dereg_client_app(); - DA_LOG(Default, "====== da_deinit EXIT ====="); + da_ret_t ret = DA_RESULT_OK; + DA_LOGV(""); + destroy_da_info_list(); + DA_LOGI("====== da_deint EXIT ====="); return ret; } -int da_start_download( - const char *url, - int *download_id) +int da_start_download(const char *url, req_data_t *ext_data, + da_cb_t *da_cb_data, int *download_id) { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_LOGD(Default); - - *download_id = DA_INVALID_ID; - - if (DA_FALSE == is_valid_url(url, &ret)) - goto ERR; - - DA_SECURE_LOGI("url = %s", url); - - ret = start_download(url, download_id); - if (ret != DA_RESULT_OK) - goto ERR; - -ERR: - DA_LOG_CRITICAL(Default, "Return: Dl req id = %d, ret = %d", *download_id, ret); - return ret; -} - -int da_start_download_with_extension( - const char *url, - extension_data_t *extension_data, - int *download_id -) -{ - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; int req_header_count = 0; int i = 0; - - DA_LOG_FUNC_LOGV(Default); + int da_id = DA_INVALID_ID; + da_info_t *da_info = DA_NULL; *download_id = DA_INVALID_ID; - if (DA_FALSE == is_valid_url(url, &ret)) - goto ERR; - - DA_SECURE_LOGI("url = %s", url); - - if (ret != DA_RESULT_OK) - goto ERR; - if (!extension_data) { - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - if (extension_data->request_header_count > 0) { - DA_LOG_VERBOSE(Default, "input request_header_count = [%d]", - extension_data->request_header_count); - for (i = 0; i < extension_data->request_header_count; i++) { - if (extension_data->request_header[i]) { + if (ext_data->request_header_count > 0) { + DA_LOGI("request_header_count[%d]", ext_data->request_header_count); + for (i = 0; i < ext_data->request_header_count; i++) { + if (ext_data->request_header[i]) { req_header_count++; - DA_SECURE_LOGI("request_header = [%s]", - extension_data->request_header[i]); + DA_SECURE_LOGI("request_header[%s]", ext_data->request_header[i]); } } - DA_LOG_VERBOSE(Default, "actual request_header_count = [%d]", req_header_count); - if (extension_data->request_header_count != req_header_count) { - DA_LOG_ERR(Default, "Request header count is not matched with number of request header array"); - extension_data->request_header = NULL; - extension_data->request_header_count = 0; + DA_LOGI("actual request_header_count[%d]", req_header_count); + if (ext_data->request_header_count != req_header_count) { + DA_LOGE("Request header count is not matched with number of request header array"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } } - if (extension_data->install_path) { - if (!is_dir_exist(extension_data->install_path)) - return DA_ERR_INVALID_INSTALL_PATH; - DA_SECURE_LOGI("install_path = [%s]", extension_data->install_path); - } - - if (extension_data->file_name) - DA_SECURE_LOGI("file_name = [%s]", extension_data->file_name); - if (extension_data->temp_file_path) - DA_SECURE_LOGI("temp_file_path = [%s]", extension_data->temp_file_path); - if (extension_data->etag) - DA_SECURE_LOGI("etag = [%s]", extension_data->etag); - if (extension_data->pkg_name) - DA_SECURE_LOGI("pkg_name = [%s]", extension_data->pkg_name); - if (extension_data->user_data) - DA_LOG_VERBOSE(Default, "user_data = [%p]", extension_data->user_data); + if (ext_data->install_path) + DA_SECURE_LOGI("install path[%s]", ext_data->install_path); + if (ext_data->file_name) + DA_SECURE_LOGI("file_name[%s]", ext_data->file_name); + if (ext_data->temp_file_path) + DA_SECURE_LOGI("temp_file_path[%s]", ext_data->temp_file_path); + if (ext_data->etag) + DA_SECURE_LOGI("etag[%s]", ext_data->etag); + if (ext_data->pkg_name) + DA_SECURE_LOGI("pkg_name[%s]", ext_data->pkg_name); + if (ext_data->network_bonding) + DA_LOGD("network bonding option[%d]", ext_data->network_bonding); + if (ext_data->user_req_data) + DA_LOGI("user_req_data[%p]", ext_data->user_req_data); + if (ext_data->user_client_data) + DA_LOGI("user_client_data[%p]", ext_data->user_client_data); + + ret = get_available_da_id(&da_id); + if (ret != DA_RESULT_OK) + goto ERR; - ret = start_download_with_extension(url, download_id, extension_data); + da_info = da_info_list[da_id]; + da_info->da_id = da_id; + ret = copy_user_input_data(da_info, url, ext_data, da_cb_data); + if (ret != DA_RESULT_OK) + goto ERR; + *download_id = da_id; + ret = start_download(da_info); ERR: - DA_LOG_CRITICAL(Default, "Return: Dl req id = %d, ret = %d", *download_id, ret); + DA_LOGI("Return:id[%d],ret[%d]", *download_id, ret); return ret; } int da_cancel_download(int download_id) { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_VERBOSE(Default, "Cancel for dl_id = %d", download_id); + da_ret_t ret = DA_RESULT_OK; - ret = cancel_download(download_id); + DA_LOGV("download_id[%d]", download_id); + ret = cancel_download(download_id, DA_TRUE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} - DA_LOG_CRITICAL(Default, "Return: Cancel id = %d, ret = %d", download_id, ret); +int da_cancel_download_without_update(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); + ret = cancel_download(download_id, DA_FALSE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); return ret; } int da_suspend_download(int download_id) { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_VERBOSE(Default, "Suspend for dl_id = %d", download_id); - + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); ret = suspend_download(download_id, DA_TRUE); - - DA_LOG_CRITICAL(Default, "Return: Suspend id = %d, ret = %d", download_id, ret); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); return ret; } int da_suspend_download_without_update(int download_id) { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_VERBOSE(Default, "Suspend for dl_id = %d", download_id); - + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); ret = suspend_download(download_id, DA_FALSE); - - DA_LOG_CRITICAL(Default, "Return: Suspend id = %d, ret = %d", download_id, ret); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); return ret; } int da_resume_download(int download_id) { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_VERBOSE(Default, "Resume for dl_id = %d", download_id); - + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); ret = resume_download(download_id); - - DA_LOG_CRITICAL(Default, "Return: Resume id = %d, ret = %d", download_id, ret); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); return ret; } @@ -230,5 +147,6 @@ int da_is_valid_download_id(int download_id) { da_bool_t ret = DA_FALSE; ret = is_valid_download_id(download_id); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); return ret; } diff --git a/agent/download-agent-mime-util.c b/agent/download-agent-mime-util.c index 53bab8b..71e08eb 100755 --- a/agent/download-agent-mime-util.c +++ b/agent/download-agent-mime-util.c @@ -69,8 +69,6 @@ pthread_mutex_t mutex_for_xdgmime = PTHREAD_MUTEX_INITIALIZER; da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type) { - DA_LOG_FUNC_LOGV(Default); - if (!in_mime_type) return DA_FALSE; @@ -79,7 +77,7 @@ da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type) for (index = 0 ; index < list_size ; index++) { if (0 == strncmp(in_mime_type, ambiguous_MIME_Type_list[index], strlen(ambiguous_MIME_Type_list[index]))) { - DA_SECURE_LOGD("It is ambiguous! [%s]", ambiguous_MIME_Type_list[index]); + //DA_SECURE_LOGD("It is ambiguous! [%s]", ambiguous_MIME_Type_list[index]); return DA_TRUE; } } @@ -87,42 +85,41 @@ da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type) return DA_FALSE; } -da_result_t da_mime_get_ext_name(char *mime, char **ext) +da_ret_t da_mime_get_ext_name(char *mime, char **ext) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; const char **extlist = DA_NULL; const char *unaliased_mimetype = DA_NULL; char ext_temp[DA_MAX_STR_LEN] = {0,}; char *temp = NULL; - DA_LOG_FUNC_LOGV(Default); + DA_LOGV(""); if (DA_NULL == mime || DA_NULL == ext) { ret = DA_ERR_INVALID_ARGUMENT; - DA_LOG_ERR(Default,"Invalid mime type"); + DA_LOGE("Invalid mime type"); goto ERR; } // DA_SECURE_LOGD("mime str[%s]ptr[%p]len[%d]",mime,mime,strlen(mime)); /* unaliased_mimetype means representative mime among similar types */ - _da_thread_mutex_lock(&mutex_for_xdgmime); + DA_MUTEX_LOCK(&mutex_for_xdgmime); unaliased_mimetype = xdg_mime_unalias_mime_type(mime); - _da_thread_mutex_unlock(&mutex_for_xdgmime); if (unaliased_mimetype == DA_NULL) { ret = DA_ERR_INVALID_MIME_TYPE; - DA_LOG_ERR(Default,"Invalid mime type : No unsaliased mime type"); + DA_LOGI("Invalid mime type : No unsaliased mime type"); + DA_MUTEX_UNLOCK(&mutex_for_xdgmime); goto ERR; } DA_SECURE_LOGD("unaliased_mimetype[%s]\n",unaliased_mimetype); /* Get extension name from shared-mime-info */ - _da_thread_mutex_lock(&mutex_for_xdgmime); extlist = xdg_mime_get_file_names_from_mime_type(unaliased_mimetype); - _da_thread_mutex_unlock(&mutex_for_xdgmime); + DA_MUTEX_UNLOCK(&mutex_for_xdgmime); if (extlist == DA_NULL || *extlist == DA_NULL) { int i = 0; ret = DA_ERR_INVALID_MIME_TYPE; - DA_LOG(Default,"No extension list"); + DA_LOGV("No extension list"); #ifdef _SAMSUNG_MIME_POLICY for (i = 0; i < MAX_SEC_MIME_TABLE_INDEX; i++) { @@ -134,8 +131,8 @@ da_result_t da_mime_get_ext_name(char *mime, char **ext) } #endif } else { /* For drm case, this else statement is needed */ - DA_SECURE_LOGD("extlist[%s]\n",*extlist); - strncpy(ext_temp, *extlist, DA_MAX_STR_LEN); +// DA_LOGD("extlist[%s]\n",*extlist); + strncpy(ext_temp, *extlist, DA_MAX_STR_LEN - 1); /* If only one extension name is existed, don't enter here */ while (*extlist != NULL) { int i = 0; @@ -151,12 +148,12 @@ da_result_t da_mime_get_ext_name(char *mime, char **ext) break; } } - DA_LOG_VERBOSE(Default,"index[%d]\n",i); + DA_LOGV("index[%d]\n",i); /* If there is a mime at extension transform table */ if (i < MAX_EXT_TABLE_INDEX) { break; } - DA_SECURE_LOGD("extlist[%s]\n",*extlist); +// DA_LOGD("extlist[%s]\n",*extlist); extlist++; } // DA_SECURE_LOGD("extension from shared mime info[%s]",ext_temp); @@ -165,18 +162,18 @@ da_result_t da_mime_get_ext_name(char *mime, char **ext) if (strlen(ext_temp) < 1) { /* If there is no mime string for OMA descriptor mime type */ if (strncmp(DD_MIME_STR, mime, strlen(DD_MIME_STR)) == 0) { - strncpy(ext_temp, DD_EXT_STR, DA_MAX_STR_LEN-1); + strncpy(ext_temp, DD_EXT_STR, DA_MAX_STR_LEN - 1); ret = DA_RESULT_OK; /* If there is no extension name for "applicaion/vnd.oma.drm.messeages" * at shared-mime-info*/ - } else if (strncmp(DRM_MIME_MSG_STR, mime, - strlen(DRM_MIME_MSG_STR)) == 0) { - strncpy(ext_temp, DRM_EXT_STR, DA_MAX_STR_LEN-1); + } else if (strncmp(DRM_MIME_MSG_STR, mime, strlen(DRM_MIME_MSG_STR)) == + 0) { + strncpy(ext_temp, DRM_EXT_STR, DA_MAX_STR_LEN - 1); /* If there is extension name at extlist, the return value can have an error.*/ ret = DA_RESULT_OK; } else { ret = DA_ERR_INVALID_MIME_TYPE; - DA_LOG_ERR(Default,"Invalid mime type : no extension name at list"); + DA_LOGI("Invalid mime type : no extension name at list"); } } if (ret != DA_RESULT_OK) @@ -188,6 +185,7 @@ da_result_t da_mime_get_ext_name(char *mime, char **ext) else temp++; + DA_SECURE_LOGD("final extension name:[%s]",temp); *ext = (char*)calloc(1, strlen(temp) + 1); if (*ext != DA_NULL) { strncpy(*ext, temp,strlen(temp)); @@ -206,11 +204,11 @@ da_bool_t da_get_extension_name_from_url(char *url, char **ext) char *temp_str = DA_NULL; int buf_len = 0; - DA_LOG_FUNC_LOGV(Default); + DA_LOGV(""); if (DA_NULL == url || DA_NULL == ext) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Invalid Argument"); + DA_LOGE("Invalid Argument"); return ret; } @@ -229,7 +227,7 @@ da_bool_t da_get_extension_name_from_url(char *url, char **ext) if (DA_NULL == *ext) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Memory Fail"); + DA_LOGE("Memory Fail"); goto ERR; } strncpy(*ext,buff,buf_len); @@ -258,24 +256,24 @@ da_bool_t da_get_file_name_from_url(char *url, char **name) int len_name = 0; char name_buff[DA_MAX_FILE_PATH_LEN] = {0,}; - DA_LOG_FUNC_LOGV(Default); + DA_LOGV(""); if (DA_NULL == url || DA_NULL == name) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Invalid Argument"); + DA_LOGE("Invalid Argument"); goto ERR; } - *name = DA_NULL; + if (!strstr(url, "http") && !strstr(url, "https")) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Invalid Argument"); + DA_LOGE("Invalid Argument"); goto ERR; } buff = (char*) calloc(1, strlen(url) +1); if(DA_NULL == buff) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Memory Fail"); + DA_LOGE("Memory Fail"); goto ERR; } @@ -339,7 +337,6 @@ da_bool_t da_get_file_name_from_url(char *url, char **name) } // DA_SECURE_LOGD("file name BEFORE removing prohibited character = %s", name_buff); delete_prohibited_char(name_buff, strlen(name_buff)); -// DA_SECURE_LOGD("file name AFTER removing prohibited character = %s", name_buff); len_name = strlen(name_buff); *name = (char*) calloc(1, len_name + 1); if (*name) { @@ -363,7 +360,7 @@ void delete_prohibited_char(char *szTarget, int str_len) int tar_len = 0; if(szTarget == NULL || str_len <= 0 || strlen(szTarget) != str_len) { - DA_LOG_ERR(Default,"Invaild Parameter\n"); + DA_LOGE("Invaild Parameter\n"); return; } @@ -399,3 +396,54 @@ void delete_prohibited_char(char *szTarget, int str_len) return; } +#ifdef _ENABLE_OMA_DRM +da_bool_t is_content_drm_dcf(char *content_type) +{ + if (content_type == DA_NULL) + return DA_FALSE; + + if (0 == strcmp(content_type, DRM_MIME_CONTENT_STR)) { + DA_LOGV("DRM_DM content"); + return DA_TRUE; + } else { + return DA_FALSE; + } +} + +da_bool_t is_content_drm_dm(char *content_type) +{ + if (content_type == DA_NULL) + return DA_FALSE; + + if (0 == strcmp(content_type, DRM_MIME_MSG_STR)) { + DA_LOGV("DRM_DM content"); + return DA_TRUE; + } else { + return DA_FALSE; + } +} +#endif + +da_ret_t get_extension_from_mime_type(char *mime_type, char **extension) +{ + da_ret_t ret = DA_RESULT_OK; + char *ext = DA_NULL; + + DA_LOGV(""); + if (DA_NULL == mime_type || DA_NULL == extension) { + DA_LOGE("received mime_type is null"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } +// DA_SECURE_LOGD("input mime type = %s", mime_type); + if (DA_RESULT_OK != (ret = da_mime_get_ext_name(mime_type, &ext))) { + DA_LOGE("can't find proper extension!"); + goto ERR; + } + *extension = ext; +// DA_SECURE_LOGD("found extension = %s", *extension); + +ERR: + return ret; +} + diff --git a/agent/download-agent-plugin-conf.c b/agent/download-agent-plugin-conf.c index 8a547f7..6cb76cb 100755 --- a/agent/download-agent-plugin-conf.c +++ b/agent/download-agent-plugin-conf.c @@ -17,12 +17,9 @@ #include <string.h> #include <stdlib.h> #include <glib-object.h> - -#ifdef _EFL_PLATFORM -#include <vconf.h> -#include <vconf-keys.h> -#include <net_connection.h> -#endif /* _EFL_PLATFORM */ +#include "vconf.h" +#include "vconf-keys.h" +#include "net_connection.h" #include "download-agent-plugin-conf.h" #include "download-agent-debug.h" @@ -30,74 +27,58 @@ #define DEFAULT_UA_STR "Mozilla/5.0 (Linux; U; Tizen 1.0; en-us) AppleWebKit/534.46 (KHTML, like Gecko) Mobile Tizen Browser/1.0" -da_result_t __get_conf_string(const char *key, char **out_string); - -da_result_t __get_conf_string(const char *key, char **out_string) +da_ret_t __get_conf_string(const char *key, char **out_string) { -#ifdef _EFL_PLATFORM if (!key || !out_string) { - DA_LOG_ERR(Default,"Invalid Argument"); + DA_LOGE("Invalid Argument"); return DA_ERR_INVALID_ARGUMENT; } *out_string = vconf_get_str(key); return DA_RESULT_OK; -#else - if (out_string) - *out_string = NULL; - - return DA_RESULT_OK; -#endif } -da_result_t get_user_agent_string(char **uagent_str) +da_ret_t get_user_agent_string(char **uagent_str) { - da_result_t ret = DA_RESULT_OK; -#ifdef _EFL_PLATFORM + da_ret_t ret = DA_RESULT_OK; char *key = DA_NULL; -#endif - DA_LOG_FUNC_LOGV(Default); + DA_LOGV(""); if (!uagent_str) { - DA_LOG_ERR(Default,"Invalid Argument"); + DA_LOGE("Invalid Argument"); return DA_ERR_INVALID_ARGUMENT; } -#ifdef _EFL_PLATFORM key = VCONFKEY_BROWSER_USER_AGENT; ret = __get_conf_string(key, uagent_str); if(ret == DA_RESULT_OK) { if(*uagent_str) { - DA_SECURE_LOGD("getting uagent_str = \n%s", *uagent_str); +// DA_SECURE_LOGD("getting uagent_str = \n%s", *uagent_str); return ret; } } - DA_LOG_ERR(Default,"No UA information from vconf !!"); - *uagent_str = strdup(DEFAULT_UA_STR); - DA_LOG(Default,"Set default UA"); -#else + DA_LOGI("No UA information from vconf !!"); *uagent_str = strdup(DEFAULT_UA_STR); -#endif + DA_LOGV("Set default UA"); return ret; } char *get_proxy_address(void) { -#ifdef _EFL_PLATFORM char *proxy = NULL; char *proxyRet = NULL; connection_h handle = NULL; - connection_address_family_e family = CONNECTION_ADDRESS_FAMILY_IPV4; + connection_address_family_e family = CONNECTION_ADDRESS_FAMILY_IPV4; - DA_LOG_FUNC_LOGV(Default); + DA_LOGV(""); if (connection_create(&handle) < 0) { - DA_LOG_ERR(Default,"Fail to create connection handle"); + DA_LOGE("Fail to create connection handle"); return NULL; } if (connection_get_proxy(handle, family, &proxyRet) < 0) { - DA_LOG_ERR(Default,"Fail to get proxy address"); + DA_LOGE("Fail to get proxy address"); connection_destroy(handle); return NULL; } @@ -112,11 +93,17 @@ char *get_proxy_address(void) } if (connection_destroy(handle) < 0) { - DA_LOG_ERR(Default,"Fail to desctory connection handle"); + DA_LOGE("Fail to desctory connection handle"); return NULL; } return NULL; -#else - return NULL; -#endif } +#ifdef _RAF_SUPPORT +// test code +void get_smart_bonding_vconf() +{ + int ret = 0; + vconf_get_int("file/private/wifi/network_bonding", &ret); + DA_LOGI("Smart Bonding Vconf:%d", ret); +} +#endif diff --git a/agent/download-agent-plugin-drm.c b/agent/download-agent-plugin-drm.c new file mode 100644 index 0000000..22e6f34 --- /dev/null +++ b/agent/download-agent-plugin-drm.c @@ -0,0 +1,124 @@ +/* + * 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 <string.h> + +#include "drm_client.h" +#include "drm_client_types.h" +#include "drm_trusted_client.h" +#include "drm_trusted_client_types.h" + +#include "download-agent-debug.h" +#include "download-agent-plugin-drm.h" + + +void __EDRM_clean_up() +{ + int ret = 0; + ret = drm_trusted_handle_request(DRM_TRUSTED_REQ_TYPE_CLIENT_CLEAN_UP, NULL, NULL); + if (DRM_RETURN_SUCCESS == ret) { + DA_LOGD( "Clean up successfull"); + } else { + DA_LOGE("ret[%0x%x]",ret); + } +} + +da_bool_t EDRM_convert(const char *in_file_path, char **out_file_path) +{ + drm_trusted_conv_info_s input; + drm_trusted_conv_resp_info_s output; + size_t len = 0; + int ret = 0; + + memset(&input, 0x0, sizeof(drm_trusted_conv_info_s)); + memset(&output, 0x0, sizeof(drm_trusted_conv_resp_info_s)); + + len = strlen(in_file_path); + if (len >= sizeof(input.filePath)) + len = sizeof(input.filePath) - 1; + memcpy(input.filePath, in_file_path, len); + + ret = drm_trusted_convert_dm(&input, &output); + + if (DRM_TRUSTED_RETURN_SUCCESS != ret) { + DA_LOGE("ret[%0x%x]",ret); + __EDRM_clean_up(); + return DA_FALSE; + } else { + DA_SECURE_LOGD("Returned filePath[%s]", output.filePath); + *out_file_path = strdup(output.filePath); + } + __EDRM_clean_up(); + return DA_TRUE; +} + +da_ret_t EDRM_wm_get_license(char *rights_url, char **out_content_url) +{ + int ret = 0; + int len = 0; + drm_initiator_info_s init_info; + drm_web_server_resp_data_s resp_data; + + if (rights_url == NULL) + return DA_ERR_DRM_FAIL; + + memset(&init_info, 0, sizeof(init_info)); + memset(&resp_data, 0, sizeof(resp_data)); + strncpy(init_info.initiator_url, rights_url, + DRM_MAX_LEN_INITIATOR_URL - 1); + len = strlen(rights_url); + if (len > DRM_MAX_LEN_INITIATOR_URL - 1) + init_info.initiator_url_len = (unsigned int)len; + else + init_info.initiator_url_len = DRM_MAX_LEN_INITIATOR_URL; + ret = drm_process_request(DRM_REQUEST_TYPE_SUBMIT_INITIATOR_URL, + &init_info, &resp_data); + if (DRM_RETURN_SUCCESS == ret) { + DA_SECURE_LOGD("resp_data.content_url = %s", resp_data.content_url); + /* Rights or Domain Certificate are installed successfully */ + /* Check for contentURL */ + if (strlen(resp_data.content_url) > 0) { + char *content_url = NULL; + size_t content_url_len = 0; + content_url_len = strlen(resp_data.content_url); + content_url = (char *)calloc(1, content_url_len + 1); + if (content_url) { + strncpy(content_url, resp_data.content_url, + content_url_len); + *out_content_url = content_url; + DA_SECURE_LOGD("drm sumitted initiator url " + "succeeded with [%s]", *out_content_url); + __EDRM_clean_up(); + return DA_RESULT_OK; + } else { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + __EDRM_clean_up(); + return DA_ERR_FAIL_TO_MEMALLOC; + } + } else { + DA_LOGV("content_url is NULL.\ + Join/Leave Domain, Metering case."); + *out_content_url = DA_NULL; + __EDRM_clean_up(); + return DA_RESULT_OK; + } + } else { + DA_LOGE("drm_process_request() failed"); + __EDRM_clean_up(); + return DA_ERR_DRM_FAIL; + } +} + diff --git a/agent/download-agent-plugin-libcurl.c b/agent/download-agent-plugin-libcurl.c new file mode 100644 index 0000000..0c221d2 --- /dev/null +++ b/agent/download-agent-plugin-libcurl.c @@ -0,0 +1,702 @@ +/* + * 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 <string.h> +#include <stdlib.h> + +#include "glib.h" + +#include "download-agent-dl-info.h" +#include "download-agent-http-msg-handler.h" +#include "download-agent-plugin-libcurl.h" + +da_bool_t using_content_sniffing = DA_FALSE; + +int __translate_error_code(int curl_error) +{ + switch (curl_error) { + case CURLE_OPERATION_TIMEDOUT: + return DA_ERR_HTTP_TIMEOUT; + case CURLE_SSL_CONNECT_ERROR: + case CURLE_SSL_ENGINE_NOTFOUND: + case CURLE_SSL_ENGINE_SETFAILED: + case CURLE_SSL_CERTPROBLEM: + case CURLE_SSL_CIPHER: + case CURLE_SSL_CACERT: + case CURLE_SSL_ENGINE_INITFAILED: + case CURLE_SSL_CACERT_BADFILE: + case CURLE_SSH: + case CURLE_SSL_SHUTDOWN_FAILED: + case CURLE_SSL_CRL_BADFILE: + case CURLE_SSL_ISSUER_ERROR: + return DA_ERR_SSL_FAIL; + case CURLE_TOO_MANY_REDIRECTS: + return DA_ERR_TOO_MANY_REDIRECTS; + case CURLE_OUT_OF_MEMORY: + return DA_ERR_FAIL_TO_MEMALLOC; + case CURLE_UNSUPPORTED_PROTOCOL: + case CURLE_URL_MALFORMAT: + case CURLE_COULDNT_RESOLVE_PROXY: + case CURLE_COULDNT_RESOLVE_HOST: + case CURLE_COULDNT_CONNECT: + case CURLE_REMOTE_ACCESS_DENIED: + case CURLE_HTTP_POST_ERROR: + case CURLE_BAD_DOWNLOAD_RESUME: + return DA_ERR_CONNECTION_FAIL; + case CURLE_ABORTED_BY_CALLBACK: + return DA_RESULT_USER_CANCELED; + default: + return DA_ERR_NETWORK_FAIL; + } +} + +int my_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *user) +{ + switch(type) { + case CURLINFO_TEXT: + if (data) + DA_SECURE_LOGI("[curl] Info:%s", data); + break; + case CURLINFO_HEADER_OUT: + DA_LOGD("[curl] Send header"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; + case CURLINFO_DATA_OUT: + DA_LOGD("[curl] Send data"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; + case CURLINFO_SSL_DATA_OUT: + DA_LOGD("[curl] Send SSL data"); + break; + case CURLINFO_HEADER_IN: + DA_LOGD("[curl] Recv header"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; +#if 0 + case CURLINFO_DATA_IN: + DA_LOGD("[curl] Recv data"); + if (data) + DA_SECURE_LOGI("[curl] %d", strlen(data)); + break; +#endif + case CURLINFO_SSL_DATA_IN: + DA_SECURE_LOGI("[curl] Recv SSL data"); + break; + default: + return 0; + } + return 0; +} + +void __parse_raw_header(const char *raw_data, http_info_t *http_info) +{ + char *ptr = DA_NULL; + char *ptr2 = DA_NULL; + int len = 0; + char *field = DA_NULL; + char *value = DA_NULL; + http_msg_response_t *http_msg_response = NULL; + + if (!raw_data || !http_info) { + DA_LOGE("NULL Check!: raw_data or http_info"); + return; + } + + if (!http_info->http_msg_response) { + http_info->http_msg_response = (http_msg_response_t *)calloc(1, + sizeof(http_msg_response_t)); + if (!http_info->http_msg_response) { + DA_LOGE("Fail to calloc"); + return; + } + http_info->http_msg_response->head = DA_NULL; + } + http_msg_response = http_info->http_msg_response; + + ptr = strchr(raw_data, ':'); + if (!ptr) + return; + len = ptr - (char *)raw_data; + field = (char *)calloc(len + 1, sizeof(char)); + if (!field) { + DA_LOGE("Fail to calloc"); + return; + } + memcpy(field, raw_data, len); + field[len] = '\0'; + ptr++; + while(ptr) { + if (*ptr == ' ') + ptr++; + else + break; + } + ptr2 = strchr(raw_data, '\n'); + if (ptr2) { + len = ptr2 - ptr -1; + } else { + len = strlen(ptr); + } + value = (char *)calloc(len + 1, sizeof(char)); + if (!value) { + DA_LOGE("Fail to calloc"); + free(field); + return; + } + memcpy(value, ptr, len); + value[len] = '\0'; + http_msg_response_add_field(http_msg_response, field, value); + free(field); + free(value); +} + +void __store_header(void *msg, da_info_t *da_info, size_t header_size, + const char *sniffed_type) +{ + http_info_t *http_info = DA_NULL; + + if (!da_info || !msg) { + DA_LOGE("NULL Check!: da_info or msg"); + return; + } + http_info = da_info->http_info; + if (!http_info) { + DA_LOGE("NULL Check!: http_info"); + return; + } + + // FIXME later : check status code and redirection case check. + + if (strncmp(msg, HTTP_FIELD_END_OF_FIELD, + strlen(HTTP_FIELD_END_OF_FIELD)) == 0) { + long status = 0; + CURLcode res; + CURL *curl; + http_raw_data_t *raw_data = DA_NULL; + curl = http_info->http_msg->curl; + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status); + if (res != CURLE_OK) { + DA_LOGE("Fail to get response status code"); + return; + } + DA_LOGV("status code[%d]", (int)status); + if (http_info->http_msg_response) { + http_info->http_msg_response->status_code = (int)status; + } + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return; + } + + raw_data->status_code = (int)status; + raw_data->type = HTTP_EVENT_GOT_HEADER; + + if (http_info->update_cb) { + http_info->update_cb(raw_data, da_info); + } else { + free(raw_data); + } + return; + } + DA_LOGI("%s",(char *)msg); + __parse_raw_header((const char *)msg, http_info); +} + +size_t __http_gotheaders_cb(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + da_info_t *da_info = DA_NULL; + if (!ptr || !userdata) { + DA_LOGE("Check NULL!: ptr, userdata"); + return 0; + } + da_info = (da_info_t *)userdata; + if (da_info->http_info && da_info->http_info->http_msg + && da_info->http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + if (!using_content_sniffing) + __store_header(ptr, da_info, (size * nmemb), DA_NULL); + else + DA_LOGV("ignore because content sniffing is turned on"); +/* +#ifdef _RAF_SUPPORT + DA_LOGI("[RAF] __http_gotheaders_cb done"); +#endif +*/ + return (size * nmemb); +} + +#ifdef _RAF_SUPPORT +da_ret_t PI_http_set_file_name_to_curl(http_msg_t *http_msg, char *file_path) +{ + NULL_CHECK_RET(http_msg); + NULL_CHECK_RET(file_path); + DA_LOGI("[RAF]set file_path[%s]", file_path); + curl_easy_setopt(http_msg->curl, CURLOPT_BOOSTER_RAF_FILE, file_path); + return DA_RESULT_OK; +} +#endif + +size_t __http_gotchunk_cb(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + http_info_t *http_info = DA_NULL; + da_info_t *da_info = DA_NULL; + http_raw_data_t *raw_data = DA_NULL; + if (!ptr || !userdata) { + DA_LOGE("Check NULL!: ptr, stream"); + return 0; + } + da_info = (da_info_t *)userdata; + NULL_CHECK_RET_OPT(da_info, 0); + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, 0); + NULL_CHECK_RET_OPT(http_info->http_msg, 0); + if (da_info->http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + //DA_LOGV("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr)); +#ifdef _RAF_SUPPORT + //DA_LOGI("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr)); + if (http_info->is_raf_mode_confirmed) { + DA_LOGI("[RAF] return chunked callback"); + return (size * nmemb); + } +#endif + + if (ptr && size * nmemb > 0) { + if (http_info->update_cb) { + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return 0; + } + raw_data->body = (char *)calloc(size, nmemb); + if (!(raw_data->body)) { + DA_LOGE("Fail to calloc"); + free(raw_data); + return 0; + } + memcpy(raw_data->body, ptr, size * nmemb); + raw_data->body_len = size*nmemb; + raw_data->type = HTTP_EVENT_GOT_PACKET; + http_info->update_cb(raw_data, da_info); + } + } + return (size * nmemb); +} + +long __http_finished_cb(void *ptr) +{ + if (!ptr) { + DA_LOGE("Check NULL!: ptr"); + return CURL_CHUNK_END_FUNC_FAIL; + } + DA_LOGI(""); + return CURL_CHUNK_END_FUNC_OK; +} + + +da_ret_t __set_proxy_on_soup_session(char *proxy_addr, CURL *curl) +{ + da_ret_t ret = DA_RESULT_OK; + + if (proxy_addr && strlen(proxy_addr) > 0) { + DA_SECURE_LOGI("received proxy[%s]", proxy_addr); + if (!strstr(proxy_addr, "0.0.0.0")) { + if (strstr((const char *)proxy_addr, "http") == DA_NULL) { + char *tmp_str = DA_NULL; + int needed_len = 0; + + needed_len = strlen(proxy_addr) + strlen( + SCHEME_HTTP) + 1; + tmp_str = (char *) calloc(1, needed_len); + if (!tmp_str) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + snprintf(tmp_str, needed_len, "%s%s", + SCHEME_HTTP, proxy_addr); + + curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr); + + free(tmp_str); + } else { + DA_LOGV("There is \"http\" on uri, so, push this address to soup directly."); + curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr); + } + } + } +ERR: + return ret; +} + +struct curl_slist *__fill_soup_msg_header(CURL *curl, http_info_t *info) +{ + http_msg_request_t *input_http_msg_request; + struct curl_slist *headers = DA_NULL; + + if (!curl) { + DA_LOGE("NULL Check!: curl"); + return DA_NULL; + } + input_http_msg_request = info->http_msg_request; + + if (input_http_msg_request) { + char *field = DA_NULL; + char *value = DA_NULL; + char *buff = DA_NULL; + int len = 0; + http_header_t *cur = DA_NULL; + cur = input_http_msg_request->head; + while (cur) { + field = cur->field; + value = cur->value; + if (field && value) { + len = strlen(field) + strlen(value) + 1; + buff = (char *)calloc(len + 1, sizeof(char)); + if (!buff) { + DA_LOGE("Fail to memalloc"); + break; + } +// DA_SECURE_LOGI("[%s] %s", field, value); + snprintf(buff, len + 1, "%s:%s", field, value); + headers = curl_slist_append(headers, (const char *)buff); + free(buff); + buff = DA_NULL; + } + cur = cur->next; + } + } else { + DA_LOGE("NULL Check!: input_http_msg_request"); + return DA_NULL; + } + if (input_http_msg_request->http_body) { + char buff[256] = {0,}; + int body_len = strlen(input_http_msg_request->http_body); + snprintf(buff, sizeof(buff), "%s:%d", HTTP_FIELD_CONTENT_LENGTH, + body_len); + headers = curl_slist_append(headers, buff); + memset(buff, 0x00, 256); + snprintf(buff, sizeof(buff), "%s:text/plain", HTTP_FIELD_CONTENT_TYPE); + headers = curl_slist_append(headers, buff); + headers = curl_slist_append(headers, input_http_msg_request->http_body); + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + return headers; +} + +#ifdef _RAF_SUPPORT +int __http_progress_cb(void *clientp, double dltotal, double dlnow, + double ultotal, double ulnow) +{ + da_info_t *da_info = DA_NULL; + http_info_t *http_info = DA_NULL; + http_raw_data_t *raw_data = DA_NULL; +/* + if (dlnow > 0 || ulnow > 0) + DA_LOGI("[RAF]dlnow/ulnow[%llu/%llu][%llu,%llu]", (da_size_t)dlnow, (da_size_t)ulnow, (da_size_t)dltotal, (da_size_t)ultotal); +*/ + +/* + if (dlnow == 0) { + DA_LOGI("[RAF]dlnow is zero. Why is this callback called although there is zero size?"); + } +*/ + NULL_CHECK_RET_OPT(clientp, -1); + da_info = (da_info_t *)clientp; + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, -1); + NULL_CHECK_RET_OPT(http_info->http_msg, -1); + + if (http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + + if (dlnow > 0) { + if (http_info->update_cb) { + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return 0; + } + raw_data->received_len = (da_size_t)dlnow; + raw_data->type = HTTP_EVENT_GOT_PACKET; + http_info->update_cb(raw_data, da_info); + } + } + return CURLE_OK; +} +#endif + +da_ret_t PI_http_start(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_method_t http_method; + CURL *curl = DA_NULL; + CURLcode res; + http_msg_t *http_msg = DA_NULL; + char *url = DA_NULL; + http_info_t *http_info = DA_NULL; + long http_status = 0; + struct curl_httppost* post = NULL; + struct curl_slist *headers = DA_NULL; + char err_buffer[CURL_ERROR_SIZE] = {0,}; + + DA_LOGV(""); +#ifdef _RAF_SUPPORT + // test code + get_smart_bonding_vconf(); +#endif + NULL_CHECK_GOTO(da_info); + NULL_CHECK_GOTO(da_info->req_info); + url = da_info->req_info->url; + NULL_CHECK_GOTO(url); + http_info = da_info->http_info; + NULL_CHECK_GOTO(http_info); + + http_method = http_info->http_method; + ret = init_http_msg_t(&http_msg); + if (ret != DA_RESULT_OK) + goto ERR; + http_info->http_msg = http_msg; + + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + + if (!curl) { + DA_LOGE("Fail to create curl"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + DA_LOGI("curl[%p]", curl); + + curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, MAX_SESSION_COUNT); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, MAX_TIMEOUT); + + __set_proxy_on_soup_session(http_info->proxy_addr, curl); + + curl_easy_setopt(curl, CURLOPT_URL, url); + switch (http_method) { + case HTTP_METHOD_GET: + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); + break; + case HTTP_METHOD_POST: + // FIXME later : If the post method is supprot, the post data should be set with curl_fromadd + curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); + DA_LOGI("Need more information for post filed"); + break; + case HTTP_METHOD_HEAD: + DA_LOGI("Donnot implement yet"); + break; + default: + DA_LOGE("Cannot enter here"); + break; + } + + if (using_content_sniffing) { + /* FIXME later*/ + } else { + /* FIXME later*/ + } + headers = __fill_soup_msg_header(curl, http_info); + + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, __http_gotheaders_cb); // can replace to started_cb + curl_easy_setopt(curl, CURLOPT_HEADERDATA, da_info); // param .. same with CURLOPT_WRITEHEADER + curl_easy_setopt(curl, CURLOPT_HEADER, 0L); // does not include header to body + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, __http_gotchunk_cb); // can replace to progress_ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, da_info); // param .. same with CURLOPT_WRITEHEADERcb + curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, __http_finished_cb); + curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, da_info); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); +// curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, err_buffer); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); +#ifdef _RAF_SUPPORT + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, __http_progress_cb); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, da_info); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); +#endif + + if (da_info->req_info->network_bonding) { +#ifdef _DOWNLOAD_BOOSTER_SUPPORT + DA_LOGI("network bonding enable"); + curl_easy_setopt(curl, CURLOPT_MULTIRAT_NEEDED, 1L); +#endif +#ifdef _RAF_SUPPORT + curl_easy_setopt(curl, CURLOPT_BOOSTER_RAF_MODE, 1L); +#endif + } + http_msg->curl = curl; + res = curl_easy_perform(curl); + DA_LOGD("perform done! res[%d]",res); + if (res != CURLE_OK) { + //DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to perform :%d[%s]", res, curl_multi_strerror(res)); + if (strlen(err_buffer) > 1) + DA_LOGE("Fail to error buffer[%s]", err_buffer); + } + if (res != CURLE_OK) { + //DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + if (strlen(err_buffer) > 1) + DA_LOGE("Fail to error buffer[%s]", err_buffer); + } else { + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status); + if (res != CURLE_OK) { + //DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res)); + ret = DA_ERR_FAIL_TO_MEMALLOC;; + goto ERR; + } else { + DA_LOGD("Response Http Status code[%d]", (int)http_status); + } + } + if (http_info->update_cb) { + http_raw_data_t *raw_data = DA_NULL; + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + if (http_msg->is_cancel_reqeusted || + res == CURLE_ABORTED_BY_CALLBACK) { + DA_LOGI("canceled exit. Err[%d]", http_info->error_code); + if (http_info->error_code < 0) + ret = http_info->error_code; + else + ret = DA_RESULT_USER_CANCELED; + } else if ((http_status > 0 && http_status < 100)) { + raw_data->error = __translate_error_code(res); + ret = DA_ERR_NETWORK_FAIL; + } else if (res != CURLE_OK) { + raw_data->error = __translate_error_code(res); + ret = DA_ERR_NETWORK_FAIL; + } else { + raw_data->status_code = (int)http_status; + } + raw_data->type = HTTP_EVENT_FINAL; + http_info->update_cb(raw_data, da_info); + } + if (DA_NULL != headers) + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + http_msg->curl = DA_NULL; + DA_MUTEX_INIT(&(http_msg->mutex), DA_NULL); +ERR: + DA_LOGD("Done"); + return ret; + +} + +da_ret_t PI_http_disconnect(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + + DA_LOGD(""); + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + DA_LOGV("session [%p]", http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + if (http_msg->is_paused) + PI_http_unpause(info); + if (http_msg->curl) + curl_easy_cleanup(http_msg->curl); + + http_msg->curl = DA_NULL; + http_msg->is_paused = DA_FALSE; + http_msg->is_cancel_reqeusted = DA_FALSE; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + DA_MUTEX_DESTROY(&(http_msg->mutex)); + destroy_http_msg_t(http_msg); + info->http_msg = DA_NULL; + return ret; +} + +da_ret_t PI_http_cancel(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + DA_LOGI("curl[%p]", http_msg->curl); + http_msg->is_cancel_reqeusted = DA_TRUE; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + DA_LOGD("Done - soup cancel"); + return ret; +} + +da_ret_t PI_http_pause(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + CURLcode res = CURLE_OK; + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + DA_LOGD("curl [%p]", http_msg->curl); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + DA_LOGE("curl_easy_pause call"); + curl_easy_pause(http_msg->curl, CURLPAUSE_ALL); + DA_LOGE("curl_easy_pause:%d", res); + if (res == CURLE_OK) { + http_msg->is_paused = DA_TRUE; + } else { + ret = DA_ERR_CANNOT_SUSPEND; + } + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + return ret; +} + +da_ret_t PI_http_unpause(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + CURLcode res = CURLE_OK; + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + DA_LOGV("curl [%p]", http_msg->curl); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + res = curl_easy_pause(http_msg->curl, CURLPAUSE_CONT); + if (res == CURLE_OK) + http_msg->is_paused = DA_FALSE; + else + ret = DA_ERR_CANNOT_RESUME; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + return ret; +} diff --git a/agent/download-agent-plugin-libsoup.c b/agent/download-agent-plugin-libsoup.c deleted file mode 100755 index 6d54afd..0000000 --- a/agent/download-agent-plugin-libsoup.c +++ /dev/null @@ -1,1002 +0,0 @@ -/* - * 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 <string.h> - -#include "download-agent-debug.h" -#include "download-agent-plugin-libsoup.h" -#include "download-agent-http-misc.h" -#include "download-agent-utils.h" -#include "download-agent-pthread.h" - -pthread_mutex_t mutex_for_session_table = PTHREAD_MUTEX_INITIALIZER; - -pi_session_table_t pi_session_table[MAX_SESSION_COUNT] = { { 0, }, }; -da_bool_t using_content_sniffing; - -da_bool_t _pi_http_is_this_session_table_entry_using( - const int in_session_table_entry); - -da_result_t PI_http_init(void) -{ - DA_LOG_FUNC_LOGV(HTTPManager); - - using_content_sniffing = DA_TRUE; - - return DA_RESULT_OK; -} - -void PI_http_deinit(void) -{ - DA_LOG_FUNC_LOGV(HTTPManager); - - return; -} - -da_result_t _set_proxy_on_soup_session(SoupSession *session, char *proxy_addr) -{ - da_result_t ret = DA_RESULT_OK; - - - if (proxy_addr && strlen(proxy_addr) > 0) { - DA_SECURE_LOGD("received proxy = %s \n", proxy_addr); - if (!strstr(proxy_addr, "0.0.0.0")) { - if (strstr((const char *)proxy_addr, "http") == DA_NULL) { - DA_LOG_VERBOSE(Default,"There is no \"http://\" on received uri, so, add it."); - - char *tmp_str = DA_NULL; - int needed_len = 0; - - needed_len = strlen(proxy_addr) + strlen( - SCHEME_HTTP) + 1; - tmp_str = (char *) calloc(1, needed_len); - if (!tmp_str) { - DA_LOG_ERR(HTTPManager,"DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - snprintf(tmp_str, needed_len, "%s%s", - SCHEME_HTTP, proxy_addr); - - g_object_set(session, SOUP_SESSION_PROXY_URI, - soup_uri_new(tmp_str), NULL); - - free(tmp_str); - } else { - DA_LOG(HTTPManager,"There is \"http\" on uri, so, push this address to soup directly."); - g_object_set(session, SOUP_SESSION_PROXY_URI, - soup_uri_new(proxy_addr), NULL); - } - } - } else { - DA_LOG_VERBOSE(HTTPManager,"There is no proxy value"); - } -ERR: - return ret; -} - -void _fill_soup_msg_header(SoupMessage *msg, - const input_for_tranx_t *input_for_tranx) -{ - SoupMessageHeaders *headers = msg->request_headers; - - http_msg_request_t *input_http_msg_request; - http_msg_iter_t http_msg_iter; - http_msg_iter_t http_msg_iter_pre; - - char *field; - char *value; - - input_http_msg_request = input_for_tranx->http_msg_request; - - http_msg_request_get_iter(input_http_msg_request, &http_msg_iter); - http_msg_iter_pre = http_msg_iter; - while (http_msg_get_field_with_iter(&http_msg_iter, &field, &value)) { - if ((field != DA_NULL) && (value != DA_NULL)) { - DA_SECURE_LOGD("[%s] %s", field, value); - soup_message_headers_append(headers, field, value); - } - http_msg_iter_pre = http_msg_iter; - } - - if (input_http_msg_request->http_body) { - char body_len_str[16] = { 0, }; - int body_len = strlen(input_http_msg_request->http_body); - - snprintf(body_len_str, sizeof(body_len_str), "%d", body_len); - - soup_message_headers_append(headers, "Content-Length", - body_len_str); - soup_message_headers_append(headers, "Content-Type", - "text/plain"); - soup_message_body_append(msg->request_body, SOUP_MEMORY_COPY, - input_http_msg_request->http_body, body_len); - } -} - -da_result_t PI_http_start_transaction(const input_for_tranx_t *input_for_tranx, - int *out_tranx_id) -{ - da_result_t ret = DA_RESULT_OK; - int session_table_entry = -1; - pi_http_method_t pi_http_method = PI_HTTP_METHOD_GET; - queue_t *queue = DA_NULL; - char *url = DA_NULL; - SoupSession *session = DA_NULL; - SoupMessage *msg = DA_NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if (DA_FALSE == _pi_http_is_valid_input_for_tranx(input_for_tranx)) { - DA_LOG_ERR(HTTPManager,"input_for_tranx is invalid"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } else { - queue = input_for_tranx->queue; - pi_http_method = input_for_tranx->http_method; - url = input_for_tranx->http_msg_request->url; - } - - session_table_entry = _pi_http_get_avaiable_session_table_entry(); - if (session_table_entry == -1) { - ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - goto ERR; - } - DA_LOG_VERBOSE(HTTPManager,"session_table_entry = %d", session_table_entry); - - if (DA_FALSE == _pi_http_register_queue_to_session_table( - session_table_entry, queue)) { - _pi_http_destroy_session_table_entry(session_table_entry); - ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - goto ERR; - } - - /* modified by keunsoon.lee 2010-09-20 use sync_new() instead of async_new() for make different soup thread from UI main thread*/ - session = soup_session_sync_new(); - /* session=soup_session_async_new(); */ - if (!session) { - DA_LOG_ERR(HTTPManager,"Fail to create session"); - return DA_ERR_INVALID_URL; - } - DA_LOG(HTTPManager,"session[%p]", session); -/* - SoupLogger* logger = soup_logger_new(SOUP_LOGGER_LOG_BODY, -1); - soup_logger_attach(logger, session); - g_object_unref(logger); -*/ - if (DA_FALSE == _pi_http_register_session_to_session_table( - session_table_entry, session)) { - _pi_http_init_session_table_entry(session_table_entry); - ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - goto ERR; - } - - g_object_set(session, SOUP_SESSION_MAX_CONNS, MAX_SESSION_COUNT, NULL); - /* Set timeout unlimited time to resume a download which has ETag when the network is re-connected - * => This is changed to 180 seconds due to limitation of max downloading items. - */ - g_object_set(session, SOUP_SESSION_TIMEOUT, MAX_TIMEOUT, NULL); - - _set_proxy_on_soup_session(session, input_for_tranx->proxy_addr); - - switch (pi_http_method) { - case PI_HTTP_METHOD_GET: - msg = soup_message_new(METHOD_GET, url); - break; - case PI_HTTP_METHOD_POST: - msg = soup_message_new(METHOD_POST, url); - break; - case PI_HTTP_METHOD_HEAD: - msg = soup_message_new(METHOD_HEAD, url); - break; - default: - DA_LOG_ERR(HTTPManager,"Cannot enter here"); - break; - } - DA_LOG_VERBOSE(HTTPManager,"msg[%p]", msg); - /* if it is failed to create a msg, the url can be invalid, becasue of the input argument of soup_message_new API */ - if (msg == NULL) { - DA_LOG_ERR(HTTPManager,"Fail to create message"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - _fill_soup_msg_header(msg, input_for_tranx); - - g_signal_connect(msg, "restarted", G_CALLBACK(_pi_http_restarted_cb), - NULL); /* for redirection case */ - g_signal_connect(msg, "got-headers", - G_CALLBACK(_pi_http_gotheaders_cb), NULL); - g_signal_connect(msg, "got-chunk", G_CALLBACK(_pi_http_gotchunk_cb), - NULL); - - if (using_content_sniffing) { - soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_SNIFFER); - g_signal_connect(msg, "content-sniffed", - G_CALLBACK(_pi_http_contentsniffed_cb), NULL); - } else { - soup_message_disable_feature(msg, SOUP_TYPE_CONTENT_SNIFFER); - } - - soup_session_queue_message(session, msg, _pi_http_finished_cb, NULL); -// g_signal_connect(msg, "finished", G_CALLBACK(_pi_http_finished_cb), NULL); - - if (DA_FALSE == _pi_http_register_msg_to_session_table( - session_table_entry, msg)) { - _pi_http_destroy_session_table_entry(session_table_entry); - ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - goto ERR; - } - - *out_tranx_id = session_table_entry; - DA_LOG(HTTPManager,"*out_tranx_id = %d", *out_tranx_id); - -ERR: - return ret; -} - -da_result_t PI_http_disconnect_transaction(int in_tranx_id) -{ - da_result_t ret = DA_RESULT_OK; - int session_table_entry = -1; - - DA_LOG_VERBOSE(HTTPManager,"in_tranx_id = %d", in_tranx_id); - - session_table_entry = in_tranx_id; - - _pi_http_destroy_session_table_entry(session_table_entry); - - return ret; -} - -da_result_t PI_http_cancel_transaction(int in_tranx_id, da_bool_t abort_option) -{ - da_result_t ret = DA_RESULT_OK; - SoupSession *session; - SoupMessage *msg; - int session_table_entry = -1; - - DA_LOG_FUNC_LOGV(HTTPManager); - - session_table_entry = in_tranx_id; - if (!_pi_http_is_this_session_table_entry_using(session_table_entry)) { - DA_LOG_CRITICAL(HTTPManager,"not using session"); - return ret; - } - session = GET_SESSION_FROM_TABLE_ENTRY(session_table_entry); - msg = GET_MSG_FROM_TABLE_ENTRY(session_table_entry); - - if (DA_NULL == session) { - DA_LOG_ERR(HTTPManager,"invalid session = %p", session); - goto ERR; - } - - if (DA_NULL == msg) { - DA_LOG_ERR(HTTPManager,"invalid message = %p", msg); - goto ERR; - } - DA_LOG(HTTPManager,"soup cancel API:abort option[%d] tranx_id[%d]", - abort_option, in_tranx_id); - if (abort_option) - soup_session_abort(session); - else - soup_session_cancel_message(session, msg, SOUP_STATUS_CANCELLED); - DA_LOG(HTTPManager,"soup cancel API-Done"); -ERR: - return ret; -} - -void PI_http_pause_transaction(int transaction_id) -{ - int session_table_entry = -1; - pthread_mutex_t *mutex; - pthread_cond_t *cond; - - DA_LOG_FUNC_LOGD(HTTPManager); - - DA_LOG(HTTPManager,"in_tranx_id = %d", transaction_id); - - session_table_entry = transaction_id; - - if (!_pi_http_is_this_session_table_entry_using(session_table_entry)) - return; - - mutex = &(pi_session_table[session_table_entry].mutex); - cond = &(pi_session_table[session_table_entry].cond); - - _da_thread_mutex_lock (mutex); - - if (pi_session_table[session_table_entry].is_paused == DA_FALSE) { - DA_LOG_CRITICAL(HTTPManager,"paused!"); - pi_session_table[session_table_entry].is_paused = DA_TRUE; - _da_thread_cond_wait(cond, mutex); - } else { - DA_LOG_CRITICAL(HTTPManager,"NOT paused!"); - } - - _da_thread_mutex_unlock (mutex); - -} - -void PI_http_unpause_transaction(int transaction_id) -{ - int session_table_entry = -1; - pthread_mutex_t *mutex; - pthread_cond_t *cond; - - DA_LOG_FUNC_LOGV(Default); - - session_table_entry = transaction_id; - - if (!_pi_http_is_this_session_table_entry_using(session_table_entry)) - return; - - mutex = &(pi_session_table[session_table_entry].mutex); - cond = &(pi_session_table[session_table_entry].cond); - - _da_thread_mutex_lock (mutex); - - if (pi_session_table[session_table_entry].is_paused == DA_TRUE) { - DA_LOG_CRITICAL(HTTPManager,"wake up!"); - pi_session_table[session_table_entry].is_paused = DA_FALSE; - _da_thread_cond_signal(cond); - } - - _da_thread_mutex_unlock (mutex); - -} - -da_bool_t _pi_http_is_valid_input_for_tranx( - const input_for_tranx_t *input_for_tranx) -{ - if (!(input_for_tranx->http_msg_request)) { - DA_LOG_ERR(HTTPManager,"http_msg_request is NULL"); - return DA_FALSE; - } - - if (!((input_for_tranx->http_method == PI_HTTP_METHOD_GET) || - (input_for_tranx->http_method == PI_HTTP_METHOD_POST) || - (input_for_tranx->http_method == PI_HTTP_METHOD_HEAD))) { - DA_LOG_ERR(HTTPManager,"http_method is neither GET or POST or HEAD"); - return DA_FALSE; - } - - return DA_TRUE; -} - -da_bool_t _pi_http_is_this_session_table_entry_using( - const int in_session_table_entry) -{ - da_bool_t is_using = DA_FALSE; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(in_session_table_entry)) - return DA_FALSE; - - _da_thread_mutex_lock (&mutex_for_session_table); - - is_using = pi_session_table[in_session_table_entry].is_using; - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return is_using; -} - -void _pi_http_init_session_table_entry(const int in_session_table_entry) -{ - int entry = in_session_table_entry; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) - return; - -// _da_thread_mutex_lock (&mutex_for_session_table); - - pi_session_table[entry].is_using = DA_TRUE; - pi_session_table[entry].msg = NULL; - pi_session_table[entry].session = NULL; - pi_session_table[entry].queue = NULL; - - _da_thread_mutex_init(&(pi_session_table[entry].mutex), DA_NULL); - _da_thread_cond_init(&(pi_session_table[entry].cond), NULL); - pi_session_table[entry].is_paused = DA_FALSE; - -// _da_thread_mutex_unlock (&mutex_for_session_table); - - return; -} - -void _pi_http_destroy_session_table_entry(const int in_session_table_entry) -{ - int entry = in_session_table_entry; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) - return; - - _da_thread_mutex_lock (&mutex_for_session_table); - - if (pi_session_table[entry].is_paused == DA_TRUE) - PI_http_unpause_transaction(entry); - - /* Warning! Do not g_object_unref(msg) here! - * soup_session_queue_message() steals msg's reference count, - * so, we don't need to do anything for memory management. - * - * But, if using soup_session_send_message(), MUST call g_object_unref(msg). */ - /* if (pi_session_table[entry].msg) - g_object_unref(pi_session_table[entry].msg); */ - - pi_session_table[entry].msg = NULL; - - /* FIXME Cannot g_object_unref(session) here, - * because msg inside this session is not destoryed yet. - * The msg's reference count is stealed by soup_session_queue_message(), - * and it will be destroyed when _pi_http_finished_cb() is returned. - * For now, this _pi_http_destroy_session_table_entry() is called inside - * _pi_http_finished_cb(), so, g_object_unref(session) is not working. - * Should find out call this function after _pi_http_finished_cb(). */ - if (pi_session_table[entry].session) - g_object_unref(pi_session_table[entry].session); - else - DA_LOG_ERR(HTTPManager,"session is NULL. Cannot unref this."); - DA_LOG(HTTPManager,"unref session [%p]",pi_session_table[entry].session); - - pi_session_table[entry].session = NULL; - - pi_session_table[entry].queue = NULL; - pi_session_table[entry].is_paused = DA_FALSE; - pi_session_table[entry].is_using = DA_FALSE; - - _da_thread_mutex_destroy(&(pi_session_table[entry].mutex)); - _da_thread_cond_destroy(&(pi_session_table[entry].cond)); - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return; -} - -int _pi_http_get_avaiable_session_table_entry(void) -{ - int i; - int avaiable_entry = -1; - - _da_thread_mutex_lock (&mutex_for_session_table); - - for (i = 0; i < MAX_SESSION_COUNT; i++) { - if (pi_session_table[i].is_using == DA_FALSE) { - /* pi_session_table[i].is_using = DA_TRUE; */ - DA_LOG_VERBOSE(HTTPManager,"available entry = %d", i); - - avaiable_entry = i; - - break; - } - } - _pi_http_init_session_table_entry(avaiable_entry); - _da_thread_mutex_unlock (&mutex_for_session_table); - - return avaiable_entry; -} - -da_bool_t _pi_http_register_queue_to_session_table( - const int in_session_table_entry, const queue_t *in_queue) -{ - int entry = in_session_table_entry; - queue_t *queue = (queue_t *) in_queue; - da_bool_t ret = DA_FALSE; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { - DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); - return DA_FALSE; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - if (pi_session_table[entry].is_using == DA_FALSE) { - DA_LOG_ERR(HTTPManager,"this entry [%d] is not using", entry); - ret = DA_FALSE; - } else { - pi_session_table[entry].queue = queue; - DA_LOG_VERBOSE(HTTPManager,"queue = %p", pi_session_table[entry].queue); - ret = DA_TRUE; - } - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return ret; -} - -da_bool_t _pi_http_register_session_to_session_table( - const int in_session_table_entry, SoupSession *session) -{ - int entry = in_session_table_entry; - da_bool_t ret = DA_FALSE; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { - DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); - return DA_FALSE; - } - - if (DA_NULL == session) { - DA_LOG_ERR(HTTPManager,"invalid session = %p",session); - return DA_FALSE; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - if (pi_session_table[entry].is_using == DA_FALSE) { - ret = DA_FALSE; - } else { - pi_session_table[entry].session = session; - ret = DA_TRUE; - } - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return ret; -} - -da_bool_t _pi_http_register_msg_to_session_table( - const int in_session_table_entry, SoupMessage *msg) -{ - int entry = in_session_table_entry; - da_bool_t ret = DA_FALSE; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { - DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); - return DA_FALSE; - } - - if (DA_NULL == msg) { - DA_LOG_ERR(HTTPManager,"invalid msg = %p",msg); - return DA_FALSE; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - if (pi_session_table[entry].is_using == DA_FALSE) { - ret = DA_FALSE; - } else { - pi_session_table[entry].msg = msg; - ret = DA_TRUE; - } - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return ret; -} - -queue_t *_pi_http_get_queue_from_session_table_entry( - const int in_session_table_entry) -{ - int entry = in_session_table_entry; - queue_t *out_queue = NULL; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { - DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); - return out_queue; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - out_queue = pi_session_table[entry].queue; - _da_thread_mutex_unlock (&mutex_for_session_table); - - return out_queue; -} - -void _pi_http_store_read_header_to_queue(SoupMessage *msg, const char *sniffedType) -{ - da_result_t ret = DA_RESULT_OK; - - queue_t *da_queue = NULL; - q_event_t *da_event = NULL; - q_event_type_data da_event_type_data; - - int session_table_entry = -1; - SoupMessageHeadersIter headers_iter; - - const char *header_name; - const char *header_value; - - http_msg_response_t *http_msg_response = NULL; - - if (msg->response_headers) { - ret = http_msg_response_create(&http_msg_response); - if (ret != DA_RESULT_OK) - return; - - http_msg_response_set_status_code(http_msg_response, - msg->status_code); - - DA_LOG_VERBOSE(HTTPManager,"\n----raw header---------------------------------------------"); - DA_LOG(HTTPManager,"status code = %d", msg->status_code); - soup_message_headers_iter_init(&headers_iter, - msg->response_headers); - while (soup_message_headers_iter_next(&headers_iter, - &header_name, &header_value)) { - if ((header_name != DA_NULL) && (header_value - != DA_NULL)) { - http_msg_response_add_field(http_msg_response, - header_name, header_value); - DA_SECURE_LOGI("[%s][%s]", header_name, header_value); - } - } - DA_LOG_VERBOSE(HTTPManager,"\n-------------------------------------------------------------\n"); - - } - - if (using_content_sniffing && sniffedType) - http_msg_response_set_content_type(http_msg_response, sniffedType); - - session_table_entry - = _pi_http_get_session_table_entry_from_message(msg); - if (session_table_entry == -1) { - DA_LOG_ERR(HTTPManager,"Fail to find matched session table entry.."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - da_event_type_data = Q_EVENT_TYPE_DATA_PACKET; - - da_queue = _pi_http_get_queue_from_session_table_entry( - session_table_entry); - - ret = Q_make_http_data_event(da_event_type_data, &da_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager,"fail to make da_event"); - goto ERR; - } else { - Q_set_status_code_on_http_data_event(da_event, msg->status_code); - da_event->type.q_event_data_http.http_response_msg - = http_msg_response; - - Q_push_event(da_queue, da_event); - } - return; - -ERR: - if (DA_RESULT_OK != ret) - http_msg_response_destroy(&http_msg_response); - - return; -} - -void _pi_http_store_read_data_to_queue(SoupMessage *msg, const char *body_data, - int received_body_len) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - - char *body_buffer = NULL; - queue_t *da_queue = NULL; - q_event_t *da_event = NULL; - q_event_type_data da_event_type_data; - int session_table_entry = -1; - int http_status = -1; - - http_status = msg->status_code; - - session_table_entry - = _pi_http_get_session_table_entry_from_message(msg); - if (session_table_entry == -1) { - DA_LOG_ERR(HTTPManager,"Fail to find matched session table entry.."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - if (received_body_len == 0) { - DA_LOG_VERBOSE(HTTPManager,"Q_EVENT_TYPE_DATA_FINAL"); - da_event_type_data = Q_EVENT_TYPE_DATA_FINAL; - } else { - da_event_type_data = Q_EVENT_TYPE_DATA_PACKET; - if (received_body_len > 0) { - body_buffer = (char*) calloc(1, received_body_len); - DA_LOG_VERBOSE(HTTPManager,"body_buffer[%p]msg[%p]",body_buffer,msg); - if (body_buffer == DA_NULL) { - DA_LOG_ERR(HTTPManager,"DA_ERR_FAIL_TO_MEMALLOC"); - goto ERR; - } - memcpy(body_buffer, body_data, received_body_len); - } - } - - da_queue = _pi_http_get_queue_from_session_table_entry( - session_table_entry); - - ret = Q_make_http_data_event(da_event_type_data, &da_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager,"fail to make da_event"); - goto ERR; - } else { - Q_set_status_code_on_http_data_event(da_event, http_status); - Q_set_http_body_on_http_data_event(da_event, received_body_len, - body_buffer); - - _da_thread_mutex_lock (&(da_queue->mutex_queue)); - b_ret = Q_push_event_without_lock(da_queue, da_event); - if (b_ret == DA_FALSE) { - DA_LOG_CRITICAL(HTTPManager,"----------------------------------------fail to push!"); - - pthread_mutex_t *session_mutex = NULL; - pthread_cond_t *session_cond = NULL; - - session_mutex - = &(pi_session_table[session_table_entry].mutex); - session_cond - = &(pi_session_table[session_table_entry].cond); - - /* MUST keep this order for these mutexes */ - _da_thread_mutex_lock (session_mutex); - _da_thread_mutex_unlock (&(da_queue->mutex_queue)); - - if (pi_session_table[session_table_entry].is_paused - == DA_FALSE) { - DA_LOG_CRITICAL(HTTPManager,"paused!"); - pi_session_table[session_table_entry].is_paused - = DA_TRUE; - _da_thread_cond_wait(session_cond, session_mutex); - } else { - DA_LOG_CRITICAL(HTTPManager,"NOT paused!"); - } - - _da_thread_mutex_unlock (session_mutex); - - DA_LOG_CRITICAL(HTTPManager,"wake up! push again"); - Q_push_event(da_queue, da_event); - } else { - _da_thread_mutex_unlock (&(da_queue->mutex_queue)); - } - - } - - return; - -ERR: - if (DA_RESULT_OK != ret) { - if (DA_NULL != body_buffer) { - free(body_buffer); - } - } - - return; -} - -int _translate_error_code(int soup_error) -{ - DA_LOG_CRITICAL(HTTPManager, "soup error code[%d]", soup_error); - switch (soup_error) { - case SOUP_STATUS_CANT_RESOLVE: - case SOUP_STATUS_CANT_RESOLVE_PROXY: - case SOUP_STATUS_CANT_CONNECT: - case SOUP_STATUS_CANT_CONNECT_PROXY: - case SOUP_STATUS_IO_ERROR: - case SOUP_STATUS_MALFORMED: - case SOUP_STATUS_TRY_AGAIN: - return DA_ERR_NETWORK_FAIL; - case SOUP_STATUS_SSL_FAILED: - return DA_ERR_SSL_FAIL; - case SOUP_STATUS_REQUEST_TIMEOUT: - return DA_ERR_HTTP_TIMEOUT; - case SOUP_STATUS_TOO_MANY_REDIRECTS: - return DA_ERR_TOO_MANY_REDIECTS; - default: - return DA_ERR_NETWORK_FAIL; - } -} - -void _pi_http_store_neterr_to_queue(SoupMessage *msg) -{ - da_result_t ret = DA_RESULT_OK; - int error_type = -1; - queue_t *da_queue = NULL; - q_event_t *da_event = NULL; - int session_table_entry = -1; - - DA_LOG_FUNC_LOGD(HTTPManager); - - error_type = _translate_error_code(msg->status_code); - - session_table_entry - = _pi_http_get_session_table_entry_from_message(msg); - if (session_table_entry == -1) { - DA_LOG_ERR(HTTPManager,"Fail to find matched session table entry.."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - da_queue = _pi_http_get_queue_from_session_table_entry( - session_table_entry); - - DA_LOG_CRITICAL(HTTPManager,"Q_EVENT_TYPE_DATA_ABORT"); - ret = Q_make_http_data_event(Q_EVENT_TYPE_DATA_ABORT, &da_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager,"fail to make da_event"); - goto ERR; - } else { - Q_set_error_type_on_http_data_event(da_event, error_type); - - Q_push_event(da_queue, da_event); - } - -ERR: - return; -} - -int _pi_http_get_session_table_entry_from_message(SoupMessage *msg) -{ - - int out_entry = -1; - int i; - - if (DA_NULL == msg) { - DA_LOG_ERR(HTTPManager,"invalid message = %p", msg); - return out_entry; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - for (i = 0; i < MAX_SESSION_COUNT; i++) { - if (pi_session_table[i].is_using == DA_TRUE) { - if (pi_session_table[i].msg == msg) { - out_entry = i; - break; - } - } - } - - _da_thread_mutex_unlock (&mutex_for_session_table); - - if (i == MAX_SESSION_COUNT) { - DA_LOG_ERR(HTTPManager,"fail to find message = %p", msg); - } - - return out_entry; - -} - -void _pi_http_finished_cb(SoupSession *session, SoupMessage *msg, gpointer data) -{ - char *url = NULL; - - DA_LOG_FUNC_LOGV(HTTPManager); - - if (!msg) { - DA_LOG_ERR(HTTPManager, "Check NULL:msg"); - return; - } - - url = soup_uri_to_string(soup_message_get_uri(msg), DA_FALSE); - - DA_SECURE_LOGI("status_code[%d], reason[%s], url[%s]",msg->status_code,msg->reason_phrase,url); - - if (url) { - free(url); - url = NULL; - } - - if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) { - if (msg->status_code == SOUP_STATUS_CANCELLED) { - _pi_http_store_read_data_to_queue(msg, DA_NULL, 0); - } else { - _pi_http_store_neterr_to_queue(msg); - } - } else { - _pi_http_store_read_data_to_queue(msg, DA_NULL, 0); - } - -} - -/* this callback is called in case of redirection */ -void _pi_http_restarted_cb(SoupMessage *msg, gpointer data) -{ - DA_LOG_FUNC_LOGD(HTTPManager); - /* Location URL is needed when extracting the file name from url. - * So, the response header should be handled by http mgr.*/ - - if (!msg) { - DA_LOG_ERR(HTTPManager, "Check NULL:msg"); - return; - } - // If there are user id and password at url, libsoup handle it automatically. - if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { - DA_LOG(HTTPManager,"Ignore:Unauthorized"); - return; - } - _pi_http_store_read_header_to_queue(msg, NULL); -} - -void _pi_http_gotheaders_cb(SoupMessage *msg, gpointer data) -{ - DA_LOG_FUNC_LOGV(HTTPManager); - - if (!msg) { - DA_LOG_ERR(HTTPManager, "Check NULL:msg"); - return; - } - - if (SOUP_STATUS_IS_REDIRECTION(msg->status_code)) { - DA_LOG(HTTPManager,"Redirection !!"); - if (SOUP_STATUS_NOT_MODIFIED != msg->status_code) - return; - } - - // If there are user id and password at url, libsoup handle it automatically. - if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { - DA_LOG(HTTPManager,"Ignore:Unauthorized"); - return; - } - - soup_message_body_set_accumulate(msg->response_body, DA_FALSE); - - if (!using_content_sniffing) - _pi_http_store_read_header_to_queue(msg, NULL); - else - DA_LOG_DEBUG(HTTPManager,"ignore because content sniffing is turned on"); -} - -void _pi_http_contentsniffed_cb(SoupMessage *msg, const char *sniffedType, - GHashTable *params, gpointer data) -{ - DA_LOG_FUNC_LOGD(HTTPManager); - - if (!msg) { - DA_LOG_ERR(HTTPManager, "Check NULL:msg"); - return; - } - - if (SOUP_STATUS_IS_REDIRECTION(msg->status_code)) { - DA_LOG(HTTPManager,"Redirection !!"); - if (SOUP_STATUS_NOT_MODIFIED != msg->status_code) - return; - } - - // If there are user id and password at url, libsoup handle it automatically. - if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { - DA_LOG(HTTPManager,"Ignore:Unauthorized"); - return; - } - - if (using_content_sniffing) - _pi_http_store_read_header_to_queue(msg, sniffedType); -} - -void _pi_http_gotchunk_cb(SoupMessage *msg, SoupBuffer *chunk, gpointer data) -{ -// DA_LOG_FUNC_LOGV(HTTPManager); - - if (!msg) { - DA_LOG_ERR(HTTPManager, "Check NULL:msg"); - return; - } - - if (!chunk) { - DA_LOG_ERR(HTTPManager, "Check NULL:chunk"); - return; - } - - if (SOUP_STATUS_IS_REDIRECTION(msg->status_code)) - return; - - if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { - DA_LOG(HTTPManager,"Ignore:Unauthorized"); - return; - } - - if (chunk->data && chunk->length > 0) { - _pi_http_store_read_data_to_queue(msg, chunk->data, - chunk->length); - } -} diff --git a/agent/download-agent-utils-dl-id-history.c b/agent/download-agent-utils-dl-id-history.c deleted file mode 100755 index c6e747d..0000000 --- a/agent/download-agent-utils-dl-id-history.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 "download-agent-type.h" -#include "download-agent-utils.h" -#include "download-agent-utils-dl-id-history.h" - -da_result_t init_dl_id_history(dl_id_history_t *dl_id_history) -{ - da_result_t ret = DA_RESULT_OK; - - /* Initial dl_id_history will be starting number for dl_id. - * dl_id will be sequentially increased from the dl_id_history, - * then dl_id_history will be updated. */ - _da_thread_mutex_init(&(dl_id_history->mutex), DA_NULL); - _da_thread_mutex_lock(&(dl_id_history->mutex)); - get_random_number(&(dl_id_history->starting_num)); - dl_id_history->cur_dl_id = DA_INVALID_ID; - _da_thread_mutex_unlock(&(dl_id_history->mutex)); - - DA_LOG_VERBOSE(Default,"starting num = %d", dl_id_history->starting_num); - return ret; -} - -da_result_t deinit_dl_id_history(dl_id_history_t *dl_id_history) -{ - da_result_t ret = DA_RESULT_OK; - - _da_thread_mutex_lock(&(dl_id_history->mutex)); - dl_id_history->starting_num = DA_INVALID_ID; - dl_id_history->cur_dl_id = DA_INVALID_ID; - _da_thread_mutex_unlock(&(dl_id_history->mutex)); - - _da_thread_mutex_destroy(&(dl_id_history->mutex)); - - return ret; -} - -int get_available_dl_id(dl_id_history_t *dl_id_history) -{ - int dl_id = 0; - - _da_thread_mutex_lock(&(dl_id_history->mutex)); - - if (dl_id_history->cur_dl_id == DA_INVALID_ID) - dl_id_history->cur_dl_id = dl_id_history->starting_num; - else if (dl_id_history->cur_dl_id > 254) - dl_id_history->cur_dl_id = 1; - else - dl_id_history->cur_dl_id++; - - dl_id = dl_id_history->cur_dl_id; - - _da_thread_mutex_unlock(&(dl_id_history->mutex)); - - DA_LOG_VERBOSE(Default,"dl_id = %d", dl_id); - return dl_id; -} diff --git a/agent/download-agent-utils.c b/agent/download-agent-utils.c deleted file mode 100755 index 71aca16..0000000 --- a/agent/download-agent-utils.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * 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 <sys/vfs.h> -#include <sys/stat.h> -#include <string.h> -#include <stdlib.h> -#include <time.h> -#include <glib.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> - -#include "download-agent-client-mgr.h" -#include "download-agent-debug.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-file.h" -#include "download-agent-http-misc.h" -#include "download-agent-mime-util.h" -#include "download-agent-utils.h" -#include "download-agent-plugin-conf.h" -#include "download-agent-dl-info-util.h" - -#define DA_HTTP_HEADER_CONTENT_TYPE "Content-Type" -#define DA_HTTP_HEADER_CONTENT_LENGTH "Content-Length" -#define DA_FILE_NUMBER_LIMIT (1024*1024) - -typedef struct _da_descriptor_mime_table_t { - char *content_type; - da_mime_type_id_t mime_type; -} da_descriptor_mime_table_t; - -da_descriptor_mime_table_t - descriptor_mime_table[] = { - {"", DA_MIME_TYPE_NONE}, - /* DRM1.0 */ - {"application/vnd.oma.drm.message", - DA_MIME_TYPE_DRM1_MESSATE}, /* drm1.0 FL.CD*/ - {"", DA_MIME_TYPE_END}}; - -void get_random_number(int *out_num) -{ - int temp = DA_INVALID_ID; - unsigned int seed = (unsigned)time(0); - - temp = (int)(rand_r(&seed) % 100 + 1.0); - *out_num = temp; -} - -da_result_t get_extension_from_mime_type(char *mime_type, char **extension) -{ - da_result_t ret = DA_RESULT_OK; - char *ext = DA_NULL; - - DA_LOG_FUNC_LOGV(Default); - if (DA_NULL == mime_type || DA_NULL == extension) { - DA_LOG_ERR(Default,"received mime_type is null"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } -// DA_SECURE_LOGD("input mime type = %s", mime_type); - if (DA_RESULT_OK != (ret = da_mime_get_ext_name(mime_type, &ext))) { - DA_LOG_ERR(Default,"can't find proper extension!"); - goto ERR; - } - *extension = ext; -// DA_SECURE_LOGD("found extension = %s", *extension); - -ERR: - return ret; -} - -int read_data_from_file(char *file, char **out_buffer) -{ - FILE *fd; - unsigned long long file_size = -1; - char *buffer = NULL; - int buffer_len = 0; - size_t read_len = 0; - - *out_buffer = NULL; - - if (!file) - return 0; - - /* open file with "rb", because fread() handles the file as binary mode */ - fd = fopen(file, "rb"); - if (!fd) { - DA_LOG_ERR(FileManager,"File open err! received file path"); - return 0; - } - - get_file_size(file, &file_size); - if (file_size <= 0) { - DA_LOG_ERR(FileManager,"file size is [%llu]", file_size); - fclose(fd); - return 0; - } - - /* A guide from www.securecoding.cert.org - * : FIO17-C. Do not rely on an ending null character when using fread() - * - * buffer is initialized with null through calloc(), so, it is always null-terminated even if fread() failed. - * allocate memory one more byte to ensure null-terminated even if the file is not null-terminated. - */ - buffer_len = sizeof(char) * file_size; - buffer = (char *)calloc(1, buffer_len + 1); - if (buffer) { - read_len = fread(buffer, sizeof(char), file_size, fd); - if (read_len == file_size) { - *out_buffer = buffer; - } else { - DA_LOG_ERR(FileManager,"File Read Not Complete read length = %d", read_len); - free(buffer); - buffer = NULL; - buffer_len = 0; - } - } else { - buffer_len = 0; - } - - fclose(fd); - - return buffer_len; -} - -da_result_t get_available_memory(da_storage_size_t *avail_memory) -{ - da_result_t ret = DA_RESULT_OK; - int fs_ret = 0; - struct statfs filesys_info = {0, }; - char *default_install_dir = NULL; - - DA_LOG_FUNC_LOGD(Default); - - if (!avail_memory) - return DA_ERR_INVALID_ARGUMENT; - - ret = get_default_install_dir(&default_install_dir); - - if (ret == DA_RESULT_OK && default_install_dir) { - fs_ret = statfs(default_install_dir, &filesys_info); - } else { - return DA_ERR_FAIL_TO_ACCESS_STORAGE; - } - - if (fs_ret != 0) { - DA_LOG_ERR(Default,"Phone file path :statfs error - [%d]", errno); - free(default_install_dir); - return DA_ERR_INVALID_INSTALL_PATH; - } - - avail_memory->b_available = filesys_info.f_bavail; - avail_memory->b_size = filesys_info.f_bsize; - - DA_LOG_VERBOSE(Default, "Available Memory(f_bavail) : %llu", filesys_info.f_bavail); - DA_LOG_VERBOSE(Default, "Available Memory(f_bsize) : %d", filesys_info.f_bsize); - DA_LOG_VERBOSE(Default, "Available Memory(kbytes) : %lu", (filesys_info.f_bavail/1024)*filesys_info.f_bsize); - - free(default_install_dir); - return DA_RESULT_OK; -} - -da_mime_type_id_t get_mime_type_id(char *content_type) -{ - int i = 0; - - if (content_type == NULL) { - DA_LOG_CRITICAL(Default, "No Mime Type Id"); - return DA_MIME_TYPE_NONE; - } - - while(descriptor_mime_table[i].mime_type != DA_MIME_TYPE_END) - { - if (!strcmp(descriptor_mime_table[i].content_type, content_type)) { - break; - } - i++; - } - //DA_LOG_VERBOSE(Default, "dd mime type check: index[%d] type[%d]", i, descriptor_mime_table[i].mime_type); - return descriptor_mime_table[i].mime_type; -} - - - -da_bool_t is_valid_url(const char *url, da_result_t *err_code) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - - int wanted_str_len = 0; - char *wanted_str = NULL; - char *wanted_str_start = NULL; - char *wanted_str_end = NULL; - - if ((DA_NULL == url) || (1 > strlen(url))) { - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - wanted_str_start = (char*)url; - wanted_str_end = strstr(url, "://"); - if (!wanted_str_end) { - DA_LOG_ERR(Default,"No protocol on this url"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - wanted_str_len = wanted_str_end - wanted_str_start; - wanted_str = (char*)calloc(1, wanted_str_len + 1); - if (!wanted_str) { - DA_LOG_ERR(Default,"DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - strncpy(wanted_str, wanted_str_start, wanted_str_len); - - b_ret = is_supporting_protocol(wanted_str); - if (!b_ret) { - ret = DA_ERR_UNSUPPORTED_PROTOCAL; - goto ERR; - } - -ERR: - if (wanted_str) { - free(wanted_str); - wanted_str = NULL; - } - - if (err_code) - *err_code = ret; - - return b_ret; -} - -da_result_t move_file(const char *from_path, const char *to_path) -{ - da_result_t ret = DA_RESULT_OK; - - if (!from_path || !to_path) - return DA_ERR_INVALID_ARGUMENT; - - if (rename(from_path, to_path) != 0) { - DA_LOG_CRITICAL(FileManager,"rename failed : syserr[%d]",errno); - if (errno == EXDEV) { - DA_LOG_CRITICAL(FileManager,"File system is diffrent. Try to copy a file"); - ret = copy_file(from_path, to_path); - if (ret == DA_RESULT_OK) { - remove_file(from_path); - } else { - if (is_file_exist(to_path)) - remove_file(to_path); - ret = DA_ERR_FAIL_TO_INSTALL_FILE; - } - } else { - ret = DA_ERR_FAIL_TO_INSTALL_FILE; - } - } - return ret; -} - -void remove_file(const char *file_path) -{ - DA_LOG_FUNC_LOGD(FileManager); - - if (file_path && is_file_exist(file_path)) { - DA_SECURE_LOGD("remove file [%s]", file_path); - if (unlink(file_path) < 0) { - DA_LOG_ERR(FileManager,"file removing failed."); - } - } -} diff --git a/agent/include/download-agent-client-mgr.h b/agent/include/download-agent-client-mgr.h index f4c6234..b2ce1c8 100755 --- a/agent/include/download-agent-client-mgr.h +++ b/agent/include/download-agent-client-mgr.h @@ -14,77 +14,14 @@ * limitations under the License. */ -#ifndef _Download_Agent_Client_Mgr_H -#define _Download_Agent_Client_Mgr_H +#ifndef DOWNLOAD_AGENT_CLIENT_MGR_H +#define DOWNLOAD_AGENT_CLIENT_MGR_H -#include <string.h> +#include "download-agent-dl-info.h" -#include "download-agent-type.h" -#include "download-agent-interface.h" - -#include "download-agent-pthread.h" - -typedef enum { - Q_CLIENT_NOTI_TYPE_STARTED_INFO = 0, - Q_CLIENT_NOTI_TYPE_PROGRESS_INFO, - Q_CLIENT_NOTI_TYPE_PAUSED_INFO, - Q_CLIENT_NOTI_TYPE_FINISHED_INFO, - Q_CLIENT_NOTI_TYPE_TERMINATE, -} client_noti_type; - -typedef struct _client_noti_t client_noti_t; -struct _client_noti_t { - int slot_id; - void *user_data; - client_noti_type noti_type; - union _client_type { - user_download_info_t update_dl_info; - user_progress_info_t update_progress_info; - user_paused_info_t paused_info; - user_finished_info_t finished_info; - } type; - - client_noti_t *next; -}; - -typedef struct _client_queue_t { - da_bool_t having_data; - client_noti_t *client_q_head; - pthread_mutex_t mutex_client_queue; - pthread_cond_t cond_client_queue; -} client_queue_t; - -typedef struct _client_app_info_t { - da_client_cb_t client_callback; - char *client_user_agent; -} client_app_info_t; - -typedef struct _client_app_mgr_t { - da_bool_t is_init; - client_queue_t client_queue; - client_app_info_t client_app_info; - pthread_t thread_id; - da_bool_t is_thread_init; - pthread_mutex_t mutex_client_mgr; -} client_app_mgr_t; - -da_result_t init_client_app_mgr(void); -da_bool_t is_client_app_mgr_init(void); - -da_result_t reg_client_app(da_client_cb_t *da_client_callback); -da_result_t dereg_client_app(void); - -da_result_t send_client_paused_info (int slot_id); -da_result_t send_client_update_dl_info (int slot_id, int dl_id, - char *file_type, unsigned long int file_size, char *tmp_saved_path, - char *pure_file_name, char *etag, char *extension); -da_result_t send_client_update_progress_info (int slot_id, int dl_id, - unsigned long int received_size); -da_result_t send_client_finished_info (int slot_id, int dl_id, - char *saved_path, char *etag, int error, int http_status); - -char *get_client_user_agent_string(void); - -void push_client_noti(client_noti_t *client_noti); +da_ret_t send_client_paused_info(da_info_t *da_info); +da_ret_t send_client_update_dl_info(da_info_t *da_info); +da_ret_t send_client_update_progress_info(da_info_t *da_info); +da_ret_t send_client_finished_info(da_info_t *da_info, int err); #endif diff --git a/agent/include/download-agent-debug.h b/agent/include/download-agent-debug.h index 24ac67e..23c2a66 100755 --- a/agent/include/download-agent-debug.h +++ b/agent/include/download-agent-debug.h @@ -14,94 +14,55 @@ * limitations under the License. */ -#ifndef _Download_Agent_Debug_H -#define _Download_Agent_Debug_H +#ifndef _DOWNLOAD_AGENT_DEBUG_H +#define _DOWNLOAD_AGENT_DEBUG_H #include "download-agent-type.h" -#define DA_DEBUG_ENV_KEY "DOWNLOAD_AGENT_DEBUG" -#define DA_DEBUG_CONFIG_FILE_PATH "/tmp/.download_agent.conf" - -#define IS_LOG_ON(channel) (DALogBitMap & (0x1<<(channel))) - -typedef enum { - Soup, - HTTPManager, - FileManager, - DRMManager, - DownloadManager, - ClientNoti, - HTTPMessageHandler, - Encoding, - QueueManager, - Parsing, - Thread, - Default, - DA_LOG_CHANNEL_MAX -} da_log_channel; - -extern int DALogBitMap; - -da_result_t init_log_mgr(void); - -#ifdef NODEBUG - #define DA_LOG(channel, format, ...) ((void)0) - #define DA_LOG_CRITICAL(channel, format, ...) ((void)0) - #define DA_LOG_VERBOSE(channel, format, ...) ((void)0) - #define DA_LOG_ERR(channel, format, ...) ((void)0) - #define DA_LOG_FUNC_LOGD(channel, ...) ((void)0) - #define DA_LOG_FUNC_LOGV(channel, ...) ((void)0) - #define DA_SECURE_LOGD(format, ...) ((void)0) - #define DA_SECURE_LOGI(format, ...) ((void)0) - #define DA_SECURE_LOGE(format, ...) ((void)0) - -#else /* NODEBUG */ #include <stdio.h> #include <stdarg.h> #include <pthread.h> -#ifdef DA_DEBUG_USING_DLOG - #include <dlog.h> +// ansi color +#define COLOR_RED "\033[0;31m" +#define COLOR_GREEN "\033[0;32m" +#define COLOR_BROWN "\033[0;33m" +#define COLOR_LIGHTBLUE "\033[0;37m" +#define COLOR_END "\033[0;m" + +#ifdef _ENABLE_DLOG +#include <unistd.h> +#include <syscall.h> +#include <dlog.h> + #ifdef LOG_TAG #undef LOG_TAG #endif /* LOG_TAG */ - #define LOG_TAG "DOWNLOAD_AGENT" - #define DA_LOG(channel, format, ...) LOGI_IF(IS_LOG_ON(channel), format, ##__VA_ARGS__) - #define DA_LOG_DEBUG(channel, format, ...) LOGD_IF(IS_LOG_ON(channel), format, ##__VA_ARGS__) - #define DA_LOG_CRITICAL(channel, format, ...) LOGI_IF(IS_LOG_ON(channel), format, ##__VA_ARGS__) - #define DA_LOG_VERBOSE(channel, format, ...) ((void)0)//LOGD_IF(IS_LOG_ON(channel), format, ##__VA_ARGS__) - #define DA_LOG_ERR(channel, format, ...) LOGE_IF(IS_LOG_ON(channel), "ERR! "format, ##__VA_ARGS__) - #define DA_LOG_FUNC_LOGD(channel, ...) LOGD_IF(IS_LOG_ON(channel), "starting...") - #define DA_LOG_FUNC_LOGV(channel, ...) ((void)0)//LOGD_IF(IS_LOG_ON(channel), "starting...") - #define DA_SECURE_LOGD(format, ...) SECURE_LOGD(format, ##__VA_ARGS__) - #define DA_SECURE_LOGI(format, ...) SECURE_LOGI(format, ##__VA_ARGS__) - #define DA_SECURE_LOGE(format, ...) SECURE_LOGE(format, ##__VA_ARGS__) -#else /* DA_DEBUG_USING_DLOG */ - #include <unistd.h> - #include <syscall.h> + #define LOG_TAG "DP_DA" + #define DA_LOGV(format, ...) ((void)0)//LOGD("[%d]:"format, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_LOGD(format, ...) LOGD(COLOR_LIGHTBLUE "[%d]:"format COLOR_END, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_LOGI(format, ...) LOGI(COLOR_BROWN "[%d]:"format COLOR_END, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_LOGE(format, ...) LOGE(COLOR_RED "[%d]:"format COLOR_END, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_SECURE_LOGD(format, ...) SECURE_LOGD(COLOR_GREEN format COLOR_END, ##__VA_ARGS__) + #define DA_SECURE_LOGI(format, ...) SECURE_LOGI(COLOR_GREEN format COLOR_END, ##__VA_ARGS__) + #define DA_SECURE_LOGE(format, ...) SECURE_LOGE(COLOR_GREEN format COLOR_END, ##__VA_ARGS__) +#else - #define DA_LOG(channel, format, ...) do {\ - IS_LOG_ON(channel) \ - ? fprintf(stderr, "[DA][%u][%s(): %d] "format"\n",(unsigned int)syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__) \ - : ((void)0);\ - }while(0) - #define DA_LOG_ERR(channel, format, ...) do {\ - IS_LOG_ON(channel) \ - ? fprintf(stderr, "[DA][%u][ERR][%s(): %d]\n",(unsigned int)syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__) \ - : ((void)0); \ +#include <unistd.h> +#include <syscall.h> + + #define DA_LOGD(format, ...) do {\ + fprintf(stderr, "[DA][%d][%s():%d] "format"\n",syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__);\ }while(0) - #define DA_LOG_FUNC_LOGD(channel, ...) do {\ - IS_LOG_ON(channel) \ - ? fprintf(stderr, "[DA][%u][%s(): %d] starting\n",(unsigned int)syscall(__NR_gettid), __FUNCTION__,__LINE__) \ - : ((void)0); \ + #define DA_LOGE(format, ...) do {\ + fprintf(stderr, "[DA][%d][ERR][%s():%d]\n",syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__);\ }while(0) - #define DA_LOG_CRITICAL DA_LOG - #define DA_LOG_VERBOSE DA_LOG - #define DA_LOG_FUNC_LOGV ((void)0) + #define DA_LOGV DA_LOGD + #define DA_LOGI DA_LOGD #define DA_SECURE_LOGD(format, ...) ((void)0) #define DA_SECURE_LOGI(format, ...) ((void)0) #define DA_SECURE_LOGE(format, ...) ((void)0) -#endif /* DA_DEBUG_USING_DLOG */ -#endif /* NDEBUG */ -#endif /* _Download_Agent_Debug_H */ +#endif /* _ENABLE_DLOG */ + +#endif /* DOWNLOAD_AGENT_DEBUG_H */ diff --git a/agent/include/download-agent-defs.h b/agent/include/download-agent-defs.h index b69690a..d5b6a5e 100755 --- a/agent/include/download-agent-defs.h +++ b/agent/include/download-agent-defs.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef _Download_Agent_Defs_H -#define _Download_Agent_Defs_H +#ifndef _DOWNLOAD_AGENT_DEFS_H +#define _DOWNLOAD_AGENT_DEFS_H #ifndef DEPRECATED #define DEPRECATED __attribute__((deprecated)) @@ -26,6 +26,7 @@ * Main reason for this restriction is because of Network bandwidth. */ #define DA_MAX_DOWNLOAD_REQ_AT_ONCE 50 +#define DA_MAX_TIME_OUT 65 #define DA_RESULT_OK 0 @@ -57,33 +58,28 @@ // System error (-200 ~ -299) #define DA_ERR_FAIL_TO_MEMALLOC -200 #define DA_ERR_FAIL_TO_CREATE_THREAD -210 -#define DA_ERR_FAIL_TO_OBTAIN_MUTEX -220 #define DA_ERR_FAIL_TO_ACCESS_FILE -230 #define DA_ERR_DISK_FULL -240 -// Platform error (-300 ~ -399) -#define DA_ERR_FAIL_TO_GET_CONF_VALUE -300 -#define DA_ERR_FAIL_TO_ACCESS_STORAGE -310 -#define DA_ERR_DLOPEN_FAIL -330 - // Network error (-400 ~ -499) #define DA_ERR_NETWORK_FAIL -400 #define DA_ERR_UNREACHABLE_SERVER -410 -#define DA_ERR_HTTP_TIMEOUT -420 -#define DA_ERR_SSL_FAIL -430 -#define DA_ERR_TOO_MANY_REDIECTS -440 +#define DA_ERR_CONNECTION_FAIL -420 +#define DA_ERR_HTTP_TIMEOUT -430 +#define DA_ERR_SSL_FAIL -440 +#define DA_ERR_TOO_MANY_REDIRECTS -450 +#define DA_ERR_NETWORK_UNAUTHORIZED -460 // HTTP error - not conforming with HTTP spec (-500 ~ -599) #define DA_ERR_MISMATCH_CONTENT_TYPE -500 -#define DA_ERR_MISMATCH_CONTENT_SIZE -501 -#define DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT -502 +#define DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT -501 +#define DA_ERR_MISMATCH_CONTENT_SIZE -502 -// DRM error - not conforming with DRM spec (-700 ~ -799) -#define DA_ERR_DRM_FAIL -700 -#define DA_ERR_DRM_FILE_FAIL -710 +// DRM error - not conforming with DRM spec (-600 ~ -699) +#define DA_ERR_DRM_FAIL -600 -// install error (-800 ~ -899) -#define DA_ERR_FAIL_TO_INSTALL_FILE -800 +// string to check invalid characters in path before using open() and fopen() API's +#define DA_INVALID_PATH_STRING ";\\\":*?<>|()" #endif diff --git a/agent/include/download-agent-dl-info-util.h b/agent/include/download-agent-dl-info-util.h deleted file mode 100755 index d6e20a8..0000000 --- a/agent/include/download-agent-dl-info-util.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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. - */ - -#ifndef _Download_Agent_Dl_Info_Util_H -#define _Download_Agent_Dl_Info_Util_H - -#include "download-agent-type.h" -#include "download-agent-http-queue.h" -#include "download-agent-utils-dl-id-history.h" - -#define DA_MAX_DOWNLOAD_ID DA_MAX_DOWNLOAD_REQ_AT_ONCE -#define DA_MAX_TYPE_COUNT 10 - -#define DOWNLOAD_NOTIFY_LIMIT (1024*32) //bytes -extern pthread_mutex_t mutex_download_state[]; - -typedef enum { - DOWNLOAD_STATE_IDLE = 0, - DOWNLOAD_STATE_NEW_DOWNLOAD = 10, /* stage */ - DOWNLOAD_STATE_FINISH = 50, /* stage */ - DOWNLOAD_STATE_PAUSED = 60, /* http */ - DOWNLOAD_STATE_CANCELED = 70, /* http */ - DOWNLOAD_STATE_ABORTED = 80 /* satge */ -} download_state_t; - -typedef enum { - HTTP_STATE_READY_TO_DOWNLOAD = 0, - HTTP_STATE_REDIRECTED = 1, - HTTP_STATE_DOWNLOAD_REQUESTED = 2, - HTTP_STATE_DOWNLOAD_STARTED = 3, - HTTP_STATE_DOWNLOADING = 4, - HTTP_STATE_DOWNLOAD_FINISH = 5, - HTTP_STATE_REQUEST_CANCEL = 6, - HTTP_STATE_REQUEST_PAUSE = 7, - HTTP_STATE_REQUEST_RESUME = 8, - HTTP_STATE_CANCELED = 9, - HTTP_STATE_PAUSED = 10, - HTTP_STATE_RESUMED = 11, - HTTP_STATE_ABORTED = 12, -} http_state_t; - -typedef struct _client_input_basic_t { - char *req_url; - char **user_request_header; - int user_request_header_count; -} client_input_basic_t; - -typedef struct _client_input_t { - void *user_data; - char *install_path; - char *file_name; - char *etag; - char *temp_file_path; - char *pkg_name; - client_input_basic_t client_input_basic; -} client_input_t; - -typedef struct _download_thread_input { - int slot_id; - client_input_t *client_input; -} download_thread_input; - -typedef struct _source_info_basic_t { - int dl_id; - char *url; - char **user_request_header; - int user_request_header_count; -} source_info_basic_t; - -typedef struct _source_info_t { - union _source_info_type { - source_info_basic_t *source_info_basic; - } source_info_type; -} source_info_t; - -#define GET_SOURCE_TYPE(SOURCE) ((SOURCE)->source_type) -#define GET_SOURCE_BASIC(SOURCE) ((SOURCE)->source_info_type.source_info_basic) -#define GET_SOURCE_BASIC_URL(SOURCE) (GET_SOURCE_BASIC(SOURCE)->url) - -typedef struct _req_dl_info { - http_info_t http_info; - - /* This is just pointer assignment from stage source info. */ - char *destination_url; - /* The location url is assigned here in case of redirection. - * At this time, the pointer should be freed. */ - char *location_url; - char **user_request_header; - int user_request_header_count; - char *user_request_etag; - char *user_request_temp_file_path; - - http_state_t http_state; - pthread_mutex_t mutex_http_state; - - da_result_t result; - /*************** will be depreciated ***********************/ - /* ToDo : previous http_info should be saved in case of pause */ - char *content_type_from_header; /* calloced in set hdr fiels on download info */ - unsigned long long content_len_from_header; - char *etag_from_header; - - unsigned long int downloaded_data_size; - - int invloved_transaction_id; -} req_dl_info; - -#define GET_REQUEST_HTTP_RESULT(REQUEST) (REQUEST->result) -#define GET_REQUEST_HTTP_TRANS_ID(REQUEST) (REQUEST->invloved_transaction_id) -#define GET_REQUEST_HTTP_REQ_URL(REQUEST) (REQUEST->destination_url) -#define GET_REQUEST_HTTP_REQ_LOCATION(REQUEST) (REQUEST->location_url) -#define GET_REQUEST_HTTP_USER_REQUEST_HEADER(REQUEST) (REQUEST->user_request_header) -#define GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT(REQUEST) (REQUEST->user_request_header_count) -#define GET_REQUEST_HTTP_USER_REQUEST_ETAG(REQUEST) (REQUEST->user_request_etag) -#define GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(REQUEST) (REQUEST->user_request_temp_file_path) -#define GET_REQUEST_HTTP_HDR_ETAG(REQUEST) (REQUEST->etag_from_header) -#define GET_REQUEST_HTTP_HDR_CONT_TYPE(REQUEST) (REQUEST->content_type_from_header) -#define GET_REQUEST_HTTP_HDR_CONT_LEN(REQUEST) (REQUEST->content_len_from_header) -#define GET_REQUEST_HTTP_CONTENT_OFFSET(REQUEST)(REQUEST->downloaded_data_size) -#define GET_REQUEST_HTTP_MUTEX_HTTP_STATE(STAGE) (GET_STAGE_TRANSACTION_INFO(STAGE)->mutex_http_state) -#define GET_HTTP_STATE_ON_STAGE(STAGE) (GET_STAGE_TRANSACTION_INFO(STAGE)->http_state) -#define CHANGE_HTTP_STATE(STATE,STAGE) {\ - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(STAGE)));\ - GET_HTTP_STATE_ON_STAGE(STAGE) = STATE;\ - DA_LOG_DEBUG(Default, "Changed http_state to - [%d] ", GET_HTTP_STATE_ON_STAGE(STAGE));\ - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(STAGE)));\ -} - -typedef struct _file_info { - void *file_handle; - char *pure_file_name; - char *extension; - char *file_name_final; /* malloced in set_file_path_for_final_saving */ - char *content_type; /* malloced in make file info. */ - char *add_to_buffer; - unsigned int file_size; /* http header's Content-Length has higher priority than DD's <size> */ - unsigned int total_bytes_written_to_file; /* current written file size */ - unsigned int bytes_written_to_file; - unsigned int current_buffer_len; -} file_info; - -#define GET_CONTENT_STORE_PURE_FILE_NAME(FILE_CNTXT) (FILE_CNTXT)->pure_file_name -#define GET_CONTENT_STORE_EXTENSION(FILE_CNTXT) (FILE_CNTXT)->extension -#define GET_CONTENT_STORE_ACTUAL_FILE_NAME(FILE_CNTXT) (FILE_CNTXT)->file_name_final -#define GET_CONTENT_STORE_FILE_HANDLE(FILE_CNTXT) (FILE_CNTXT)->file_handle -#define GET_CONTENT_STORE_FILE_SIZE(FILE_CNTXT) (FILE_CNTXT)->file_size -#define GET_CONTENT_STORE_CURRENT_FILE_SIZE(FILE_CNTXT) (FILE_CNTXT)->total_bytes_written_to_file -#define IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(FILE_CNTXT) (FILE_CNTXT)->bytes_written_to_file -#define GET_CONTENT_STORE_FILE_BUFFER(FILE_CNTXT) (FILE_CNTXT)->add_to_buffer -#define GET_CONTENT_STORE_FILE_BUFF_LEN(FILE_CNTXT) ((FILE_CNTXT)->current_buffer_len) -#define GET_CONTENT_STORE_CONTENT_TYPE(FILE_CNTXT) (FILE_CNTXT)->content_type - -typedef struct _stage_info { - int dl_id; - int thread_id; - source_info_t dl_request; - req_dl_info dl_tansaction_context; - file_info dl_content_storage; - struct _stage_info *next_stage_info; -} stage_info; - -#define GET_STAGE_DL_ID(STAGE) ((STAGE)->dl_id) -#define GET_STAGE_THREAD_ID(STAGE) ((STAGE)->thread_id) -#define GET_STAGE_SOURCE_INFO(STAGE) (&((STAGE)->dl_request)) -#define GET_STAGE_TRANSACTION_INFO(STAGE) (&((STAGE)->dl_tansaction_context)) -#define GET_STAGE_CONTENT_STORE_INFO(STAGE) (&((STAGE)->dl_content_storage)) -#define GET_STAGE_INSTALLATION_INFO(STAGE) (&((STAGE)->post_dl_context)) - -typedef struct { - da_bool_t is_using; - int slot_id; - int dl_id; - pthread_t active_dl_thread_id; - download_state_t state; - stage_info *download_stage_data; - queue_t queue; - int http_status; - da_bool_t enable_pause_update; - // FIXME have client_input itself, not to have each of them - char *user_install_path; - char *user_file_name; - char *user_etag; - char *user_temp_file_path; - void *user_data; -} dl_info_t; - -#define GET_DL_THREAD_ID(ID) (download_mgr.dl_info[ID].active_dl_thread_id) -#define GET_DL_STATE_ON_ID(ID) (download_mgr.dl_info[ID].state) -#define GET_DL_STATE_ON_STAGE(STAGE) (GET_DL_STATE_ON_ID(GET_STAGE_DL_ID(STAGE))) -#define GET_DL_CURRENT_STAGE(ID) (download_mgr.dl_info[ID].download_stage_data) -#define GET_DL_ID(ID) (download_mgr.dl_info[ID].dl_id) -#define GET_DL_QUEUE(ID) &(download_mgr.dl_info[ID].queue) -#define GET_DL_ENABLE_PAUSE_UPDATE(ID) (download_mgr.dl_info[ID].enable_pause_update) -#define GET_DL_USER_INSTALL_PATH(ID) (download_mgr.dl_info[ID].user_install_path) -#define GET_DL_USER_FILE_NAME(ID) (download_mgr.dl_info[ID].user_file_name) -#define GET_DL_USER_ETAG(ID) (download_mgr.dl_info[ID].user_etag) -#define GET_DL_USER_TEMP_FILE_PATH(ID) (download_mgr.dl_info[ID].user_temp_file_path) -#define GET_DL_USER_DATA(ID) (download_mgr.dl_info[ID].user_data) -#define IS_THIS_DL_ID_USING(ID) (download_mgr.dl_info[ID].is_using) - -#define CHANGE_DOWNLOAD_STATE(STATE,STAGE) {\ - _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(STAGE)]);\ - GET_DL_STATE_ON_STAGE(STAGE) = STATE;\ - DA_LOG_DEBUG(Default, "Changed download_state to - [%d] ", GET_DL_STATE_ON_STAGE(STAGE));\ - _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(STAGE)]);\ - } - -typedef struct _download_mgr_t { - da_bool_t is_init; - dl_info_t dl_info[DA_MAX_DOWNLOAD_ID]; - dl_id_history_t dl_id_history; - /* FIXME: This is temporary solution to prevent crash on following case; - * 1) OMA download(that is, DA's libsoup is using) is on progressing on Browser - * 2) User push END hard key - * 3) da_deinit() is called. - on UI thread - * 4) cancel_download(all) is called. - * 5) plugin-libsoup.c calls soup_session_cancel_message(). - * 6) da_deinit() is finished and process is over. - * 7) soup's callback for soup_session_cancel_message() is trying to be called - on UI thread - * 8) Browser crashed because the callback address is no longer exist. - * - * Here is a temporary solution; - * If cancel is from da_deinit(), plugin-libsoup.c will not call soup_session_cancel_message(). - * So, append following variable to recognize this. - **/ - //da_bool_t is_progressing_deinit; -} download_mgr_t; - -extern download_mgr_t download_mgr; - -da_result_t init_download_mgr(); -da_result_t deinit_download_mgr(void); -void init_download_info(int slot_id); -void destroy_download_info(int slot_id); -void *Add_new_download_stage(int slot_id); -void remove_download_stage(int slot_id, stage_info *in_stage); -void empty_stage_info(stage_info *in_stage); -void clean_up_client_input_info(client_input_t *client_input); -da_result_t get_available_slot_id(int *available_id); -da_result_t get_slot_id_for_dl_id(int dl_id , int* slot_id); -da_bool_t is_valid_slot_id(int slot_id); -void store_http_status(int dl_id, int status); -int get_http_status(int dl_id); -#endif /* _Download_Agent_Dl_Info_Util_H */ diff --git a/agent/include/download-agent-dl-info.h b/agent/include/download-agent-dl-info.h new file mode 100644 index 0000000..820135e --- /dev/null +++ b/agent/include/download-agent-dl-info.h @@ -0,0 +1,197 @@ +/* + * 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. + */ + +#ifndef _DOWNLOAD_AGENT_INFO_H +#define _DOWNLOAD_AGENT_INFO_H + +#include "download-agent-type.h" +#include "download-agent-interface.h" +#include "download-agent-pthread.h" + +#include "curl/curl.h" + +typedef struct { + CURL *curl; + pthread_mutex_t mutex; + da_bool_t is_paused; + da_bool_t is_cancel_reqeusted; +} http_msg_t; + +typedef enum { + HTTP_STATE_READY_TO_DOWNLOAD = 0, + HTTP_STATE_REDIRECTED = 1, + HTTP_STATE_DOWNLOAD_REQUESTED = 2, + HTTP_STATE_DOWNLOAD_STARTED = 3, + HTTP_STATE_DOWNLOADING = 4, + HTTP_STATE_DOWNLOAD_FINISH = 5, + HTTP_STATE_REQUEST_CANCEL = 6, + HTTP_STATE_REQUEST_PAUSE = 7, + HTTP_STATE_REQUEST_RESUME = 8, + HTTP_STATE_CANCELED = 9, + HTTP_STATE_FAILED = 10, + HTTP_STATE_PAUSED = 11, + HTTP_STATE_RESUMED = 12, + HTTP_STATE_ABORTED = 13, + HTTP_STATE_WAIT_FOR_NET_ERR = 14, +} http_state_t; + +typedef enum { + HTTP_METHOD_GET = 1, + HTTP_METHOD_HEAD, + HTTP_METHOD_POST +} http_method_t; + +typedef struct { + char *url; + char **req_header; + int req_header_count; + char *install_path; + char *file_name; + char *etag; + char *temp_file_path; + char *pkg_name; + int network_bonding; + void *user_req_data; + void *user_client_data; +} req_info_t; + +typedef enum { + HTTP_EVENT_GOT_HEADER = 0, + HTTP_EVENT_GOT_PACKET, + HTTP_EVENT_FINAL, +// HTTP_EVENT_ABORT +} http_event_type_t; + +typedef struct _http_header_options_t http_header_options_t; +struct _http_header_options_t{ + char *field; + char *value; + http_header_options_t *next; +}; + +typedef struct _http_header_t http_header_t; +typedef http_header_t *http_msg_iter_t; +struct _http_header_t{ + char *field; + char *value; + http_header_options_t *options; + char *raw_value; // raw string including options + http_header_t *next; +}; + +typedef struct{ + char *http_method; + char *url; + http_header_t *head; + char *http_body; +} http_msg_request_t; + + +typedef struct{ + int status_code; + http_header_t *head; +} http_msg_response_t; + +typedef struct { + http_event_type_t type; + char *body; + int body_len; +#ifdef _RAF_SUPPORT + da_size_t received_len; +#endif + int status_code; + int error; +} http_raw_data_t; + +typedef void (*http_update_cb) (http_raw_data_t *data, void *user_param); + +typedef struct { + char *location_url; + http_state_t state; + pthread_mutex_t mutex_state; + pthread_mutex_t mutex_http; + pthread_cond_t cond_http; + http_msg_request_t *http_msg_request; + http_msg_response_t *http_msg_response; + http_method_t http_method; + http_msg_t *http_msg; + char *proxy_addr; + char *content_type_from_header; + char *file_name_from_header; + da_size_t content_len_from_header; + char *etag_from_header; + int error_code; // for error value for http abort. + da_size_t total_size; +#ifdef _RAF_SUPPORT + da_bool_t is_raf_mode_confirmed; +#endif + http_update_cb update_cb; +} http_info_t; + +typedef struct { + void *file_handle; + char *pure_file_name; + char *extension; + char *file_path; /* malloced in set_file_path_for_final_saving */ + char *mime_type;// For drm converting + char *buffer; + da_size_t buffer_len; + da_size_t file_size; /* http header's Content-Length has higher priority than DD's <size> */ + da_size_t bytes_written_to_file; /* The file size to be written at actual file */ +#ifdef _RAF_SUPPORT + da_size_t file_size_of_temp_file; /* If the temporary file is existed, the file size of it */ +#endif + da_bool_t is_updated; /* The flag for updating progress event only if the data is wrriten to file not buffer */ +} file_info_t; + +typedef struct { + int da_id; + int tid; + pthread_t thread_id; + http_info_t *http_info; + file_info_t *file_info; + req_info_t *req_info; + da_cb_t cb_info; + da_bool_t is_cb_update; + int update_time; +} da_info_t; + +da_info_t *da_info_list[DA_MAX_ID]; + +#define GET_STATE_MUTEX(INFO) (INFO->mutex_state) +#define GET_STATE(INFO) (INFO->state) +#define CHANGE_STATE(STATE,INFO) {\ + DA_MUTEX_LOCK (&GET_STATE_MUTEX(INFO));\ + GET_STATE(INFO) = STATE;\ + DA_LOGV("Changed state[%d]", GET_STATE(INFO));\ + DA_MUTEX_UNLOCK (&GET_STATE_MUTEX(INFO));\ + } + +da_ret_t get_available_da_id(int *available_id); +da_ret_t copy_user_input_data(da_info_t *da_info, const char *url, + req_data_t *ext_data, da_cb_t *da_cb_data); +da_bool_t is_valid_download_id(int id); +void destroy_da_info(int id); +void destroy_da_info_list(void); +da_ret_t get_da_info_with_da_id(int id, da_info_t **out_info); +da_ret_t init_http_msg_t(http_msg_t **http_msg); +void destroy_http_msg_t(http_msg_t *http_msg); +void reset_http_info(http_info_t *http_info); +void reset_http_info_for_resume(http_info_t *http_info); +void destroy_http_info(http_info_t *http_info); +void destroy_file_info(file_info_t *file_info); + +#endif /* _DOWNLOAD_AGENT_INFO_H */ diff --git a/agent/include/download-agent-dl-mgr.h b/agent/include/download-agent-dl-mgr.h index b273fd8..c6be7c7 100755 --- a/agent/include/download-agent-dl-mgr.h +++ b/agent/include/download-agent-dl-mgr.h @@ -14,20 +14,14 @@ * limitations under the License. */ -#ifndef _Download_Agent_Dl_Mgr_H -#define _Download_Agent_Dl_Mgr_H +#ifndef _Download_Agent_Basic_H +#define _Download_Agent_Basic_H -#include "download-agent-type.h" -#include "download-agent-dl-info-util.h" +#include "download-agent-dl-info.h" -da_result_t cancel_download(int dl_id); -da_result_t suspend_download(int dl_id, da_bool_t is_enable_cb); -da_result_t resume_download (int dl_id); +da_ret_t start_download(da_info_t *da_info); +da_ret_t cancel_download(int dl_id, da_bool_t is_enable_cb); +da_ret_t suspend_download(int dl_id, da_bool_t is_enable_cb); +da_ret_t resume_download(int dl_id); -da_result_t requesting_download(stage_info *stage); -da_result_t handle_after_download(stage_info *stage); -da_result_t send_user_noti_and_finish_download_flow( - int slot_id, char *installed_path, char *etag); - -da_bool_t is_valid_download_id(int dl_id); #endif diff --git a/agent/include/download-agent-encoding.h b/agent/include/download-agent-encoding.h index c5c7fe5..49e74e9 100755 --- a/agent/include/download-agent-encoding.h +++ b/agent/include/download-agent-encoding.h @@ -20,7 +20,7 @@ #include "download-agent-type.h" da_bool_t is_base64_encoded_word(const char *in_str); -da_result_t decode_base64_encoded_str(const char *in_encoded_str, +da_ret_t decode_base64_encoded_str(const char *in_encoded_str, char **out_decoded_ascii_str); void decode_url_encoded_str(const char *in_encoded_str, char **out_str); diff --git a/agent/include/download-agent-file.h b/agent/include/download-agent-file.h index b4d3995..2788fdd 100755 --- a/agent/include/download-agent-file.h +++ b/agent/include/download-agent-file.h @@ -14,39 +14,32 @@ * limitations under the License. */ -#ifndef _Download_Agent_File_H -#define _Download_Agent_File_H +#ifndef _DOWNLOAD_AGENT_FILE_H +#define _DOWNLOAD_AGENT_FILE_H #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include "download-agent-type.h" -#include "download-agent-dl-mgr.h" +#include "download-agent-dl-info.h" -#define DA_DEFAULT_INSTALL_PATH_FOR_PHONE "/opt/usr/media/Downloads" +#define DA_FILE_BUF_SIZE (1024*32) //bytes +da_ret_t check_drm_convert(file_info_t *file_info); da_bool_t is_file_exist(const char *file_path); -da_bool_t is_dir_exist(const char *dir_path); - -void get_file_size(char *file_path, unsigned long long *out_file_size); - -da_result_t clean_files_from_dir(char *dir_path); -da_result_t file_write_ongoing(stage_info *stage, char *body, int body_len); -da_result_t file_write_complete(stage_info *stage); -da_result_t start_file_writing(stage_info *stage); -da_result_t start_file_writing_append(stage_info *stage); -da_result_t start_file_writing_append_with_new_download(stage_info *stage); - -da_result_t get_mime_type(stage_info *stage, char **out_mime_type); -da_result_t discard_download(stage_info *stage) ; -void clean_paused_file(stage_info *stage); -da_result_t replace_content_file_in_stage(stage_info *stage, const char *dest_dd_file_path); -da_result_t decide_tmp_file_path(stage_info *stage); -char *get_full_path_avoided_duplication(char *in_dir, char *in_candidate_file_name, char *in_extension); - -da_result_t copy_file(const char *src, const char *dest); -da_result_t create_dir(const char *install_dir); -da_result_t get_default_install_dir(char **out_path); - +void get_file_size(char *file_path, da_size_t *out_file_size); +da_ret_t file_write_ongoing(file_info_t *file_info, char *body, int body_len); +da_ret_t file_write_complete(file_info_t *file_info); +#ifdef _RAF_SUPPORT +da_ret_t file_write_complete_for_raf(file_info_t *file_info); +#endif +da_ret_t start_file_writing(da_info_t *da_info); +da_ret_t start_file_append(file_info_t *file_info); +da_ret_t discard_download(file_info_t *file_info) ; +void clean_paused_file(file_info_t *file_info); +char *get_full_path_avoided_duplication(char *in_dir, + char *in_candidate_file_name, char *in_extension); +void remove_file(const char *file_path); +da_ret_t get_available_memory(char *dir_path, da_size_t len); #endif diff --git a/agent/include/download-agent-http-mgr.h b/agent/include/download-agent-http-mgr.h index 6653af0..95a0b3a 100755 --- a/agent/include/download-agent-http-mgr.h +++ b/agent/include/download-agent-http-mgr.h @@ -21,27 +21,14 @@ #include "download-agent-type.h" #include "download-agent-dl-mgr.h" -#include "download-agent-http-queue.h" #define DA_MAX_SESSION_INFO DA_MAX_DOWNLOAD_ID -#define DA_MAX_TRANSACTION_INFO 10 -#define DA_MAX_TRANSACTION_MUTEX DA_MAX_SESSION_INFO*DA_MAX_TRANSACTION_INFO -typedef struct _http_mgr_t -{ - da_bool_t is_init; - da_bool_t is_http_init; -}http_mgr_t; - -extern http_mgr_t http_mgr; - -da_result_t init_http_mgr(void); -void deinit_http_mgr(void); -da_result_t make_req_dl_info_http(stage_info *stage, req_dl_info *out_info); -da_result_t request_http_download(stage_info *stage); -da_result_t request_to_cancel_http_download(stage_info *stage); -da_result_t request_to_abort_http_download(stage_info *stage); -da_result_t request_to_suspend_http_download(stage_info *stage); -da_result_t request_to_resume_http_download(stage_info *stage); +da_ret_t request_http_download(da_info_t *da_info); +da_ret_t request_to_cancel_http_download(da_info_t *da_info); +da_ret_t request_to_abort_http_download(da_info_t *da_info); +da_ret_t request_to_suspend_http_download(da_info_t *da_info); +da_ret_t request_to_resume_http_download(da_info_t *da_info); +da_bool_t is_stopped_state(da_info_t *da_info); #endif diff --git a/agent/include/download-agent-http-misc.h b/agent/include/download-agent-http-misc.h deleted file mode 100755 index 3bf137b..0000000 --- a/agent/include/download-agent-http-misc.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - */ - -#ifndef _Download_Agent_Http_Misc_H -#define _Download_Agent_Http_Misc_H - -#include <string.h> - -#include "download-agent-type.h" - -#define SCHEME_HTTP "http://" -#define SCHEME_HTTPS "https://" -#define SCHEME_CID "cid:" - -#define METHOD_GET "GET" -#define METHOD_POST "POST" -#define METHOD_HEAD "HEAD" - -#define HTTP_TAG_UAGENT "User-Agent: " -#define HTTP_TAG_HOST "Host: " -#define HTTP_TAG_UAPROF "X-Wap-Profile: " -#define HTTP_TAG_CONTENT_LENGTH "Content-Length: " -#define HTTP_TAG_CONTENT_TYPE "Content-Type: " -#define HTTP_TAG_IF_MATCH "If-Match: " -#define HTTP_TAG_RANGE "Range: " -#define HTTP_TAG_IF_RANGE "If-Range: " - -#define END_OF_FIELD "\r\n" - -char *get_user_agent(); - -da_bool_t is_supporting_protocol(const char *protocol); - -#endif diff --git a/agent/include/download-agent-http-msg-handler.h b/agent/include/download-agent-http-msg-handler.h index 29d0ae4..70abbda 100755 --- a/agent/include/download-agent-http-msg-handler.h +++ b/agent/include/download-agent-http-msg-handler.h @@ -18,103 +18,60 @@ #define _Download_Agent_Http_Msg_Handler_H #include "download-agent-type.h" +#include "download-agent-dl-info.h" +// Reqeust Header #define HTTP_FIELD_UAGENT "User-Agent" #define HTTP_FIELD_HOST "Host" #define HTTP_FIELD_UAPROF "X-Wap-Profile" -#define HTTP_FIELD_CONTENT_LENGTH "Content-Length" -#define HTTP_FIELD_CONTENT_TYPE "Content-Type" #define HTTP_FIELD_IF_MATCH "If-Match" #define HTTP_FIELD_RANGE "Range" #define HTTP_FIELD_IF_RANGE "If-Range" #define HTTP_FIELD_ACCEPT_LANGUAGE "Accept-Language" #define HTTP_FIELD_ACCEPT_CHARSET "Accept-Charset" -typedef struct _http_header_options_t http_header_options_t; -struct _http_header_options_t{ - char *field; - char *value; - - http_header_options_t *next; -}; - -typedef struct _http_header_t http_header_t; -struct _http_header_t{ - char *field; - char *value; - http_header_options_t *options; - - char *raw_value; // raw string including options - - http_header_t *next; -}; - -typedef struct{ - char *http_method; - char *url; - http_header_t *head; - char *http_body; -}http_msg_request_t; - - -typedef struct{ - int status_code; - http_header_t *head; -}http_msg_response_t; - -typedef http_header_t *http_msg_iter_t; - - -typedef struct{ - http_msg_request_t *http_msg_request; - http_msg_response_t *http_msg_response; -}http_info_t; +// Response Header +#define HTTP_FIELD_CONTENT_LENGTH "Content-Length" +#define HTTP_FIELD_CONTENT_TYPE "Content-Type" +#define HTTP_FIELD_CONTENT_DISPOSITION "Content-Disposition" +#define HTTP_FIELD_LOCATION "Location" +#define HTTP_FIELD_DATA "Date" +#define HTTP_FIELD_ETAG "ETag" +#ifdef _RAF_SUPPORT +#define HTTP_FIELD_RAF_MODE "x-direct-write" +#endif +#define HTTP_FIELD_END_OF_FIELD "\r\n" -da_result_t http_msg_request_create(http_msg_request_t **http_msg_request); +da_ret_t http_msg_request_create(http_msg_request_t **http_msg_request); void http_msg_request_destroy(http_msg_request_t **http_msg_request); +da_ret_t http_msg_request_set_url(http_msg_request_t *http_msg_request, const char *url); +da_ret_t http_msg_request_get_url(http_msg_request_t *http_msg_request, const char **url); +da_ret_t http_msg_request_add_field(http_msg_request_t *http_msg_request, const char *field, const char *value); -da_result_t http_msg_request_set_method(http_msg_request_t *http_msg_request, const char *method); -da_result_t http_msg_request_get_method(http_msg_request_t *http_msg_request, const char **method); - -da_result_t http_msg_request_set_url(http_msg_request_t *http_msg_request, const char *url); -da_result_t http_msg_request_get_url(http_msg_request_t *http_msg_request, const char **url); - -da_result_t http_msg_request_set_body(http_msg_request_t *http_msg_request, const char *body); -da_result_t http_msg_request_get_body(http_msg_request_t *http_msg_request, const char **body); - -da_result_t http_msg_request_add_field(http_msg_request_t *http_msg_request, const char *field, const char *value); - - -da_result_t http_msg_response_create(http_msg_response_t **http_msg_response); +da_ret_t http_msg_response_create(http_msg_response_t **http_msg_response); void http_msg_response_destroy(http_msg_response_t **http_msg_response); - -da_result_t http_msg_response_set_status_code(http_msg_response_t *http_msg_response, int status_code); -da_result_t http_msg_response_get_status_code(http_msg_response_t *http_msg_response, int *status_code); - -da_result_t http_msg_response_add_field(http_msg_response_t *http_msg_response, const char *field, const char *value); - +da_ret_t http_msg_response_add_field(http_msg_response_t *http_msg_response, const char *field, const char *value); /* Caution! Caller must free memory for every "char** out_xxx" for followings */ da_bool_t http_msg_response_get_content_type(http_msg_response_t *http_msg_response, char **out_type); void http_msg_response_set_content_type(http_msg_response_t *http_msg_response, const char *in_type); -da_bool_t http_msg_response_get_content_length(http_msg_response_t *http_msg_response, unsigned long long *out_length); +da_bool_t http_msg_response_get_content_length(http_msg_response_t *http_msg_response, da_size_t *out_length); da_bool_t http_msg_response_get_content_disposition(http_msg_response_t *http_msg_response, char **out_disposition, char **out_file_name); da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response, char **out_value); da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response, char **out_value); da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, char **out_value); -// should be refactored later -da_result_t http_msg_response_get_boundary(http_msg_response_t *http_msg_response, char **out_val); - - -da_result_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, http_msg_iter_t *http_msg_iter); -da_result_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, http_msg_iter_t *http_msg_iter); - +#ifdef _RAF_SUPPORT +da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response, + char **out_value); +#endif +da_ret_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, http_msg_iter_t *http_msg_iter); +da_ret_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, http_msg_iter_t *http_msg_iter); // should remove later da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter, char **field, char **value); da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter, char **out_field, http_header_t **out_header); - -char *get_http_response_header_raw(http_msg_response_t *http_msg_response); - da_bool_t extract_attribute_from_header(char *szHeadStr, const char *szFindStr, char **ppRtnValue); +da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request, char **out_value); +da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request, char **out_value); + #endif // _Download_Agent_Http_Msg_Handler_H diff --git a/agent/include/download-agent-http-queue.h b/agent/include/download-agent-http-queue.h deleted file mode 100755 index 9973698..0000000 --- a/agent/include/download-agent-http-queue.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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. - */ - -#ifndef _Download_Agent_Http_Queue_H -#define _Download_Agent_Http_Queue_H - - -#include "download-agent-type.h" -#include "download-agent-http-msg-handler.h" - -#include <pthread.h> -#include <stdlib.h> - -#define MAX_QUEUE_SIZE 1024*64 - -typedef enum -{ - Q_EVENT_TYPE_DATA_HTTP, - Q_EVENT_TYPE_DATA_DRM, - Q_EVENT_TYPE_CONTROL, -}q_event_type; - -typedef enum -{ - Q_EVENT_TYPE_CONTROL_NONE = 0, - Q_EVENT_TYPE_CONTROL_CANCEL, - Q_EVENT_TYPE_CONTROL_SUSPEND, - Q_EVENT_TYPE_CONTROL_RESUME, - Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED, - Q_EVENT_TYPE_CONTROL_ABORT, -// [090205][jungki]not used yet. -// Q_EVENT_TYPE_CONTROL_USER_CONFIRM_RESULT, -// Q_EVENT_TYPE_CONTROL_INSTALL_RESULT, -}q_event_type_control; - -typedef enum -{ - Q_EVENT_TYPE_DATA_PACKET, - Q_EVENT_TYPE_DATA_FINAL, - Q_EVENT_TYPE_DATA_ABORT, -}q_event_type_data; - -typedef struct _q_event_data_http_t -{ - q_event_type_data data_type; - - int status_code; - - http_msg_response_t* http_response_msg; - - int body_len; - char *body_data; - - da_result_t error_type; -}q_event_data_http_t; - -typedef struct _q_event_control_t -{ - q_event_type_control control_type; -}q_event_control_t; - -typedef struct _q_event_t q_event_t; -struct _q_event_t -{ - int size; - q_event_type event_type; - union _type - { - q_event_data_http_t q_event_data_http; - q_event_control_t q_event_control; - } type; - - q_event_t *next; -}; - -typedef struct _queue_t -{ - da_bool_t having_data; - - q_event_t *control_head; - q_event_t *data_head; - - pthread_mutex_t mutex_queue; - pthread_cond_t cond_queue; - - int queue_size; -}queue_t; - -void Q_init_queue(queue_t *queue); -void Q_destroy_queue(queue_t *queue); - -void Q_init_q_event(q_event_t *q_event); -void Q_destroy_q_event(q_event_t **q_event); - -da_result_t Q_make_control_event(q_event_type_control control_type, q_event_t **out_event); - -da_result_t Q_make_http_data_event(q_event_type_data data_type, q_event_t **out_event); -da_result_t Q_set_status_code_on_http_data_event(q_event_t *q_event, int status_code); -da_result_t Q_set_http_body_on_http_data_event(q_event_t *q_event, int body_len, char *body_data); -da_result_t Q_set_error_type_on_http_data_event(q_event_t *q_event, int error_type); - - -da_bool_t Q_push_event(const queue_t *in_queue, const q_event_t *in_event); -da_bool_t Q_push_event_without_lock(const queue_t *in_queue, const q_event_t *in_event); -void Q_pop_event(const queue_t *in_queue, q_event_t **out_event); - -#define GET_IS_Q_HAVING_DATA(QUEUE) (QUEUE->having_data) - -void Q_goto_sleep(const queue_t *in_queue); -void Q_wake_up(const queue_t *in_queue); - - -#endif diff --git a/agent/include/download-agent-interface.h b/agent/include/download-agent-interface.h index 44081bd..f5ce653 100755 --- a/agent/include/download-agent-interface.h +++ b/agent/include/download-agent-interface.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef _Download_Agent_Interface_H -#define _Download_Agent_Interface_H +#ifndef _DOWNLOAD_AGENT_INTERFACE_H +#define _DOWNLOAD_AGENT_INTERFACE_H #ifndef EXPORT_API #define EXPORT_API __attribute__((visibility("default"))) @@ -29,450 +29,69 @@ extern "C" #include "download-agent-defs.h" #include <stdarg.h> -/** - * @struct user_paused_info_t - * @brief Download Agent will send its state through this structure. - * @see da_paused_info_cb - * @par - * This is used only by callback /a user_paused_info_t. \n - */ -typedef struct { - /// download request id for this notification - int download_id; -} user_paused_info_t; - -/** - * @struct user_progress_info_t - * @brief Download Agent will send current downloading file's information through this structure. - * @see da_progress_info_cb - * @par - * This is used only by callback /a da_progress_info_cb. \n - */ -typedef struct { - /// download request id for this updated download information - int download_id; - /// received size of chunked data. - unsigned long int received_size; -} user_progress_info_t; - -/** - * @struct user_download_info_t - * @brief Download Agent will send current download's information through this structure. - * @see da_started_info_cb - * @par - * This is used only by callback /a da_started_info_cb. \n - */ typedef struct { - /// download request id for this updated download information int download_id; - /// file's mime type from http header. char *file_type; - /// file size from http header. - unsigned long int file_size; - /// This is temporary file path. + unsigned long long file_size; char *tmp_saved_path; - /// This is the file name for showing to user. char *content_name; - /// etag string value for resume download, char *etag; -} user_download_info_t; +} download_info_t; typedef struct { - /// download request id for this updated download information int download_id; - /// This has only file name for now. char *saved_path; - /// etag string value for resume download, - /// This is returned when the download is failed and the etag is received from content server char *etag; - /// convey error code if necessary, or it is zero. int err; - /// http status code if necessary, or it is zero. int http_status; -} user_finished_info_t; +} finished_info_t; typedef struct { const char **request_header; int request_header_count; const char *install_path; const char *file_name; - const char *temp_file_path; /* For resume download, the "etag" value should be existed together */ - const char *etag; /* For resume download */ - const char *pkg_name; /* For system resource */ - void *user_data; -} extension_data_t; - -/** - * @typedef da_paused_cb - * @brief Download Agent will call this function to paused its state. - * - * This is user callback function registered on \a da_init. \n - * - * @remarks For the most of time, this state is just informative, so, user doesn't need to do any action back to Download Agent. - * - * @warning Download will be holding until getting user confirmation result through the function. - * - * @param[in] state state from Download Agent - * @param[in] user_param user parameter which is set with \a DA_FEATURE_USER_DATA - * - * @see da_init - * @see da_client_cb_t - */ -typedef void (*da_paused_info_cb) (user_paused_info_t *paused_info, void *user_param); - -/** - * @brief Download Agent will call this function to update received size of download-requested file. - * - * This is user callback function registered on \a da_init. \n - * This is informative, so, user doesn't need to do any action back to Download Agent.\n - * - * @param[in] progress_info updated downloading information - * @param[in] user_param user parameter which is set with \a DA_FEATURE_USER_DATA - * - * @see da_init - * @see da_client_cb_t - */ -typedef void (*da_progress_info_cb) (user_progress_info_t *progress_info, void *user_param); - -/** - * @brief Download Agent will call this function to update mime type, temp file name, total file sizeand installed path. - * - * This is user callback function registered on \a da_init. \n - * This is informative, so, user doesn't need to do any action back to Download Agent.\n - * - * @param[in] download_info updated download information - * @param[in] user_param user parameter which is set with \a DA_FEATURE_USER_DATA - * - * @see da_init - * @see da_client_cb_t - */ -typedef void (*da_started_info_cb) (user_download_info_t *download_info, void *user_param); + const char *temp_file_path; + const char *etag; + const char *pkg_name; + int network_bonding; + void *user_req_data; + void *user_client_data; +} req_data_t; + +typedef void (*da_paused_cb) (int download_id, + void *user_param1, void *user_param2); +typedef void (*da_progress_cb) (int download_id, + unsigned long long received_size, + void *user_param1, void *user_param2); +typedef void (*da_started_cb) (download_info_t *download_info, + void *user_param1, void *user_param2); +typedef void (*da_finished_cb) (finished_info_t *finished_info, + void *user_param1, void *user_param2); -typedef void (*da_finished_info_cb) (user_finished_info_t *finished_info, void *user_param); - /** - * @struct da_client_cb_t - * @brief This structure convey User's callback functions for \a da_init - * @see da_init - */ typedef struct { - /// callback to convey download information - da_started_info_cb update_dl_info_cb; - /// callback to convey downloading information while downloading including received file size - da_progress_info_cb update_progress_info_cb; - /// callback to convey saved path - da_finished_info_cb finished_info_cb; - /// callback to convey etag value - da_paused_info_cb paused_info_cb; -} da_client_cb_t; - -/** - * @fn int da_init (da_client_cb_t *da_client_callback) - * @brief This function initiates Download Agent and registers user callback functions. - * @warning This should be called at once when client application is initialized before using other Download Agent APIs - * @warning This function is paired with da_deinit function. - * - * @pre None. - * @post None. - * - * @param[in] da_client_callback User callback function structure. The type is struct data pointer. - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. - * @remarks User MUST call this function first rather than any other DA APIs. \n - * Please do not call UI code at callback function in direct. \n - * It is better that it returns as soon as copying the data of callback functon. \n - * @see da_deinit - * @par Example - * @code - * #include <download-agent-interface.h> - * - * void da_started_info_cb(user_download_info_t *download_info,void *user_param); - * void da_progress_info_cb(user_downloading_info_t *downloading_info,void *user_param); - * void da_finished_cb(user_finished_info_t *complted_info, void *user_param); - * void da_paused_info_cb(user_paused_info_t *paused_info, void *user_param); - * - * int download_initialize() - * { - * int da_ret; - * da_client_cb_t da_cb = {0}; - * - * da_cb.update_dl_info_cb = &update_download_info_cb; - * da_cb.update_progress_info_cb = &progress_info_cb; - * da_cb.finished_info_cb = &finished_info_cb; - * da_cb.paused_info_cb = &paused_cb; - * - * da_ret = da_init (&da_cb, 0); - * if (da_ret == DA_RESULT_OK) { - * // printf("successed\n"); - * return true; - * } else { - * // printf("failed with error code %d\n", da_ret); - * return fail; - * } - * } - * @endcode - */ -EXPORT_API int da_init(da_client_cb_t *da_client_callback); + da_started_cb download_info_cb; + da_progress_cb progress_cb; + da_finished_cb finished_cb; + da_paused_cb paused_cb; +} da_cb_t; - /** - * @fn int da_deinit () - * @brief This function deinitiates Download Agent. - * - * This function destroys all infomation for client manager. - * When Download Agent is not used any more, please call this function. - * Usually when client application is destructed, this is needed. - * - * @remarks This is paired with da_init. \n - * The client Id should be the one from /a da_init(). \n - * Otherwise, it cannot excute to deinitialize. \n - * - * @pre da_init() must be called in advance. - * @post None. - * - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. - * @see da_init - * @par Example - * @code - * #include <download-agent-interface.h> - * - * - * int download_deinitialize() - * { - * int da_ret; - * da_ret = da_deinit(); - * if(da_ret == DA_RESULT_OK) { - * // printf("successed\n"); - * return true; - * } else { - * // printf("failed with error code %d\n", da_ret); - * return fail; - * } - * } - @endcode - */ +EXPORT_API int da_init(); EXPORT_API int da_deinit(); - /** - * @fn int da_start_download(const char *url, int *download_id) - * @brief This function starts to download a content on passed URL. - * - * Useful information and result are conveyed through following callbacks. - * @li da_started_info_cb - * @li da_progress_cb - * - * @pre da_init() must be called in advance. - * @post None. - * @remarks - * Downloaded file is automatically registered to system. (e.g. File DB) \n - * If there is another file has same name on registering directory, new one's name would have numbering postfix. \n - * (e.g. abc.mp3 to abc_1.mp3) - * - * @param[in] url url to start download - * @param[out] download_id assigned download request id for this URL - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. - * - * @see None. - * - * @par Example - * @code - * #include <download-agent-interface.h> - * - * int da_ret; - * int download_id; - * char *url = "http://www.test.com/sample.mp3"; - * - * da_ret = da_start_download(url,&download_id); - * if (da_ret == DA_RESULT_OK) - * printf("download requesting is successed\n"); - * else - * printf("download requesting is failed with error code %d\n", da_ret); - * @endcode - */ -EXPORT_API int da_start_download(const char *url, int *download_id); - -/** -* @fn int da_start_download_with_extension(const char *url, extension_data_t ext_data, int *download_id) -* @brief This function starts to download a content on passed URL with passed extension. -* -* Useful information and result are conveyed through following callbacks. -* @li da_started_info_cb -* @li da_progress_cb -* -* @pre da_init() must be called in advance. -* @post None. -* @remarks This API operation is exactly same with da_start_download(), except for input properties. \n -* -* @param[in] url url to start download -* @param[in] ext_data extension data -* @param[out] download_id assigned download request id for this URL -* @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. -* -* -* @par Example -* @code - #include <download-agent-interface.h> - - int da_ret; - int download_id; - extension_data_t ext_data = {0,}; - const char *url = "https://www.test.com/sample.mp3"; - const char *install_path = "/myFiles/music"; - const char *my_data = strdup("data"); - ext_data.install_path = install_path; - ext_data.user_data = (void *)my_data; - - da_ret = da_start_download_with_extension(url, &download_id, &ext_data); - if (da_ret == DA_RESULT_OK) - printf("download requesting is successed\n"); - else - printf("download requesting is failed with error code %d\n", da_ret); - @endcode -*/ -EXPORT_API int da_start_download_with_extension(const char *url, - extension_data_t *ext_data, - int *download_id -); - - -/** - * @fn int da_cancel_download(int download_id) - * @brief This function cancels a download for passed download_id. - * - * Client can use this function if user wants to cancel already requested download. - * - * @remarks Should check return value. \n - * If return value is not DA_RESULT_OK, then previous requested download can be keep downloading. - * @remarks After calling this function, all information for the download_id will be deleted. So, client cannot request anything for the download_id. - * - * @pre There should be exist ongoing or suspended download for download_id. - * @post None. - * - * @param[in] download_id download request id - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail - * - * @see None. - * - * @par Example - * @code - #include <download-agent-interface.h> - - int da_ret; - int download_id; - - da_ret = da_cancel_download(download_id); - if(da_ret == DA_RESULT_OK) { - // printf("download with [%d] is successfully canceled.\n", download_id); - } - else { - // in this case, downloading with download_id is keep ongoing. - printf("failed to cancel with error code %d\n", da_ret); - } - @endcode - */ +EXPORT_API int da_start_download(const char *url, req_data_t *ext_data, + da_cb_t *da_cb_data, int *download_id); EXPORT_API int da_cancel_download(int download_id); - - -/** - * @fn int da_suspend_download(int download_id) - * @brief This function suspends downloading for passed download_id. - * - * Client can use this function if user wants to suspend already requested download. - * - * @remarks Should check return value. \n - * If return value is not DA_RESULT_OK, then previous requested download can be keep downloading. - * @remarks After calling this function, all information for the download_id will be remained. So, client can request resume for the download_id. - * @remarks Client should cancel or resume for this download_id, or all information for the download_id will be leaved forever. - * - * @pre There should be exist ongoing download for download_id. - * @post None. - * - * @param[in] download_id download request id - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail - * - * @see da_resume_download() - * @see da_cancel_download() - * - * @par Example - * @code - #include <download-agent-interface.h> - - int da_ret; - int download_id; - - da_ret = da_suspend_download(download_id); - if(da_ret == DA_RESULT_OK) { - // printf("download with [%d] is successfully suspended.\n", download_id); - } - else { - // in this case, downloading with download_id is keep ongoing. - printf("failed to suspend with error code %d\n", da_ret); - } - @endcode - */ +EXPORT_API int da_cancel_download_without_update(int download_id); EXPORT_API int da_suspend_download(int download_id); - EXPORT_API int da_suspend_download_without_update(int download_id); -/** - * @fn int da_resume_download(int download_id) - * @brief This function resumes downloading for passed download_id. - * - * Client can use this function if user wants to resume suspended download. - * - * @remarks Should check return value. \n - * If return value is not DA_RESULT_OK, then requested download can be not to resume. - * - * @pre There should be exist suspended download for download_id. - * @post None. - * - * @param[in] download_id download request id - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail - * - * @see da_suspend_download() - * - * @par Example - * @code - #include <download-agent-interface.h> - - int da_ret; - int download_id; - - da_ret = da_resume_download(download_id); - if(da_ret == DA_RESULT_OK) { - // printf("download with [%d] is successfully resumed.\n", download_id); - } - else { - // in this case, downloading with download_id is keep suspended. - printf("failed to resume with error code %d\n", da_ret); - } - @endcode - */ EXPORT_API int da_resume_download(int download_id); - -/** - * @fn int da_is_valid_download_id(int download_id) - * @brief This function return the download id is valid and the download thread is still alive. - * - * Client can use this function if user wants to resume download. - * If the download id is vaild and the download thread is alive, it can resume download with using da_resume_download() - * If the the download thread was already terminated due to restarting the process, - * it can resume download with using da_start_download_with_extension() - * - * - * - * @remarks Should check return value. \n - * If return value is not DA_RESULT_OK, then requested download can be not to resume. - * - * @pre There should be exist suspended download for download_id. - * @post None. - * - * @param[in] download_id download request id - * @return 1 for success, or 0 for fail - * - */ EXPORT_API int da_is_valid_download_id(int download_id); #ifdef __cplusplus } #endif -#endif //_Download_Agent_Interface_H +#endif //_DOWNLOAD_AGENT_INTERFACE_H diff --git a/agent/include/download-agent-mime-util.h b/agent/include/download-agent-mime-util.h index 5f143e9..7f57899 100755 --- a/agent/include/download-agent-mime-util.h +++ b/agent/include/download-agent-mime-util.h @@ -34,7 +34,15 @@ typedef struct { da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type); da_bool_t da_get_extension_name_from_url(char *url, char **ext); -da_result_t da_mime_get_ext_name(char *mime, char **ext); +da_ret_t da_mime_get_ext_name(char *mime, char **ext); da_bool_t da_get_file_name_from_url(char *url, char **name) ; void delete_prohibited_char(char *szTarget, int str_len); +da_ret_t get_extension_from_mime_type(char *mime_type, char **extension); +#ifdef _ENABLE_OMA_DRM +da_bool_t is_content_drm_dcf(char *content_type); +da_bool_t is_content_drm_dm(char *content_type); +#endif + + + #endif diff --git a/agent/include/download-agent-plugin-conf.h b/agent/include/download-agent-plugin-conf.h index 2c4f55f..11e8095 100755 --- a/agent/include/download-agent-plugin-conf.h +++ b/agent/include/download-agent-plugin-conf.h @@ -19,9 +19,12 @@ #include "download-agent-type.h" #include "download-agent-interface.h" -#include "download-agent-utils.h" -da_result_t get_user_agent_string(char **uagent_str); +da_ret_t get_user_agent_string(char **uagent_str); char *get_proxy_address(void); +#ifdef _RAF_SUPPORT +//test code +void get_smart_bonding_vconf(); +#endif #endif diff --git a/agent/include/download-agent-basic.h b/agent/include/download-agent-plugin-drm.h index 340a34a..361f387 100755..100644 --- a/agent/include/download-agent-basic.h +++ b/agent/include/download-agent-plugin-drm.h @@ -14,16 +14,12 @@ * limitations under the License. */ -#ifndef _Download_Agent_Basic_H -#define _Download_Agent_Basic_H - -#include <string.h> +#ifndef _Download_Agent_Plugin_Drm_H +#define _Download_Agent_Plugin_Drm_H #include "download-agent-type.h" -#include "download-agent-interface.h" -#include "download-agent-dl-mgr.h" -da_result_t start_download(const char *url, int *dl_id); -da_result_t start_download_with_extension(const char *url , int *dl_id, extension_data_t *extension_data); +da_bool_t EDRM_convert(const char *in_file_path, char **out_file_path); +da_ret_t EDRM_wm_get_license(char *rights_url, char **out_content_url); #endif diff --git a/agent/include/download-agent-plugin-http-interface.h b/agent/include/download-agent-plugin-http-interface.h deleted file mode 100755 index b9698bb..0000000 --- a/agent/include/download-agent-plugin-http-interface.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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. - */ - -#ifndef _Download_Agent_Plugin_Http_Interface_H -#define _Download_Agent_Plugin_Http_Interface_H - -#include "download-agent-type.h" -#include "download-agent-http-msg-handler.h" - -typedef enum { - PI_HTTP_METHOD_GET = 1, - PI_HTTP_METHOD_POST = 2, - PI_HTTP_METHOD_HEAD = 3 -} pi_http_method_t; - - -typedef struct _input_for_tranx_t { - pi_http_method_t http_method; - - char *proxy_addr; - queue_t *queue; - - http_msg_request_t* http_msg_request; -} input_for_tranx_t; - - - -da_result_t PI_http_init(void); -void PI_http_deinit(void); - -da_result_t PI_http_start_transaction(const input_for_tranx_t *input_for_tranx, int *out_tranx_id); -da_result_t PI_http_cancel_transaction(int in_tranx_id, da_bool_t abort_option); -da_result_t PI_http_disconnect_transaction(int in_tranx_id); -void PI_http_pause_transaction(int transaction_id); -void PI_http_unpause_transaction(int transaction_id); - -#endif - diff --git a/agent/include/download-agent-plugin-libcurl.h b/agent/include/download-agent-plugin-libcurl.h new file mode 100644 index 0000000..67a4c53 --- /dev/null +++ b/agent/include/download-agent-plugin-libcurl.h @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#ifndef _Download_Agent_Plugin_Libcurl_H +#define _Download_Agent_Plugin_Libcrul_H + +#include "download-agent-type.h" +#include "download-agent-dl-info.h" + +#define MAX_SESSION_COUNT DA_MAX_DOWNLOAD_REQ_AT_ONCE +#define MAX_TIMEOUT DA_MAX_TIME_OUT + +da_ret_t PI_http_start(da_info_t *da_info); +da_ret_t PI_http_disconnect(http_info_t *info); +da_ret_t PI_http_cancel(http_info_t *info); +da_ret_t PI_http_pause(http_info_t *info); +da_ret_t PI_http_unpause(http_info_t *info); +#ifdef _RAF_SUPPORT +da_ret_t PI_http_set_file_name_to_curl(http_msg_t *http_msg, char *file_path); +#endif + +#endif diff --git a/agent/include/download-agent-plugin-libsoup.h b/agent/include/download-agent-plugin-libsoup.h deleted file mode 100755 index 8160042..0000000 --- a/agent/include/download-agent-plugin-libsoup.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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. - */ - -#ifndef _Download_Agent_Plugin_Libsoup_H -#define _Download_Agent_Plugin_Libsoup_H - -#include <string.h> -#include <libsoup/soup.h> - -#include "download-agent-http-queue.h" -#include "download-agent-pthread.h" -#include "download-agent-plugin-http-interface.h" - -typedef struct _pi_session_table_t { - da_bool_t is_using; - SoupSession *session; - SoupMessage *msg; - queue_t *queue; - pthread_mutex_t mutex; - pthread_cond_t cond; - da_bool_t is_paused; -} pi_session_table_t; - -extern pi_session_table_t pi_session_table[]; - -#define MAX_SESSION_COUNT DA_MAX_DOWNLOAD_REQ_AT_ONCE -#define MAX_TIMEOUT 60 // second - -#define IS_VALID_SESSION_TABLE_ENTRY(ENTRY) ((((ENTRY) < 0) || ((ENTRY) > MAX_SESSION_COUNT-1)) ? 0 : 1) - - -#define GET_SESSION_FROM_TABLE_ENTRY(ENTRY) (pi_session_table[ENTRY].session) -#define GET_MSG_FROM_TABLE_ENTRY(ENTRY) (pi_session_table[ENTRY].msg) -#define GET_QUEUE_FROM_TABLE_ENTRY(ENTRY) (pi_session_table[ENTRY].queue) - - -da_bool_t _pi_http_is_valid_input_for_tranx(const input_for_tranx_t *input_for_tranx); - -void _pi_http_init_session_table_entry(const int in_session_table_entry); -void _pi_http_destroy_session_table_entry(const int in_session_table_entry); -int _pi_http_get_avaiable_session_table_entry(void); - -da_bool_t _pi_http_register_queue_to_session_table(const int session_table_entry, const queue_t *in_queue); -da_bool_t _pi_http_register_session_to_session_table(const int in_session_table_entry, SoupSession *session); -da_bool_t _pi_http_register_msg_to_session_table(const int in_session_table_entry, SoupMessage *msg); - -queue_t *_pi_http_get_queue_from_session_table_entry(const int in_session_table_entry); -int _pi_http_get_session_table_entry_from_message(SoupMessage *msg); - -void _pi_http_store_read_data_to_queue(SoupMessage *msg, const char *body_data, int received_body_len); -void _pi_http_store_read_header_to_queue(SoupMessage *msg, const char *sniffedType); -void _pi_http_store_neterr_to_queue(SoupMessage *msg); - - -void _pi_http_finished_cb(SoupSession *session, SoupMessage *msg, gpointer data); -void _pi_http_restarted_cb(SoupMessage *msg, gpointer data); -void _pi_http_gotheaders_cb(SoupMessage *msg, gpointer data); -void _pi_http_contentsniffed_cb(SoupMessage *msg, const char *sniffedType, GHashTable *params, gpointer data); -void _pi_http_gotchunk_cb(SoupMessage *msg, SoupBuffer *chunk, gpointer data); - - -#endif diff --git a/agent/include/download-agent-pthread.h b/agent/include/download-agent-pthread.h index 8523567..2748581 100755 --- a/agent/include/download-agent-pthread.h +++ b/agent/include/download-agent-pthread.h @@ -14,134 +14,131 @@ * limitations under the License. */ -#ifndef _Download_Agent_Pthread_H -#define _Download_Agent_Pthread_H +#ifndef _DOWNLOAD_AGENT_PTHREAD_H +#define _DOWNLOAD_AGENT_PTHREAD_H #include <pthread.h> #include <errno.h> #include <time.h> -#include "download-agent-type.h" #include "download-agent-debug.h" -#define _da_thread_mutex_init(mutex_add, attr) { \ - int ret = 0; \ - do{ \ - ret = pthread_mutex_init(mutex_add, attr); \ - if (0 == ret){ \ - break; \ - } \ - else if(EINVAL == ret){ \ - DA_LOG_ERR(Default, "pthread_mutex_init FAIL with EINVAL."); \ - break; \ - } \ - else if(ENOMEM == ret){ \ - DA_LOG_ERR(Default, "pthread_mutex_init FAIL with ENOMEM."); \ - break; \ - } \ - else{ \ - DA_LOG_ERR(Default, "pthread_mutex_init FAIL with %d.", ret); \ - break; \ - } \ - }while(1); \ - } - -#define _da_thread_cond_init(cond_add, attr) do{ \ - if (0 != pthread_cond_init(cond_add, attr)){\ - DA_LOG_ERR(Default, "pthread_cond_init FAIL");} \ - }while(0) - - - -#define _da_thread_mutex_lock(mutex_add) {\ - int ret = 0;\ - do{\ - ret = pthread_mutex_lock(mutex_add);\ - if (0 == ret){\ - break;\ - }\ - else if(EINVAL == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_lock FAIL with EINVAL.");\ - break;\ - }\ - else if(EDEADLK == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_lock FAIL with EDEADLK.");\ - break;\ - }\ - else{\ - DA_LOG_ERR(Default, "pthread_mutex_lock FAIL with %d.", ret);\ - break;\ - }\ - }while(1);\ - } - - -#define _da_thread_mutex_unlock(mutex_add) {\ - int ret = 0;\ - do{\ - ret = pthread_mutex_unlock(mutex_add);\ - if (0 == ret){\ - break;\ - }\ - else if(EINVAL == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_unlock FAIL with EINVAL.");\ - break;\ - }\ - else if(EPERM == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_unlock FAIL with EPERM.");\ - break;\ - }\ - else{\ - DA_LOG_ERR(Default, "pthread_mutex_unlock FAIL with %d.", ret);\ - break;\ - }\ - }while(1);\ - } - - -#define _da_thread_cond_signal(cond_add) do{ \ - if (0 != pthread_cond_signal(cond_add)){\ - DA_LOG_ERR(Default, "pthread_cond_signal FAIL");} \ - }while(0) - - - -#define _da_thread_cond_wait(cond_add, mutex_add) do{ \ - if (0 != pthread_cond_wait(cond_add, mutex_add)){\ - DA_LOG_ERR(Default, "pthread_cond_wait FAIL");} \ - }while(0) - -#define _da_thread_cond_timed_wait(cond_add, mutex_add, time) do{ \ - if (0 != pthread_cond_timedwait(cond_add, mutex_add, time)){\ - DA_LOG_ERR(Default, "pthread_cond_wait FAIL");} \ - }while(0) - - -#define _da_thread_cond_destroy(cond_add) do{ \ - if (0 != pthread_cond_destroy(cond_add)){\ - DA_LOG_ERR(Default, "pthread_cond_destroy FAIL");} \ - }while(0) - -#define _da_thread_mutex_destroy(mutex_add) {\ - int ret = 0;\ - do{\ - ret = pthread_mutex_destroy(mutex_add);\ - if (0 == ret){\ - break;\ - }\ - else if(EINVAL == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_destroy FAIL with EINVAL.");\ - break;\ - }\ - else if(EBUSY == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_destroy FAIL with EBUSY.");\ - break;\ - }\ - else{\ - DA_LOG_ERR(Default, "pthread_mutex_destroy FAIL with %d.", ret);\ - break;\ - }\ - }while(1);\ - } - +#define DA_MUTEX_INIT(mutex_add, attr) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_init(mutex_add, attr);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret){\ + DA_LOGE("pthread_mutex_init FAIL with EINVAL.");\ + break;\ + }\ + else if (ENOMEM == ret){\ + DA_LOGE("pthread_mutex_init FAIL with ENOMEM.");\ + break;\ + }\ + else{\ + DA_LOGE("pthread_mutex_init FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} + +#define DA_COND_INIT(cond_add, attr) do {\ + if (0 != pthread_cond_init(cond_add, attr)){\ + DA_LOGE("pthread_cond_init FAIL");\ + }\ +} while(0) + +#define DA_MUTEX_LOCK(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_lock(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret){\ + DA_LOGE("pthread_mutex_lock FAIL with EINVAL.");\ + break;\ + }\ + else if (EDEADLK == ret){\ + DA_LOGE("pthread_mutex_lock FAIL with EDEADLK.");\ + break;\ + }\ + else{\ + DA_LOGE("pthread_mutex_lock FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} + +#define DA_MUTEX_UNLOCK(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_unlock(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret) {\ + DA_LOGE("pthread_mutex_unlock FAIL with EINVAL.");\ + break;\ + }\ + else if (EPERM == ret) {\ + DA_LOGE("pthread_mutex_unlock FAIL with EPERM.");\ + break;\ + }\ + else {\ + DA_LOGE("pthread_mutex_unlock FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} + +#define DA_COND_SIGNAL(cond_add) do {\ + if (0 != pthread_cond_signal(cond_add)) {\ + DA_LOGE("pthread_cond_signal FAIL");\ + }\ + } while(0) + +#define DA_COND_WAIT(cond_add, mutex_add) do {\ + if (0 != pthread_cond_wait(cond_add, mutex_add)){\ + DA_LOGE("pthread_cond_wait FAIL");\ + }\ + } while(0) + +#define DA_COND_TIMED_WAIT(cond_add, mutex_add, time) do {\ + if (0 != pthread_cond_timedwait(cond_add, mutex_add, time)){\ + DA_LOGE("pthread_cond_wait FAIL");\ + }\ + } while(0) + + +#define DA_COND_DESTROY(cond_add) do {\ + if (0 != pthread_cond_destroy(cond_add)){\ + DA_LOGE("pthread_cond_destroy FAIL");\ + }\ + } while(0) + +#define DA_MUTEX_DESTROY(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_destroy(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret){\ + DA_LOGE("pthread_mutex_destroy FAIL with EINVAL.");\ + break;\ + }\ + else if (EBUSY == ret){\ + DA_LOGE("pthread_mutex_destroy FAIL with EBUSY.");\ + break;\ + }\ + else {\ + DA_LOGE("pthread_mutex_destroy FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} #endif diff --git a/agent/include/download-agent-type.h b/agent/include/download-agent-type.h index 86fa5ca..e77c121 100755 --- a/agent/include/download-agent-type.h +++ b/agent/include/download-agent-type.h @@ -14,13 +14,14 @@ * limitations under the License. */ -#ifndef _Download_Agent_Types_H -#define _Download_Agent_Types_H +#ifndef _DOWNLOAD_AGENT_TYPE_H +#define _DOWNLOAD_AGENT_TYPE_H #include "download-agent-defs.h" -typedef int da_result_t; +typedef int da_ret_t; typedef int da_bool_t; +typedef unsigned long long da_size_t; #define IS_NOT_VALID_ID(x) (x <= DA_INVALID_ID) @@ -31,5 +32,42 @@ typedef int da_bool_t; #define DA_MAX_MIME_STR_LEN 256 #define DA_MAX_PROXY_ADDR_LEN 64 // e.g. 100.200.300.400:10000 +#define SCHEME_HTTP "http://" + +#define DA_DEFAULT_INSTALL_PATH_FOR_PHONE "/opt/usr/media/Downloads" + +#define DA_MAX_ID DA_MAX_DOWNLOAD_REQ_AT_ONCE + +#define SAVE_FILE_BUFFERING_SIZE_50KB (50*1024) + +#define NULL_CHECK(DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + return;\ + }\ +} + +#define NULL_CHECK_RET(DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + return DA_ERR_INVALID_ARGUMENT;\ + }\ +} + +#define NULL_CHECK_GOTO(DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + ret = DA_ERR_INVALID_ARGUMENT;\ + goto ERR;\ + }\ +} + +#define NULL_CHECK_RET_OPT(DATA, RET_DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + return RET_DATA;\ + }\ +} + #endif diff --git a/agent/include/download-agent-utils.h b/agent/include/download-agent-utils.h deleted file mode 100755 index ee73307..0000000 --- a/agent/include/download-agent-utils.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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. - */ - -#ifndef _Download_Agent_Utils_H -#define _Download_Agent_Utils_H - -#include <time.h> -#include "download-agent-defs.h" -#include "download-agent-interface.h" -#include "download-agent-dl-mgr.h" - -#define SAVE_FILE_BUFFERING_SIZE_50KB (50*1024) -#define SAVE_FILE_BUFFERING_SIZE_5MB (5*1024*1024) - -#define DA_SLEEP(x) \ - do \ - { \ - struct timespec interval,remainder; \ - interval.tv_sec = (unsigned int)((x)/1000); \ - interval.tv_nsec = (((x)-(interval.tv_sec*1000))*1000000); \ - nanosleep(&interval,&remainder); \ - } while(0) - -typedef struct _da_storage_size_t { - unsigned long b_available; - unsigned long b_size; -} da_storage_size_t; - -typedef enum { - DA_MIME_TYPE_NONE, - DA_MIME_TYPE_DRM1_MESSATE, - DA_MIME_TYPE_END -} da_mime_type_id_t; - -void get_random_number(int *out_num); -da_result_t get_available_dd_id(int *available_id); -da_result_t get_extension_from_mime_type(char *mime_type, char **extension); -da_mime_type_id_t get_mime_type_id(char *content_type); -da_result_t get_available_memory(da_storage_size_t *avail_memory); -da_bool_t is_valid_url(const char *url, da_result_t *err_code); - -int read_data_from_file(char *file, char**out_buffer); -da_result_t move_file(const char *from_path, const char *to_path); -void remove_file(const char *file_path); -char *_stristr(const char *long_str, const char *find_str); - -#endif diff --git a/download-provider-schema.sql b/download-provider-schema.sql deleted file mode 100644 index 44beda2..0000000 --- a/download-provider-schema.sql +++ /dev/null @@ -1,74 +0,0 @@ -CREATE TABLE IF NOT EXISTS groups -( -id INTEGER UNIQUE PRIMARY KEY, -uid INTEGER DEFAULT 0, -gid INTEGER DEFAULT 0, -extra_int INTEGER DEFAULT 0, -packagename TEXT DEFAULT NULL, -smack_label TEXT DEFAULT NULL, -extra TEXT DEFAULT NULL, -date_first_connected DATE, -date_last_connected DATE -); - -CREATE TABLE IF NOT EXISTS logging -( -id INTEGER UNIQUE PRIMARY KEY, -state INTEGER DEFAULT 0, -errorcode INTEGER DEFAULT 0, -startcount INTEGER DEFAULT 0, -packagename TEXT DEFAULT NULL, -createtime DATE, -accesstime DATE -); - -CREATE TABLE IF NOT EXISTS requestinfo -( -id INTEGER UNIQUE PRIMARY KEY, -auto_download BOOLEAN DEFAULT 0, -state_event BOOLEAN DEFAULT 0, -progress_event BOOLEAN DEFAULT 0, -noti_enable BOOLEAN DEFAULT 0, -network_type TINYINT DEFAULT 0, -filename TEXT DEFAULT NULL, -destination TEXT DEFAULT NULL, -url TEXT DEFAULT NULL, -FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS downloadinfo -( -id INTEGER UNIQUE PRIMARY KEY, -http_status INTEGER DEFAULT 0, -content_size UNSIGNED BIG INT DEFAULT 0, -mimetype VARCHAR(64) DEFAULT NULL, -content_name TEXT DEFAULT NULL, -saved_path TEXT DEFAULT NULL, -tmp_saved_path TEXT DEFAULT NULL, -etag TEXT DEFAULT NULL, -FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS httpheaders -( -id INTEGER NOT NULL, -header_field TEXT DEFAULT NULL, -header_data TEXT DEFAULT NULL, -FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS notification -( -id INTEGER NOT NULL, -extra_key TEXT DEFAULT NULL, -extra_data TEXT DEFAULT NULL, -raw_bundle_data_complete_state BLOB DEFAULT NULL, -raw_bundle_data_fail_state BLOB DEFAULT NULL, -raw_bundle_data_ongoing_state BLOB DEFAULT NULL, -title TEXT DEFAULT NULL, -description TEXT DEFAULT NULL, -noti_type INTEGER DEFAULT 0, -FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE -); - -CREATE UNIQUE INDEX IF NOT EXISTS requests_index ON logging (id, state, errorcode, packagename, createtime, accesstime); diff --git a/download-provider-w.manifest b/download-provider-w.manifest new file mode 100644 index 0000000..e72ee5e --- /dev/null +++ b/download-provider-w.manifest @@ -0,0 +1,36 @@ +<manifest> + <define> + <domain name="download-provider" /> + <provide> + <label name="download-provider::db" /> + </provide> + <request> + <smack request="download-provider::db" type="rw" /> + <smack request="system::use_internet" type="w" /> + <smack request="sys-assert::core" type="rwxat" /> + <smack request="device::sys_logging" type="w" /> + <smack request="system::media" type="arwxt" /> + <smack request="system::ext_media" type="arwxt" /> + <smack request="connman" type="rw" /> + <smack request="net-config" type="rw" /> + <smack request="wifi-direct::info" type="r" /> + <smack request="connman::get" type="rw" /> + <smack request="telephony_framework::api_ps_public" type="rw" /> + </request> + <permit> + <smack permit="system::use_internet" type="w" /> + </permit> + </define> + <request> + <domain name="download-provider" /> + </request> + <assign> + <filesystem path="/usr/lib/libdownload-provider-interface.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/libdownloadagent2.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/graphical.target.wants/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/sockets.target.wants/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/opt/etc/dump.d/module.d/dump-download-provider.sh" label="_" exec_label="none" /> + </assign> +</manifest> diff --git a/download-provider.manifest b/download-provider.manifest index ffeb523..ae67354 100755..100644 --- a/download-provider.manifest +++ b/download-provider.manifest @@ -9,14 +9,17 @@ <smack request="system::use_internet" type="w" /> <smack request="sys-assert::core" type="rwxat" /> <smack request="device::sys_logging" type="w" /> - <smack request="system::media" type="arwxt" /> + <smack request="system::ext_storage" type="arwxt" /> <smack request="system::ext_media" type="arwxt" /> + <smack request="system::media" type="rwxat" /> + <smack request="system::media::root" type="rwxat" /> <smack request="connman" type="rw" /> <smack request="net-config" type="rw" /> + <smack request="wifi-direct::info" type="r" /> + <smack request="connman::get" type="rw" /> + <smack request="telephony_framework::api_ps_public" type="rw" /> </request> <permit> - <smack permit="org.tizen.indicator" type="rx" /> - <smack permit="org.tizen.quickpanel" type="rx" /> <smack permit="system::use_internet" type="w" /> </permit> </define> @@ -24,11 +27,13 @@ <domain name="download-provider" /> </request> <assign> + <filesystem path="/usr/share/download-provider*" label="_" /> <filesystem path="/usr/lib/libdownload-provider-interface.so*" label="_" exec_label="none" /> <filesystem path="/usr/lib/libdownloadagent2.so*" label="_" exec_label="none" /> - <filesystem path="/usr/lib/systemd/user/download-provider.service" label="_" exec_label="none" /> - <filesystem path="/usr/lib/systemd/user/tizen-middleware.target.wants/download-provider.service" label="_" exec_label="none" /> - <filesystem path="/usr/lib/systemd/user/download-provider.socket" label="_" exec_label="none" /> - <filesystem path="/usr/lib/systemd/user/sockets.target.wants/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/graphical.target.wants/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/sockets.target.wants/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/opt/etc/dump.d/module.d/dump-download-provider.sh" label="_" exec_label="none" /> </assign> </manifest> diff --git a/download-provider.rule b/download-provider.rule deleted file mode 100644 index 9739e6d..0000000 --- a/download-provider.rule +++ /dev/null @@ -1,17 +0,0 @@ -root download-provider rw--- -_default_ download-provider rw--- -download-provider _ -w--- -download-provider data-provider-master::notification.client -w--- -download-provider data-provider-master::notification rw--- -download-provider ail::db rw--- -download-provider device::app_logging -w--- -download-provider system::vconf rwx-- -download-provider system::ext_media rwxat -download-provider system::media rwxat -download-provider device::sys_logging -w--- -download-provider sys-assert::core rwxat -download-provider system::use_internet -w--- -download-provider download-provider::db rw--- -system::use_internet download-provider -w--- -org.tizen.quickpanel download-provider r-x-- -org.tizen.indicator download-provider rwx-- diff --git a/dump-download-provider.sh b/dump-download-provider.sh new file mode 100644 index 0000000..e639496 --- /dev/null +++ b/dump-download-provider.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +PKG_NAME=download-provider + +DUMP_DIR=$1/$PKG_NAME +/bin/mkdir -p $DUMP_DIR + +# Download DB +DB_DIR=/opt/usr/data/download-provider/database +if [ "$DB_DIR" ] +then + /bin/echo "copy download DB ..." + /bin/cp -rf ${DB_DIR}* $DUMP_DIR +fi diff --git a/packaging/download-provider.spec b/packaging/download-provider.spec index d2db7e5..0c271de 100755..100644 --- a/packaging/download-provider.spec +++ b/packaging/download-provider.spec @@ -1,38 +1,44 @@ +%define _ux_define tizen2.3 Name: download-provider -Summary: download the contents in background. -Version: 1.1.6 +Summary: Download the contents in background +Version: 2.1.23 Release: 0 Group: Development/Libraries License: Apache License, Version 2.0 Source0: %{name}-%{version}.tar.gz Requires(post): sys-assert Requires(post): libdevice-node -Requires(post): org.tizen.indicator -Requires(post): org.tizen.quickpanel Requires(post): sqlite Requires(post): connman BuildRequires: cmake -BuildRequires: libprivilege-control-conf -BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(gobject-2.0) BuildRequires: pkgconfig(dlog) -BuildRequires: pkgconfig(libsoup-2.4) +BuildRequires: pkgconfig(gobject-2.0) BuildRequires: pkgconfig(xdgmime) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(bundle) BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(capi-appfw-application) BuildRequires: pkgconfig(capi-network-connection) -BuildRequires: pkgconfig(notification) BuildRequires: pkgconfig(appsvc) -BuildRequires: pkgconfig(wifi-direct) +BuildRequires: pkgconfig(libcurl) +BuildRequires: pkgconfig(capi-content-mime-type) BuildRequires: pkgconfig(libsmack) BuildRequires: gettext-devel BuildRequires: pkgconfig(libsystemd-daemon) +BuildRequires: pkgconfig(capi-network-wifi-direct) +BuildRequires: pkgconfig(system-resource) +BuildRequires: model-build-features +BuildRequires: pkgconfig(storage) +%if "%{?tizen_profile_name}" == "wearable" +BuildRequires: pkgconfig(security-server) +%else if "%{?tizen_profile_name}" == "mobile" +BuildRequires: pkgconfig(notification) +%endif %description -Description: download the contents in background +Description: Download the contents in background %package devel Summary: download-provider @@ -40,20 +46,40 @@ Group: Development/Libraries Requires: %{name} = %{version}-%{release} %description devel -Description: download the contents in background (developement files) +Description: Download the contents in background (development files) %prep %setup -q -%define _data_install_path /usr/share/%{name} -%define _imagedir %{_data_install_path}/images -%define _localedir %{_data_install_path}/locales -%define _sqlschemadir %{_data_install_path}/sql -%define _databasedir /opt/usr/dbspace -%define _databasefile %{_databasedir}/.download-provider.db -%define _sqlschemafile %{_sqlschemadir}/download-provider-schema.sql +%define _data_install_path /opt/usr/data/%{name} +%define _resource_install_path /usr/share/%{name} +%define _imagedir %{_resource_install_path}/images +%define _localedir %{_resource_install_path}/locales +%define _databasedir %{_data_install_path}/database +%define _database_client_dir %{_databasedir}/clients +%define _notifydir %{_data_install_path}/notify +%define _ipc_socket /opt/data/%{name}/%{name}.sock %define _licensedir /usr/share/license -%define _smackruledir /opt/etc/smack/accesses.d +%define _logdump_script_dir /opt/etc/dump.d/module.d +%define _http_lib libcurl + +%define download_booster OFF +%define sys_resource OFF +%define support_oma_drm OFF +%define wifi_direct ON +%define support_security_privilege OFF +%define support_companion_mode OFF +%define support_notification ON +%define _manifest_name %{name}.manifest + +%if 0%{?model_build_feature_wlan_p2p_disable } +%define wifi_direct OFF +%endif +%if "%{?tizen_profile_name}" == "wearable" +%define download_booster OFF +%define support_notification OFF +%define _manifest_name %{name}-w.manifest +%endif %define cmake \ CFLAGS="${CFLAGS:-%optflags} -fPIC -D_REENTRANT -fvisibility=hidden"; export CFLAGS \ @@ -67,16 +93,55 @@ Description: download the contents in background (developement files) -DPKG_NAME=%{name} \\\ -DPKG_VERSION=%{version} \\\ -DPKG_RELEASE=%{release} \\\ + -DIPC_SOCKET:PATH=%{_ipc_socket} \\\ + -DPROVIDER_DIR:PATH=%{_data_install_path} \\\ + -DNOTIFY_DIR:PATH=%{_notifydir} \\\ + -DDATABASE_DIR:PATH=%{_databasedir} \\\ + -DDATABASE_CLIENT_DIR:PATH=%{_database_client_dir} \\\ -DIMAGE_DIR:PATH=%{_imagedir} \\\ -DLOCALE_DIR:PATH=%{_localedir} \\\ - -DDATABASE_SCHEMA_DIR=%{_sqlschemadir} \\\ - -DDATABASE_FILE:PATH=%{_databasefile} \\\ - -DDATABASE_SCHEMA_FILE=%{_sqlschemafile} \\\ -DLICENSE_DIR:PATH=%{_licensedir} \\\ - -DSMACK_RULE_DIR:PATH=%{_smackruledir} \\\ + %if "%{?wifi_direct}" == "ON" \ + -DSUPPORT_WIFI_DIRECT:BOOL=ON \\\ + %else \ -DSUPPORT_WIFI_DIRECT:BOOL=OFF \\\ + %endif \ + %if "%{?sys_resource}" == "ON" \ + -DSUPPORT_SYS_RESOURCE:BOOL=ON \\\ + %else \ + -DSUPPORT_SYS_RESOURCE:BOOL=OFF \\\ + %endif \ + %if "%{?download_booster}" == "ON" \ + -DSUPPORT_DOWNLOAD_BOOSTER:BOOL=ON \\\ + %else \ + -DSUPPORT_DOWNLOAD_BOOSTER:BOOL=OFF \\\ + %endif \ + %if "%{?support_notification}" == "ON" \ + -DSUPPORT_NOTIFICATION:BOOL=ON \\\ + %else \ + -DSUPPORT_NOTIFICATION:BOOL=OFF \\\ + %endif \ -DSUPPORT_LOG_MESSAGE:BOOL=ON \\\ - -DSUPPORT_CHECK_IPC:BOOL=ON \\\ + %if "%{?support_oma_drm}" == "ON" \ + -DSUPPORT_OMA_DRM:BOOL=ON \\\ + %else \ + -DSUPPORT_OMA_DRM:BOOL=OFF \\\ + %endif \ + %if "%{?support_security_privilege}" == "ON" \ + -DSUPPORT_SECURITY_PRIVILEGE:BOOL=ON \\\ + %else \ + -DSUPPORT_SECURITY_PRIVILEGE:BOOL=OFF \\\ + %endif \ + %if "%{?support_companion_mode}" == "ON" \ + -DSUPPORT_COMPANION_MODE:BOOL=ON \\\ + %else \ + -DSUPPORT_COMPANION_MODE:BOOL=OFF \\\ + %endif \ + %if "%{?_ux_define}" == "tizen2.3" \ + -DTIZEN_2_3_UX:BOOL=ON \\\ + %endif \ + -DCMAKE_LOG_DUMP_SCRIPT_DIR=%{_logdump_script_dir} \\\ + -DHTTP_LIB=%{_http_lib} \\\ %if "%{?_lib}" == "lib64" \ %{?_cmake_lib_suffix64} \\\ %endif \ @@ -84,11 +149,9 @@ Description: download the contents in background (developement files) -DBUILD_SHARED_LIBS:BOOL=ON %build -%if 0%{?tizen_build_binary_release_type_eng} -export CFLAGS="$CFLAGS -DTIZEN_ENGINEER_MODE" -export CXXFLAGS="$CXXFLAGS -DTIZEN_ENGINEER_MODE" -export FFLAGS="$FFLAGS -DTIZEN_ENGINEER_MODE" -%endif +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" %cmake . make %{?jobs:-j%jobs} @@ -96,29 +159,25 @@ make %{?jobs:-j%jobs} rm -rf %{buildroot} %make_install mkdir -p %{buildroot}%{_licensedir} -mkdir -p %{buildroot}/%{_data_install_path} mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants mkdir -p %{buildroot}%{_libdir}/systemd/system/sockets.target.wants ln -s ../download-provider.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/ ln -s ../download-provider.socket %{buildroot}%{_libdir}/systemd/system/sockets.target.wants/ %post -mkdir -p %{_databasedir} - -if [ ! -f %{_databasefile} ]; -then -sqlite3 %{_databasefile} '.read %{_sqlschemafile}' -chmod 660 %{_databasefile} -chmod 660 %{_databasefile}-journal -fi +#make notify dir in post section for smack +mkdir -p %{_notifydir} +mkdir -p --mode=0700 %{_databasedir} +chsmack -a 'download-provider' %{_databasedir} +mkdir -p --mode=0700 %{_database_client_dir} +chsmack -a 'download-provider' %{_database_client_dir} %files %defattr(-,root,root,-) -%manifest download-provider.manifest +%manifest %{_manifest_name} %{_imagedir}/*.png -%{_imagedir}/*.gif -%{_localedir}/* -%{_libdir}/libdownloadagent2.so.0.0.1 +%{_localedir}/*/*/download-provider.mo +%{_libdir}/libdownloadagent2.so.0.1.0 %{_libdir}/libdownloadagent2.so %{_libdir}/systemd/system/download-provider.service %{_libdir}/systemd/system/graphical.target.wants/download-provider.service @@ -128,47 +187,15 @@ fi %{_libdir}/libdownload-provider-interface.so.0 %{_bindir}/%{name} %{_licensedir}/%{name} -%{_smackruledir}/%{name}.rule -%{_sqlschemafile} +%attr(0544,root,root) %{_logdump_script_dir}/dump-%{name}.sh %files devel %defattr(-,root,root,-) -%{_libdir}/libdownloadagent2.so.0.0.1 +%{_libdir}/libdownloadagent2.so.0.1.0 %{_libdir}/libdownloadagent2.so %{_libdir}/libdownload-provider-interface.so -%{_includedir}/download-provider/download-provider-defs.h +%{_includedir}/download-provider/download-provider.h %{_includedir}/download-provider/download-provider-interface.h %{_bindir}/%{name} %{_libdir}/pkgconfig/download-provider.pc %{_libdir}/pkgconfig/download-provider-interface.pc - -%changelog -* Tue Oct 29 2013 Jungki Kwak <jungki.kwak@samsung.com> -- Resolve a bug about invalid url - -* Tue Sep 17 2013 Jungki Kwak <jungki.kwak@samsung.com> -- Add depenency of connman for smack label - -* Thu Sep 12 2013 Jungki Kwak <jungki.kwak@samsung.com> -- Resolve a bug to check return value -- Resolve build warnnings and add error exception -- Register download notification when client process is exited - -* Wed Sep 11 2013 Jungki Kwak <jungki.kwak@samsung.com> -- Implement auto-resume in ip-changed case -- Remove dbus-activation feature -- Implementation of new APIs for notification - -* Tue Sep 05 2013 Jungki Kwak <jungki.kwak@samsung.com> -- Update downloading icon for ongoing notification -- Return disk full error when file system call return in case of ENOSPC - -* Tue Jul 09 2013 Jungki Kwak <jungki.kwak@samsung.com> -- Change to use vconf for downloading icon of indicator - -* Mon Jul 08 2013 Jungki Kwak <jungki.kwak@samsung.com> -- Add to check smack enable state - -* Thu Jul 04 2013 Jungki Kwak <jungki.kwak@samsung.com> -- Check smack integrity about install directory and downloaded file - diff --git a/po/POTFILES.in.in b/po/POTFILES.in.in deleted file mode 100755 index bcb7f1f..0000000 --- a/po/POTFILES.in.in +++ /dev/null @@ -1,2 +0,0 @@ -# List of source files containing translatable strings. -@@APPNAME@@.c diff --git a/po/ar.po b/po/ar.po deleted file mode 100755 index db4e25e..0000000 --- a/po/ar.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "تم التنزيل" - diff --git a/po/az.po b/po/az.po deleted file mode 100755 index 8120d37..0000000 --- a/po/az.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Yükləmə tamamlandı" - diff --git a/po/bg.po b/po/bg.po deleted file mode 100755 index b8b9584..0000000 --- a/po/bg.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Изтеглянето завършено" - diff --git a/po/ca.po b/po/ca.po deleted file mode 100755 index 291f7a7..0000000 --- a/po/ca.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Descàrrega completa" - diff --git a/po/cs.po b/po/cs.po deleted file mode 100755 index cf228be..0000000 --- a/po/cs.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Stahování dokončeno" - diff --git a/po/da.po b/po/da.po deleted file mode 100755 index ffba089..0000000 --- a/po/da.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Overførsel fuldført" - diff --git a/po/de_DE.po b/po/de_DE.po deleted file mode 100755 index 1c9c61a..0000000 --- a/po/de_DE.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Download beendet" - diff --git a/po/en.po b/po/en.po deleted file mode 100755 index 03ffa61..0000000 --- a/po/en.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Download complete" - diff --git a/po/en_PH.po b/po/en_PH.po deleted file mode 100755 index 03ffa61..0000000 --- a/po/en_PH.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Download complete" - diff --git a/po/en_US.po b/po/en_US.po deleted file mode 100755 index 03ffa61..0000000 --- a/po/en_US.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Download complete" - diff --git a/po/es_ES.po b/po/es_ES.po deleted file mode 100755 index 3cd494a..0000000 --- a/po/es_ES.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Descarga completa" - diff --git a/po/es_MX.po b/po/es_MX.po deleted file mode 100755 index 3cd494a..0000000 --- a/po/es_MX.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Descarga completa" - diff --git a/po/eu.po b/po/eu.po deleted file mode 100755 index b1e418a..0000000 --- a/po/eu.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Deskarga osatuta" - diff --git a/po/fi.po b/po/fi.po deleted file mode 100755 index 058a8d6..0000000 --- a/po/fi.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Lataus valmis" - diff --git a/po/fr_CA.po b/po/fr_CA.po deleted file mode 100755 index 64e4156..0000000 --- a/po/fr_CA.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Téléchargement terminé" - diff --git a/po/fr_FR.po b/po/fr_FR.po deleted file mode 100755 index 64e4156..0000000 --- a/po/fr_FR.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Téléchargement terminé" - diff --git a/po/ga.po b/po/ga.po deleted file mode 100755 index 5e9474a..0000000 --- a/po/ga.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Íoslódáilte" - diff --git a/po/gl.po b/po/gl.po deleted file mode 100755 index 3cd494a..0000000 --- a/po/gl.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Descarga completa" - diff --git a/po/hi.po b/po/hi.po deleted file mode 100755 index 5ece567..0000000 --- a/po/hi.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "डाउनलोड पूर्ण" - diff --git a/po/hr.po b/po/hr.po deleted file mode 100755 index b4ae9f2..0000000 --- a/po/hr.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Skidanje dovršeno" - diff --git a/po/hu.po b/po/hu.po deleted file mode 100755 index 239c6b9..0000000 --- a/po/hu.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "A letöltés befejeződött" - diff --git a/po/hy.po b/po/hy.po deleted file mode 100755 index 12ea497..0000000 --- a/po/hy.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Ներբեռնումն ավարտվեց" - diff --git a/po/is.po b/po/is.po deleted file mode 100755 index 470a453..0000000 --- a/po/is.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Niðurhali lokið" - diff --git a/po/it_IT.po b/po/it_IT.po deleted file mode 100755 index e96495c..0000000 --- a/po/it_IT.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Download completato" - diff --git a/po/ja_JP.po b/po/ja_JP.po deleted file mode 100755 index 41ea60e..0000000 --- a/po/ja_JP.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "ダウンロード完了" - diff --git a/po/kk.po b/po/kk.po deleted file mode 100755 index 40ff8b2..0000000 --- a/po/kk.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Жүктеу аяқталды" - diff --git a/po/ko_KR.po b/po/ko_KR.po deleted file mode 100755 index 1f47a18..0000000 --- a/po/ko_KR.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "다운로드 완료" - diff --git a/po/lt.po b/po/lt.po deleted file mode 100755 index ea1075f..0000000 --- a/po/lt.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Atsisiuntimas baigtas" - diff --git a/po/lv.po b/po/lv.po deleted file mode 100755 index d3bf10c..0000000 --- a/po/lv.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Lejupielāde pabeigta" - diff --git a/po/mk.po b/po/mk.po deleted file mode 100755 index 8ae0de2..0000000 --- a/po/mk.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Преземањето заврши" - diff --git a/po/nb.po b/po/nb.po deleted file mode 100755 index 33af7b7..0000000 --- a/po/nb.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Nedlasting fullført" - diff --git a/po/nl_NL.po b/po/nl_NL.po deleted file mode 100755 index 2273390..0000000 --- a/po/nl_NL.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Downloaden voltooid" - diff --git a/po/pl.po b/po/pl.po deleted file mode 100755 index 8a48b82..0000000 --- a/po/pl.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Pobieranie zakończone" - diff --git a/po/pt_BR.po b/po/pt_BR.po deleted file mode 100755 index f97065e..0000000 --- a/po/pt_BR.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Download concluído" - diff --git a/po/pt_PT.po b/po/pt_PT.po deleted file mode 100755 index cbe7377..0000000 --- a/po/pt_PT.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Transferência concluída" - diff --git a/po/CMakeLists.txt b/po/redwood/CMakeLists.txt index 9e2d8c6..706d725 100755..100644 --- a/po/CMakeLists.txt +++ b/po/redwood/CMakeLists.txt @@ -1,10 +1,9 @@ # for i18n -SET(POFILES ar.po az.po bg.po ca.po cs.po da.po de_DE.po el_GR.po en.po en_PH.po - en_US.po es_ES.po es_MX.po et.po eu.po fi.po fr_CA.po fr_FR.po ga.po gl.po hi.po - hr.po hu.po hy.po is.po it_IT.po ja_JP.po ka.po kk.po ko_KR.po lt.po lv.po mk.po - nb.po nl_NL.po pl.po pt_BR.po pt_PT.po ro.po ru_RU.po sk.po sl.po sr.po sv.po - tr_TR.po uk.po uz.po zh_CN.po zh_HK.po zh_SG.po zh_TW.po) +SET(POFILES az.po bg.po ca.po cs.po da.po de.po el_GR.po en.po en_US.po es_ES.po + es_US.po et.po eu.po fi.po fr_CA.po fr.po gl.po hr.po hu.po hy.po is.po + it_IT.po ka.po kk.po ko_KR.po lt.po lv.po mn_MN.po nb.po nl.po pl.po + pt_BR.po pt_PT.po ro.po ru_RU.po sk.po sl.po sr.po sv.po tr_TR.po uk.po uz.po) SET(MSGFMT "/usr/bin/msgfmt") diff --git a/po/redwood/az.po b/po/redwood/az.po new file mode 100644 index 0000000..f8d4868 --- /dev/null +++ b/po/redwood/az.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yükləmə tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yükləmə alınmadı" + diff --git a/po/redwood/bg.po b/po/redwood/bg.po new file mode 100644 index 0000000..4b2b9cb --- /dev/null +++ b/po/redwood/bg.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Изтеглянето завършено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Изтеглянето неуспешно" + diff --git a/po/redwood/ca.po b/po/redwood/ca.po new file mode 100644 index 0000000..e4cb32e --- /dev/null +++ b/po/redwood/ca.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descàrrega completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descàrrega fallida" + diff --git a/po/redwood/cs.po b/po/redwood/cs.po new file mode 100644 index 0000000..7c33b8b --- /dev/null +++ b/po/redwood/cs.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Stahování dokončeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Stažení se nezdařilo" + diff --git a/po/redwood/da.po b/po/redwood/da.po new file mode 100644 index 0000000..1cbbbec --- /dev/null +++ b/po/redwood/da.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Overførsel fuldført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Overførsel mislykkedes" + diff --git a/po/redwood/de.po b/po/redwood/de.po new file mode 100644 index 0000000..8301d76 --- /dev/null +++ b/po/redwood/de.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download beendet" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download fehlgeschlagen" + diff --git a/po/el_GR.po b/po/redwood/el_GR.po index 29efbc7..f96c0a1 100755..100644 --- a/po/el_GR.po +++ b/po/redwood/el_GR.po @@ -1,3 +1,6 @@ msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" msgstr "Η λήψη ολοκληρώθηκε" +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Αποτυχία λήψης" + diff --git a/po/redwood/en.po b/po/redwood/en.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/redwood/en.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/redwood/en_US.po b/po/redwood/en_US.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/redwood/en_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/redwood/es_ES.po b/po/redwood/es_ES.po new file mode 100644 index 0000000..300e275 --- /dev/null +++ b/po/redwood/es_ES.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error de descarga" + diff --git a/po/redwood/es_US.po b/po/redwood/es_US.po new file mode 100644 index 0000000..6be685a --- /dev/null +++ b/po/redwood/es_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error al descargar" + diff --git a/po/et.po b/po/redwood/et.po index 4ad6fad..6ffe386 100755..100644 --- a/po/et.po +++ b/po/redwood/et.po @@ -1,3 +1,6 @@ msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" msgstr "Allalaadimine on lõpule viidud" +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Allalaadimine nurjus" + diff --git a/po/redwood/eu.po b/po/redwood/eu.po new file mode 100644 index 0000000..b9db71f --- /dev/null +++ b/po/redwood/eu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Deskarga osatuta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Deskargak huts egin du" + diff --git a/po/redwood/fi.po b/po/redwood/fi.po new file mode 100644 index 0000000..7929571 --- /dev/null +++ b/po/redwood/fi.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lataus valmis" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lataus epäonnistui" + diff --git a/po/redwood/fr.po b/po/redwood/fr.po new file mode 100644 index 0000000..f1e8884 --- /dev/null +++ b/po/redwood/fr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Echec du téléchargement" + diff --git a/po/redwood/fr_CA.po b/po/redwood/fr_CA.po new file mode 100644 index 0000000..608ae3d --- /dev/null +++ b/po/redwood/fr_CA.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Échec du téléchargement" + diff --git a/po/redwood/gl.po b/po/redwood/gl.po new file mode 100644 index 0000000..8527d75 --- /dev/null +++ b/po/redwood/gl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Erro na descarga" + diff --git a/po/redwood/hr.po b/po/redwood/hr.po new file mode 100644 index 0000000..0f225a4 --- /dev/null +++ b/po/redwood/hr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Skidanje dovršeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Skidanje neuspješno" + diff --git a/po/redwood/hu.po b/po/redwood/hu.po new file mode 100644 index 0000000..847e5af --- /dev/null +++ b/po/redwood/hu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "A letöltés befejeződött" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sikertelen letöltés" + diff --git a/po/redwood/hy.po b/po/redwood/hy.po new file mode 100644 index 0000000..8636b2b --- /dev/null +++ b/po/redwood/hy.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Ներբեռնումն ավարտվեց" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Ներբեռնումը ձախողվեց" + diff --git a/po/redwood/is.po b/po/redwood/is.po new file mode 100644 index 0000000..3bb7f29 --- /dev/null +++ b/po/redwood/is.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Niðurhali lokið" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Niðurhal mistókst" + diff --git a/po/redwood/it_IT.po b/po/redwood/it_IT.po new file mode 100644 index 0000000..51a407e --- /dev/null +++ b/po/redwood/it_IT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download completato" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download non riuscito" + diff --git a/po/ka.po b/po/redwood/ka.po index 10a084d..83aea79 100755..100644 --- a/po/ka.po +++ b/po/redwood/ka.po @@ -1,3 +1,6 @@ msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" msgstr "ჩამოტვირთვა დასრულდა" +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "ვერ ჩამოიტვირთა" + diff --git a/po/redwood/kk.po b/po/redwood/kk.po new file mode 100644 index 0000000..bd25ab4 --- /dev/null +++ b/po/redwood/kk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Жүктеу аяқталды" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Жүктеу орындалмады" + diff --git a/po/redwood/ko_KR.po b/po/redwood/ko_KR.po new file mode 100644 index 0000000..80d1e37 --- /dev/null +++ b/po/redwood/ko_KR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "다운로드 완료" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "다운로드 안 됨" + diff --git a/po/redwood/lt.po b/po/redwood/lt.po new file mode 100644 index 0000000..d08e1d5 --- /dev/null +++ b/po/redwood/lt.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Atsisiuntimas baigtas" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Atsisiųsti nepavyko" + diff --git a/po/redwood/lv.po b/po/redwood/lv.po new file mode 100644 index 0000000..323c609 --- /dev/null +++ b/po/redwood/lv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lejupielāde pabeigta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lejupielāde neizdevās" + diff --git a/po/redwood/mn_MN.po b/po/redwood/mn_MN.po new file mode 100644 index 0000000..7060f68 --- /dev/null +++ b/po/redwood/mn_MN.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Татан авалт дууссан" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Татаж авч чадсангүй" + diff --git a/po/redwood/nb.po b/po/redwood/nb.po new file mode 100644 index 0000000..49448f5 --- /dev/null +++ b/po/redwood/nb.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Nedlasting fullført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Nedlastingen mislyktes" + diff --git a/po/redwood/nl.po b/po/redwood/nl.po new file mode 100644 index 0000000..1195f04 --- /dev/null +++ b/po/redwood/nl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Downloaden voltooid" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Downloaden mislukt" + diff --git a/po/redwood/pl.po b/po/redwood/pl.po new file mode 100644 index 0000000..9e52a17 --- /dev/null +++ b/po/redwood/pl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Pobieranie zakończone" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Pobieranie nie powiodło się" + diff --git a/po/redwood/pt_BR.po b/po/redwood/pt_BR.po new file mode 100644 index 0000000..0fdce74 --- /dev/null +++ b/po/redwood/pt_BR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download concluído" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Falha no download" + diff --git a/po/redwood/pt_PT.po b/po/redwood/pt_PT.po new file mode 100644 index 0000000..c934937 --- /dev/null +++ b/po/redwood/pt_PT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Transferência concluída" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "A transferência falhou" + diff --git a/po/redwood/ro.po b/po/redwood/ro.po new file mode 100644 index 0000000..820ab33 --- /dev/null +++ b/po/redwood/ro.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descărcare finalizată" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descărcarea nu a reuşit" + diff --git a/po/ru_RU.po b/po/redwood/ru_RU.po index 27aa56c..e3cb63a 100755..100644 --- a/po/ru_RU.po +++ b/po/redwood/ru_RU.po @@ -1,3 +1,6 @@ msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" msgstr "Загрузка завершена" +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Сбой загрузки" + diff --git a/po/redwood/sk.po b/po/redwood/sk.po new file mode 100644 index 0000000..6d92c75 --- /dev/null +++ b/po/redwood/sk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Sťahovanie je dokončené" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sťahovanie zlyhalo" + diff --git a/po/redwood/sl.po b/po/redwood/sl.po new file mode 100644 index 0000000..1c256ab --- /dev/null +++ b/po/redwood/sl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Prenos je končan" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Prenos ni uspel" + diff --git a/po/redwood/sr.po b/po/redwood/sr.po new file mode 100644 index 0000000..2e6331a --- /dev/null +++ b/po/redwood/sr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Preuzimanje završeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Neuspešno preuzimanje" + diff --git a/po/redwood/sv.po b/po/redwood/sv.po new file mode 100644 index 0000000..e792e63 --- /dev/null +++ b/po/redwood/sv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Hämtningen är klar" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Hämtningen misslyckades" + diff --git a/po/redwood/tr_TR.po b/po/redwood/tr_TR.po new file mode 100644 index 0000000..73277df --- /dev/null +++ b/po/redwood/tr_TR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "İndirme tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "İndirme başarısız" + diff --git a/po/uk.po b/po/redwood/uk.po index 504e5f1..ad32cd3 100755..100644 --- a/po/uk.po +++ b/po/redwood/uk.po @@ -1,3 +1,6 @@ msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" msgstr "Завантаження завершено" +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Збій завантаження" + diff --git a/po/redwood/uz.po b/po/redwood/uz.po new file mode 100644 index 0000000..ff9b724 --- /dev/null +++ b/po/redwood/uz.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yuklab olish yakunlandi" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yuklab olib bo‘lmadi" + diff --git a/po/ro.po b/po/ro.po deleted file mode 100755 index d82366c..0000000 --- a/po/ro.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Descărcare finalizată" - diff --git a/po/sk.po b/po/sk.po deleted file mode 100755 index 178001d..0000000 --- a/po/sk.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Sťahovanie je dokončené" - diff --git a/po/sl.po b/po/sl.po deleted file mode 100755 index d031ce5..0000000 --- a/po/sl.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Prenos je končan" - diff --git a/po/sr.po b/po/sr.po deleted file mode 100755 index e21e6d3..0000000 --- a/po/sr.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Preuzimanje završeno" - diff --git a/po/sv.po b/po/sv.po deleted file mode 100755 index 8f0dce9..0000000 --- a/po/sv.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Hämtningen är klar" - diff --git a/po/tizen2.3/CMakeLists.txt b/po/tizen2.3/CMakeLists.txt new file mode 100644 index 0000000..1ff1ce8 --- /dev/null +++ b/po/tizen2.3/CMakeLists.txt @@ -0,0 +1,30 @@ +# for i18n + +SET(POFILES + ar.po az.po bg.po ca.po cs.po da.po de.po el_GR.po en.po + en_PH.po en_US.po es_ES.po es_US.po et.po eu.po fi.po fr.po + fr_CA.po ga.po gl.po hi.po hr.po hu.po hy.po is.po it_IT.po + ja_JP.po ka.po kk.po ko_KR.po lt.po lv.po mk.po nb.po nl.po + pl.po pt_BR.po pt_PT.po ro.po ru_RU.po sk.po sl.po sr.po sv.po + tr_TR.po uk.po uz.po zh_CN.po zh_HK.po zh_TW.po) + +SET(MSGFMT "/usr/bin/msgfmt") + +FOREACH(pofile ${POFILES}) + SET(pofile ${CMAKE_CURRENT_SOURCE_DIR}/${pofile}) + MESSAGE("PO: ${pofile}") + GET_FILENAME_COMPONENT(absPofile ${pofile} ABSOLUTE) + GET_FILENAME_COMPONENT(lang ${absPofile} NAME_WE) + SET(moFile ${CMAKE_CURRENT_BINARY_DIR}/${lang}.mo) + ADD_CUSTOM_COMMAND( + OUTPUT ${moFile} + COMMAND ${MSGFMT} -o ${moFile} ${absPofile} + DEPENDS ${absPofile} + ) + INSTALL(FILES ${moFile} + DESTINATION ${LOCALE_DIR}/${lang}/LC_MESSAGES RENAME ${PKG_NAME}.mo) + SET(moFiles ${moFiles} ${moFile}) +ENDFOREACH(pofile) + +MESSAGE(".mo files: ${moFiles}") +ADD_CUSTOM_TARGET(po ALL DEPENDS ${moFiles}) diff --git a/po/tizen2.3/ar.po b/po/tizen2.3/ar.po new file mode 100644 index 0000000..1bf0a3c --- /dev/null +++ b/po/tizen2.3/ar.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "تم التنزيل" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "فشل التنزيل" + diff --git a/po/tizen2.3/az.po b/po/tizen2.3/az.po new file mode 100644 index 0000000..f8d4868 --- /dev/null +++ b/po/tizen2.3/az.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yükləmə tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yükləmə alınmadı" + diff --git a/po/tizen2.3/bg.po b/po/tizen2.3/bg.po new file mode 100644 index 0000000..4b2b9cb --- /dev/null +++ b/po/tizen2.3/bg.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Изтеглянето завършено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Изтеглянето неуспешно" + diff --git a/po/tizen2.3/ca.po b/po/tizen2.3/ca.po new file mode 100644 index 0000000..e4cb32e --- /dev/null +++ b/po/tizen2.3/ca.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descàrrega completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descàrrega fallida" + diff --git a/po/tizen2.3/cs.po b/po/tizen2.3/cs.po new file mode 100644 index 0000000..7c33b8b --- /dev/null +++ b/po/tizen2.3/cs.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Stahování dokončeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Stažení se nezdařilo" + diff --git a/po/tizen2.3/da.po b/po/tizen2.3/da.po new file mode 100644 index 0000000..1cbbbec --- /dev/null +++ b/po/tizen2.3/da.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Overførsel fuldført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Overførsel mislykkedes" + diff --git a/po/tizen2.3/de.po b/po/tizen2.3/de.po new file mode 100644 index 0000000..8301d76 --- /dev/null +++ b/po/tizen2.3/de.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download beendet" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download fehlgeschlagen" + diff --git a/po/tizen2.3/el_GR.po b/po/tizen2.3/el_GR.po new file mode 100644 index 0000000..f96c0a1 --- /dev/null +++ b/po/tizen2.3/el_GR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Η λήψη ολοκληρώθηκε" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Αποτυχία λήψης" + diff --git a/po/tizen2.3/en.po b/po/tizen2.3/en.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/tizen2.3/en.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/tizen2.3/en_PH.po b/po/tizen2.3/en_PH.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/tizen2.3/en_PH.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/tizen2.3/en_US.po b/po/tizen2.3/en_US.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/tizen2.3/en_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/tizen2.3/es_ES.po b/po/tizen2.3/es_ES.po new file mode 100644 index 0000000..300e275 --- /dev/null +++ b/po/tizen2.3/es_ES.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error de descarga" + diff --git a/po/tizen2.3/es_US.po b/po/tizen2.3/es_US.po new file mode 100644 index 0000000..6be685a --- /dev/null +++ b/po/tizen2.3/es_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error al descargar" + diff --git a/po/tizen2.3/et.po b/po/tizen2.3/et.po new file mode 100644 index 0000000..6ffe386 --- /dev/null +++ b/po/tizen2.3/et.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Allalaadimine on lõpule viidud" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Allalaadimine nurjus" + diff --git a/po/tizen2.3/eu.po b/po/tizen2.3/eu.po new file mode 100644 index 0000000..b9db71f --- /dev/null +++ b/po/tizen2.3/eu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Deskarga osatuta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Deskargak huts egin du" + diff --git a/po/tizen2.3/fi.po b/po/tizen2.3/fi.po new file mode 100644 index 0000000..7929571 --- /dev/null +++ b/po/tizen2.3/fi.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lataus valmis" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lataus epäonnistui" + diff --git a/po/tizen2.3/fr.po b/po/tizen2.3/fr.po new file mode 100644 index 0000000..f1e8884 --- /dev/null +++ b/po/tizen2.3/fr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Echec du téléchargement" + diff --git a/po/tizen2.3/fr_CA.po b/po/tizen2.3/fr_CA.po new file mode 100644 index 0000000..608ae3d --- /dev/null +++ b/po/tizen2.3/fr_CA.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Échec du téléchargement" + diff --git a/po/tizen2.3/ga.po b/po/tizen2.3/ga.po new file mode 100644 index 0000000..f8651ef --- /dev/null +++ b/po/tizen2.3/ga.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Íoslódáilte" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Theip ar íoslódáil" + diff --git a/po/tizen2.3/gl.po b/po/tizen2.3/gl.po new file mode 100644 index 0000000..8527d75 --- /dev/null +++ b/po/tizen2.3/gl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Erro na descarga" + diff --git a/po/tizen2.3/hi.po b/po/tizen2.3/hi.po new file mode 100644 index 0000000..36382aa --- /dev/null +++ b/po/tizen2.3/hi.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "डाउनलोड पूर्ण" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "डाउनलोड विफल" + diff --git a/po/tizen2.3/hr.po b/po/tizen2.3/hr.po new file mode 100644 index 0000000..0f225a4 --- /dev/null +++ b/po/tizen2.3/hr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Skidanje dovršeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Skidanje neuspješno" + diff --git a/po/tizen2.3/hu.po b/po/tizen2.3/hu.po new file mode 100644 index 0000000..847e5af --- /dev/null +++ b/po/tizen2.3/hu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "A letöltés befejeződött" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sikertelen letöltés" + diff --git a/po/tizen2.3/hy.po b/po/tizen2.3/hy.po new file mode 100644 index 0000000..8636b2b --- /dev/null +++ b/po/tizen2.3/hy.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Ներբեռնումն ավարտվեց" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Ներբեռնումը ձախողվեց" + diff --git a/po/tizen2.3/is.po b/po/tizen2.3/is.po new file mode 100644 index 0000000..3bb7f29 --- /dev/null +++ b/po/tizen2.3/is.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Niðurhali lokið" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Niðurhal mistókst" + diff --git a/po/tizen2.3/it_IT.po b/po/tizen2.3/it_IT.po new file mode 100644 index 0000000..51a407e --- /dev/null +++ b/po/tizen2.3/it_IT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download completato" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download non riuscito" + diff --git a/po/tizen2.3/ja_JP.po b/po/tizen2.3/ja_JP.po new file mode 100644 index 0000000..b466c9b --- /dev/null +++ b/po/tizen2.3/ja_JP.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "ダウンロード完了" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "ダウンロード失敗" + diff --git a/po/tizen2.3/ka.po b/po/tizen2.3/ka.po new file mode 100644 index 0000000..83aea79 --- /dev/null +++ b/po/tizen2.3/ka.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "ჩამოტვირთვა დასრულდა" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "ვერ ჩამოიტვირთა" + diff --git a/po/tizen2.3/kk.po b/po/tizen2.3/kk.po new file mode 100644 index 0000000..bd25ab4 --- /dev/null +++ b/po/tizen2.3/kk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Жүктеу аяқталды" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Жүктеу орындалмады" + diff --git a/po/tizen2.3/ko_KR.po b/po/tizen2.3/ko_KR.po new file mode 100644 index 0000000..80d1e37 --- /dev/null +++ b/po/tizen2.3/ko_KR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "다운로드 완료" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "다운로드 안 됨" + diff --git a/po/tizen2.3/lt.po b/po/tizen2.3/lt.po new file mode 100644 index 0000000..d08e1d5 --- /dev/null +++ b/po/tizen2.3/lt.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Atsisiuntimas baigtas" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Atsisiųsti nepavyko" + diff --git a/po/tizen2.3/lv.po b/po/tizen2.3/lv.po new file mode 100644 index 0000000..323c609 --- /dev/null +++ b/po/tizen2.3/lv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lejupielāde pabeigta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lejupielāde neizdevās" + diff --git a/po/tizen2.3/mk.po b/po/tizen2.3/mk.po new file mode 100644 index 0000000..0ef6f04 --- /dev/null +++ b/po/tizen2.3/mk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Преземањето заврши" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Преземањето не успеа" + diff --git a/po/tizen2.3/nb.po b/po/tizen2.3/nb.po new file mode 100644 index 0000000..49448f5 --- /dev/null +++ b/po/tizen2.3/nb.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Nedlasting fullført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Nedlastingen mislyktes" + diff --git a/po/tizen2.3/nl.po b/po/tizen2.3/nl.po new file mode 100644 index 0000000..1195f04 --- /dev/null +++ b/po/tizen2.3/nl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Downloaden voltooid" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Downloaden mislukt" + diff --git a/po/tizen2.3/pl.po b/po/tizen2.3/pl.po new file mode 100644 index 0000000..9e52a17 --- /dev/null +++ b/po/tizen2.3/pl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Pobieranie zakończone" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Pobieranie nie powiodło się" + diff --git a/po/tizen2.3/pt_BR.po b/po/tizen2.3/pt_BR.po new file mode 100644 index 0000000..0fdce74 --- /dev/null +++ b/po/tizen2.3/pt_BR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download concluído" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Falha no download" + diff --git a/po/tizen2.3/pt_PT.po b/po/tizen2.3/pt_PT.po new file mode 100644 index 0000000..c934937 --- /dev/null +++ b/po/tizen2.3/pt_PT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Transferência concluída" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "A transferência falhou" + diff --git a/po/tizen2.3/ro.po b/po/tizen2.3/ro.po new file mode 100644 index 0000000..820ab33 --- /dev/null +++ b/po/tizen2.3/ro.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descărcare finalizată" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descărcarea nu a reuşit" + diff --git a/po/tizen2.3/ru_RU.po b/po/tizen2.3/ru_RU.po new file mode 100644 index 0000000..e3cb63a --- /dev/null +++ b/po/tizen2.3/ru_RU.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Загрузка завершена" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Сбой загрузки" + diff --git a/po/tizen2.3/sk.po b/po/tizen2.3/sk.po new file mode 100644 index 0000000..6d92c75 --- /dev/null +++ b/po/tizen2.3/sk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Sťahovanie je dokončené" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sťahovanie zlyhalo" + diff --git a/po/tizen2.3/sl.po b/po/tizen2.3/sl.po new file mode 100644 index 0000000..1c256ab --- /dev/null +++ b/po/tizen2.3/sl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Prenos je končan" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Prenos ni uspel" + diff --git a/po/tizen2.3/sr.po b/po/tizen2.3/sr.po new file mode 100644 index 0000000..2e6331a --- /dev/null +++ b/po/tizen2.3/sr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Preuzimanje završeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Neuspešno preuzimanje" + diff --git a/po/tizen2.3/sv.po b/po/tizen2.3/sv.po new file mode 100644 index 0000000..e792e63 --- /dev/null +++ b/po/tizen2.3/sv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Hämtningen är klar" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Hämtningen misslyckades" + diff --git a/po/tizen2.3/tr_TR.po b/po/tizen2.3/tr_TR.po new file mode 100644 index 0000000..73277df --- /dev/null +++ b/po/tizen2.3/tr_TR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "İndirme tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "İndirme başarısız" + diff --git a/po/tizen2.3/uk.po b/po/tizen2.3/uk.po new file mode 100644 index 0000000..ad32cd3 --- /dev/null +++ b/po/tizen2.3/uk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Завантаження завершено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Збій завантаження" + diff --git a/po/tizen2.3/uz.po b/po/tizen2.3/uz.po new file mode 100644 index 0000000..ff9b724 --- /dev/null +++ b/po/tizen2.3/uz.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yuklab olish yakunlandi" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yuklab olib bo‘lmadi" + diff --git a/po/tizen2.3/zh_CN.po b/po/tizen2.3/zh_CN.po new file mode 100644 index 0000000..f5e03c8 --- /dev/null +++ b/po/tizen2.3/zh_CN.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "下载完成" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "下载失败" + diff --git a/po/tizen2.3/zh_HK.po b/po/tizen2.3/zh_HK.po new file mode 100644 index 0000000..ef7afd3 --- /dev/null +++ b/po/tizen2.3/zh_HK.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "下載完成" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "下載失敗" + diff --git a/po/tizen2.3/zh_TW.po b/po/tizen2.3/zh_TW.po new file mode 100644 index 0000000..ef7afd3 --- /dev/null +++ b/po/tizen2.3/zh_TW.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "下載完成" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "下載失敗" + diff --git a/po/tr_TR.po b/po/tr_TR.po deleted file mode 100755 index ec760e5..0000000 --- a/po/tr_TR.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "İndirme tamamlandı" - diff --git a/po/uz.po b/po/uz.po deleted file mode 100755 index c97fec7..0000000 --- a/po/uz.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "Yuklab olish yakunlandi" - diff --git a/po/zh_CN.po b/po/zh_CN.po deleted file mode 100755 index 3238acd..0000000 --- a/po/zh_CN.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "下载完成" - diff --git a/po/zh_HK.po b/po/zh_HK.po deleted file mode 100755 index 51101ba..0000000 --- a/po/zh_HK.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "下載完成" - diff --git a/po/zh_SG.po b/po/zh_SG.po deleted file mode 100755 index 3238acd..0000000 --- a/po/zh_SG.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "下载完成" - diff --git a/po/zh_TW.po b/po/zh_TW.po deleted file mode 100755 index 51101ba..0000000 --- a/po/zh_TW.po +++ /dev/null @@ -1,3 +0,0 @@ -msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" -msgstr "下載完成" - diff --git a/provider-interface/CMakeLists.txt b/provider-interface/CMakeLists.txt index eb523c4..70792e7 100755 --- a/provider-interface/CMakeLists.txt +++ b/provider-interface/CMakeLists.txt @@ -8,7 +8,7 @@ IF("${CMAKE_BUILD_TYPE}" STREQUAL "") ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") -SET(PC_REQUIRED "glib-2.0 gobject-2.0 dlog capi-base-common capi-appfw-app-manager bundle") +SET(PC_REQUIRED "glib-2.0 gobject-2.0 dlog capi-base-common capi-appfw-app-manager capi-appfw-application bundle") INCLUDE(FindPkgConfig) @@ -32,7 +32,12 @@ SET(PROVIDER_INTERFACE_LINK_LIBRARIES SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -Wall") +ADD_DEFINITIONS(-DDOWNLOAD_PROVIDER_LOG_TAG=\"DOWNLOAD_PROVIDER_INTERFACE\") + ADD_LIBRARY(${PROJECT_NAME} SHARED + ${CMAKE_SOURCE_DIR}/provider/download-provider-utils.c + ${CMAKE_SOURCE_DIR}/provider/download-provider-ipc.c + ${CMAKE_SOURCE_DIR}/provider/download-provider-pthread.c ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.c ) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${provider_interface_pkgs_LDFLAGS} ${PROVIDER_INTERFACE_LINK_LIBRARIES}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${PKG_VERSION}) diff --git a/provider-interface/download-provider-interface.c b/provider-interface/download-provider-interface.c index ac93263..8b0790e 100755 --- a/provider-interface/download-provider-interface.c +++ b/provider-interface/download-provider-interface.c @@ -30,27 +30,24 @@ #include <dlog.h> #include <download-provider-interface.h> #include <download-provider.h> +#include <download-provider-log.h> +#include <download-provider-pthread.h> +#include <download-provider-ipc.h> +#include <download-provider-utils.h> + +#include <bundle.h> // for notification bundle +#include <app_control.h> +#include <app_control_internal.h> #ifdef SUPPORT_CHECK_IPC #include <sys/ioctl.h> #endif #define DP_CHECK_CONNECTION do {\ - if (__check_connections() != DP_ERROR_NONE) {\ - pthread_mutex_unlock(&g_function_mutex);\ - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR;\ - }\ -} while(0) - -#define DP_CHECK_PROVIDER_STATUS do {\ - dp_error_type errorcode = DP_ERROR_NONE;\ - errorcode = __ipc_check_ready_status(g_interface_info->cmd_socket);\ - if (errorcode != DP_ERROR_NONE) {\ - pthread_mutex_unlock(&g_interface_info->mutex);\ - if (errorcode == DP_ERROR_IO_ERROR)\ - __disconnect_from_provider();\ - pthread_mutex_unlock(&g_function_mutex);\ - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR;\ + int dp_errorcode = __check_connections();\ + if (dp_errorcode != DP_ERROR_NONE) {\ + CLIENT_MUTEX_UNLOCK(&g_function_mutex);\ + return __dp_interface_convert_errorcode(dp_errorcode);\ }\ } while(0) @@ -61,111 +58,30 @@ }\ } while(0) -#define MAX_DOWNLOAD_HANDLE 32 - -#ifdef SUPPORT_LOG_MESSAGE -#include <dlog.h> -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "DOWNLOAD_PROVIDER_INTERFACE" -#define TRACE_DEBUG(format, ARG...) LOGD(format, ##ARG) -#define TRACE_ERROR(format, ARG...) LOGE(format, ##ARG) -#define TRACE_STRERROR(format, ARG...) LOGE(format" [%s]", ##ARG, strerror(errno)) -#define TRACE_INFO(format, ARG...) LOGI(format, ##ARG) - -#ifdef SECURE_LOGD -#define TRACE_SECURE_DEBUG(format, ARG...) SECURE_LOGD(format, ##ARG) -#else -#define TRACE_SECURE_DEBUG(...) do { } while(0) -#endif -#ifdef SECURE_LOGI -#define TRACE_SECURE_INFO(format, ARG...) SECURE_LOGI(format, ##ARG) -#else -#define TRACE_SECURE_INFO(...) do { } while(0) -#endif -#ifdef SECURE_LOGE -#define TRACE_SECURE_ERROR(format, ARG...) SECURE_LOGE(format, ##ARG) -#else -#define TRACE_SECURE_ERROR(...) do { } while(0) -#endif - -#else -#define TRACE_DEBUG(...) do { } while(0) -#define TRACE_ERROR(...) do { } while(0) -#define TRACE_STRERROR(...) do { } while(0) -#define TRACE_INFO(...) do { } while(0) -#define TRACE_SECURE_DEBUG(...) do { } while(0) -#define TRACE_SECURE_INFO(...) do { } while(0) -#define TRACE_SECURE_ERROR(...) do { } while(0) -#endif - // define type typedef struct { - // send command * get return value. - int cmd_socket; - // getting event from download-provider - int event_socket; - pthread_mutex_t mutex; // lock before using, unlock after using -} dp_interface_info; + int channel; // query & response + int notify; // event from provider +} dp_interface_ipc; typedef struct { + int id; dp_interface_state_changed_cb state; void *state_data; dp_interface_progress_cb progress; void *progress_data; -} dp_interface_callback; - -typedef struct { - int id; - dp_interface_callback callback; } dp_interface_slot; // declare the variables -dp_interface_info *g_interface_info = NULL; +dp_interface_ipc *g_dp_client = NULL; dp_interface_slot g_interface_slots[MAX_DOWNLOAD_HANDLE]; static pthread_mutex_t g_function_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_clear_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t g_interface_event_thread_id = 0; +static pthread_t g_dp_event_thread_id = 0; //////////// defines functions ///////////////// - -static int __dp_interface_convert_network_adaptor(int type) -{ - switch (type) { - case DOWNLOAD_ADAPTOR_NETWORK_WIFI: - return DP_NETWORK_TYPE_WIFI; - case DOWNLOAD_ADAPTOR_NETWORK_DATA_NETWORK: - return DP_NETWORK_TYPE_DATA_NETWORK; - case DOWNLOAD_ADAPTOR_NETWORK_WIFI_DIRECT: - return DP_NETWORK_TYPE_WIFI_DIRECT; - case DOWNLOAD_ADAPTOR_NETWORK_ALL: - return DP_NETWORK_TYPE_ALL; - default: - break; - } - return type; -} - -static int __dp_interface_convert_network_provider(int type) -{ - switch (type) { - case DP_NETWORK_TYPE_WIFI: - return DOWNLOAD_ADAPTOR_NETWORK_WIFI; - case DP_NETWORK_TYPE_DATA_NETWORK: - return DOWNLOAD_ADAPTOR_NETWORK_DATA_NETWORK; - case DP_NETWORK_TYPE_WIFI_DIRECT: - return DOWNLOAD_ADAPTOR_NETWORK_WIFI_DIRECT; - case DOWNLOAD_ADAPTOR_NETWORK_ALL: - return DP_NETWORK_TYPE_ALL; - default: - break; - } - return type; -} - static int __dp_interface_convert_state(int state) { switch (state) { @@ -181,9 +97,6 @@ static int __dp_interface_convert_state(int state) case DP_STATE_DOWNLOADING: TRACE_DEBUG("DOWNLOADING"); return DOWNLOAD_ADPATOR_STATE_DOWNLOADING; - case DP_STATE_PAUSE_REQUESTED: - TRACE_DEBUG("PAUSE_REQUESTED/DOWNLOADING"); - return DOWNLOAD_ADPATOR_STATE_DOWNLOADING; case DP_STATE_PAUSED: TRACE_DEBUG("PAUSED"); return DOWNLOAD_ADPATOR_STATE_PAUSED; @@ -235,6 +148,7 @@ static int __dp_interface_convert_errorcode(int errorcode) TRACE_DEBUG("ERROR_INVALID_STATE"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE; case DP_ERROR_CONNECTION_FAILED: + case DP_ERROR_NETWORK_ERROR: TRACE_DEBUG("ERROR_CONNECTION_TIMED_OUT/CONNECTION_FAILED"); return DOWNLOAD_ADAPTOR_ERROR_CONNECTION_TIMED_OUT; case DP_ERROR_INVALID_URL: @@ -273,6 +187,9 @@ static int __dp_interface_convert_errorcode(int errorcode) case DP_ERROR_UNKNOWN: TRACE_DEBUG("ERROR_INVALID_STATE/UNKNOWN"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE; + case DP_ERROR_INVALID_NETWORK_TYPE: + TRACE_DEBUG("ERROR_INVALID_NETWORK_TYPE"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_NETWORK_TYPE; default: break; } @@ -298,335 +215,9 @@ static int __get_empty_slot_index() return -1; } -static dp_error_type __get_standard_errorcode(dp_error_type basecode) -{ - dp_error_type errorcode = basecode; - if (errno == EPIPE) { - TRACE_ERROR("[EPIPE] Broken Pipe [%d]", errno); - errorcode = DP_ERROR_IO_ERROR; - } else if (errno == EAGAIN) { - TRACE_ERROR - ("[EAGAIN] Resource temporarily unavailable [%d]", - errno); - errorcode = DP_ERROR_IO_EAGAIN; - } else if (errno == EINTR) { - TRACE_ERROR("[EINTR] Interrupted System Call [%d]", errno); - errorcode = DP_ERROR_IO_ERROR; - } - return errorcode; -} - -static int __ipc_read_custom_type(int fd, void *value, size_t type_size) -{ - if (fd < 0) { - TRACE_ERROR("[CHECK SOCKET]"); - return -1; - } - if (value == NULL) { - TRACE_ERROR("[CHECK value]"); - return -1; - } - if (type_size <= 0) { - TRACE_ERROR("[CHECK size]"); - return -1; - } - - ssize_t recv_bytes = read(fd, value, type_size); - if (recv_bytes < 0) { - TRACE_STRERROR("[CRITICAL] read"); - return -1; - } - return 0; -} - -static int __ipc_read_int(int fd) -{ - int value = -1; - - if (fd < 0) { - TRACE_ERROR("[CHECK SOCKET]"); - return -1; - } - ssize_t recv_bytes = read(fd, &value, sizeof(int)); - if (recv_bytes < 0) { - TRACE_STRERROR("[CRITICAL] read"); - return -1; - } - return value; -} - -static int __ipc_read_download_id(int fd) -{ - int value = -1; - int read_len = 0; - int try_count = 5; - - if (fd < 0) { - TRACE_ERROR("[CHECK SOCKET]"); - return -1; - } - do { - read_len = read(fd, &value, sizeof(int)); - if (read_len < 0) { - TRACE_STRERROR("[CRITICAL] read"); - return -1; - } - try_count--; - } while (read_len == 0 && value == 0 && try_count > 0); - return value; -} - -// keep the order/ unsigned , str -static char *__ipc_read_string(int fd) -{ - unsigned length = 0; - size_t recv_size = 0; - unsigned remain_size = 0; - size_t buffer_size = 0; - char *str = NULL; - - if (fd < 0) { - TRACE_ERROR("[ERROR] CHECK FD[%d]", fd); - return NULL; - } - - // read flexible URL from client. - ssize_t recv_bytes = read(fd, &length, sizeof(unsigned)); - if (recv_bytes < 0) { - TRACE_STRERROR("[ERROR] read FD[%d] length[%d]", fd, length); - return NULL; - } - if (length < 1 || length > DP_MAX_URL_LEN) { - TRACE_ERROR("[STRING LEGNTH] [%d]", length); - return NULL; - } - str = (char *)calloc((length + 1), sizeof(char)); - if (str == NULL) { - TRACE_STRERROR("[ERROR] calloc length:%d FD[%d]", length, fd); - return NULL; - } - remain_size = length; - do { - buffer_size = 0; - if (remain_size > DP_DEFAULT_BUFFER_SIZE) - buffer_size = DP_DEFAULT_BUFFER_SIZE; - else - buffer_size = remain_size; - recv_size = (size_t)read(fd, str + (int)(length - remain_size), - buffer_size * sizeof(char)); - if (recv_size > DP_DEFAULT_BUFFER_SIZE) { - recv_size = -1; - break; - } - if (recv_size > 0) - remain_size = remain_size - (unsigned)recv_size; - } while (recv_size > 0 && remain_size > 0); - - if (recv_size == 0) { - TRACE_STRERROR("[ERROR] closed peer:%d", fd); - free(str); - return NULL; - } - str[length] = '\0'; - return str; -} - -int __ipc_read_bundle(int fd, bundle_raw **b) -{ - unsigned length = 0; - size_t recv_size = 0; - unsigned remain_size = 0; - size_t buffer_size = 0; - bundle_raw *b_raw = NULL; - - if (fd < 0) { - TRACE_ERROR("[ERROR] CHECK FD[%d]", fd); - return 0; - } - - // read bundle data from client. - ssize_t recv_bytes = read(fd, &length, sizeof(unsigned)); - if (recv_bytes < 0) { - TRACE_STRERROR("[ERROR] read FD[%d] length[%d]", fd, length); - return 0; - } - if (length < 1 || length > DP_MAX_URL_LEN) { - TRACE_ERROR("[STRING LEGNTH] [%d]", length); - return 0; - } - b_raw = (bundle_raw *)calloc(length, 1); - if (b_raw == NULL) { - TRACE_STRERROR("[ERROR] calloc length:%d FD[%d]", length, fd); - return 0; - } - remain_size = length; - do { - buffer_size = 0; - if (remain_size > DP_DEFAULT_BUFFER_SIZE) - buffer_size = DP_DEFAULT_BUFFER_SIZE; - else - buffer_size = remain_size; - recv_size = (size_t)read(fd, b_raw + (int)(length - remain_size), - buffer_size); - if (recv_size > DP_DEFAULT_BUFFER_SIZE) { - recv_size = -1; - break; - } - if (recv_size > 0) - remain_size = remain_size - (unsigned)recv_size; - } while (recv_size > 0 && remain_size > 0); - - if (recv_size == 0) { - TRACE_STRERROR("[ERROR] closed peer:%d", fd); - bundle_free_encoded_rawdata(&b_raw); - return 0; - } - *b = b_raw; - return (int)length; -} - -static dp_error_type __ipc_return(int fd) -{ - dp_error_type errorcode = DP_ERROR_NONE; - - if (fd < 0) { - TRACE_ERROR("[CHECK SOCKET]"); - return DP_ERROR_IO_ERROR; - } - ssize_t recv_bytes = read(fd, &errorcode, sizeof(dp_error_type)); - if (recv_bytes < 0) { - TRACE_STRERROR("[CRITICAL] read"); - return __get_standard_errorcode(DP_ERROR_IO_ERROR); - } - if (errorcode != DP_ERROR_NONE) - TRACE_ERROR("return : %d", errorcode); - return errorcode; -} - -static dp_event_info* __ipc_event(int fd) -{ - dp_event_info *event = NULL; - - if (fd < 0) { - TRACE_ERROR("[CHECK SOCKET]"); - return NULL; - } - - event = (dp_event_info *) calloc(1, sizeof(dp_event_info)); - if (event == NULL) { - TRACE_ERROR("[CHECK ALLOCATION]"); - return NULL; - } - ssize_t recv_bytes = read(fd, event, sizeof(dp_event_info)); - if (recv_bytes < 0) { - TRACE_STRERROR("[CRITICAL] read"); - free(event); - return NULL; - } - return event; -} - -static int __ipc_send_int(int fd, int value) -{ - if (fd < 0) { - TRACE_ERROR("[CHECK FD] [%d]", fd); - return -1; - } - - if (fd >= 0 && write(fd, &value, sizeof(int)) < 0) { - TRACE_STRERROR("[CRITICAL] send"); - return -1; - } - return 0; -} - -// keep the order/ unsigned , str -static dp_error_type __ipc_send_string(int fd, const char *str) -{ - unsigned length = 0; - - if (fd < 0) { - TRACE_ERROR("[CHECK FD]"); - return DP_ERROR_IO_ERROR; - } - if (str == NULL || (length = strlen(str)) <= 0) { - TRACE_ERROR("[CHECK STRING]"); - return DP_ERROR_INVALID_PARAMETER; - } - - if (fd >= 0 && write(fd, &length, sizeof(unsigned)) < 0) { - TRACE_STRERROR("[CRITICAL] send"); - return DP_ERROR_IO_ERROR; - } - if (fd >= 0 && write(fd, str, length * sizeof(char)) < 0) { - TRACE_STRERROR("[CRITICAL] send"); - return DP_ERROR_IO_ERROR; - } - return DP_ERROR_NONE; -} - -static dp_error_type __ipc_send_raw_bundle(int fd, int type, const bundle_raw *b, int len) -{ - if (fd < 0) { - TRACE_ERROR("[CHECK FD]"); - return DP_ERROR_IO_ERROR; - } - if (b == NULL || len <= 0) { - TRACE_ERROR("[CHECK STRING]"); - return DP_ERROR_INVALID_PARAMETER; - } - if (fd >= 0 && write(fd, &type, sizeof(unsigned)) < 0) { - TRACE_STRERROR("[CRITICAL] send"); - return DP_ERROR_IO_ERROR; - } - if (fd >= 0 && write(fd, &len, sizeof(unsigned)) < 0) { - TRACE_STRERROR("[CRITICAL] send"); - return DP_ERROR_IO_ERROR; - } - if (fd >= 0 && write(fd, b, len) < 0) { - TRACE_STRERROR("[CRITICAL] send"); - return DP_ERROR_IO_ERROR; - } - return DP_ERROR_NONE; -} - -static dp_error_type __ipc_send_command - (int fd, int id, dp_command_type cmd) -{ - if (fd < 0) { - TRACE_ERROR("[CHECK SOCKET]"); - return DP_ERROR_IO_ERROR; - } - - dp_command command; - command.id = id; - command.cmd = cmd; - if (fd >= 0 && write(fd, &command, sizeof(dp_command)) < 0) { - TRACE_STRERROR("[CRITICAL] send"); - return DP_ERROR_IO_ERROR; - } - return DP_ERROR_NONE; -} - -static dp_error_type __ipc_send_command_return - (int id, dp_command_type cmd) -{ - if (cmd <= DP_CMD_NONE) { - TRACE_ERROR("[CHECK COMMAND] (%d)", cmd); - return DP_ERROR_INVALID_PARAMETER; - } - // send commnad with ID - if (__ipc_send_command(g_interface_info->cmd_socket, id, cmd) != - DP_ERROR_NONE) - return DP_ERROR_IO_ERROR; - // return from provider. - return __ipc_return(g_interface_info->cmd_socket); -} - static int __create_socket() { int sockfd = -1; - struct timeval tv_timeo = { 2, 500000 }; //2.5 second struct sockaddr_un clientaddr; if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { @@ -634,21 +225,18 @@ static int __create_socket() return -1; } - if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, - sizeof( tv_timeo ) ) < 0) { - TRACE_STRERROR("[CRITICAL] setsockopt SO_RCVTIMEO"); - close(sockfd); - return -1; - } - bzero(&clientaddr, sizeof clientaddr); clientaddr.sun_family = AF_UNIX; memset(clientaddr.sun_path, 0x00, sizeof(clientaddr.sun_path)); - strncpy(clientaddr.sun_path, DP_IPC, strlen(DP_IPC)); - clientaddr.sun_path[strlen(DP_IPC)] = '\0'; + strncpy(clientaddr.sun_path, IPC_SOCKET, strlen(IPC_SOCKET)); + clientaddr.sun_path[strlen(IPC_SOCKET)] = '\0'; if (connect(sockfd, (struct sockaddr*)&clientaddr, sizeof(clientaddr)) < 0) { close(sockfd); + if (errno == EACCES || errno == EPERM) { + TRACE_STRERROR("check permission"); + return -DP_ERROR_PERMISSION_DENIED; + } return -1; } TRACE_DEBUG("sockfd [%d]", sockfd); @@ -658,88 +246,53 @@ static int __create_socket() static void __clear_interface() { TRACE_DEBUG(""); - pthread_mutex_lock(&g_clear_mutex); - if (g_interface_info != NULL) { - shutdown(g_interface_info->cmd_socket, 0); - close(g_interface_info->cmd_socket); - g_interface_info->cmd_socket= -1; - shutdown(g_interface_info->event_socket, 0); - close(g_interface_info->event_socket); - g_interface_info->event_socket = -1; - pthread_mutex_destroy(&g_interface_info->mutex); - free(g_interface_info); - g_interface_info = NULL; - } - pthread_mutex_unlock(&g_clear_mutex); -} - -static int __disconnect_from_provider() -{ - TRACE_DEBUG(""); - if (g_interface_event_thread_id > 0 && - pthread_kill(g_interface_event_thread_id, 0) != ESRCH) { - if (pthread_cancel(g_interface_event_thread_id) != 0) { - TRACE_STRERROR("pthread:%d", (int)g_interface_event_thread_id); + CLIENT_MUTEX_LOCK(&g_clear_mutex); + if (g_dp_client != NULL) { + if (g_dp_client->channel >= 0) + close(g_dp_client->channel); + g_dp_client->channel= -1; + if (g_dp_client->notify >= 0) + close(g_dp_client->notify); + g_dp_client->notify = -1; + free(g_dp_client); + g_dp_client = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_clear_mutex); +} + +static int __bp_disconnect(const char *funcname) +{ + TRACE_DEBUG("%s", funcname); + if (g_dp_event_thread_id > 0 && + pthread_kill(g_dp_event_thread_id, 0) != ESRCH) { + if (pthread_cancel(g_dp_event_thread_id) != 0) { + TRACE_STRERROR("pthread:%d", (int)g_dp_event_thread_id); } - g_interface_event_thread_id = 0; + g_dp_event_thread_id = 0; } __clear_interface(); return DP_ERROR_NONE; } -#ifdef SUPPORT_CHECK_IPC -// clear read buffer. call in head of API before calling IPC_SEND -static void __clear_read_buffer(int fd) -{ - long i; - long unread_count; - char tmp_char; - - // FIONREAD : Returns the number of bytes immediately readable - if (ioctl(fd, FIONREAD, &unread_count) >= 0) { - if (unread_count > 0) { - TRACE_DEBUG("[CLEAN] garbage packet[%ld]", unread_count); - for ( i = 0; i < unread_count; i++) { - if (read(fd, &tmp_char, sizeof(char)) < 0) { - TRACE_STRERROR("[CHECK] read"); - break; - } - } - } - } -} -#endif - -// ask to provider before sending a command. -// if provider wait in some commnad, can not response immediately -// capi will wait in read block. -// after asking, call clear_read_buffer. -static dp_error_type __ipc_check_ready_status(int fd) -{ - dp_error_type errorcode = DP_ERROR_NONE; - -#ifdef SUPPORT_CHECK_IPC - // echo from provider - errorcode = __ipc_send_command_return(-1, DP_CMD_ECHO); - if (errorcode == DP_ERROR_NONE) - __clear_read_buffer(fd); -#endif - return errorcode; -} - // listen ASYNC state event, no timeout -static void *__dp_interface_event_manager(void *arg) +static void *__dp_event_manager(void *arg) { - int maxfd, index; - fd_set rset, read_fdset; - dp_event_info *eventinfo = NULL; - - if (g_interface_info == NULL) { + if (g_dp_client == NULL) { TRACE_STRERROR("[CRITICAL] INTERFACE null"); return 0; } - if (g_interface_info->event_socket < 0) { - TRACE_STRERROR("[CRITICAL] IPC NOT ESTABILISH"); + + size_t path_size = sizeof(NOTIFY_DIR) + 11; + char notify_fifo[path_size]; + snprintf((char *)¬ify_fifo, path_size,"%s/%d", NOTIFY_DIR, getpid()); + TRACE_DEBUG("IPC ESTABILISH %s", notify_fifo); + g_dp_client->notify = open(notify_fifo, O_RDONLY, 0600); + if (g_dp_client->notify < 0) { + TRACE_STRERROR("[CRITICAL] failed to ESTABILISH IPC %s", notify_fifo); + g_dp_event_thread_id = 0; + CLIENT_MUTEX_LOCK(&g_function_mutex); + __clear_interface(); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return 0; } @@ -747,603 +300,421 @@ static void *__dp_interface_event_manager(void *arg) // ex) function : select, read in this thread pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); - maxfd = g_interface_info->event_socket; - FD_ZERO(&read_fdset); - FD_SET(g_interface_info->event_socket, &read_fdset); - - int sock = g_interface_info->event_socket; + while(g_dp_client != NULL && g_dp_client->notify >= 0) { - while(g_interface_info != NULL - && g_interface_info->event_socket >= 0) { - rset = read_fdset; - if (select((maxfd + 1), &rset, 0, 0, 0) < 0) { - TRACE_STRERROR("[CRITICAL] select"); + if (g_dp_event_thread_id <= 0 || + pthread_self() != g_dp_event_thread_id) { + TRACE_ERROR("competitive threads self:%0x global:%0x", + pthread_self(), g_dp_event_thread_id); + // another thread may work. just terminate break; } - if (g_interface_event_thread_id <=0 - || pthread_self() != g_interface_event_thread_id) { - TRACE_ERROR - ("[CRITICAL] [CHECK TID] SELF ID [%d] Global ID (%d)", - pthread_self(), g_interface_event_thread_id); - // another thread may work. just terminate - break; + // blocking fifo. + dp_ipc_event_fmt eventinfo; + memset(&eventinfo, 0x00, sizeof(dp_ipc_event_fmt)); + if (dp_ipc_read(g_dp_client->notify, &eventinfo, + sizeof(dp_ipc_event_fmt), __FUNCTION__) <= 0 || + (eventinfo.id <= 0 && + eventinfo.errorcode == DP_ERROR_CLIENT_DOWN)) { + TRACE_INFO("expelled by provider"); + g_dp_event_thread_id = 0; + CLIENT_MUTEX_LOCK(&g_function_mutex); + __clear_interface(); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return 0; } - if (FD_ISSET(sock, &rset) > 0) { - // read state info from socket - eventinfo = __ipc_event(sock); - if (eventinfo == NULL || eventinfo->id <= 0) { - // failed to read from socket // ignore this status - free(eventinfo); - TRACE_STRERROR("[CRITICAL] Can not read Event packet"); - g_interface_event_thread_id = 0; - __clear_interface(); - return 0; - } + int index = -1; + if ((index = __get_my_slot_index(eventinfo.id)) < 0) { + TRACE_ERROR("[CRITICAL] not found slot id:%d", eventinfo.id); + continue; + } - if ((index = __get_my_slot_index(eventinfo->id)) < 0) { - TRACE_ERROR("[CRITICAL] not found slot for [%d]", - eventinfo->id); - free(eventinfo); - continue; + // begin protect callback sections & thread safe + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + if (eventinfo.state == DP_STATE_DOWNLOADING && + eventinfo.received_size > 0) { + if (eventinfo.id == g_interface_slots[index].id && + g_interface_slots[index].progress != NULL) { + // progress event + g_interface_slots[index].progress(eventinfo.id, + eventinfo.received_size, + g_interface_slots[index].progress_data); } - - // begin protect callback sections & thread safe - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - dp_interface_callback *callback = - &g_interface_slots[index].callback; - - if (eventinfo->state == DP_STATE_DOWNLOADING - && eventinfo->received_size > 0) { - if (eventinfo->id == g_interface_slots[index].id && - callback->progress != NULL) { - // progress event - callback->progress(eventinfo->id, - eventinfo->received_size, - callback->progress_data); - } - } else { - if (eventinfo->id == g_interface_slots[index].id && - callback->state != NULL) { - // state event - callback->state(eventinfo->id, - __dp_interface_convert_state(eventinfo->state), - callback->state_data); - } + } else { + if (eventinfo.id == g_interface_slots[index].id && + g_interface_slots[index].state != NULL) { + // state event + g_interface_slots[index].state(eventinfo.id, + __dp_interface_convert_state(eventinfo.state), + g_interface_slots[index].state_data); } - free(eventinfo); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); } + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); } // while - FD_CLR(sock, &read_fdset); - g_interface_event_thread_id = 0; // set 0 to not call pthread_cancel + g_dp_event_thread_id = 0; // set 0 to not call pthread_cancel TRACE_DEBUG("thread end by itself"); return 0; } + + + + + +////////////////// new download-provider /////////////////////////////// +////////////////// created on 7 November, 2013 ///////////////////////// + +#define DP_CHECK_IPC_SOCK (g_dp_client == NULL ? -1 : g_dp_client->channel) + +static void __dp_ipc_clear_garbage(int sock, const size_t length) +{ + if (length > 0) { + char garbage[length]; + if (read(sock, &garbage, length) == 0) { + TRACE_ERROR("sock:%d closed peer", sock); + } + } +} + +static int __dp_ipc_response(int sock, int download_id, short section, + unsigned property, size_t *size) +{ + dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(sock); + if (ipc_info == NULL || ipc_info->section != section || + ipc_info->property != property || + (download_id >= 0 && ipc_info->id != download_id)) { + TRACE_STRERROR("socket read ipcinfo"); + free(ipc_info); + return DP_ERROR_IO_ERROR; + } + int errorcode = ipc_info->errorcode; + if (size != NULL) + *size = ipc_info->size; + free(ipc_info); + return errorcode; +} + static int __connect_to_provider() { - pthread_mutex_lock(&g_clear_mutex); - if (g_interface_info == NULL) { + int errorcode = DP_ERROR_NONE; - g_interface_info = - (dp_interface_info *) calloc(1, sizeof(dp_interface_info)); + CLIENT_MUTEX_LOCK(&g_clear_mutex); + + if (g_dp_client == NULL) { + g_dp_client = + (dp_interface_ipc *)calloc(1, sizeof(dp_interface_ipc)); + + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { + TRACE_ERROR("failed to ignore SIGPIPE signal"); + } } - if (g_interface_info != NULL) { + if (g_dp_client != NULL) { int connect_retry = 3; - g_interface_info->cmd_socket = -1; - while(g_interface_info->cmd_socket < 0 && connect_retry-- > 0) { - g_interface_info->cmd_socket = __create_socket(); - if (g_interface_info->cmd_socket < 0) - usleep(50000); - } - if (g_interface_info->cmd_socket < 0) { - TRACE_STRERROR("[CRITICAL] connect system error"); - free(g_interface_info); - g_interface_info = NULL; - pthread_mutex_unlock(&g_clear_mutex); - return DP_ERROR_IO_ERROR; - } - // send a command - if (__ipc_send_int(g_interface_info->cmd_socket, - DP_CMD_SET_COMMAND_SOCKET) < 0) { - close(g_interface_info->cmd_socket); - free(g_interface_info); - g_interface_info = NULL; - pthread_mutex_unlock(&g_clear_mutex); - return DP_ERROR_IO_ERROR; - } -#ifndef SO_PEERCRED - // send PID. Not support SO_PEERCRED - if (__ipc_send_int(g_interface_info->cmd_socket, getpid()) < 0) { - close(g_interface_info->cmd_socket); - free(g_interface_info); - g_interface_info = NULL; - pthread_mutex_unlock(&g_clear_mutex); - return DP_ERROR_IO_ERROR; - } - if (__ipc_send_int(g_interface_info->cmd_socket, getuid()) < 0) { - close(g_interface_info->cmd_socket); - free(g_interface_info); - g_interface_info = NULL; - pthread_mutex_unlock(&g_clear_mutex); - return DP_ERROR_IO_ERROR; - } - if (__ipc_send_int(g_interface_info->cmd_socket, getgid()) < 0) { - close(g_interface_info->cmd_socket); - free(g_interface_info); - g_interface_info = NULL; - pthread_mutex_unlock(&g_clear_mutex); - return DP_ERROR_IO_ERROR; + g_dp_client->channel = -1; + while(g_dp_client->channel < 0 && connect_retry-- > 0) { + int ret = __create_socket(); + if (ret == -1) { + TRACE_STRERROR("failed to connect to provider(remains:%d)", connect_retry); + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 20000000; + nanosleep(&ts, NULL); + } else if (ret >= 0) { + struct timeval tv_timeo = { 1, 500000 }; // 1.5 second + g_dp_client->channel = ret; + if (setsockopt(g_dp_client->channel, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, sizeof(tv_timeo)) < 0) { + TRACE_STRERROR("[CRITICAL] setsockopt SO_RCVTIMEO"); + } + } else { + errorcode = -ret; + TRACE_STRERROR("check error:%d", errorcode); + goto EXIT_CONNECT; + } } -#endif - g_interface_info->event_socket = __create_socket(); - if (g_interface_info->event_socket < 0) { + if (g_dp_client->channel < 0) { TRACE_STRERROR("[CRITICAL] connect system error"); - close(g_interface_info->cmd_socket); - free(g_interface_info); - g_interface_info = NULL; - pthread_mutex_unlock(&g_clear_mutex); - return DP_ERROR_IO_ERROR; + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; } - // send a command - if (__ipc_send_int(g_interface_info->event_socket, - DP_CMD_SET_EVENT_SOCKET) < 0) { - close(g_interface_info->cmd_socket); - close(g_interface_info->event_socket); - free(g_interface_info); - g_interface_info = NULL; - pthread_mutex_unlock(&g_clear_mutex); - return DP_ERROR_IO_ERROR; + + if (dp_ipc_query(g_dp_client->channel, -1, DP_SEC_INIT, + DP_PROP_NONE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; } #ifndef SO_PEERCRED + dp_credential cred; + cred.pid = getpid(); + cred.uid = getuid(); + cred.gid = getgid(); // send PID. Not support SO_PEERCRED - if (__ipc_send_int - (g_interface_info->event_socket, getpid()) < 0) { - close(g_interface_info->cmd_socket); - close(g_interface_info->event_socket); - free(g_interface_info); - g_interface_info = NULL; - pthread_mutex_unlock(&g_clear_mutex); - return DP_ERROR_IO_ERROR; + if (dp_ipc_write(g_dp_client->channel, + &cred, sizeof(dp_credential)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; } #endif - int ret = pthread_mutex_init(&g_interface_info->mutex, NULL); - if (ret != 0) { - TRACE_STRERROR("ERR:pthread_mutex_init FAIL with %d.", ret); - __clear_interface(); - pthread_mutex_unlock(&g_clear_mutex); - return DP_ERROR_IO_ERROR; + errorcode = __dp_ipc_response(g_dp_client->channel, + -1, DP_SEC_INIT, DP_PROP_NONE, NULL); + // Commented by justine.bang + // Above ipc_query call try to wake up download-provider. + // But, we can sometimes meet EINTR, EAGAIN or EINPROGRESS signal if systemd is slow. + // So, If meet EINTR ,EAGAIN or EINPROGRESS in this line, it's better to wait response from download-provider one more time. + if (errorcode == DP_ERROR_IO_ERROR && (errno == EINTR || errno == EAGAIN || errno == EINPROGRESS)) { + errorcode = __dp_ipc_response(g_dp_client->channel, + -1, DP_SEC_INIT, DP_PROP_NONE, NULL); } - } - pthread_mutex_unlock(&g_clear_mutex); - if (g_interface_event_thread_id <= 0) { - // create thread here ( getting event_socket ) - pthread_attr_t thread_attr; - if (pthread_attr_init(&thread_attr) != 0) { - TRACE_STRERROR("[CRITICAL] pthread_attr_init"); - __disconnect_from_provider(); - return DP_ERROR_IO_ERROR; - } - if (pthread_attr_setdetachstate(&thread_attr, - PTHREAD_CREATE_DETACHED) != 0) { - TRACE_STRERROR - ("[CRITICAL] pthread_attr_setdetachstate"); - __disconnect_from_provider(); - return DP_ERROR_IO_ERROR; - } - if (pthread_create(&g_interface_event_thread_id, - &thread_attr, __dp_interface_event_manager, - g_interface_info) != 0) { - TRACE_STRERROR("[CRITICAL] pthread_create"); - __clear_interface(); - g_interface_event_thread_id = 0; - return DP_ERROR_IO_ERROR; + if (errorcode == DP_ERROR_NONE && g_dp_event_thread_id <= 0) { + if (pthread_create(&g_dp_event_thread_id, NULL, + __dp_event_manager, g_dp_client) != 0) { + TRACE_STRERROR("failed to create event-manager"); + errorcode = DP_ERROR_IO_ERROR; + } else { + pthread_detach(g_dp_event_thread_id); + } } + } - return DP_ERROR_NONE; + +EXIT_CONNECT: + CLIENT_MUTEX_UNLOCK(&g_clear_mutex); + if (errorcode != DP_ERROR_NONE) + __bp_disconnect(__FUNCTION__); + + return errorcode; } static dp_error_type __check_connections() { int ret = 0; - if (g_interface_info == NULL) + if (g_dp_client == NULL) if ((ret = __connect_to_provider()) != DP_ERROR_NONE) return ret; - if (g_interface_info == NULL || g_interface_info->cmd_socket < 0) { + if (g_dp_client == NULL || g_dp_client->channel < 0) { TRACE_ERROR("[CHECK IPC]"); return DP_ERROR_IO_ERROR; } return DP_ERROR_NONE; } -// used frequently -static dp_error_type __dp_interface_set_string - (const int id, const dp_command_type cmd, const char *value) -{ - dp_error_type errorcode = DP_ERROR_NONE; - if (value == NULL || strlen(value) <= 0) { - TRACE_ERROR("[CHECK url]"); - return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; - } - - DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - int fd = g_interface_info->cmd_socket; - - // send commnad with ID - errorcode = __ipc_send_command_return(id, cmd); - if (errorcode == DP_ERROR_NONE) { - // send string - errorcode = __ipc_send_string(fd, value); - if (errorcode == DP_ERROR_NONE) { - // return from provider. - errorcode = __ipc_return(fd); - } - } - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); -} - -static dp_error_type __dp_interface_set_strings - (const int id, const dp_command_type cmd, const char **strings, - const unsigned count) +static int __dp_ipc_set_binary(const int id, const unsigned property, + const bundle_raw *string, const size_t length, const char *funcname) { - dp_error_type errorcode = DP_ERROR_NONE; - if (strings == NULL || count == 0) { - TRACE_ERROR("[CHECK strings]"); + int errorcode = DP_ERROR_NONE; + if (string == NULL || length <= 0) { + TRACE_ERROR("%s check binary (%d)", funcname, length); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - + CLIENT_MUTEX_LOCK(&g_function_mutex); DP_CHECK_CONNECTION; - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - int fd = g_interface_info->cmd_socket; - - // send commnad with ID - errorcode = __ipc_send_command_return(id, cmd); - if (errorcode == DP_ERROR_NONE) { - if (__ipc_send_int(fd, (int)count) == 0) { - int i = 0; - for (; i < count; i++) { - // send string - errorcode = __ipc_send_string(fd, strings[i]); - if (errorcode != DP_ERROR_NONE) - break; - } - } else { + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_SET, property, DP_ERROR_NONE, length * sizeof(unsigned char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void*)string, length * sizeof(unsigned char)) < 0) { errorcode = DP_ERROR_IO_ERROR; - } - if (errorcode == DP_ERROR_NONE) { - // return from provider. - errorcode = __ipc_return(fd); + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, DP_SEC_SET, property, NULL); } } - pthread_mutex_unlock(&g_interface_info->mutex); if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return __dp_interface_convert_errorcode(errorcode); } -static dp_error_type __dp_interface_get_string - (const int id, const dp_command_type cmd, char **value) +static int __dp_ipc_set_string(const int id, const short section, const unsigned property, + const char *string, const char *funcname) { int errorcode = DP_ERROR_NONE; - char *recv_str = NULL; - - if (value == NULL) { - TRACE_ERROR("[CHECK buffer]"); + size_t length = 0; + if (string == NULL || (length = strlen(string)) <= 0 || + length > DP_MAX_STR_LEN) { + TRACE_ERROR("%s check string (%d:%s)", funcname, length, string); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - + CLIENT_MUTEX_LOCK(&g_function_mutex); DP_CHECK_CONNECTION; - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - int fd = g_interface_info->cmd_socket; - - errorcode = __ipc_send_command_return(id, cmd); - if (errorcode == DP_ERROR_NONE) { - // getting state with ID from provider. - recv_str = __ipc_read_string(fd); - if (recv_str != NULL) - *value = recv_str; - else - errorcode = __get_standard_errorcode(DP_ERROR_IO_ERROR); + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void*)string, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } } - pthread_mutex_unlock(&g_interface_info->mutex); if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return __dp_interface_convert_errorcode(errorcode); } -static dp_error_type __dp_interface_get_strings - (const int id, const dp_command_type cmd, const char **strings, - const unsigned length, char ***values, unsigned *count) +static int __dp_ipc_get_string(const int id, const unsigned property, + char **string, const char *funcname) { int errorcode = DP_ERROR_NONE; - int i = 0; - int recv_str_index = 0; - char **recv_strings = NULL; - if (values == NULL || count == NULL) { - TRACE_ERROR("[CHECK buffer]"); + if (string == NULL) { + TRACE_ERROR("%s check buffer", funcname); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } - DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - + CLIENT_MUTEX_LOCK(&g_function_mutex); DP_CHECK_CONNECTION; - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - int fd = g_interface_info->cmd_socket; - - errorcode = __ipc_send_command_return(id, cmd); - if (errorcode == DP_ERROR_NONE) { - if (length > 0 && strings != NULL) { - if (__ipc_send_int(fd, (int)length) == 0) { - for (i = 0; i < length; i++) { - // send string - errorcode = __ipc_send_string(fd, strings[i]); - if (errorcode != DP_ERROR_NONE) - break; - } - } else { - errorcode = DP_ERROR_IO_ERROR; - } - } + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + size_t string_length = 0; + *string = NULL; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, property, &string_length); if (errorcode == DP_ERROR_NONE) { - // return from provider. - errorcode = __ipc_return(fd); - } - } - if (errorcode == DP_ERROR_NONE) { - int recv_int = __ipc_read_int(fd); - if (recv_int < 0) { - errorcode = DP_ERROR_IO_ERROR; - } else if (recv_int > 0) { - recv_strings = (char **)calloc(recv_int, sizeof(char *)); - if (recv_strings == NULL) { - errorcode = DP_ERROR_OUT_OF_MEMORY; - } else { - for (i = 0; i < recv_int; i++) { - char *recv_str = __ipc_read_string(fd); - if (recv_str == NULL) { - errorcode = - __get_standard_errorcode(DP_ERROR_IO_ERROR); - break; + if (string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, string_length); + } else { + if (dp_ipc_read(sock, recv_str, string_length, funcname) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); } else { - recv_strings[recv_str_index++] = recv_str; + recv_str[string_length] = '\0'; + *string = recv_str; } } + } else { + errorcode = DP_ERROR_IO_ERROR; } } - if (errorcode == DP_ERROR_NONE) { - *count = recv_str_index; - *values = recv_strings; - } else { - *count = 0; - for (i = 0; i < recv_str_index; i++) - free(recv_strings[i]); - free(recv_strings); - } } - pthread_mutex_unlock(&g_interface_info->mutex); + if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return __dp_interface_convert_errorcode(errorcode); } -static dp_error_type __dp_interface_get_int - (const int id, dp_command_type cmd, int *value) +// send command and int & return errorcode +static int __dp_ipc_set_int(const int id, const unsigned section, const unsigned property, + const int value, const char *funcname) { int errorcode = DP_ERROR_NONE; - int recv_int = -1; - - if (value == NULL) { - TRACE_ERROR("[CHECK buffer]"); - return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; - } DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - + CLIENT_MUTEX_LOCK(&g_function_mutex); DP_CHECK_CONNECTION; - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - int fd = g_interface_info->cmd_socket; - - errorcode = __ipc_send_command_return(id, cmd); - if (errorcode == DP_ERROR_NONE) { - recv_int = __ipc_read_int(fd); - if (recv_int >= 0) { - *value = recv_int; - TRACE_DEBUG("ID : %d recv_int : %d", id, *value); + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void *)&value, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); } else { - errorcode = __get_standard_errorcode(DP_ERROR_IO_ERROR); + errorcode = __dp_ipc_response(sock, id, section, property, NULL); } } - pthread_mutex_unlock(&g_interface_info->mutex); if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return __dp_interface_convert_errorcode(errorcode); } -static dp_error_type __dp_interface_set_int - (const int id, dp_command_type cmd, const int value) +// send command & return errorcode and int +static int __dp_ipc_get_int(const int id, const unsigned property, + int *value, const char *funcname) { int errorcode = DP_ERROR_NONE; - DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - int fd = g_interface_info->cmd_socket; - - // send commnad with ID - errorcode = __ipc_send_command_return(id, cmd); - if (errorcode == DP_ERROR_NONE) { - // send string - if (__ipc_send_int(fd, value) == 0) { - // return from provider. - errorcode = __ipc_return(fd); - } else { - errorcode = DP_ERROR_IO_ERROR; - } - } - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); -} - -static dp_error_type __dp_interface_set_raw_bundle - (const int id, const dp_command_type cmd, int type, const bundle_raw *b, int len) -{ - dp_error_type errorcode = DP_ERROR_NONE; - if (b == NULL) { - TRACE_ERROR("[CHECK bundle]"); + if (value == NULL) { + TRACE_ERROR("%s check buffer", funcname); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - + CLIENT_MUTEX_LOCK(&g_function_mutex); DP_CHECK_CONNECTION; - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - int fd = g_interface_info->cmd_socket; - - // send commnad with ID - errorcode = __ipc_send_command_return(id, cmd); - if (errorcode == DP_ERROR_NONE) { - // send raw bundle - errorcode = __ipc_send_raw_bundle(fd, type, b, len); + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, property, &extra_size); if (errorcode == DP_ERROR_NONE) { - // return from provider. - errorcode = __ipc_return(fd); + if (extra_size == sizeof(int)) { + if (dp_ipc_read(sock, value, extra_size, funcname) < 0) + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = DP_ERROR_IO_ERROR; + } } } - pthread_mutex_unlock(&g_interface_info->mutex); + if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return __dp_interface_convert_errorcode(errorcode); } -static dp_error_type __dp_interface_get_raw_bundle - (const int id, const dp_command_type cmd, int type, bundle_raw **value, int *len) +// send command & return errorcode. +int __dp_ipc_echo(const int id, const short section, + const unsigned property, const char *funcname) { int errorcode = DP_ERROR_NONE; - if (value == NULL) { - TRACE_ERROR("[CHECK buffer]"); - return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; - } - DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - + CLIENT_MUTEX_LOCK(&g_function_mutex); DP_CHECK_CONNECTION; - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - int fd = g_interface_info->cmd_socket; - - errorcode = __ipc_send_command_return(id, cmd); - if (errorcode == DP_ERROR_NONE) { - errorcode = __ipc_send_int(fd, type); - if(errorcode == 0) { - errorcode = __ipc_return(g_interface_info->cmd_socket); - if (errorcode == DP_ERROR_NONE) { - *len = __ipc_read_bundle(fd, value); - if (*len <= 0) - errorcode = __get_standard_errorcode(DP_ERROR_IO_ERROR); - } else { - TRACE_ERROR("[ERROR] Fail to get result for sending type value]"); - errorcode = DP_ERROR_IO_ERROR; - } - } else { - TRACE_ERROR("[ERROR] Fail to send type]"); - errorcode = DP_ERROR_IO_ERROR; - } - } else { - TRACE_ERROR("[ERROR] Fail to send command]"); + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, 0) < 0) { errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); } - pthread_mutex_unlock(&g_interface_info->mutex); + if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return __dp_interface_convert_errorcode(errorcode); } - /////////////////////// APIs ///////////////////////////////// int dp_interface_create(int *id) { int errorcode = DP_ERROR_NONE; - int t_id = 0; int index = -1; if (id == NULL) { @@ -1351,626 +722,267 @@ int dp_interface_create(int *id) return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } - pthread_mutex_lock(&g_function_mutex); + CLIENT_MUTEX_LOCK(&g_function_mutex); if ((index = __get_empty_slot_index()) < 0) { TRACE_ERROR ("[ERROR] TOO_MANY_DOWNLOADS[%d]", MAX_DOWNLOAD_HANDLE); - pthread_mutex_unlock(&g_function_mutex); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; } DP_CHECK_CONNECTION; - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - errorcode = __ipc_send_command_return(-1, DP_CMD_CREATE); - if (errorcode == DP_ERROR_NONE) { - // getting state with ID from provider. - t_id = __ipc_read_download_id(g_interface_info->cmd_socket); - if (t_id > 0) { - *id = t_id; - g_interface_slots[index].id = t_id; - g_interface_slots[index].callback.state = NULL; - g_interface_slots[index].callback.state_data = NULL; - g_interface_slots[index].callback.progress = NULL; - g_interface_slots[index].callback.progress_data = NULL; - errorcode = DP_ERROR_NONE; + dp_ipc_fmt *ipc_info = NULL; + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, -1, DP_SEC_CONTROL, DP_PROP_CREATE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + } else { + ipc_info = dp_ipc_get_fmt(sock); + if (ipc_info == NULL) { + TRACE_ERROR("[ERROR] IPC INFO is NULL"); + errorcode = DP_ERROR_IO_ERROR; + } else if (ipc_info->section != DP_SEC_CONTROL || + ipc_info->property != DP_PROP_CREATE || + ipc_info->size != 0) { + TRACE_ERROR("sock:%d id:%d section:%d property:%d size:%d", + sock, ipc_info->id, ipc_info->section, ipc_info->property, + ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; } else { - errorcode = __get_standard_errorcode(DP_ERROR_IO_ERROR); + TRACE_DEBUG("download_id:%d", ipc_info->id); + if (errorcode == DP_ERROR_NONE && ipc_info->id > 0) { + *id = ipc_info->id; + g_interface_slots[index].id = ipc_info->id; + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } } } - pthread_mutex_unlock(&g_interface_info->mutex); + free(ipc_info); if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return __dp_interface_convert_errorcode(errorcode); } int dp_interface_destroy(const int id) { int index = -1; - int errorcode = DP_ERROR_NONE; - DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - + CLIENT_MUTEX_LOCK(&g_function_mutex); DP_CHECK_CONNECTION; - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - if ((index = __get_my_slot_index(id)) >= 0) { g_interface_slots[index].id = 0; - g_interface_slots[index].callback.state = NULL; - g_interface_slots[index].callback.state_data = NULL; - g_interface_slots[index].callback.progress = NULL; - g_interface_slots[index].callback.progress_data = NULL; - } - errorcode = __ipc_send_command_return(id, DP_CMD_DESTROY); - if (errorcode == DP_ERROR_NONE) { - // after getting errorcode, send FREE to provider. - // send again DP_CMD_FREE with ID. - errorcode = __ipc_send_command - (g_interface_info->cmd_socket, id, DP_CMD_FREE); - } - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_DESTROY, __FUNCTION__); } int dp_interface_start(const int id) { - int errorcode = DP_ERROR_NONE; - - DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - errorcode = __ipc_send_command_return(id, DP_CMD_START); - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_START, __FUNCTION__); } int dp_interface_pause(const int id) { - int errorcode = DP_ERROR_NONE; - - DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - errorcode = __ipc_send_command_return(id, DP_CMD_PAUSE); - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_PAUSE, __FUNCTION__); } int dp_interface_cancel(const int id) { - int errorcode = DP_ERROR_NONE; - - DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - errorcode = __ipc_send_command_return(id, DP_CMD_CANCEL); - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_CANCEL, __FUNCTION__); } int dp_interface_set_url(const int id, const char *url) { - return __dp_interface_set_string(id, DP_CMD_SET_URL, url); + if (url == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_URL, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_URL, url, __FUNCTION__); } int dp_interface_get_url(const int id, char **url) { - return __dp_interface_get_string(id, DP_CMD_GET_URL, url); -} - -int dp_interface_set_network_type(const int id, int net_type) -{ - return __dp_interface_set_int(id, DP_CMD_SET_NETWORK_TYPE, - __dp_interface_convert_network_adaptor(net_type)); -} - -int dp_interface_get_network_type(const int id, int *net_type) -{ - if (net_type == NULL) { - TRACE_ERROR("[CHECK buffer]"); - return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; - } - int network_type = DP_NETWORK_TYPE_ALL; - int ret = __dp_interface_get_int - (id, DP_CMD_GET_NETWORK_TYPE, &network_type); - if (ret == DOWNLOAD_ADAPTOR_ERROR_NONE) - *net_type = - __dp_interface_convert_network_provider(network_type); - return ret; + return __dp_ipc_get_string(id, DP_PROP_URL, url, __FUNCTION__); } int dp_interface_set_destination(const int id, const char *path) { - return __dp_interface_set_string(id, DP_CMD_SET_DESTINATION, path); + if (path == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_DESTINATION, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_DESTINATION, path, __FUNCTION__); } - int dp_interface_get_destination(const int id, char **path) { - return __dp_interface_get_string(id, DP_CMD_GET_DESTINATION, path); + return __dp_ipc_get_string(id, DP_PROP_DESTINATION, path, __FUNCTION__); } int dp_interface_set_file_name(const int id, const char *file_name) { - return __dp_interface_set_string(id, DP_CMD_SET_FILENAME, file_name); + if (file_name == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_FILENAME, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_FILENAME, file_name, __FUNCTION__); } int dp_interface_get_file_name(const int id, char **file_name) { - return __dp_interface_get_string(id, DP_CMD_GET_FILENAME, file_name); + return __dp_ipc_get_string(id, DP_PROP_FILENAME, file_name, __FUNCTION__); } -int dp_interface_set_ongoing_notification(const int id, int enable) +int dp_interface_get_downloaded_file_path(const int id, char **path) { - return dp_interface_set_notification(id, enable); + return __dp_ipc_get_string(id, DP_PROP_SAVED_PATH, path, __FUNCTION__); } -int dp_interface_set_notification(const int id, int enable) +int dp_interface_get_temp_path(const int id, char **temp_path) { - return __dp_interface_set_int(id, DP_CMD_SET_NOTIFICATION, enable); + return __dp_ipc_get_string(id, DP_PROP_TEMP_SAVED_PATH, temp_path, __FUNCTION__); } -int dp_interface_get_ongoing_notification(const int id, int *enable) +int dp_interface_get_content_name(const int id, char **content_name) { - return dp_interface_get_notification(id, enable); + return __dp_ipc_get_string(id, DP_PROP_CONTENT_NAME, content_name, __FUNCTION__); } -int dp_interface_get_notification(const int id, int *enable) +int dp_interface_get_etag(const int id, char **etag) { - return __dp_interface_get_int(id, DP_CMD_GET_NOTIFICATION, enable); + return __dp_ipc_get_string(id, DP_PROP_ETAG, etag, __FUNCTION__); } -int dp_interface_get_downloaded_file_path(const int id, char **path) +int dp_interface_set_temp_file_path(const int id, const char *path) { - return __dp_interface_get_string(id, DP_CMD_GET_SAVED_PATH, path); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_TEMP_SAVED_PATH, path, __FUNCTION__); } -int dp_interface_set_notification_extra_param(const int id, char *key, - char *value) +int dp_interface_set_network_type(const int id, int net_type) { -#if 0 - DP_PRE_CHECK_ID; - - if (key == NULL || value == NULL) { - TRACE_ERROR("[CHECK param]"); - return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; - } - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - // send commnad with ID - if (__ipc_send_command - (g_interface_info->cmd_socket, id, DP_CMD_SET_EXTRA_PARAM) - != DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - if (__ipc_send_string(g_interface_info->cmd_socket, key) - != DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - - if (__ipc_send_string(g_interface_info->cmd_socket, value) - != DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - - int errorcode = - __ipc_return(g_interface_info->cmd_socket); - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) { - TRACE_ERROR("[CHECK IO] (%d)", id); - __disconnect_from_provider(); - } - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); -#endif - return DOWNLOAD_ADAPTOR_ERROR_NONE; + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NETWORK_TYPE, + net_type, __FUNCTION__); } -int dp_interface_get_notification_extra_param(const int id, char **key, - char **value) -{ -#if 0 - int errorcode = DP_ERROR_NONE; - char *key_str = NULL; - char *value_str = NULL; - - DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - errorcode = __ipc_send_command_return(id, DP_CMD_GET_EXTRA_PARAM); - if (errorcode != DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); - } - // getting state with ID from provider. - key_str = __ipc_read_string(g_interface_info->cmd_socket); - if (key_str == NULL) { - pthread_mutex_unlock(&g_interface_info->mutex); - errorcode = __get_standard_errorcode(DP_ERROR_IO_ERROR); - if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); - } - - value_str = __ipc_read_string(g_interface_info->cmd_socket); - pthread_mutex_unlock(&g_interface_info->mutex); - if (value_str == NULL) { - free(key_str); - errorcode = __get_standard_errorcode(DP_ERROR_IO_ERROR); - if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); - } - - *key = key_str; - *value = value_str; - pthread_mutex_unlock(&g_function_mutex); -#endif - return DOWNLOAD_ADAPTOR_ERROR_NONE; -} - -int dp_interface_add_http_header_field(const int id, const char *field, - const char *value) +int dp_interface_get_network_type(const int id, int *net_type) { - int errorcode = DP_ERROR_NONE; - - DP_PRE_CHECK_ID; - - if (field == NULL || value == NULL) { - TRACE_ERROR("[CHECK field or value]"); + if (net_type == NULL) { + TRACE_ERROR("check buffer"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - // send commnad with ID - if (__ipc_send_command_return(id, DP_CMD_SET_HTTP_HEADER) != - DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - - if (__ipc_send_string(g_interface_info->cmd_socket, field) - != DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - - if (__ipc_send_string(g_interface_info->cmd_socket, value) - != DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - // return from provider. - errorcode = __ipc_return(g_interface_info->cmd_socket); - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) { - TRACE_ERROR("[CHECK IO] (%d)", id); - __disconnect_from_provider(); - } - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); + return __dp_ipc_get_int(id, DP_PROP_NETWORK_TYPE, net_type, __FUNCTION__); } -int dp_interface_get_http_header_field(const int id, const char *field, - char **value) +int dp_interface_get_network_bonding(const int id, int *enable) { - int errorcode = DP_ERROR_NONE; - char *str = NULL; - - DP_PRE_CHECK_ID; - - if (field == NULL || value == NULL) { - TRACE_ERROR("[CHECK field or value]"); + if (enable == NULL) { + TRACE_ERROR("check buffer"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - if (__ipc_send_command_return(id, DP_CMD_GET_HTTP_HEADER) != - DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - - if (__ipc_send_string(g_interface_info->cmd_socket, field) - != DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - - errorcode = __ipc_return(g_interface_info->cmd_socket); - if (errorcode == DP_ERROR_NONE) { - // getting string with ID from provider. - str = __ipc_read_string(g_interface_info->cmd_socket); - if (str != NULL) { - *value = str; - } else { - errorcode = __get_standard_errorcode(DP_ERROR_IO_ERROR); - } - } - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR || str == NULL) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); + return __dp_ipc_get_int(id, DP_PROP_NETWORK_BONDING, enable, __FUNCTION__); } -int dp_interface_get_http_header_field_list(const int id, char ***fields, - int *length) -{ - return __dp_interface_get_strings(id, DP_CMD_GET_HTTP_HEADER_LIST, - NULL, 0, fields, (unsigned *)length); -} - -int dp_interface_remove_http_header_field(const int id, - const char *field) +int dp_interface_set_network_bonding(const int id, int enable) { - int errorcode = DP_ERROR_NONE; - - DP_PRE_CHECK_ID; - - if (field == NULL) { - TRACE_ERROR("[CHECK field]"); - return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; - } - - pthread_mutex_lock(&g_function_mutex); - - DP_CHECK_CONNECTION; - - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - // send commnad with ID - if (__ipc_send_command_return(id, DP_CMD_DEL_HTTP_HEADER) != - DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - if (__ipc_send_string(g_interface_info->cmd_socket, field) - != DP_ERROR_NONE) { - pthread_mutex_unlock(&g_interface_info->mutex); - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); - return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; - } - // return from provider. - errorcode = __ipc_return(g_interface_info->cmd_socket); - pthread_mutex_unlock(&g_interface_info->mutex); - if (errorcode == DP_ERROR_IO_ERROR) { - TRACE_ERROR("[CHECK IO] (%d)", id); - __disconnect_from_provider(); - } - pthread_mutex_unlock(&g_function_mutex); - return __dp_interface_convert_errorcode(errorcode); + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NETWORK_BONDING, + enable, __FUNCTION__); } int dp_interface_set_state_changed_cb(const int id, dp_interface_state_changed_cb callback, void *user_data) { - int errorcode = DP_ERROR_NONE; - int index = -1; - - if (callback == NULL) { - dp_interface_unset_state_changed_cb(id); - return DOWNLOAD_ADAPTOR_ERROR_NONE; - } - - errorcode = - __dp_interface_set_int(id, DP_CMD_SET_STATE_CALLBACK, 1); + int errorcode = __dp_ipc_echo(id, DP_SEC_SET, DP_PROP_STATE_CALLBACK, __FUNCTION__); if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { - pthread_mutex_lock(&g_function_mutex); - // search same info in array. - index = __get_my_slot_index(id); + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); if (index < 0) { index = __get_empty_slot_index(); if (index >= 0) { g_interface_slots[index].id = id; } else { - TRACE_ERROR("[ERROR] TOO_MANY_DOWNLOADS [%d]", + TRACE_ERROR("too many download limit:%d", MAX_DOWNLOAD_HANDLE); errorcode = DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; } } if (index >= 0) { - g_interface_slots[index].callback.state = callback; - g_interface_slots[index].callback.state_data = user_data; + g_interface_slots[index].state = callback; + g_interface_slots[index].state_data = user_data; } - pthread_mutex_unlock(&g_function_mutex); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); } return errorcode; } int dp_interface_unset_state_changed_cb(const int id) { - int errorcode = DP_ERROR_NONE; - int index = -1; - - errorcode = - __dp_interface_set_int(id, DP_CMD_SET_STATE_CALLBACK, 0); - // clear by force although failed to clear in provider - pthread_mutex_lock(&g_function_mutex); - if ((index = __get_my_slot_index(id)) >= 0) { - g_interface_slots[index].callback.state = NULL; - g_interface_slots[index].callback.state_data = NULL; + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index >= 0) { + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; } - pthread_mutex_unlock(&g_function_mutex); - return errorcode; + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + if (index < 0) + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_STATE_CALLBACK, __FUNCTION__); } int dp_interface_set_progress_cb(const int id, dp_interface_progress_cb callback, void *user_data) { - int errorcode = DP_ERROR_NONE; - int index = -1; - - if (callback == NULL) { - dp_interface_unset_progress_cb(id); - return DOWNLOAD_ADAPTOR_ERROR_NONE; - } - - errorcode = - __dp_interface_set_int(id, DP_CMD_SET_PROGRESS_CALLBACK, 1); + int errorcode = __dp_ipc_echo(id, DP_SEC_SET, DP_PROP_PROGRESS_CALLBACK, __FUNCTION__); if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { - pthread_mutex_lock(&g_function_mutex); - // search same info in array. - index = __get_my_slot_index(id); + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); if (index < 0) { index = __get_empty_slot_index(); if (index >= 0) { g_interface_slots[index].id = id; } else { - TRACE_ERROR("[ERROR] TOO_MANY_DOWNLOADS [%d]", + TRACE_ERROR("too many download limit:%d", MAX_DOWNLOAD_HANDLE); errorcode = DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; } } if (index >= 0) { - g_interface_slots[index].callback.progress = callback; - g_interface_slots[index].callback.progress_data = user_data; + g_interface_slots[index].progress = callback; + g_interface_slots[index].progress_data = user_data; } - pthread_mutex_unlock(&g_function_mutex); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); } return errorcode; } int dp_interface_unset_progress_cb(const int id) { - int errorcode = DP_ERROR_NONE; - int index = -1; - - errorcode = - __dp_interface_set_int(id, DP_CMD_SET_PROGRESS_CALLBACK, 0); - // clear by force although failed to clear in provider - pthread_mutex_lock(&g_function_mutex); - if ((index = __get_my_slot_index(id)) >= 0) { - g_interface_slots[index].callback.progress = NULL; - g_interface_slots[index].callback.progress_data = NULL; + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index >= 0) { + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; } - pthread_mutex_unlock(&g_function_mutex); - return errorcode; + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + if (index < 0) + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_PROGRESS_CALLBACK, __FUNCTION__); } int dp_interface_get_state(const int id, int *state) { if (state == NULL) { - TRACE_ERROR("[CHECK buffer]"); + TRACE_ERROR("check buffer"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } - int statecode = DOWNLOAD_ADPATOR_STATE_NONE; - int ret = __dp_interface_get_int(id, DP_CMD_GET_STATE, &statecode); - if (ret == DOWNLOAD_ADAPTOR_ERROR_NONE) - *state = __dp_interface_convert_state(statecode); - return ret; -} - -int dp_interface_get_temp_path(const int id, char **temp_path) -{ - return __dp_interface_get_string - (id, DP_CMD_GET_TEMP_SAVED_PATH, temp_path); -} - -int dp_interface_get_content_name(const int id, char **content_name) -{ - return __dp_interface_get_string - (id, DP_CMD_GET_CONTENT_NAME, content_name); + int dp_state = DP_STATE_NONE; + int errorcode = __dp_ipc_get_int(id, DP_PROP_STATE, &dp_state, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) + *state = __dp_interface_convert_state(dp_state); + return errorcode; } int dp_interface_get_content_size(const int id, @@ -1979,60 +991,72 @@ int dp_interface_get_content_size(const int id, int errorcode = DP_ERROR_NONE; if (content_size == NULL) { - TRACE_ERROR("[CHECK buffer content_size]"); + TRACE_ERROR("check buffer"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } DP_PRE_CHECK_ID; - - pthread_mutex_lock(&g_function_mutex); - + CLIENT_MUTEX_LOCK(&g_function_mutex); DP_CHECK_CONNECTION; - pthread_mutex_lock(&g_interface_info->mutex); - - DP_CHECK_PROVIDER_STATUS; - - errorcode = - __ipc_send_command_return(id, DP_CMD_GET_TOTAL_FILE_SIZE); - if (errorcode == DP_ERROR_NONE) { - // getting content_size from provider. - if (__ipc_read_custom_type(g_interface_info->cmd_socket, - content_size, sizeof(unsigned long long)) < 0) { - errorcode = __get_standard_errorcode(DP_ERROR_IO_ERROR); + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, DP_PROP_TOTAL_FILE_SIZE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", __FUNCTION__, sock); + } else { + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, DP_PROP_TOTAL_FILE_SIZE, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(unsigned long long)) { + if (dp_ipc_read(sock, content_size, extra_size, __FUNCTION__) < 0) + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = DP_ERROR_IO_ERROR; + } } } - pthread_mutex_unlock(&g_interface_info->mutex); + if (errorcode == DP_ERROR_IO_ERROR) - __disconnect_from_provider(); - pthread_mutex_unlock(&g_function_mutex); + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); return __dp_interface_convert_errorcode(errorcode); } int dp_interface_get_mime_type(const int id, char **mime_type) { - return __dp_interface_get_string - (id, DP_CMD_GET_MIME_TYPE, mime_type); + if (mime_type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_MIME_TYPE, mime_type, + __FUNCTION__); } int dp_interface_set_auto_download(const int id, int enable) { - return __dp_interface_set_int(id, DP_CMD_SET_AUTO_DOWNLOAD, enable); + short section = DP_SEC_SET; + if (enable <= 0) + section = DP_SEC_UNSET; + return __dp_ipc_echo(id, section, DP_PROP_AUTO_DOWNLOAD, __FUNCTION__); } int dp_interface_get_auto_download(const int id, int *enable) { - return __dp_interface_get_int(id, DP_CMD_GET_AUTO_DOWNLOAD, enable); + if (enable == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_AUTO_DOWNLOAD, enable, __FUNCTION__); } int dp_interface_get_error(const int id, int *error) { if (error == NULL) { - TRACE_ERROR("[CHECK buffer error]"); + TRACE_ERROR("check buffer"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } int errorcode = DP_ERROR_NONE; - int ret = __dp_interface_get_int(id, DP_CMD_GET_ERROR, &errorcode); + int ret = __dp_ipc_get_int(id, DP_PROP_ERROR, &errorcode, __FUNCTION__); if (ret == DOWNLOAD_ADAPTOR_ERROR_NONE) *error = __dp_interface_convert_errorcode(errorcode); return ret; @@ -2040,107 +1064,497 @@ int dp_interface_get_error(const int id, int *error) int dp_interface_get_http_status(const int id, int *http_status) { - return __dp_interface_get_int - (id, DP_CMD_GET_HTTP_STATUS, http_status); + if (http_status == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_HTTP_STATUS, http_status, + __FUNCTION__); } -int dp_interface_add_noti_extra(const int id, const char *key, - const char **values, const unsigned length) +int dp_interface_set_notification_title(const int id, const char *title) { - int i = 0; + if (title == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_SUBJECT, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_NOTIFICATION_SUBJECT, title, __FUNCTION__); +} - if (key == NULL || values == NULL) { - TRACE_ERROR("[CHECK key/values] (%d)", id); - return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; - } - if (length <= 0) { - TRACE_ERROR("[CHECK legnth] (%d)", id); +int dp_interface_get_notification_title(const int id, char **title) +{ + if (title == NULL) { + TRACE_ERROR("check buffer"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } + return __dp_ipc_get_string(id, DP_PROP_NOTIFICATION_SUBJECT, title, __FUNCTION__); +} - char *strings[length + 1]; - strings[0] = (char *)key; - for (i = 0; i < length; i++) { - strings[i + 1] = (char *)values[i]; - } - return __dp_interface_set_strings(id, DP_CMD_ADD_EXTRA_PARAM, - (const char **)strings, length + 1); +int dp_interface_set_notification_description(const int id, const char *description) +{ + if (description == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_DESCRIPTION, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_NOTIFICATION_DESCRIPTION, description, __FUNCTION__); } -int dp_interface_get_noti_extra_values(const int id, const char *key, - char ***values, unsigned *length) +int dp_interface_get_notification_description(const int id, char **description) { - return __dp_interface_get_strings(id, DP_CMD_GET_EXTRA_PARAM, - &key, 1, values, length); + if (description == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_NOTIFICATION_DESCRIPTION, description, __FUNCTION__); } -int dp_interface_remove_noti_extra_key(const int id, const char *key) +int dp_interface_set_notification_type(const int id, int type) { - return __dp_interface_set_string - (id, DP_CMD_REMOVE_EXTRA_PARAM, key); + if (type == DP_NOTIFICATION_TYPE_NONE) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_TYPE, __FUNCTION__); + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_TYPE, type, __FUNCTION__); } -int dp_interface_set_notification_bundle(const int id, int type, bundle *b) +int dp_interface_get_notification_type(const int id, int *type) { - bundle_raw *r = NULL; - int len = 0; - int retval = -1; - retval = bundle_encode_raw(b, &r, &len); - if (retval == 0) - retval = __dp_interface_set_raw_bundle(id, DP_CMD_SET_NOTIFICATION_BUNDLE, type, r, len); - else { - bundle_free_encoded_rawdata(&r); + if (type == NULL) { + TRACE_ERROR("check buffer"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } - bundle_free_encoded_rawdata(&r); - return retval; + return __dp_ipc_get_int(id, DP_PROP_NOTIFICATION_TYPE, type, __FUNCTION__); +} + +int dp_interface_set_notification_bundle(const int id, const int type, void *bundle_param) +{ + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_BUNDLE_TYPE_ONGOING && + type != DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE && + type != DP_NOTIFICATION_BUNDLE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + if (bundle_param == NULL) { // unset + return __dp_ipc_set_int(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + } else { // set + int length = 0; + bundle_raw *raw_buffer = NULL; + int result = bundle_encode_raw(bundle_param, &raw_buffer, &length); + if (result == 0 && length > 0) { + errorcode = __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + errorcode = __dp_ipc_set_binary(id, DP_PROP_NOTIFICATION_RAW, raw_buffer, (size_t)length, __FUNCTION__); + } + } else { + TRACE_ERROR("failed to encode raws error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (raw_buffer != NULL) + bundle_free_encoded_rawdata(&raw_buffer); + } + return errorcode; } -int dp_interface_get_notification_bundle(const int id, int type, bundle **b) +int dp_interface_get_notification_bundle(const int id, const int type, void **bundle_param) { - bundle_raw *r = NULL; - int len = 0; - download_adaptor_error_e error = DOWNLOAD_ADAPTOR_ERROR_NONE; - - if (b == NULL) { - TRACE_ERROR("[CHECK bundle] (%d)", id); + if (bundle_param == NULL) { + TRACE_ERROR("check buffer"); return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; } + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_BUNDLE_TYPE_ONGOING && + type != DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE && + type != DP_NOTIFICATION_BUNDLE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + + // send type, get errorcode with extra_size, get bundle binary + + errorcode = DP_ERROR_NONE; - error = __dp_interface_get_raw_bundle(id, DP_CMD_GET_NOTIFICATION_BUNDLE, type, &r, &len); - if (error == DOWNLOAD_ADAPTOR_ERROR_NONE) { - *b = bundle_decode_raw(r, len); + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + const unsigned section = DP_SEC_GET; + const unsigned property = DP_PROP_NOTIFICATION_RAW; + size_t extra_size = 0; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void *)&type, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + } + } + if (errorcode == DP_ERROR_NONE && extra_size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(extra_size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, extra_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, extra_size); + } else { + if (dp_ipc_read(sock, recv_raws, extra_size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_raws); + } else { + TRACE_DEBUG("sock:%d length:%d raws", sock, extra_size); + *bundle_param = bundle_decode_raw(recv_raws, extra_size); + free(recv_raws); + } + } } - bundle_free_encoded_rawdata(&r); - return error; + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); } -int dp_interface_set_notification_title(const int id, const char *title) -{ - return __dp_interface_set_string(id, DP_CMD_SET_NOTIFICATION_TITLE, title); +int dp_interface_set_notification_service_handle(const int id, const int type, void *handle) +{ + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_SERVICE_TYPE_ONGOING && + type != DP_NOTIFICATION_SERVICE_TYPE_COMPLETE && + type != DP_NOTIFICATION_SERVICE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + if (handle == NULL) { // unset + return __dp_ipc_set_int(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + } else { // set + int length = 0; + bundle_raw *raw_buffer = NULL; + bundle *bundle_data = NULL; + int result = app_control_export_as_bundle((app_control_h) handle, &bundle_data); + if (result == APP_CONTROL_ERROR_NONE) { + result = bundle_encode_raw(bundle_data, &raw_buffer, &length); + if (result == 0 && length > 0) { + errorcode = __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + errorcode = __dp_ipc_set_binary(id, DP_PROP_NOTIFICATION_RAW, raw_buffer, (size_t)length, __FUNCTION__); + } + } else { + TRACE_ERROR("failed to encode raws error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + } else { + TRACE_ERROR("failed to encode service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (raw_buffer != NULL) + bundle_free_encoded_rawdata(&raw_buffer); + if (bundle_data != NULL) + bundle_free(bundle_data); + } + return errorcode; } -int dp_interface_get_notification_title(const int id, char **title) +int dp_interface_get_notification_service_handle(const int id, const int type, void **handle) { - return __dp_interface_get_string(id, DP_CMD_GET_NOTIFICATION_TITLE, title); + bundle *bundle_data = NULL; + if (handle == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_SERVICE_TYPE_ONGOING && + type != DP_NOTIFICATION_SERVICE_TYPE_COMPLETE && + type != DP_NOTIFICATION_SERVICE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + + // send type, get errorcode with extra_size, get bundle binary + + errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + const unsigned section = DP_SEC_GET; + const unsigned property = DP_PROP_NOTIFICATION_RAW; + size_t extra_size = 0; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void *)&type, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + } + } + if (errorcode == DP_ERROR_NONE && extra_size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(extra_size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, extra_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, extra_size); + } else { + if (dp_ipc_read(sock, recv_raws, extra_size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_raws); + } else { + TRACE_DEBUG("sock:%d length:%d raws", sock, extra_size); + + bundle_data = bundle_decode_raw(recv_raws, extra_size); + if (bundle_data) { + int result = 0; + result = app_control_create((app_control_h *)handle); + if (result == APP_CONTROL_ERROR_NONE) { + result = app_control_import_from_bundle((app_control_h)*handle, bundle_data); + if (result != APP_CONTROL_ERROR_NONE) { + TRACE_ERROR("failed to import service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + } else { + TRACE_ERROR("failed to create service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + bundle_free(bundle_data); + } + free(recv_raws); + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); } -int dp_interface_set_notification_description(const int id, const char *description) +int dp_interface_add_http_header_field(const int id, const char *field, + const char *value) { - return __dp_interface_set_string(id, DP_CMD_SET_NOTIFICATION_DESCRIPTION, description); + // cmd + field string + value string + // wait response + int errorcode = DP_ERROR_NONE; + size_t field_length = 0; + size_t value_length = 0; + if (field == NULL || (field_length = strlen(field)) <= 0 || + field_length > DP_MAX_STR_LEN) { + TRACE_ERROR("check field (%d:%s)", field_length, field); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (value == NULL || (value_length = strlen(value)) <= 0 || + value_length > DP_MAX_STR_LEN) { + TRACE_ERROR("check value (%d:%s)", value_length, value); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_SET; + unsigned property = DP_PROP_HTTP_HEADER; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, field_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)field, field_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + if (errorcode == DP_ERROR_NONE) { + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, value_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)value, value_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); } -int dp_interface_get_notification_description(const int id, char **description) +int dp_interface_get_http_header_field(const int id, const char *field, + char **value) { - return __dp_interface_get_string(id, DP_CMD_GET_NOTIFICATION_DESCRIPTION, description); + // cmd + field string + // wait response + value string + int errorcode = DP_ERROR_NONE; + size_t length = 0; + if (field == NULL || (length = strlen(field)) <= 0 || + length > DP_MAX_STR_LEN) { + TRACE_ERROR("check field (%d:%s)", length, field); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (value == NULL) { + TRACE_ERROR("check pointer for value"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_GET; + unsigned property = DP_PROP_HTTP_HEADER; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)field, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + size_t string_length = 0; + *value = NULL; + errorcode = __dp_ipc_response(sock, id, section, property, &string_length); + if (errorcode == DP_ERROR_NONE) { + if (string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, string_length); + } else { + if (dp_ipc_read(sock, recv_str, string_length, __FUNCTION__) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + *value = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); } -int dp_interface_set_notification_type(const int id, int type) +int dp_interface_get_http_header_field_list(const int id, char ***fields, + int *length) { - return __dp_interface_set_int(id, DP_CMD_SET_NOTIFICATION_TYPE, type); + // cmd + // wait response + // wait size + // wait strings + int errorcode = DP_ERROR_NONE; + if (fields == NULL) { + TRACE_ERROR("check pointer for fields"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (length == NULL) { + TRACE_ERROR("check pointer for length"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_GET; + unsigned property = DP_PROP_HTTP_HEADERS; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + + int array_size = 0; + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(int)) { + if (dp_ipc_read(sock, &array_size, extra_size, __FUNCTION__) < 0) { + errorcode = DP_ERROR_IO_ERROR; + } else { + if (array_size <= 0) { + errorcode = DP_ERROR_NO_DATA; + *length = 0; + } else { + int i = 0; + char **recv_strings = NULL; + recv_strings = (char **)calloc(array_size, sizeof(char *)); + if (recv_strings == NULL) { + TRACE_STRERROR("check memory size:%d", array_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + *length = 0; + } else { + // get strings. + for (; i < array_size; i++) { + size_t string_length = 0; + errorcode = __dp_ipc_response(sock, id, section, property, &string_length); + recv_strings[i] = NULL; + if (errorcode == DP_ERROR_NONE && string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length * sizeof(char)); + errorcode = DP_ERROR_OUT_OF_MEMORY; + break; + } else { + if (dp_ipc_read(sock, recv_str, string_length, __FUNCTION__) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + recv_strings[i] = recv_str; + } + } + } + } + *fields = recv_strings; + } + if (errorcode != DP_ERROR_NONE) { // if error, free all allocated memories + int j = 0; + for (; j < i; j++) { + free(recv_strings[j]); + } + free(recv_strings); + *length = 0; + *fields = NULL; + if (errorcode != DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); // clear IPC, can not expect the size of futher packets + } + *length = i; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + + + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); } -int dp_interface_get_notification_type(const int id, int *type) +int dp_interface_remove_http_header_field(const int id, + const char *field) { - return __dp_interface_get_int(id, DP_CMD_GET_NOTIFICATION_TYPE, type); + return __dp_ipc_set_string(id, DP_SEC_UNSET, DP_PROP_HTTP_HEADER, field, __FUNCTION__); } diff --git a/provider-interface/download-provider-interface.pc.in b/provider-interface/download-provider-interface.pc.in index b6e579c..35e1cc9 100644 --- a/provider-interface/download-provider-interface.pc.in +++ b/provider-interface/download-provider-interface.pc.in @@ -4,5 +4,5 @@ Name: @PROJECT_NAME@ Description: @PACKAGE_DESCRIPTION@ Version: @VERSION@ Requires: @PC_REQUIRED@ -Libs: -L@LIB_INSTALL_DIR@ -l@PROJECT_NAME@ +Libs: -L/usr/lib -l@PROJECT_NAME@ Cflags: -I/usr/include/@PKG_NAME@ diff --git a/provider-interface/include/download-provider-interface.h b/provider-interface/include/download-provider-interface.h index eb96e19..e9d3d59 100755 --- a/provider-interface/include/download-provider-interface.h +++ b/provider-interface/include/download-provider-interface.h @@ -22,7 +22,6 @@ #endif #include <tizen.h> -#include <bundle.h> #ifdef __cplusplus extern "C" @@ -58,25 +57,27 @@ typedef enum DOWNLOAD_ADAPTOR_ERROR_NETWORK_UNREACHABLE = TIZEN_ERROR_NETWORK_UNREACHABLE, /**< Network is unreachable */ DOWNLOAD_ADAPTOR_ERROR_CONNECTION_TIMED_OUT = TIZEN_ERROR_CONNECTION_TIME_OUT, /**< Http session time-out */ DOWNLOAD_ADAPTOR_ERROR_NO_SPACE = TIZEN_ERROR_FILE_NO_SPACE_ON_DEVICE, /**< No space left on device */ - DOWNLOAD_ADAPTOR_ERROR_FIELD_NOT_FOUND = TIZEN_ERROR_KEY_NOT_AVAILABLE, /**< Specified field not found */ DOWNLOAD_ADAPTOR_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */ - DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE = TIZEN_ERROR_WEB_CLASS | 0x21, /**< Invalid state */ - DOWNLOAD_ADAPTOR_ERROR_CONNECTION_FAILED = TIZEN_ERROR_WEB_CLASS | 0x22, /**< Connection failed */ - DOWNLOAD_ADAPTOR_ERROR_INVALID_URL = TIZEN_ERROR_WEB_CLASS | 0x24, /**< Invalid URL */ - DOWNLOAD_ADAPTOR_ERROR_INVALID_DESTINATION = TIZEN_ERROR_WEB_CLASS | 0x25, /**< Invalid destination */ - DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS = TIZEN_ERROR_WEB_CLASS | 0x26, /**< Full of available simultaneous downloads */ - DOWNLOAD_ADAPTOR_ERROR_QUEUE_FULL = TIZEN_ERROR_WEB_CLASS | 0x27, /**< Full of available downloading items from server*/ - DOWNLOAD_ADAPTOR_ERROR_ALREADY_COMPLETED = TIZEN_ERROR_WEB_CLASS | 0x28, /**< The download is already completed */ - DOWNLOAD_ADAPTOR_ERROR_FILE_ALREADY_EXISTS = TIZEN_ERROR_WEB_CLASS | 0x29, /**< It is failed to rename the downloaded file */ - DOWNLOAD_ADAPTOR_ERROR_CANNOT_RESUME = TIZEN_ERROR_WEB_CLASS | 0x2a, /**< It cannot resume */ - DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_REDIRECTS = TIZEN_ERROR_WEB_CLASS | 0x30, /**< In case of too may redirects from http response header*/ - DOWNLOAD_ADAPTOR_ERROR_UNHANDLED_HTTP_CODE = TIZEN_ERROR_WEB_CLASS | 0x31, /**< The download cannot handle the http status value */ - DOWNLOAD_ADAPTOR_ERROR_REQUEST_TIMEOUT = TIZEN_ERROR_WEB_CLASS | 0x32, /**< There are no action after client create a download id*/ - DOWNLOAD_ADAPTOR_ERROR_RESPONSE_TIMEOUT = TIZEN_ERROR_WEB_CLASS | 0x33, /**< It does not call start API in some time although the download is created*/ - DOWNLOAD_ADAPTOR_ERROR_SYSTEM_DOWN = TIZEN_ERROR_WEB_CLASS | 0x34, /**< There are no response from client after rebooting download daemon*/ - DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND = TIZEN_ERROR_WEB_CLASS | 0x35, /**< The download id is not existed in download service module*/ + DOWNLOAD_ADAPTOR_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE = TIZEN_ERROR_DOWNLOAD | 0x21, /**< Invalid state */ + DOWNLOAD_ADAPTOR_ERROR_CONNECTION_FAILED = TIZEN_ERROR_DOWNLOAD | 0x22, /**< Connection failed */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_URL = TIZEN_ERROR_DOWNLOAD | 0x24, /**< Invalid URL */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_DESTINATION = TIZEN_ERROR_DOWNLOAD | 0x25, /**< Invalid destination */ + DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS = TIZEN_ERROR_DOWNLOAD | 0x26, /**< Full of available simultaneous downloads */ + DOWNLOAD_ADAPTOR_ERROR_QUEUE_FULL = TIZEN_ERROR_DOWNLOAD | 0x27, /**< Full of available downloading items from server*/ + DOWNLOAD_ADAPTOR_ERROR_ALREADY_COMPLETED = TIZEN_ERROR_DOWNLOAD | 0x28, /**< The download is already completed */ + DOWNLOAD_ADAPTOR_ERROR_FILE_ALREADY_EXISTS = TIZEN_ERROR_DOWNLOAD | 0x29, /**< It is failed to rename the downloaded file */ + DOWNLOAD_ADAPTOR_ERROR_CANNOT_RESUME = TIZEN_ERROR_DOWNLOAD | 0x2a, /**< It cannot resume */ + DOWNLOAD_ADAPTOR_ERROR_FIELD_NOT_FOUND = TIZEN_ERROR_DOWNLOAD | 0x2b, /**< Specified field not found */ + DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_REDIRECTS = TIZEN_ERROR_DOWNLOAD | 0x30, /**< In case of too may redirects from http response header*/ + DOWNLOAD_ADAPTOR_ERROR_UNHANDLED_HTTP_CODE = TIZEN_ERROR_DOWNLOAD | 0x31, /**< The download cannot handle the http status value */ + DOWNLOAD_ADAPTOR_ERROR_REQUEST_TIMEOUT = TIZEN_ERROR_DOWNLOAD | 0x32, /**< There are no action after client create a download id*/ + DOWNLOAD_ADAPTOR_ERROR_RESPONSE_TIMEOUT = TIZEN_ERROR_DOWNLOAD | 0x33, /**< It does not call start API in some time although the download is created*/ + DOWNLOAD_ADAPTOR_ERROR_SYSTEM_DOWN = TIZEN_ERROR_DOWNLOAD | 0x34, /**< There are no response from client after rebooting download daemon*/ + DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND = TIZEN_ERROR_DOWNLOAD | 0x35, /**< The download id is not existed in download service module*/ + DOWNLOAD_ADAPTOR_ERROR_INVALID_NETWORK_TYPE = TIZEN_ERROR_DOWNLOAD | 0x36, /**< error when setting network bonding and network all is not set */ DOWNLOAD_ADAPTOR_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data because the set API is not called */ - DOWNLOAD_ADAPTOR_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR , /**< Internal I/O error */ + DOWNLOAD_ADAPTOR_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR /**< Internal I/O error */ } download_adaptor_error_e; // sync types with url-download.. @@ -98,40 +99,37 @@ EXPORT_API int dp_interface_pause(const int id); EXPORT_API int dp_interface_cancel(const int id); EXPORT_API int dp_interface_set_url(const int id, const char *url); -EXPORT_API int dp_interface_get_url(const int id, char **url); +EXPORT_API int dp_interface_set_destination(const int id, const char *path); +EXPORT_API int dp_interface_set_file_name(const int id, const char *file_name); EXPORT_API int dp_interface_set_network_type(const int id, int net_type); +EXPORT_API int dp_interface_set_network_bonding(const int id, int enable); +EXPORT_API int dp_interface_set_auto_download(const int id, int enable); +EXPORT_API int dp_interface_get_url(const int id, char **url); EXPORT_API int dp_interface_get_network_type(const int id, int *net_type); -EXPORT_API int dp_interface_set_destination(const int id, const char *path); +EXPORT_API int dp_interface_get_network_bonding(const int id, int *enable); EXPORT_API int dp_interface_get_destination(const int id, char **path); -EXPORT_API int dp_interface_set_file_name(const int id, const char *file_name); EXPORT_API int dp_interface_get_file_name(const int id, char **file_name); -EXPORT_API int dp_interface_set_notification(const int id, int enable); -EXPORT_API int dp_interface_get_notification(const int id, int *enable); -EXPORT_API int dp_interface_set_notification_extra_param(const int id, char *key, char *value); -EXPORT_API int dp_interface_get_notification_extra_param(const int id, char **key, char **value); EXPORT_API int dp_interface_get_downloaded_file_path(const int id, char **path); EXPORT_API int dp_interface_get_mime_type(const int id, char **mime_type); -EXPORT_API int dp_interface_set_auto_download(const int id, int enable); EXPORT_API int dp_interface_get_auto_download(const int id, int *enable); -EXPORT_API int dp_interface_add_http_header_field(const int id, const char *field, const char *value); -EXPORT_API int dp_interface_get_http_header_field(const int id, const char *field, char **value); -EXPORT_API int dp_interface_get_http_header_field_list(const int id, char ***fields, int *length); -EXPORT_API int dp_interface_remove_http_header_field(const int id, const char *field); EXPORT_API int dp_interface_get_state(const int id, int *state); EXPORT_API int dp_interface_get_temp_path(const int id, char **temp_path); EXPORT_API int dp_interface_get_content_name(const int id, char **content_name); EXPORT_API int dp_interface_get_content_size(const int id, unsigned long long *content_size); EXPORT_API int dp_interface_get_error(const int id, int *error); EXPORT_API int dp_interface_get_http_status(const int id, int *http_status); +EXPORT_API int dp_interface_get_etag(const int id, char **etag); +EXPORT_API int dp_interface_set_temp_file_path(const int id, const char *path); -// Notification Extra Param -// N values per a key -EXPORT_API int dp_interface_add_noti_extra(const int id, const char *key, const char **values, const unsigned length); -EXPORT_API int dp_interface_get_noti_extra_values(const int id, const char *key, char ***values, unsigned *length); -EXPORT_API int dp_interface_remove_noti_extra_key(const int id, const char *key); +EXPORT_API int dp_interface_add_http_header_field(const int id, const char *field, const char *value); +EXPORT_API int dp_interface_get_http_header_field(const int id, const char *field, char **value); +EXPORT_API int dp_interface_get_http_header_field_list(const int id, char ***fields, int *length); +EXPORT_API int dp_interface_remove_http_header_field(const int id, const char *field); -EXPORT_API int dp_interface_set_notification_bundle(const int id, int type, bundle *b); -EXPORT_API int dp_interface_get_notification_bundle(const int id, int type, bundle **b); +EXPORT_API int dp_interface_set_notification_bundle(const int id, const int type, void *bundle_param); +EXPORT_API int dp_interface_get_notification_bundle(const int id, const int type, void **bundle_param); +EXPORT_API int dp_interface_set_notification_service_handle(const int id, const int type, void *handle); +EXPORT_API int dp_interface_get_notification_service_handle(const int id, const int type, void **handle); EXPORT_API int dp_interface_set_notification_title(const int id, const char *title); EXPORT_API int dp_interface_get_notification_title(const int id, char **title); EXPORT_API int dp_interface_set_notification_description(const int id, const char *description); diff --git a/provider/CMakeLists.txt b/provider/CMakeLists.txt index be89a9d..0c59760 100755 --- a/provider/CMakeLists.txt +++ b/provider/CMakeLists.txt @@ -14,8 +14,7 @@ pkg_check_modules(dp2_pkgs REQUIRED glib-2.0 sqlite3 capi-appfw-app-manager capi-network-connection - wifi-direct - notification + capi-content-mime-type appsvc bundle libsmack @@ -26,6 +25,46 @@ FOREACH(flag ${dp2_pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) +IF(SUPPORT_WIFI_DIRECT) +MESSAGE("WIFI direct:On") +pkg_check_modules(dp2_wifi_direct_pkgs REQUIRED + capi-network-wifi-direct) +FOREACH(flag ${dp2_wifi_direct_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +ELSE (SUPPORT_WIFI_DIRECT) +MESSAGE("WIFI direct:Off") +ENDIF(SUPPORT_WIFI_DIRECT) + +IF(SUPPORT_SECURITY_PRIVILEGE) +pkg_check_modules(dp2_security_privilege_pkgs REQUIRED security-server) +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${dp2_security_privilege_pkgs_CFLAGS}") +ENDIF(SUPPORT_SECURITY_PRIVILEGE) + +IF(SUPPORT_NOTIFICATION) +MESSAGE("Notification:On") +pkg_check_modules(dp2_noti_pkgs REQUIRED + notification) +FOREACH(flag ${dp2_noti_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +ADD_DEFINITIONS(-DSUPPORT_NOTIFICATION) +ELSE (SUPPORT_NOTIFICATION) +MESSAGE("Notification:Off") +ENDIF(SUPPORT_NOTIFICATION) + +IF(SUPPORT_COMPANION_MODE) +MESSAGE("Companion:On") +pkg_check_modules(dp2_companion_pkgs REQUIRED + sap-client-stub-api) +FOREACH(flag ${dp2_companion_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +ADD_DEFINITIONS(-DSUPPORT_COMPANION_MODE) +ELSE (SUPPORT_COMPANION_MODE) +MESSAGE("Companion:Off") +ENDIF(SUPPORT_COMPANION_MODE) + ## INCLUDES INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/agent/include) @@ -38,37 +77,46 @@ set(DP2_LINK_LIBRARIES ${GLIB-2_LIBRARIES} SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -Wall") -IF(DEFINED DATABASE_FILE) - ADD_DEFINITIONS(-DDATABASE_FILE=\"${DATABASE_FILE}\") -ENDIF(DEFINED DATABASE_FILE) - -IF(DEFINED DATABASE_SCHEMA_FILE) - ADD_DEFINITIONS(-DDATABASE_SCHEMA_FILE=\"${DATABASE_SCHEMA_FILE}\") -ENDIF(DEFINED DATABASE_SCHEMA_FILE) - IF(DEFINED IMAGE_DIR) ADD_DEFINITIONS(-DIMAGE_DIR=\"${IMAGE_DIR}\") ENDIF(DEFINED IMAGE_DIR) +IF(DEFINED PROVIDER_DIR) + ADD_DEFINITIONS(-DPROVIDER_DIR=\"${PROVIDER_DIR}\") +ENDIF(DEFINED PROVIDER_DIR) + +IF(DEFINED DATABASE_CLIENT_DIR) + ADD_DEFINITIONS(-DDATABASE_CLIENT_DIR=\"${DATABASE_CLIENT_DIR}\") +ENDIF(DEFINED DATABASE_CLIENT_DIR) + +IF(DEFINED DATABASE_DIR) + ADD_DEFINITIONS(-DDATABASE_DIR=\"${DATABASE_DIR}\") +ENDIF(DEFINED DATABASE_DIR) + IF(DEFINED LOCALE_DIR) ADD_DEFINITIONS(-DPKG_NAME=\"${PKG_NAME}\") ADD_DEFINITIONS(-DLOCALE_DIR=\"${LOCALE_DIR}\") ENDIF(DEFINED LOCALE_DIR) +ADD_DEFINITIONS(-DDOWNLOAD_PROVIDER_LOG_TAG=\"DOWNLOAD_PROVIDER\") ADD_EXECUTABLE(${PROJECT_NAME} - ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-pid.c - ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-socket.c - ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-slots.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-pthread.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-ipc.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notify.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-smack.c ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-network.c ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-db.c - ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-request.c - ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-da-interface.c - ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-thread-request.c - ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-thread-queue.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-plugin-download-agent.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-queue.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-queue-manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-client.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-client-manager.c ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notification.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notification-manager.c ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-main.c ) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${dp2_pkgs_LDFLAGS} ${DP2_LINK_LIBRARIES} -ldl) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${dp2_pkgs_LDFLAGS} ${DP2_LINK_LIBRARIES} ${dp2_noti_pkgs_LDFLAGS} ${dp2_companion_pkgs_LDFLAGS} ${dp2_wifi_direct_pkgs_LDFLAGS} ${dp2_security_privilege_pkgs_LDFLAGS} -ldl) INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BIN_INSTALL_DIR}) -INSTALL(FILES include/download-provider-defs.h DESTINATION ${INCLUDE_INSTALL_DIR}/${PKG_NAME}) +INSTALL(FILES include/download-provider.h DESTINATION ${INCLUDE_INSTALL_DIR}/${PKG_NAME}) diff --git a/provider/download-provider-client-manager.c b/provider/download-provider-client-manager.c new file mode 100644 index 0000000..28ecaf3 --- /dev/null +++ b/provider/download-provider-client-manager.c @@ -0,0 +1,741 @@ +/* + * Copyright (c) 2013 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 <unistd.h> +#include <time.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <signal.h> + +#include <app_manager.h> +#include <systemd/sd-daemon.h> +#include <glib-object.h> + +#include <download-provider.h> +#include <download-provider-log.h> +#include <download-provider-config.h> +#include <download-provider-pthread.h> +#include <download-provider-smack.h> +#include <download-provider-client.h> +#include <download-provider-notification.h> +#include <download-provider-notification-manager.h> +#include <download-provider-utils.h> +#include <download-provider-ipc.h> +#include <download-provider-notify.h> +#include <download-provider-db-defs.h> +#include <download-provider-db.h> +#include <download-provider-queue-manager.h> +#include <download-provider-client-manager.h> +#include <download-provider-plugin-download-agent.h> +#include <download-provider-network.h> + +int g_dp_sock = -1; +dp_client_slots_fmt *g_dp_client_slots = NULL; +static void *g_db_handle = 0; +static pthread_mutex_t g_db_mutex = PTHREAD_MUTEX_INITIALIZER; + +void dp_terminate(int signo) +{ + TRACE_DEBUG("Received SIGTERM:%d", signo); + close(g_dp_sock); + g_dp_sock = -1; +} + +void dp_broadcast_signal() +{ + TRACE_INFO("broadcast"); + // announce to all thread for clients + // signo 10 : ip changed + if (g_dp_client_slots != NULL) { + int i = 0; + for (; i < DP_MAX_CLIENTS; i++) { + if (g_dp_client_slots[i].thread > 0 && + pthread_kill(g_dp_client_slots[i].thread, 0) != ESRCH) + pthread_kill(g_dp_client_slots[i].thread, SIGUSR1); + } + } + +} + +char *dp_db_get_client_smack_label(const char *pkgname) +{ + char *smack_label = NULL; + unsigned length = 0; + int errorcode = DP_ERROR_NONE; + + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_get_client_property_string(g_db_handle, pkgname, DP_DB_COL_SMACK_LABEL, (unsigned char **)&smack_label, &length, &errorcode) < 0) { + TRACE_SECURE_ERROR("failed to get smack label for %s", pkgname); + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + + return smack_label; +} + +static int __dp_db_open_client_manager() +{ + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_open_client_manager(&g_db_handle) < 0) { + TRACE_ERROR("[CRITICAL] can not open SQL"); + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + return -1; + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + return 0; +} + +static void __dp_db_free_client_manager() +{ + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (g_db_handle != 0) { + TRACE_SECURE_DEBUG("TRY to close [%s]", DP_DBFILE_CLIENTS); + dp_db_close(g_db_handle); + g_db_handle = 0; + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); +} + +static int __dp_accept_socket_new() +{ + int fd_base, listen_fds = sd_listen_fds(1); + TRACE_DEBUG("sd_listen_fds:%d", listen_fds); + for (fd_base = 0 ; fd_base < listen_fds; fd_base++) { + if (sd_is_socket_unix(fd_base + SD_LISTEN_FDS_START, SOCK_STREAM, 1, IPC_SOCKET, 0) >= 0) { + TRACE_INFO("listen systemd socket:%d", fd_base + SD_LISTEN_FDS_START); + return fd_base + SD_LISTEN_FDS_START; + } + } + return -1; +} + +int dp_client_slot_free(dp_client_slots_fmt *slot) +{ + if (slot->client.channel >= 0) { + close(slot->client.channel); + slot->client.channel = -1; + } + if (slot->client.dbhandle != 0) { + dp_db_close(slot->client.dbhandle); + slot->client.dbhandle = 0; + } + // free all requests + // remove notify fifo + if (slot->client.notify >= 0) { + close(slot->client.notify); + slot->client.notify = -1; + } + dp_notify_deinit(slot->credential.pid); + // kill thread + if (slot->thread != 0) + pthread_cancel(slot->thread); + slot->thread = 0; + if (slot->pkgname != NULL) { + TRACE_SECURE_DEBUG("TRY to close [%s]", slot->pkgname); + free(slot->pkgname); + slot->pkgname = NULL; + } + return 0; +} + +// precondition : all slots are empty +static int __dp_manage_client_requests(dp_client_slots_fmt *clients) +{ + int errorcode = DP_ERROR_NONE; + int i = 0; + int slot_index = 0; + + dp_notification_manager_kill(); + dp_queue_manager_kill(); + + // get all clients info from clients database. + + int *ids = (int *)calloc(DP_MAX_CLIENTS, sizeof(int)); + if (ids == NULL) { + TRACE_ERROR("failed to allocate the clients"); + return -1; + } + // getting ids of clients + int rows_count = dp_db_get_ids(g_db_handle, DP_TABLE_CLIENTS, NULL, ids, NULL, DP_MAX_CLIENTS, DP_DB_COL_ACCESS_TIME, "ASC", &errorcode); + for (; i < rows_count; i++) { + char *pkgname = NULL; + unsigned length = 0; + errorcode = DP_ERROR_NONE; + if (dp_db_get_property_string(g_db_handle, ids[i], DP_TABLE_CLIENTS, DP_DB_COL_PACKAGE, (unsigned char **)&pkgname, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get pkgname for id:%d", ids[i]); + continue; + } + + if (pkgname != NULL) { + if (dp_db_remove_database(pkgname, time(NULL), DP_CARE_CLIENT_INFO_PERIOD * 3600) == 0) { // old database + // remove info from client database; + if (dp_db_delete(g_db_handle, ids[i], DP_TABLE_CLIENTS, &errorcode) == 0) { + TRACE_SECURE_ERROR("clear info for %s", pkgname); + // remove database file + } + TRACE_SECURE_INFO("remove database for %s", pkgname); + free(pkgname); + continue; + } + + dp_credential credential; + credential.pid = 0; + if (dp_db_get_property_int(g_db_handle, ids[i], DP_TABLE_CLIENTS, DP_DB_COL_UID, &credential.uid, &errorcode) < 0 || + dp_db_get_property_int(g_db_handle, ids[i], DP_TABLE_CLIENTS, DP_DB_COL_GID, &credential.gid, &errorcode) < 0) { + TRACE_SECURE_ERROR("failed to get credential for %s", pkgname); + free(pkgname); + continue; + } + if (dp_mutex_init(&clients[slot_index].mutex, NULL) != 0) { + TRACE_SECURE_ERROR("failed to initialize mutex for %s", pkgname); + free(pkgname); + continue; + } + // open database of a clients + if (dp_db_open_client_v2(&clients[slot_index].client.dbhandle, pkgname) < 0) { + TRACE_SECURE_ERROR("failed to open database for %s", pkgname); + // remove this client from clients database + if (dp_db_delete(g_db_handle, ids[i], DP_TABLE_CLIENTS, &errorcode) == 0) { + TRACE_SECURE_ERROR("clear info for %s", pkgname); + // remove database file + if (dp_db_remove_database(pkgname, time(NULL), 0) == 0) { + TRACE_SECURE_INFO("remove database for %s", pkgname); + } else { + TRACE_SECURE_ERROR("failed to remove database for %s", pkgname); + } + } + free(pkgname); + continue; + } + + // get ids if state is QUEUED, CONNECTING or DOWNLOADING with auto_download + int *request_ids = (int *)calloc(DP_MAX_REQUEST, sizeof(int)); + if (request_ids == NULL) { + TRACE_SECURE_ERROR("failed to allocate the requests for %s", pkgname); + free(pkgname); + continue; + } + int request_count = dp_db_get_crashed_ids(clients[slot_index].client.dbhandle, DP_TABLE_LOGGING, request_ids, DP_MAX_REQUEST, &errorcode); + TRACE_DEBUG("client: %s requests:%d", pkgname, request_count); + int ids_i = 0; + if (request_count > 0) { + clients[slot_index].pkgname = pkgname; + clients[slot_index].client.channel = -1; + clients[slot_index].client.notify = -1; + clients[slot_index].credential.pid = credential.pid; + clients[slot_index].credential.uid = credential.uid; + clients[slot_index].credential.gid = credential.gid; + for (ids_i = 0; ids_i < request_count; ids_i++) { + // loading requests from client's database... attach to client.requests + dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt)); + if (request == NULL) { + TRACE_ERROR("check memory download-id:%d", request_ids[ids_i]); + break; + } + request->id = request_ids[ids_i]; + request->agent_id = -1; + request->state = DP_STATE_QUEUED; + request->error = DP_ERROR_NONE; + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, &request->network_type, &errorcode) < 0) { + TRACE_ERROR("failed to get network type for id:%d", request->id); + request->network_type = DP_NETWORK_WIFI; + } + request->access_time = (int)time(NULL); + request->state_cb = 0; + request->progress_cb = 0; + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_LOGGING, DP_DB_COL_STARTCOUNT, &request->startcount, &errorcode) < 0) { + TRACE_ERROR("failed to get start count for id:%d", request->id); + request->startcount = 0; + } + request->startcount++; + request->noti_type = DP_NOTIFICATION_TYPE_NONE; + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, &request->noti_type, &errorcode) < 0) { + TRACE_ERROR("failed to get notification type for id:%d", request->id); + } + if (request->noti_type == DP_NOTIFICATION_TYPE_NONE) { + TRACE_INFO("enable notification for id:%d", request->id); + request->noti_type = DP_NOTIFICATION_TYPE_COMPLETE_ONLY; + } + request->progress_lasttime = 0; + request->received_size = 0; // ? + request->content_type = DP_CONTENT_UNKNOWN; + request->file_size = 0; // ? + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, &request->noti_priv_id, &errorcode) < 0) { + TRACE_ERROR("failed to get notification noti_priv_id for id:%d", request->id); + request->noti_priv_id = -1; + } + + dp_request_create(&clients[slot_index].client, request); + + if (dp_db_update_logging(clients[slot_index].client.dbhandle, request->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log download-id:%d", request->id); + errorcode = DP_ERROR_DISK_BUSY; + break; + } + if (dp_queue_manager_push_queue((void *)&clients[slot_index], (void *)request) < 0) { + errorcode = DP_ERROR_QUEUE_FULL; + TRACE_INFO("failed to push to queue for id:%d", request->id); + dp_request_destroy(&(clients[slot_index].client), NULL, request); + break; + } + // notification + if (dp_notification_manager_push_notification((void *)&clients[slot_index], (void *)request, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + + } + + slot_index++; + + } else { + free(pkgname); + } + free(request_ids); + } + } + free(ids); + TRACE_DEBUG("slot_index:%d", slot_index); + if (slot_index > 0) + dp_queue_manager_wake_up(); + return slot_index; +} + +static int __dp_client_run(int clientfd, dp_client_slots_fmt *slot, + dp_credential credential) +{ + int errorcode = DP_ERROR_NONE; + // make notify fifo + slot->client.notify = dp_notify_init(credential.pid); + if (slot->client.notify < 0) { + TRACE_STRERROR("failed to open fifo slot:%d", clientfd); + errorcode = DP_ERROR_IO_ERROR; + } else { + char *smack_label = NULL; + if (dp_smack_is_mounted() == 1) { + smack_label = dp_smack_get_label_from_socket(clientfd); + if (smack_label == NULL) { + TRACE_SECURE_ERROR("smack_new_label_from_socket"); + } + } + // save client info to database + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_update_client_info(g_db_handle, + slot->pkgname, smack_label, + credential.uid, credential.gid, &errorcode) < 0) { + TRACE_ERROR("check error:%s", dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + free(smack_label); + } + if (errorcode == DP_ERROR_NONE) { + + // create a thread for client + if (pthread_create(&slot->thread, NULL, + dp_client_request_thread, (void *)slot) != 0) { + TRACE_ERROR("failed to create client thread slot:%d", clientfd); + errorcode = DP_ERROR_OUT_OF_MEMORY; + slot->thread = 0; + dp_client_slot_free(slot); // => make pkgname as NULL + } else { + pthread_detach(slot->thread); + TRACE_SECURE_INFO("accept client[%s] pid:%d sock:%d", + slot->pkgname, credential.pid, clientfd); + slot->client.channel = clientfd; + slot->credential.pid = credential.pid; + slot->credential.uid = credential.uid; + slot->credential.gid = credential.gid; + } + } + return errorcode; +} + + +static int __dp_client_new(int clientfd, dp_client_slots_fmt *clients, + dp_credential credential) +{ + // search in clients list. + // if same pkgname. update it. + // search same pkg or pid in clients + int errorcode = DP_ERROR_NONE; + int i = 0; + int pkg_len = 0; + char *pkgname = NULL; + + // getting the package name via pid + if (app_manager_get_package(credential.pid, &pkgname) != + APP_MANAGER_ERROR_NONE) + TRACE_ERROR("[CRITICAL] app_manager_get_package"); + + //// TEST CODE ... to allow sample client ( no package name ). + if (pkgname == NULL) { + //pkgname = dp_strdup("unknown_app"); + char *temp_pkgname = (char *)calloc(41, sizeof(char)); + if (temp_pkgname == NULL || + snprintf(temp_pkgname, 41,"unknown_app_%d", credential.pid) < 0) { + pkgname = dp_strdup("unknown_app"); + } else { + pkgname = temp_pkgname; + } + } + + if (pkgname == NULL) { + TRACE_ERROR("[CRITICAL] app_manager_get_package"); + return DP_ERROR_INVALID_PARAMETER; + } + if ((pkg_len = strlen(pkgname)) <= 0) { + TRACE_ERROR("[CRITICAL] pkgname:%s", pkgname); + free(pkgname); + return DP_ERROR_INVALID_PARAMETER; + } + +#ifdef SUPPORT_SECURITY_PRIVILEGE + int result = security_server_check_privilege_by_sockfd(clientfd, SECURITY_PRIVILEGE_INTERNET, "w"); + if (result != SECURITY_SERVER_API_SUCCESS) { + TRACE_ERROR("check privilege permission:%d", result); + return DP_ERROR_PERMISSION_DENIED; + } +#endif + + // EINVAL: empty slot + // EBUSY : occupied slot + // locked & thread == 0 : downloading without client <= check target + // thread == 0, requests == NULL : clear target + + // Have this client ever been connected before ? + for (i = 0; i < DP_MAX_CLIENTS; i++) { + + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked != 0) { // empty or used by other thread. it would be same client, but it's busy + continue; + } + TRACE_DEBUG("locked slot:%d", i); + if (locked == 0 && clients[i].thread == 0) { // this slot has run without the client + if (clients[i].pkgname != NULL) { + // check package name. + TRACE_DEBUG("check client[%s] slot:%d", clients[i].pkgname, i); + int cname_len = strlen(clients[i].pkgname); + if (pkg_len == cname_len && + strncmp(clients[i].pkgname, pkgname, pkg_len) == 0) { + TRACE_SECURE_INFO("update client[%s] slot:%d pid:%d sock:%d", + pkgname, i, credential.pid, clientfd); + if (clients[i].client.channel >= 0 && + clients[i].client.channel != clientfd) { + dp_ipc_socket_free(clients[i].client.channel); + if (clients[i].client.notify >= 0) + close(clients[i].client.notify); + dp_notify_deinit(clients[i].credential.pid); + } + errorcode = __dp_client_run(clientfd, &clients[i], credential); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + if (errorcode != DP_ERROR_NONE) + dp_mutex_destroy(&clients[i].mutex); + free(pkgname); + return errorcode; + } + } + if (clients[i].client.requests == NULL) { // clear + dp_client_slot_free(&clients[i]); + dp_mutex_destroy(&clients[i].mutex); + continue; + } + } + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + } + + TRACE_DEBUG("search empty client[%s] slot:%d", pkgname, i); + // search empty slot + for (i = 0; i < DP_MAX_CLIENTS; i++) { + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked == EINVAL) { + if (dp_mutex_init(&clients[i].mutex, NULL) == 0) { + CLIENT_MUTEX_LOCK(&clients[i].mutex); + TRACE_DEBUG("found empty client[%s] slot:%d", pkgname, i); + clients[i].pkgname = pkgname; + clients[i].client.dbhandle = 0; + clients[i].client.requests = NULL; + errorcode = __dp_client_run(clientfd, &clients[i], credential); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + if (errorcode != DP_ERROR_NONE) + dp_mutex_destroy(&clients[i].mutex); + return errorcode; + } + } + if (locked == 0) + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + } + + TRACE_SECURE_INFO("busy client[%s] pid:%d sock:%d", pkgname, + credential.pid, clientfd); + free(pkgname); + return DP_ERROR_TOO_MANY_DOWNLOADS; +} + +void *dp_client_manager(void *arg) +{ + fd_set rset, eset, listen_fdset, except_fdset; + struct timeval timeout; // for timeout of select + socklen_t clientlen; + struct sockaddr_un clientaddr; + dp_credential credential; + unsigned i; + int errorcode = DP_ERROR_NONE; + GMainLoop *event_loop = (GMainLoop *)arg; + + g_dp_sock = __dp_accept_socket_new(); + if (g_dp_sock < 0) { + TRACE_STRERROR("failed to open listen socket"); + g_main_loop_quit(event_loop); + return 0; + } + + if (signal(SIGTERM, dp_terminate) == SIG_ERR || + signal(SIGPIPE, SIG_IGN) == SIG_ERR || + signal(SIGINT, dp_terminate) == SIG_ERR) { + TRACE_ERROR("failed to register signal callback"); + g_main_loop_quit(event_loop); + return 0; + } + + dp_notification_clear_ongoings(); + +#ifdef PROVIDER_DIR + dp_rebuild_dir(PROVIDER_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); +#endif +#ifdef DATABASE_DIR + dp_rebuild_dir(DATABASE_DIR, S_IRWXU); +#endif +#ifdef DATABASE_CLIENT_DIR + dp_rebuild_dir(DATABASE_CLIENT_DIR, S_IRWXU); +#endif +#ifdef NOTIFY_DIR + dp_rebuild_dir(NOTIFY_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); +#endif + + if (__dp_db_open_client_manager() < 0) { + TRACE_STRERROR("failed to open database for client-manager"); + g_main_loop_quit(event_loop); + return 0; + } + + dp_client_slots_fmt *clients = + (dp_client_slots_fmt *)calloc(DP_MAX_CLIENTS, + sizeof(dp_client_slots_fmt)); + if (clients == NULL) { + TRACE_ERROR("failed to allocate client slots"); + g_main_loop_quit(event_loop); + return 0; + } + g_dp_client_slots = clients; + for (i = 0; i < DP_MAX_CLIENTS; i++) { + dp_mutex_destroy(&clients[i].mutex); // clear mutex init + } + + int maxfd = g_dp_sock; + FD_ZERO(&listen_fdset); + FD_ZERO(&except_fdset); + FD_SET(g_dp_sock, &listen_fdset); + FD_SET(g_dp_sock, &except_fdset); + + while (g_dp_sock >= 0) { + + int clientfd = -1; + + // initialize timeout structure for calling timeout exactly + memset(&timeout, 0x00, sizeof(struct timeval)); + timeout.tv_sec = DP_CARE_CLIENT_MANAGER_INTERVAL; + credential.pid = -1; + credential.uid = -1; + credential.gid = -1; + + rset = listen_fdset; + eset = except_fdset; + + if (select((maxfd + 1), &rset, 0, &eset, &timeout) < 0) { + TRACE_STRERROR("interrupted by terminating"); + break; + } + + if (g_dp_sock < 0) { + TRACE_DEBUG("queue-manager is closed by other thread"); + break; + } + + if (FD_ISSET(g_dp_sock, &eset) > 0) { + TRACE_STRERROR("exception of socket"); + break; + } else if (FD_ISSET(g_dp_sock, &rset) > 0) { + + // Anyway accept client. + clientlen = sizeof(clientaddr); + clientfd = accept(g_dp_sock, (struct sockaddr *)&clientaddr, + &clientlen); + if (clientfd < 0) { + TRACE_STRERROR("too many client ? accept failure"); + // provider need the time of refresh. + break; + } + + // blocking & timeout to prevent the lockup by client. + struct timeval tv_timeo = {1, 500000}; // 1.5 sec + if (setsockopt(clientfd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, + sizeof(tv_timeo)) < 0) { + TRACE_ERROR("failed to set timeout in blocking socket"); + close(clientfd); + continue; + } + + dp_ipc_fmt ipc_info; + memset(&ipc_info, 0x00, sizeof(dp_ipc_fmt)); + if (read(clientfd, &ipc_info, sizeof(dp_ipc_fmt)) <= 0 || + ipc_info.section == DP_SEC_NONE || + ipc_info.property != DP_PROP_NONE || + ipc_info.id != -1 || + ipc_info.size != 0) { + TRACE_ERROR("peer terminate ? ignore this connection"); + close(clientfd); + continue; + } + +#ifdef SO_PEERCRED // getting the info of client + socklen_t cr_len = sizeof(credential); + if (getsockopt(clientfd, SOL_SOCKET, SO_PEERCRED, + &credential, &cr_len) < 0) { + TRACE_ERROR("failed to cred from sock:%d", clientfd); + close(clientfd); + continue; + } +#else // In case of not supported SO_PEERCRED + if (read(clientfd, &credential, sizeof(dp_credential)) <= 0) { + TRACE_ERROR("failed to cred from client:%d", clientfd); + close(clientfd); + continue; + } +#endif + + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_check_connection(g_db_handle) < 0) { + TRACE_ERROR("check database, provider can't work anymore"); + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + close(clientfd); + break; + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + + if (ipc_info.section == DP_SEC_INIT) { + + // new client + errorcode = __dp_client_new(clientfd, clients, credential); + + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + } + if (dp_ipc_query(clientfd, -1, DP_SEC_INIT, DP_PROP_NONE, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", clientfd); + } + if (errorcode == DP_ERROR_NONE) { + // write client info into database + + } else { + TRACE_ERROR("sock:%d id:%d section:%s property:%s errorcode:%s size:%d", + clientfd, ipc_info.id, + dp_print_section(ipc_info.section), + dp_print_property(ipc_info.property), + dp_print_errorcode(ipc_info.errorcode), + ipc_info.size); + close(clientfd); // ban this client + } + + } else { + + // take care zombie client, slots + unsigned connected_clients = 0; + int i = 0; + for (; i < DP_MAX_CLIENTS; i++) { + + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked == EINVAL) { // not initialized + continue; + } else if (locked == EBUSY) { // already locked + connected_clients++; + continue; + } + + if (locked == 0) { // locked + + // if no client thread, requests should be checked here + // if no queued, connecting or downloading, close the slot + if (clients[i].pkgname != NULL) { + if (clients[i].thread == 0) { + dp_client_clear_requests(&clients[i]); + if (clients[i].client.requests == NULL) { + dp_client_slot_free(&clients[i]); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + dp_mutex_destroy(&clients[i].mutex); + continue; + } + } + connected_clients++; + } + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + } + } + TRACE_DEBUG("%d clients are active now", connected_clients); + // terminating download-provider if no clients. + if (connected_clients == 0) { + if (__dp_manage_client_requests(clients) <= 0) // if no crashed job + break; + } else { + dp_queue_manager_wake_up(); + dp_notification_manager_wake_up(); + } + } + + } + if (g_dp_sock >= 0) + close(g_dp_sock); + g_dp_sock = -1; + + dp_queue_manager_kill(); + dp_notification_clear_ongoings(); + dp_notification_manager_kill(); + + __dp_db_free_client_manager(); + + // kill other clients + TRACE_DEBUG("try to deallocate the resources for all clients"); + for (i = 0; i < DP_MAX_CLIENTS; i++) { + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked == EBUSY) { // already locked + CLIENT_MUTEX_LOCK(&clients[i].mutex); + } else if (locked == EINVAL) { // not initialized, empty slot + continue; + } + dp_client_slot_free(&clients[i]); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + dp_mutex_destroy(&clients[i].mutex); + } + free(clients); + // free all resources + + TRACE_INFO("client-manager's working is done"); + g_main_loop_quit(event_loop); + return 0; +} diff --git a/provider/download-provider-client.c b/provider/download-provider-client.c new file mode 100644 index 0000000..53c5909 --- /dev/null +++ b/provider/download-provider-client.c @@ -0,0 +1,2110 @@ +/* + * Copyright (c) 2013 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 <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <signal.h> + +#include <download-provider-log.h> +#include <download-provider-config.h> +#include <download-provider-ipc.h> +#include <download-provider-network.h> +#include <download-provider-client.h> +#include <download-provider-pthread.h> +#include <download-provider-notify.h> +#include <download-provider-notification-manager.h> +#include <download-provider-queue-manager.h> +#include <download-provider-client-manager.h> +#include <download-provider-db-defs.h> +#include <download-provider-db.h> +#include <download-provider-plugin-download-agent.h> +#include <download-provider-smack.h> + +char *dp_print_state(int state) +{ + switch(state) + { + case DP_STATE_NONE : + return "NONE"; + case DP_STATE_READY : + return "READY"; + case DP_STATE_QUEUED : + return "QUEUED"; + case DP_STATE_CONNECTING : + return "CONNECTING"; + case DP_STATE_DOWNLOADING : + return "DOWNLOADING"; + case DP_STATE_PAUSED : + return "PAUSED"; + case DP_STATE_COMPLETED : + return "COMPLETED"; + case DP_STATE_CANCELED : + return "CANCELED"; + case DP_STATE_FAILED : + return "FAILED"; + default : + break; + } + return "UNKNOWN"; +} + +char *dp_print_errorcode(int errorcode) +{ + switch(errorcode) + { + case DP_ERROR_NONE : + return "NONE"; + case DP_ERROR_INVALID_PARAMETER : + return "INVALID_PARAMETER"; + case DP_ERROR_OUT_OF_MEMORY : + return "OUT_OF_MEMORY"; + case DP_ERROR_IO_ERROR : + return "IO_ERROR"; + case DP_ERROR_NETWORK_UNREACHABLE : + return "NETWORK_UNREACHABLE"; + case DP_ERROR_CONNECTION_TIMED_OUT : + return "CONNECTION_TIMED_OUT"; + case DP_ERROR_NO_SPACE : + return "NO_SPACE"; + case DP_ERROR_FIELD_NOT_FOUND : + return "FIELD_NOT_FOUND"; + case DP_ERROR_INVALID_STATE : + return "INVALID_STATE"; + case DP_ERROR_CONNECTION_FAILED : + return "CONNECTION_FAILED"; + case DP_ERROR_INVALID_URL : + return "INVALID_URL"; + case DP_ERROR_INVALID_DESTINATION : + return "INVALID_DESTINATION"; + case DP_ERROR_QUEUE_FULL : + return "QUEUE_FULL"; + case DP_ERROR_ALREADY_COMPLETED : + return "ALREADY_COMPLETED"; + case DP_ERROR_FILE_ALREADY_EXISTS : + return "FILE_ALREADY_EXISTS"; + case DP_ERROR_TOO_MANY_DOWNLOADS : + return "TOO_MANY_DOWNLOADS"; + case DP_ERROR_NO_DATA : + return "NO_DATA"; + case DP_ERROR_UNHANDLED_HTTP_CODE : + return "UNHANDLED_HTTP_CODE"; + case DP_ERROR_CANNOT_RESUME : + return "CANNOT_RESUME"; + case DP_ERROR_PERMISSION_DENIED : + return "PERMISSION_DENIED"; + case DP_ERROR_RESPONSE_TIMEOUT : + return "RESPONSE_TIMEOUT"; + case DP_ERROR_REQUEST_TIMEOUT : + return "REQUEST_TIMEOUT"; + case DP_ERROR_SYSTEM_DOWN : + return "SYSTEM_DOWN"; + case DP_ERROR_CLIENT_DOWN : + return "CLIENT_DOWN"; + case DP_ERROR_DISK_BUSY: + return "DISK_BUSY"; + case DP_ERROR_ID_NOT_FOUND : + return "ID_NOT_FOUND"; + default : + break; + } + return "UNKNOWN"; +} + +char *dp_print_section(short section) +{ + switch (section) { + case DP_SEC_NONE: + return "NONE"; + case DP_SEC_INIT: + return "INIT"; + case DP_SEC_DEINIT: + return "DEINIT"; + case DP_SEC_CONTROL: + return "CONTROL"; + case DP_SEC_GET: + return "GET"; + case DP_SEC_SET: + return "SET"; + case DP_SEC_UNSET: + return "UNSET"; + default: + break; + } + return "UNKNOWN"; +} + +char *dp_print_property(unsigned property) +{ + switch (property) { + case DP_PROP_NONE: + return "NONE"; + case DP_PROP_CREATE: + return "CREATE"; + case DP_PROP_START: + return "START"; + case DP_PROP_PAUSE: + return "PAUSE"; + case DP_PROP_CANCEL: + return "CANCEL"; + case DP_PROP_DESTROY: + return "DESTROY"; + case DP_PROP_URL: + return "URL"; + case DP_PROP_DESTINATION: + return "DESTINATION"; + case DP_PROP_FILENAME: + return "FILENAME"; + case DP_PROP_STATE_CALLBACK: + return "STATE_CB"; + case DP_PROP_PROGRESS_CALLBACK: + return "PROGRESS_CB"; + case DP_PROP_AUTO_DOWNLOAD: + return "AUTO_DOWNLOAD"; + case DP_PROP_NETWORK_TYPE: + return "NETWORK_TYPE"; + case DP_PROP_NETWORK_BONDING: + return "NETWORK_BONDING"; + case DP_PROP_SAVED_PATH: + return "SAVED_PATH"; + case DP_PROP_TEMP_SAVED_PATH: + return "TEMP_SAVED_PATH"; + case DP_PROP_MIME_TYPE: + return "MIME_TYPE"; + case DP_PROP_RECEIVED_SIZE: + return "RECEIVED_SIZE"; + case DP_PROP_TOTAL_FILE_SIZE: + return "TOTAL_FILE_SIZE"; + case DP_PROP_CONTENT_NAME: + return "CONTENT_NAME"; + case DP_PROP_HTTP_STATUS: + return "HTTP_STATUS"; + case DP_PROP_ETAG: + return "ETAG"; + case DP_PROP_STATE: + return "STATE"; + case DP_PROP_ERROR: + return "ERROR"; + case DP_PROP_NOTIFICATION_RAW: + return "NOTIFICATION_RAW"; + case DP_PROP_NOTIFICATION_SUBJECT: + return "NOTIFICATION_SUBJECT"; + case DP_PROP_NOTIFICATION_DESCRIPTION: + return "NOTIFICATION_DESCRIPTION"; + case DP_PROP_NOTIFICATION_TYPE: + return "NOTIFICATION_TYPE"; + case DP_PROP_HTTP_HEADERS: + return "HTTP_HEADERS"; + case DP_PROP_HTTP_HEADER: + return "HTTP_HEADER"; + default: + break; + } + return "UNKNOWN"; +} + +static int __dp_get_download_id(dp_client_fmt *client) +{ + int download_id = -1; + static int last_download_id = 0; + int check_duplicate = 0; + int errorcode = DP_ERROR_NONE; + + do { + do { + struct timeval tval; + int cipher = 1; + int c = 0; + + download_id = -1; + gettimeofday(&tval, NULL); + + int usec = tval.tv_usec; + for (c = 0; ; c++, cipher++) { + if ((usec /= 10) <= 0) + break; + } + if (tval.tv_usec == 0) + tval.tv_usec = (tval.tv_sec & 0x0fff); + int disit_unit = 10; + for (c = 0; c < cipher - 3; c++) + disit_unit = disit_unit * 10; + download_id = tval.tv_sec + ((tval.tv_usec << 2) * 100) + + ((tval.tv_usec >> (cipher - 1)) * disit_unit) + + ((tval.tv_usec + (tval.tv_usec % 10)) & 0x0fff); + } while (last_download_id == download_id); + last_download_id = download_id; + check_duplicate = dp_db_check_duplicated_int(client->dbhandle, + DP_TABLE_LOGGING, DP_DB_COL_ID, download_id, &errorcode); + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("ERROR [%d]", errorcode); + } + } while (check_duplicate != 0); // means duplicated id + return download_id; +} + +void dp_request_create(dp_client_fmt *client, dp_request_fmt *request) +{ + // new request + // find the tail of linked list & check limitation + int i = 0; + dp_request_fmt *tailp = client->requests; + dp_request_fmt *prevp = NULL; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (tailp == NULL) + break; + TRACE_DEBUG("link %d info: id:%d access-time:%d", i, tailp->id, tailp->access_time); + prevp = tailp; + tailp = tailp->next; + } + request->next = NULL; + if (prevp == NULL) // it's first link + client->requests = request; + else + prevp->next = request; // attach at the tail + + TRACE_DEBUG("sock:%d download-id:%d", client->channel, request->id); +} + +static int __dp_request_create(dp_client_fmt *client, dp_ipc_fmt *ipc_info) +{ + int errorcode = DP_ERROR_NONE; + + int download_id = __dp_get_download_id(client); + + // allocation new request. + dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt)); + if (request == NULL) { + TRACE_ERROR("check memory sock:%d download-id:%d", client->channel, download_id); + return DP_ERROR_OUT_OF_MEMORY; + } + + if (dp_db_new_logging(client->dbhandle, download_id, DP_STATE_READY, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("new log sock:%d download-id:%d", client->channel, download_id); + free(request); + return DP_ERROR_DISK_BUSY; + } + + request->id = download_id; + request->agent_id = -1; + request->state = DP_STATE_READY; + request->error = DP_ERROR_NONE; + request->network_type = DP_NETWORK_ALL; + request->access_time = (int)time(NULL); + request->state_cb = 0; + request->progress_cb = 0; + request->startcount = 0; + request->noti_type = DP_NOTIFICATION_TYPE_NONE; + request->progress_lasttime = 0; + request->received_size = 0; + request->content_type = DP_CONTENT_UNKNOWN; + request->file_size = 0; + request->noti_priv_id = -1; + + dp_request_create(client, request); + ipc_info->id = download_id; + return errorcode; +} + +void dp_request_free(dp_request_fmt *request) +{ + // free notification handle here + TRACE_DEBUG("destory id:%d", request->id); + free(request); +} + +void dp_client_clear_requests(void *slotp) +{ + dp_client_slots_fmt *slot = (dp_client_slots_fmt *)slotp; + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return ; + } + dp_client_fmt *client = &slot->client; + if (client == NULL) { + TRACE_ERROR("check client memory"); + return ; + } + + int now_time = (int)time(NULL); + int i = 0; + unsigned queued_count = 0; + unsigned ongoing_count = 0; + dp_request_fmt *tailp = client->requests; + dp_request_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + + unsigned can_unload = 0; + if (tailp->id <= 0 || tailp->state == DP_STATE_NONE) { + TRACE_ERROR("id:%d unexpected request (%ld/%ld)", tailp->id, tailp->access_time, now_time); + can_unload = 1; + } else if (tailp->access_time > 0 && + (now_time - tailp->access_time) > DP_CARE_CLIENT_CLEAR_INTERVAL) { + // check accesstime. if difference is bigger than DP_CARE_CLIENT_CLEAR_INTERVAL, clear. + + if (tailp->state == DP_STATE_READY || + tailp->state == DP_STATE_COMPLETED || + tailp->state == DP_STATE_CANCELED || + tailp->state == DP_STATE_FAILED) { + can_unload = 1; + } else if (tailp->state == DP_STATE_CONNECTING) { // it take 120 sec over to connect. it means zombie. + TRACE_ERROR("id:%d connection timeout (%ld/%ld)", tailp->id, tailp->access_time, now_time); + if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id); + } + tailp->state = DP_STATE_FAILED; + tailp->error = DP_ERROR_CONNECTION_TIMED_OUT; + if (tailp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + tailp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, tailp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", tailp->id); + } + } + } + } else if (tailp->state == DP_STATE_PAUSED && + dp_is_alive_download(tailp->agent_id) == 0) { + // paused & agent_id not exist.... unload from memory. + TRACE_ERROR("id:%d hanged as paused (%ld/%ld)", tailp->id, tailp->access_time, now_time); + can_unload = 1; + } + + if (can_unload == 1) { + dp_request_fmt *removep = tailp; + if (prevp == NULL) // first request. + client->requests = tailp->next; + else + prevp->next = tailp->next; + tailp = tailp->next; + TRACE_DEBUG("request %d clear: id:%d state:%s", i, removep->id, dp_print_state(removep->state)); + dp_request_free(removep); + continue; + } else { + ongoing_count++; + } + + if (tailp->state == DP_STATE_QUEUED) + queued_count++; + + prevp = tailp; + tailp = tailp->next; + } + TRACE_DEBUG("info requests:%d queued:%d", ongoing_count, queued_count); + if (queued_count > 0) + dp_queue_manager_wake_up(); +} + +int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + int errorcode = DP_ERROR_NONE; + + if (requestp != NULL && client->requests != NULL) { + if (requestp == client->requests) { + // cancel downloading ... after checking status + client->requests = requestp->next; + dp_request_free(requestp); + } else { + int i = 1; + dp_request_fmt *prevp = client->requests; + dp_request_fmt *removep = client->requests->next; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (removep == NULL) { + errorcode = DP_ERROR_ID_NOT_FOUND; + break; + } + if (removep == requestp) { + // cancel downloading ... after checking status + prevp->next = removep->next; + dp_request_free(removep); + break; + } + prevp = removep; + removep = removep->next; + } + } + } + + TRACE_DEBUG("sock:%d id:%d errorcode:%s", client->channel, + (ipc_info) ? ipc_info->id : -1, dp_print_errorcode(errorcode)); + + return errorcode; +} + +static int __dp_request_read_int(int sock, dp_ipc_fmt *ipc_info, int *value) +{ + int errorcode = DP_ERROR_NONE; + if (ipc_info->size == sizeof(int)) { + if (dp_ipc_read(sock, value, ipc_info->size, __FUNCTION__) < 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; +} + +static int __dp_request_feedback_string(int sock, dp_ipc_fmt *ipc_info, void *string, size_t length, int errorvalue) +{ + int errorcode = DP_ERROR_NONE; + + if (length == 0 && errorvalue == DP_ERROR_NONE) + errorvalue = DP_ERROR_NO_DATA; + + if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, length); + } + if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) { + if (dp_ipc_write(sock, string, sizeof(char) * length) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, length); + } + } + return errorcode; +} + +static int __dp_request_read_string(int sock, dp_ipc_fmt *ipc_info, char **string) +{ + int errorcode = DP_ERROR_NONE; + if (ipc_info->size > 0) { + char *recv_str = (char *)calloc((ipc_info->size + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + if (dp_ipc_read(sock, recv_str, ipc_info->size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[ipc_info->size] = '\0'; + TRACE_DEBUG("sock:%d length:%d string:%s", sock, ipc_info->size, recv_str); + *string = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; +} + +static int __dp_request_feedback_int(int sock, dp_ipc_fmt *ipc_info, void *value, int errorvalue, size_t extra_size) +{ + int errorcode = DP_ERROR_NONE; + if (errorvalue != DP_ERROR_NONE) + extra_size = 0; + if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, extra_size) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + } + if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) { + if (dp_ipc_write(sock, value, extra_size) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + } + } + return errorcode; +} + +static int __dp_request_get_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + int errorcode = DP_ERROR_NONE; + switch (ipc_info->property) { + case DP_PROP_URL: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_DESTINATION: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_FILENAME: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_STATE_CALLBACK: + { + int callback = 0; + if (requestp != NULL) { + callback = requestp->state_cb; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, &callback, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + int callback = 0; + if (requestp != NULL) { + callback = requestp->progress_cb; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, &callback, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + int autodownload = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, &autodownload, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&autodownload, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + int network = 0; + if (requestp != NULL) { + network = requestp->network_type; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, &network, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NETWORK_BONDING: + { + int network_bonding = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, &network_bonding, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network_bonding, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_SAVED_PATH: + { + char *string = NULL; + unsigned length = 0; + 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) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_TEMP_SAVED_PATH: + { + char *string = NULL; + unsigned length = 0; + 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) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_MIME_TYPE: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_MIMETYPE, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_RECEIVED_SIZE: + { + unsigned long long recv_size = 0; + if (requestp != NULL) { + recv_size = requestp->received_size; + } else { + errorcode = DP_ERROR_INVALID_STATE; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&recv_size, errorcode, sizeof(unsigned long long)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_TOTAL_FILE_SIZE: + { + unsigned long long file_size = 0; + if (requestp != NULL) { + file_size = requestp->file_size; + } else { + // load content_size(INT64) from database; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, &file_size, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&file_size, errorcode, sizeof(unsigned long long)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_CONTENT_NAME: + { + char *string = NULL; + unsigned length = 0; + 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) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_HTTP_STATUS: + { + int httpstatus = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_HTTP_STATUS, &httpstatus, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&httpstatus, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_ETAG: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_STATE: + { + int state = DP_STATE_NONE; + if (requestp != NULL) { + state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &state, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&state, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_ERROR: + { + int errorvalue = DP_ERROR_NONE; + if (requestp != NULL) { + errorvalue = requestp->error; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_ERRORCODE, &errorvalue, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&errorvalue, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int noti_type = 0; + if (requestp != NULL) { + noti_type = requestp->noti_type; + // if already notification, unregister from notification bar. + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, ¬i_type, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)¬i_type, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + char *string = NULL; + unsigned length = 0; + 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) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + char *string = NULL; + unsigned length = 0; + 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) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_NOTIFICATION_RAW: // read type, send raw binary for type + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + + if (raw_column == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + TRACE_ERROR("invalid type %d type:%d", dp_print_property(ipc_info->property), bundle_type); + if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, ipc_info->property, errorcode, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + } + if (errorcode == DP_ERROR_NONE) { + unsigned char *raws_buffer = NULL; + unsigned length = 0; + // get blob binary from database by raw_column + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, raws_buffer, (size_t)length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(raws_buffer); + } + break; + } + case DP_PROP_HTTP_HEADERS: + { + // 1. response + // 2. send the number of header fields by id + // 3. send response & field string for each fields + int field_count = dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ID, ipc_info->id, &errorcode); + if (field_count < 0 ) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + field_count = 0; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&field_count, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } else if (field_count > 0) { + // get fields from database. + int *ids = (int *)calloc(field_count, sizeof(int)); + if (ids == NULL) { + TRACE_ERROR("failed to allocate the clients"); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + // getting ids of clients + int i = 0; + 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); + for (; i < rows_count; i++) { + char *string = NULL; + unsigned length = 0; + 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) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + free(string); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + break; + } + } + } + } + + break; + } + case DP_PROP_HTTP_HEADER: + { + // 1. read field string + // 2. response with extra size + // 3. send string. + char *header_field = NULL; + char *string = NULL; + unsigned length = 0; + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + if (dp_db_get_header_value(client->dbhandle, ipc_info->id, header_field, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(header_field); + free(string); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + return errorcode; +} + +static int __dp_request_set_info(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + // if completed or downloading, invalid state. + int download_state = DP_STATE_NONE; + if (requestp != NULL) { + download_state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; + } + } + // should the state be checked ? + TRACE_DEBUG("state:%s set property:%s", dp_print_state(download_state), dp_print_property(ipc_info->property)); + + switch (ipc_info->property) { + case DP_PROP_URL: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_DESTINATION: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + if (dp_smack_is_mounted() == 1) { + // check here destination is available. with checking smack + char *smack_label = dp_db_get_client_smack_label(slot->pkgname); + if (smack_label == NULL) { + TRACE_SECURE_ERROR("[SMACK][%d] no label", ipc_info->id); + errorcode = DP_ERROR_PERMISSION_DENIED; + } else if (dp_is_valid_dir(recv_str) != 0) { + errorcode = DP_ERROR_INVALID_DESTINATION; + } else if (dp_smack_is_valid_dir(slot->credential.uid, slot->credential.gid, smack_label, recv_str) != 0) { + errorcode = DP_ERROR_PERMISSION_DENIED; + } + free(smack_label); + } + if (errorcode == DP_ERROR_NONE && + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_TEMP_SAVED_PATH: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_TEMP_FILE_PATH, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_FILENAME: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_STATE_CALLBACK: + { + // check state here + // DP_ERROR_INVALID_STATE if downloading or finished + // update database here + if (requestp != NULL) { + requestp->state_cb = 1; + } + int enable_cb = 1; + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + // check state here + // DP_ERROR_INVALID_STATE if downloading or finished + // update database here + if (requestp != NULL) { + requestp->progress_cb = 1; + } + int enable_cb = 1; + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + // update autodownload property as 1 in database + int enable_cb = 1; + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (recv_int <= DP_NETWORK_OFF || + recv_int > DP_NETWORK_ALL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // update in database + if (requestp != NULL) { + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else { + requestp->network_type = recv_int; + if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + // pause & push queue + if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id); + } else { + requestp->state = DP_STATE_PAUSED; + requestp->error = DP_ERROR_NONE; + if (dp_queue_manager_push_queue(slot, requestp) < 0) { + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } + requestp->state = DP_STATE_FAILED; + requestp->error = DP_ERROR_QUEUE_FULL; + errorcode = DP_ERROR_QUEUE_FULL; + } + } + } + } + } + int enable_cb = recv_int; + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + break; + } + case DP_PROP_NETWORK_BONDING: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (errorcode == DP_ERROR_NONE) { + if(requestp != NULL && requestp->network_type != DP_NETWORK_ALL) { + errorcode = DP_ERROR_INVALID_NETWORK_TYPE; + TRACE_ERROR("[ERROR] wrong network type"); + } 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (recv_int == DP_NOTIFICATION_TYPE_NONE || + recv_int == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + recv_int == DP_NOTIFICATION_TYPE_ALL) { + // check state request->state == DP_STATE_COMPLETED + // DP_ERROR_INVALID_STATE + // update notificatio type in database + int noti_type = recv_int; + if (requestp != NULL) { + if (recv_int < requestp->noti_type) { + // if already notification, unregister from notification bar. + if (recv_int == DP_NOTIFICATION_TYPE_NONE) { + if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to clear notification %s", dp_print_property(ipc_info->property)); + } + } + if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to clear ongoing %s", dp_print_property(ipc_info->property)); + } + } + requestp->noti_type = recv_int; + } + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_NOTIFICATION_RAW: // bundle_type(db column) + bundle_binary + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + else + errorcode = DP_ERROR_INVALID_PARAMETER; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + if (errorcode == DP_ERROR_NONE) { + dp_ipc_fmt *raw_info = dp_ipc_get_fmt(client->channel); + if (raw_info == NULL || raw_info->section != ipc_info->section || + raw_info->property != ipc_info->property || + (raw_info->id != ipc_info->id)) { + TRACE_ERROR("there is a confusion waiting raw binary in %s section", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_IO_ERROR; + } + if (raw_info != NULL && raw_info->size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(raw_info->size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", client->channel, raw_info->size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + if (dp_ipc_read(client->channel, recv_raws, raw_info->size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", client->channel, raw_info->size); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("sock:%d length:%d raws", client->channel, raw_info->size); + // save to database + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, (void *)recv_raws, raw_info->size, 3, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + free(recv_raws); + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + free(raw_info); + } + break; + } + case DP_PROP_HTTP_HEADER: // a request can have one or more fields, a fields can have only one value. + { + char *header_field = NULL; + char *header_value = NULL; + // 1. read field string + // 2. response after checking sql status + // 3. read query IPC for checking IPC + // 4. read value string + // 5. response + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + // check sql + 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); + if (check_field < 0) { + errorcode = DP_ERROR_DISK_BUSY; + } else { + errorcode = DP_ERROR_NONE; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } else { + dp_ipc_fmt *header_ipc = dp_ipc_get_fmt(client->channel); + if (header_ipc == NULL || header_ipc->section != ipc_info->section || + header_ipc->property != ipc_info->property || + (header_ipc->id != ipc_info->id)) { + TRACE_ERROR("there is a confusion during waiting http string in %s section", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = __dp_request_read_string(client->channel, header_ipc, &header_value); + if (errorcode == DP_ERROR_NONE && header_value != NULL) { + if (check_field == 0) { // insert + if (dp_db_new_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { // update + if (dp_db_update_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_value == NULL) { + TRACE_ERROR("failed to set %s, do you want to run as unset?", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + } + free(header_ipc); + } + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + free(header_field); + free(header_value); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; +} + +static int __dp_request_unset_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + switch (ipc_info->property) { + case DP_PROP_URL: + // it would be run like cancel operation + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_DESTINATION: + // if downloading, change destination to da_agent + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_FILENAME: + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_STATE_CALLBACK: + { + if (requestp != NULL) { + requestp->state_cb = 0; + } + int enable_cb = 0; + 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) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + if (requestp != NULL) { + requestp->progress_cb = 0; + } + int enable_cb = 0; + 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) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + // update autodownload property as 0 in database + int enable_cb = 0; + 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) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + // check state here + // update database here + if (requestp != NULL) { + requestp->network_type = DP_NETWORK_OFF; + } + int enable_cb = DP_NETWORK_OFF; + 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) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int noti_type = DP_NOTIFICATION_TYPE_NONE; + if (requestp != NULL) { + requestp->noti_type = noti_type; + } + 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) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + } + case DP_PROP_NOTIFICATION_RAW: + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + if (raw_column != NULL) { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + } else { + TRACE_ERROR("invalid param set: %s type:%d", dp_print_property(ipc_info->property), bundle_type); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + break; + } + case DP_PROP_HTTP_HEADER: // unset value by field + { + char *header_field = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + 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); + if (is_present < 0) + errorcode = DP_ERROR_DISK_BUSY; + else if (is_present == 0) + errorcode = DP_ERROR_FIELD_NOT_FOUND; + else if (dp_db_cond_delete(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, header_field, 2, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s for %s", dp_print_property(ipc_info->property), header_field); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + free(header_field); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_UNSET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; +} + +static int __dp_call_cancel_agent(dp_request_fmt *request) +{ + int ret = -1; + if (request != NULL) { + if (request->agent_id >= 0) { + TRACE_INFO("cancel download(%d) id: %d state:%s", request->agent_id, + request->id, dp_print_state(request->state)); + if (dp_cancel_agent_download_without_update(request->agent_id) == 0) + ret = 0; + } else { + TRACE_ERROR("invalid agent-id:%d id:%d", request->agent_id, + request->id); + } + } + return ret; +} + +static int __dp_request_controls(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + if (ipc_info->property == DP_PROP_CREATE) { + // check packets again + if (ipc_info->size != 0 || ipc_info->id != -1) { + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = __dp_request_create(client, ipc_info); + } + } else { + + // get now state. + int download_state = DP_STATE_NONE; + if (requestp != NULL) { + download_state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; + } + } + TRACE_DEBUG("id:%d state:%s set property:%s", ipc_info->id, dp_print_state(download_state), dp_print_property(ipc_info->property)); + + if (ipc_info->property == DP_PROP_START) { + + if (download_state == DP_STATE_COMPLETED || + download_state == DP_STATE_DOWNLOADING) { + errorcode = DP_ERROR_INVALID_STATE; + } else { + + if (requestp == NULL) { // load from databse + // check state + // load and add new request to client->requests. + } + if (requestp == NULL) { + TRACE_ERROR("failed to load id:%d from database sock:%d", ipc_info->id, client->channel); + errorcode = DP_ERROR_DISK_BUSY; + } + if (errorcode == DP_ERROR_NONE) { + // update database + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + requestp->state = DP_STATE_QUEUED; + requestp->error = DP_ERROR_NONE; + // if it's the first request for this client-> push a request at the head of queue. + // check count queued, connecting.downloading in requets of client + // else push at the tail of queue. + // push to queue + if (dp_queue_manager_push_queue(slot, requestp) < 0) { + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } + requestp->state = DP_STATE_FAILED; + requestp->error = DP_ERROR_QUEUE_FULL; + errorcode = DP_ERROR_QUEUE_FULL; + } else { // push ok + dp_queue_manager_wake_up(); + // notification + if (requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + } + } + TRACE_DEBUG("id:%d check start error:%s", ipc_info->id, dp_print_errorcode(errorcode)); + } + + } else if (ipc_info->property == DP_PROP_PAUSE) { + + if (download_state > DP_STATE_DOWNLOADING) { + errorcode = DP_ERROR_INVALID_STATE; + } else { // change state regardless it's on memory or not. + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_PAUSED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + // call da_pause API + if (requestp != NULL) { + // pop from queue. if state is queued. + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->state = DP_STATE_PAUSED; + requestp->error = DP_ERROR_NONE; + } + } + } + + } else if (ipc_info->property == DP_PROP_CANCEL) { + + if (download_state > DP_STATE_COMPLETED) { + errorcode = DP_ERROR_INVALID_STATE; + } else { // change state regardless it's on memory or not. + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + // call da_cancel API + if (requestp != NULL) { + // pop from queue. if state is queued. + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + if (__dp_call_cancel_agent(requestp) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->agent_id = -1; + requestp->state = DP_STATE_CANCELED; + requestp->error = DP_ERROR_NONE; + if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + } + } + + } else if (ipc_info->property == DP_PROP_DESTROY) { + + // check state + // pop from queue. if state is queued. + if (requestp != NULL) { + if (requestp->state == DP_STATE_QUEUED) + dp_queue_manager_clear_queue(requestp); + if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + // update state property database; + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } else { + // call da_cancel API + if (__dp_call_cancel_agent(requestp) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->state = DP_STATE_CANCELED; + } + if (requestp->state == DP_STATE_QUEUED || requestp->state == DP_STATE_CANCELED) { + + if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + requestp->agent_id = -1; + } + errorcode = dp_request_destroy(client, ipc_info, requestp); + + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + TRACE_ERROR("invalid param - id:%d set property:%s", ipc_info->id, dp_print_property(ipc_info->property)); + } + } + + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_CONTROL, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + + // workaround. client still request the feedback by cancelation + if (ipc_info->property == DP_PROP_CANCEL || + ipc_info->property == DP_PROP_PAUSE) { + if (requestp != NULL && requestp->state_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, ipc_info->id, requestp->state, errorcode, 0) < 0) { + TRACE_ERROR("id:%d disable state callback by IO_ERROR", ipc_info->id); + requestp->state_cb = 0; + } + } + } + + return errorcode; +} + +static int __dp_client_requests(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + // check id except create command /////////// DP_ERROR_ID_NOT_FOUND + dp_request_fmt *requestp = NULL; + if (ipc_info->section != DP_SEC_CONTROL || + ipc_info->property != DP_PROP_CREATE) { + // check on requests + int i = 0; + requestp = client->requests; + errorcode = DP_ERROR_ID_NOT_FOUND; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (requestp == NULL) + break; + //TRACE_DEBUG("link %d info: id:%d access-time:%d", i, requestp->id, requestp->access_time); + if (requestp->id == ipc_info->id) { + errorcode = DP_ERROR_NONE; + break; + } + requestp = requestp->next; + } + if (errorcode == DP_ERROR_ID_NOT_FOUND) { + // check in database + if (dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_LOGGING, DP_DB_COL_ID, ipc_info->id, &errorcode) > 0) { + //TRACE_DEBUG("found %d from database", ipc_info->id); + errorcode = DP_ERROR_NONE; + } + } + } + + // Check size for prevent + if (ipc_info->size > 4294967295U) { + TRACE_ERROR("Check socket. Invalid size value. sock:%d", client->channel); + return DP_ERROR_IO_ERROR; + } + if (errorcode != DP_ERROR_NONE) { // prechecking + TRACE_ERROR("precheck errorcode:%s sock:%d id:%d section:%s property:%s", + dp_print_errorcode(errorcode), + client->channel, ipc_info->id, + dp_print_section(ipc_info->section), + dp_print_property(ipc_info->property)); + + // clear followed packets. + if (ipc_info->size > 0) { + char garbage[ipc_info->size]; + if (read(client->channel, &garbage, ipc_info->size) == 0) { + TRACE_ERROR("sock:%d closed peer", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + } + + if (dp_ipc_query(client->channel, ipc_info->id, + ipc_info->section, ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; + } + + switch (ipc_info->section) { + case DP_SEC_CONTROL: + errorcode = __dp_request_controls(slot, ipc_info, requestp); + break; + case DP_SEC_GET: + errorcode = __dp_request_get_info(client, ipc_info, requestp); + break; + case DP_SEC_SET: + errorcode = __dp_request_set_info(slot, ipc_info, requestp); + break; + case DP_SEC_UNSET: + errorcode = __dp_request_unset_info(client, ipc_info, requestp); + break; + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + return errorcode; +} + +static void __dp_client_stop_all_requests(dp_client_slots_fmt *slot) +{ + unsigned push_count = 0; + int errorcode = DP_ERROR_NONE; + int i = 0; + dp_request_fmt *tailp = slot->client.requests; + for (; tailp != NULL; i++) { + TRACE_DEBUG("request %d stop id:%d state:%s", i, tailp->id, dp_print_state(tailp->state)); + int state = tailp->state; + if (state == DP_STATE_CONNECTING) { + if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id); + } + } else if (state == DP_STATE_DOWNLOADING) { + if (dp_pause_agent_download(tailp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", tailp->agent_id, tailp->id); + } + } + if (state == DP_STATE_DOWNLOADING || state == DP_STATE_CONNECTING) { + tailp->state = DP_STATE_QUEUED; + // This is error code for checking the reason when changing ip configuration process + tailp->error = DP_ERROR_IO_EAGAIN; + // push to queue now + // in da callback, check DP_ERROR_IO_EAGAIN, then ignore. + if (dp_db_update_logging(slot->client.dbhandle, tailp->id, tailp->state, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", slot->client.channel, tailp->id); + } + if (dp_queue_manager_push_queue(slot, tailp) < 0) { + TRACE_ERROR("Fail to push queueg sock:%d download-id:%d", slot->client.channel, tailp->id); + // FIXME later : error case. How can handle this item? + } else { + push_count++; + } + } + tailp = tailp->next; + } + if (push_count > 0) + dp_queue_manager_wake_up(); +} + +void dp_client_sig_handler(int signo) +{ + TRACE_INFO("thread:%0x signal:%d", pthread_self(), signo); +} + +void *dp_client_request_thread(void *arg) +{ + dp_client_slots_fmt *slot = (dp_client_slots_fmt *)arg; + if (slot == NULL) { + TRACE_ERROR("slot null, can not launch the thread for client"); + return 0; + } + + // wait detaching thread + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_INFO("slot %p thread:%0x", slot, slot->thread); + + struct sigaction act = {{0},}; + sigset_t newmask; + sigemptyset(&newmask); + sigaddset(&newmask, SIGUSR1); + act.sa_handler = dp_client_sig_handler; + sigaction(SIGUSR1, &act, NULL); + + fd_set imask, emask; + int errorcode = DP_ERROR_NONE; + dp_client_fmt *client = &slot->client; + int client_sock = client->channel; + struct timeval timeout; // for timeout of select + + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + + while (slot != NULL && client_sock >= 0 && + client_sock == slot->client.channel) { + + memset(&timeout, 0x00, sizeof(struct timeval)); + timeout.tv_sec = DP_CARE_CLIENT_REQUEST_INTERVAL; + FD_ZERO(&imask ); + FD_ZERO(&emask ); + FD_SET(client_sock, &imask); + FD_SET(client_sock, &emask); + if (select(client_sock + 1, &imask, 0, &emask, &timeout) < 0 ) { + if (slot != NULL && slot->client.channel >= 0) { + TRACE_INFO("broadcast by client-manager"); + CLIENT_MUTEX_LOCK(&slot->mutex); + // check all requests + __dp_client_stop_all_requests(slot); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + continue; + } else { + TRACE_STRERROR("interrupted by client-manager sock:%d", client_sock); + break; + } + } + if (FD_ISSET(client_sock, &imask) > 0) { + + CLIENT_MUTEX_LOCK(&slot->mutex); + + if (client->dbhandle == 0 || dp_db_check_connection(client->dbhandle) < 0) { + if (dp_db_open_client(&client->dbhandle, slot->pkgname) < 0) { + TRACE_ERROR("failed to open database for sock:%d", client_sock); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + break; + } + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + client->access_time = (int)time(NULL); + + // read ipc_fmt first. below func will deal followed packets + dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(client_sock); + if (ipc_info == NULL) { + TRACE_STRERROR("sock:%d maybe closed", client_sock); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("sock:%d id:%d section:%s property:%s errorcode:%s size:%d", + client_sock, ipc_info->id, + dp_print_section(ipc_info->section), + dp_print_property(ipc_info->property), + dp_print_errorcode(ipc_info->errorcode), + ipc_info->size); + + // JOB + errorcode = __dp_client_requests(slot, ipc_info); + } + free(ipc_info); + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + if (errorcode == DP_ERROR_IO_ERROR || + errorcode == DP_ERROR_OUT_OF_MEMORY || + errorcode == DP_ERROR_INVALID_PARAMETER) { + TRACE_ERROR("disconnect client errorcode:%s sock:%d", + dp_print_errorcode(errorcode), client_sock); + break; + } + + } else if (FD_ISSET(client_sock, &emask) > 0) { + TRACE_ERROR("[EXCEPTION]"); + break; + } else { + + // timeout + if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) == 0) { + // 1. clear zombie requests. clean requests finished. paused or ready for long time + dp_client_clear_requests(slot); + + int sql_errorcode = DP_ERROR_NONE; + + // 2. maintain only 1000 rows for each client + if (dp_db_limit_rows(client->dbhandle, DP_TABLE_LOGGING, DP_LOG_DB_LIMIT_ROWS, &sql_errorcode) < 0) { + TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode)); + } + // 3. maintain for 48 hours + if (dp_db_limit_time(client->dbhandle, DP_TABLE_LOGGING, DP_CARE_CLIENT_INFO_PERIOD, &sql_errorcode) < 0) { + TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode)); + } + // 4. if no requests, exit by itself. + if (slot->client.requests == NULL) { + TRACE_DEBUG("no requests"); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + break; + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + } + + FD_CLR(client_sock, &imask); + FD_CLR(client_sock, &emask); + + // if no requests, clear slot after disconnect with client. + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_INFO("thread done slot %p thread:%0x sock:%d", slot, slot->thread, client_sock); + + slot->thread = 0;// to prevent kill thread twice + + int i = 0; + dp_request_fmt *tailp = slot->client.requests; + dp_request_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->state != DP_STATE_QUEUED && + tailp->state != DP_STATE_CONNECTING && + tailp->state != DP_STATE_DOWNLOADING) { + dp_request_fmt *removep = tailp; + if (prevp == NULL) // first request. + client->requests = tailp->next; + else + prevp->next = tailp->next; + tailp = tailp->next; + TRACE_DEBUG("request %d remove: id:%d state:%s", i, removep->id, dp_print_state(removep->state)); + dp_request_free(removep); + continue; + } + TRACE_DEBUG("request %d remain: id:%d state:%s", i, tailp->id, dp_print_state(tailp->state)); + prevp = tailp; + tailp = tailp->next; + + } + // if no requests after clear finished requests. + if (slot->client.requests == NULL) { + dp_client_slot_free(slot); + } else { + if (slot->client.notify >= 0) + close(slot->client.notify); + dp_notify_deinit(slot->credential.pid); + slot->client.notify = -1; + if (slot->client.channel > 0) + close(slot->client.channel); + slot->client.channel = -1; + } + TRACE_INFO("thread done slot %p thread:%0x sock:%d", slot, slot->thread, client_sock); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return 0; +} + diff --git a/provider/download-provider-da-interface.c b/provider/download-provider-da-interface.c deleted file mode 100755 index f0b222a..0000000 --- a/provider/download-provider-da-interface.c +++ /dev/null @@ -1,903 +0,0 @@ -/* - * 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("/usr/lib/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); -} - diff --git a/provider/download-provider-db.c b/provider/download-provider-db.c index 4bc1353..d05eabd 100755 --- a/provider/download-provider-db.c +++ b/provider/download-provider-db.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2013 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. @@ -14,1722 +14,1288 @@ * limitations under the License. */ +//#include <string.h> +//#include <errno.h> #include <stdio.h> -#include <string.h> -#include <errno.h> +#include <stdlib.h> // alloc +//#include <unistd.h> // unlink -#include <stdlib.h> #include <sqlite3.h> -#include "download-provider-config.h" +#include "download-provider.h" +#include "download-provider-db-defs.h" #include "download-provider-db.h" -#include "download-provider-slots.h" #include "download-provider-log.h" -#include "download-provider-pthread.h" - -//BASIC -#define DP_DB_BASIC_GET_QUERY_FORMAT "SELECT %s FROM %s WHERE id = ?" -#define DP_DB_BASIC_SET_QUERY_FORMAT "UPDATE %s SET %s = ? WHERE id = ?" -#define DP_DB_BASIC_INSERT_QUERY_FORMAT "INSERT INTO %s (id, %s) VALUES (?, ?)" -#define DP_DB_BASIC_NOW_DATE_QUERY_FORMAT "UPDATE %s SET %s = DATETIME('now') WHERE id = ?" - -// COND -#define DP_DB_COND_GET_QUERY_FORMAT "SELECT %s FROM %s WHERE id = ? AND %s = ?" -#define DP_DB_COND_SET_QUERY_FORMAT "UPDATE %s SET %s = ? WHERE id = ? AND %s = ?" - -typedef enum { - DP_DB_QUERY_TYPE_GET = 10, - DP_DB_QUERY_TYPE_SET = 20, - DP_DB_QUERY_TYPE_INSERT = 30, - DP_DB_QUERY_TYPE_NOW_DATE = 40 -} db_query_type; - -sqlite3 *g_dp_db_handle = 0; -sqlite3_stmt *g_dp_db_logging_new_stmt = NULL; -sqlite3_stmt *g_dp_db_logging_status_stmt = NULL; -sqlite3_stmt *g_dp_db_logging_get_state_stmt = NULL; +#include "download-provider-utils.h" -static void __dp_finalize(sqlite3_stmt *stmt) -{ - if (sqlite3_finalize(stmt) != SQLITE_OK) - TRACE_ERROR("failed sqlite3_finalize [%s]", - sqlite3_errmsg(g_dp_db_handle)); -} -// called when terminating process -void dp_db_close() +static void __basic_property(sqlite3 *handle) { - if (g_dp_db_handle) { - if (g_dp_db_logging_new_stmt != NULL) - __dp_finalize(g_dp_db_logging_new_stmt); - if (g_dp_db_logging_status_stmt != NULL) - __dp_finalize(g_dp_db_logging_status_stmt); - sqlite3_exec(g_dp_db_handle, "VACUUM;", 0, 0, 0); // remove empty page of db - sqlite3_close(g_dp_db_handle); - } - g_dp_db_handle = 0; + if (sqlite3_exec(handle, "PRAGMA journal_mode=PERSIST;", 0, 0, 0) != SQLITE_OK) + TRACE_ERROR("check property journal_mode:PERSIST"); + if (sqlite3_exec(handle, "PRAGMA foreign_keys=ON;", 0, 0, 0) != SQLITE_OK) + TRACE_ERROR("check property foreign_keys:ON"); } -static void __load_sql_schema() +static void __dp_finalize(sqlite3_stmt *stmt) { - char *rebuild_query = - sqlite3_mprintf("sqlite3 %s '.read %s'", DATABASE_FILE, DATABASE_SCHEMA_FILE); - if (rebuild_query != NULL) { - TRACE_SECURE_INFO("[QUERY] %s", rebuild_query); - system(rebuild_query); - sqlite3_free(rebuild_query); + if (stmt != 0) { + if (sqlite3_finalize(stmt) != SQLITE_OK) { + sqlite3 *handle = sqlite3_db_handle(stmt); + TRACE_ERROR("sqlite3_finalize:%s", sqlite3_errmsg(handle)); + } } } -static int __dp_sql_open() +static int __check_table(sqlite3 *handle, char *table) { - return dp_db_open(); -} - -static int __check_table(char *table) -{ - //"SELECT name FROM sqlite_master WHERE type='table' AND name='" + table +"'"; sqlite3_stmt *stmt = NULL; - if (table == NULL) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); + if (handle == 0 || table == NULL) { + TRACE_ERROR("check handle or table:%s", table); return -1; } char *query = sqlite3_mprintf("SELECT name FROM sqlite_master WHERE type='table' AND name='%s'", table); if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); + TRACE_ERROR("failed to make query statement"); return -1; } - - int ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL); + int ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); sqlite3_free(query); + int result = 0; if (ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; + TRACE_ERROR("sqlite3_prepare:%s", sqlite3_errmsg(handle)); + result = -1; } - if (sqlite3_step(stmt) == SQLITE_ROW) { - __dp_finalize(stmt); - return 1; + if (result == 0 && sqlite3_step(stmt) != SQLITE_ROW) { + TRACE_DEBUG("not found table:%s", table); + result = -1; } __dp_finalize(stmt); - return 0; + return result; } -// called when launching process or in every API -int dp_db_open() +static int __rebuild_client_tables(sqlite3 *handle) { - if (g_dp_db_handle == 0) { - TRACE_SECURE_INFO("TRY to open [%s]", DATABASE_FILE); - if (sqlite3_open_v2(DATABASE_FILE, &g_dp_db_handle, - SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) { - TRACE_ERROR("[ERROR][%s][%s]", DATABASE_FILE, - sqlite3_errmsg(g_dp_db_handle)); - int errorcode = sqlite3_errcode(g_dp_db_handle); - dp_db_close(); - if (errorcode == SQLITE_CORRUPT) { - TRACE_SECURE_INFO("unlink [%s]", DATABASE_FILE); - unlink(DATABASE_FILE); - errorcode = SQLITE_CANTOPEN; - } - if (errorcode == SQLITE_CANTOPEN) { - __load_sql_schema(); - return dp_db_open(); - } - return -1; - } - sqlite3_exec(g_dp_db_handle, "PRAGMA journal_mode=PERSIST;", 0, 0, 0); - sqlite3_exec(g_dp_db_handle, "PRAGMA foreign_keys=ON;", 0, 0, 0); + int ret = SQLITE_OK; - // if not found group table. load again. (FOTA) - // new table(groups) created by smack_label. 2013.07.09 - if (__check_table(DP_DB_TABLE_GROUPS) == 0) - __load_sql_schema(); + if (__check_table(handle, DP_TABLE_LOGGING) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_LOGGING, 0, 0, 0); + if (ret == SQLITE_OK) { + ret = sqlite3_exec(handle, DP_SCHEMA_LOGGING_INDEX, 0, 0, 0); + } } - return g_dp_db_handle ? 0 : -1; -} - -int dp_db_is_full_error() -{ - if (g_dp_db_handle == 0) { - TRACE_ERROR("HANDLE is null"); + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_DOWNLOAD) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_DOWNLOAD, 0, 0, 0); + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_REQUEST) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_REQUEST, 0, 0, 0); + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_HEADERS) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_HEADER, 0, 0, 0); + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_NOTIFICATION) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_NOTIFICATION, 0, 0, 0); + } + if (ret != SQLITE_OK) { + TRACE_ERROR("create tables:%d error:%s", ret, sqlite3_errmsg(handle)); return -1; } - if (sqlite3_errcode(g_dp_db_handle) == SQLITE_FULL) - return 0; - return -1; + return 0; } -int dp_db_get_count_by_limit_time() +static int __rebuild_client_manager_tables(sqlite3 *handle) { - int errorcode = SQLITE_OK; - sqlite3_stmt *stmt = NULL; - - if (__dp_sql_open() < 0) { - TRACE_ERROR("db_util_open is failed [%s]", - sqlite3_errmsg(g_dp_db_handle)); - return -1; + int ret = SQLITE_OK; + if (__check_table(handle, DP_TABLE_CLIENTS) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_CLIENTS, 0, 0, 0); } - - errorcode = - sqlite3_prepare_v2(g_dp_db_handle, - "SELECT count(id) FROM logging \ - WHERE createtime < DATETIME('now','-48 hours')", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); + if (ret != SQLITE_OK) { + TRACE_ERROR("create tables:%d error:%s", ret, sqlite3_errmsg(handle)); return -1; } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_ROW) { - int count = sqlite3_column_int(stmt, 0); - __dp_finalize(stmt); - return count; - } - __dp_finalize(stmt); return 0; } -int dp_db_get_list_by_limit_time(dp_request_slots *requests, int limit) +static int __db_open(sqlite3 **handle, char *database) { - int errorcode = SQLITE_OK; - int i = 0; - sqlite3_stmt *stmt = NULL; - - if (__dp_sql_open() < 0) { - TRACE_ERROR("db_util_open is failed [%s]", - sqlite3_errmsg(g_dp_db_handle)); - return -1; + if (sqlite3_open_v2(database, handle, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) { + int errorcode = sqlite3_errcode(*handle); + TRACE_ERROR("error(%d):%s", errorcode, sqlite3_errmsg(*handle)); + *handle = 0; + if (errorcode == SQLITE_CORRUPT) { // remove & re-create + TRACE_SECURE_INFO("unlink [%s]", database); + unlink(database); + errorcode = SQLITE_CANTOPEN; + } + if (errorcode == SQLITE_CANTOPEN) { + // create empty database + if (sqlite3_open(database, handle) != SQLITE_OK ) { + TRACE_SECURE_INFO("failed to connect:%s", database); + unlink(database); + *handle = 0; + return -1; + } + } else { + TRACE_ERROR("can not handle this error:%d", errorcode); + *handle = 0; + return -1; + } } + __basic_property(*handle); + return 0; +} - errorcode = - sqlite3_prepare_v2(g_dp_db_handle, - "SELECT id, state FROM logging WHERE \ - createtime < DATETIME('now','-48 hours') \ - ORDER BY createtime ASC LIMIT ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); +int dp_db_check_connection(void *handle) +{ + if (handle == 0) { + TRACE_ERROR("connection handler is null"); return -1; } - if (sqlite3_bind_int(stmt, 1, limit) - != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int[%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); + int phighwater = 0; + int pcur = 0; + int ret = sqlite3_db_status(handle, SQLITE_DBSTATUS_STMT_USED, &pcur, &phighwater, 0); + if (ret != SQLITE_OK) { + TRACE_INFO("sql(%p) error:%d, used memory:%d, highwater:%d", handle, ret, pcur, phighwater); return -1; } + return 0; +} - while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW && i < limit) { - // allocation & initialization - requests[i].request = dp_request_new(); - // ID - requests[i].request->id = sqlite3_column_int(stmt, 0); - // state - requests[i].request->state = sqlite3_column_int(stmt, 1); - i++; +int dp_db_open_client_manager(void **handle) +{ + if (*handle == 0) { + char *database = sqlite3_mprintf("%s/%s", DATABASE_DIR, DP_DBFILE_CLIENTS); + if (database == NULL) { + TRACE_ERROR("failed to make clients database file path"); + return -1; + } + if (__db_open((sqlite3 **)handle, database) < 0) { + TRACE_ERROR("failed to open %s", database); + *handle = 0; + } else { + // whenever open new handle, check all tables. it's simple + if (__rebuild_client_manager_tables(*handle) < 0) { + dp_db_close(*handle); + *handle = 0; + } + } + sqlite3_free(database); } - - __dp_finalize(stmt); - return i; + return *handle ? 0 : -1; } -int dp_db_crashed_list(dp_request_slots *requests, int limit) +static char *__dp_db_get_client_db_path(char *pkgname) { - int errorcode = SQLITE_OK; - int i = 0; - int buffer_length = 0; - sqlite3_stmt *stmt = NULL; - char *buffer = NULL; + if (pkgname == NULL) + return NULL; + return sqlite3_mprintf("%s/clients/.%s", DATABASE_DIR, pkgname); +} - if (__dp_sql_open() < 0) { - TRACE_ERROR("db_util_open is failed [%s]", - sqlite3_errmsg(g_dp_db_handle)); - return -1; +// 0 : remove, -1: error or skip by diff_time +int dp_db_remove_database(char *pkgname, long now_time, long diff_time) +{ + // get file name + char *database = __dp_db_get_client_db_path(pkgname); + if (database == NULL) { + TRACE_ERROR("failed to make db file path"); + return -1; + } + int result = -1; + // get modified time of database file. + long modified_time = dp_get_file_modified_time(database); + if (modified_time >= now_time) { + TRACE_ERROR("check system timezone %ld vs %ld", modified_time, now_time); + } else if ((now_time - modified_time) > diff_time) { + char *database_journal = sqlite3_mprintf("%s-journal", database); + if (database_journal == NULL) { + TRACE_ERROR("failed to make db journal file path"); + } else { + if (dp_remove_file(database_journal) < 0) { + TRACE_ERROR("failed to remove db journal file path"); + } else { + if (dp_remove_file(database) < 0) { + TRACE_ERROR("failed to remove db file path"); + } else { + result = 0; + } + } + sqlite3_free(database_journal); + } } + sqlite3_free(database); + return result; +} - errorcode = - sqlite3_prepare_v2(g_dp_db_handle, - "SELECT id, state, packagename FROM logging WHERE \ - (state = ? OR state = ? OR state = ?) \ - AND createtime > DATETIME('now','-48 hours') LIMIT ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, DP_STATE_QUEUED) != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 2, DP_STATE_DOWNLOADING) != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 3, DP_STATE_CONNECTING) != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); +int dp_db_open_client_v2(void **handle, char *pkgname) +{ + char *database = __dp_db_get_client_db_path(pkgname); + if (database == NULL) { + TRACE_ERROR("failed to make db file path"); return -1; } - - if (sqlite3_bind_int(stmt, 4, limit) - != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int[%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); + if (sqlite3_open_v2(database, (sqlite3 **)handle, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) { + int errorcode = sqlite3_errcode(*handle); + TRACE_ERROR("error(%d):%s", errorcode, sqlite3_errmsg(*handle)); + *handle = 0; + sqlite3_free(database); return -1; } + sqlite3_free(database); + __basic_property(*handle); + return 0; +} - while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { - // allocation & initialization - requests[i].request = dp_request_new(); - // ID - requests[i].request->id = sqlite3_column_int(stmt, 0); - // state - requests[i].request->state = sqlite3_column_int(stmt, 1); - // packagename - buffer = (char *)(sqlite3_column_text(stmt, 2)); - requests[i].request->packagename = NULL; - if (buffer) { - buffer_length = strlen(buffer); - if (buffer_length > 1) { - requests[i].request->packagename - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(requests[i].request->packagename, buffer, - buffer_length * sizeof(char)); - requests[i].request->packagename[buffer_length] = '\0'; +int dp_db_open_client(void **handle, char *pkgname) +{ + if (*handle == 0) { + char *database = __dp_db_get_client_db_path(pkgname); + if (database == NULL) { + TRACE_ERROR("failed to make db file path"); + return -1; + } + if (__db_open((sqlite3 **)handle, database) < 0) { + TRACE_SECURE_ERROR("failed to open %s", database); + *handle = 0; + } else { + // whenever open new handle, check all tables. it's simple + if (__rebuild_client_tables(*handle) < 0) { + dp_db_close(*handle); + *handle = 0; } } - i++; + sqlite3_free(database); } - - __dp_finalize(stmt); - return i; + return *handle ? 0 : -1; } -int dp_db_limit_rows(int limit) +void dp_db_close(void *handle) { - int errorcode = SQLITE_OK; - sqlite3_stmt *stmt = NULL; - - if (limit <= 0) { - TRACE_ERROR("[CHECK LIMIT] %d", limit); - return -1; + if (handle != 0) { + // remove empty page of db + //sqlite3_exec(handle, "VACUUM;", 0, 0, 0); + if (sqlite3_close((sqlite3 *)handle) != SQLITE_OK) + TRACE_ERROR("check sqlite close"); } +} - if (__dp_sql_open() < 0) { - TRACE_ERROR("__dp_sql_open[%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; +void dp_db_reset(void *stmt) +{ + if (stmt != 0) { + sqlite3_stmt *stmtp = stmt; + sqlite3_clear_bindings(stmtp); + if (sqlite3_reset(stmtp) != SQLITE_OK) { + sqlite3 *handle = sqlite3_db_handle(stmtp); + TRACE_ERROR("reset:%s", sqlite3_errmsg(handle)); + } } +} - // apply "ON DELETE CASCADE" - errorcode = - sqlite3_prepare_v2(g_dp_db_handle, - "DELETE FROM logging WHERE id NOT IN \ - (SELECT id FROM logging ORDER BY createtime ASC LIMIT ?)", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_ERROR("sqlite3_prepare_v2 [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, limit) - != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int[%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; - } - __dp_finalize(stmt); - return -1; +void dp_db_finalize(void *stmt) +{ + __dp_finalize((sqlite3_stmt *)stmt); } -dp_request *dp_db_load_logging_request(int id) +int dp_db_get_errorcode(void *handle) +{ + if (handle == 0) { + TRACE_ERROR("check connection handle"); + return DP_ERROR_DISK_BUSY; + } + int errorcode = sqlite3_errcode((sqlite3 *)handle); + if (errorcode == SQLITE_FULL) { + TRACE_ERROR("SQLITE_FULL-NO_SPACE"); + return DP_ERROR_NO_SPACE; + } else if (errorcode == SQLITE_TOOBIG || + errorcode == SQLITE_LOCKED || errorcode == SQLITE_BUSY) { + TRACE_ERROR("DISK_BUSY %s", sqlite3_errmsg((sqlite3 *)handle)); + return DP_ERROR_DISK_BUSY; + } + return DP_ERROR_NONE; +} + + +#define DP_DB_PARAM_NULL_CHECK do {\ + if (handle == 0) {\ + TRACE_ERROR("check connection handle");\ + return -1;\ + }\ +} while(0) + +#define DP_DB_BUFFER_NULL_CHECK(buffer) do {\ + if (buffer == NULL) {\ + TRACE_ERROR("check available memory");\ + return -1;\ + }\ +} while(0) + +#define DP_DB_BASIC_EXCEPTION_CHECK do {\ + if (errorcode != SQLITE_OK) {\ + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE)\ + *error = DP_ERROR_INVALID_PARAMETER;\ + __dp_finalize(stmt);\ + return -1;\ + }\ +} while(0) + +#define DP_DB_WRITE_STEP_EXCEPTION_CHECK do {\ + errorcode = sqlite3_step(stmt);\ + __dp_finalize(stmt);\ + if (errorcode != SQLITE_DONE) {\ + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE)\ + *error = DP_ERROR_INVALID_PARAMETER;\ + return -1;\ + }\ +} while(0) + +int dp_db_get_ids(void *handle, const char *table, char *idcolumn, int *ids, const char *where, const int limit, char *ordercolumn, char *ordering, int *error) { + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; int errorcode = SQLITE_OK; - int buffer_length = 0; + int rows_count = 0; sqlite3_stmt *stmt = NULL; - char *buffer = NULL; - dp_request *request = NULL; - if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return NULL; - } + char *order_query = NULL; + if (ordercolumn != NULL) + order_query = sqlite3_mprintf("ORDER BY %s %s", ordercolumn, ( ordering == NULL ? "ASC" : ordering )); - if (__dp_sql_open() < 0) { - TRACE_ERROR("db_util_open is failed [%s]", - sqlite3_errmsg(g_dp_db_handle)); - return NULL; - } + if (idcolumn == NULL) + idcolumn = DP_DB_COL_ID; - errorcode = - sqlite3_prepare_v2(g_dp_db_handle, - "SELECT state, errorcode, startcount, packagename \ - FROM logging WHERE id = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return NULL; - } - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return NULL; - } + char *query = sqlite3_mprintf("SELECT %s FROM %s %s %s LIMIT ?", idcolumn, table, ( where == NULL ? "" : where ), ( order_query == NULL ? "" : order_query )); + DP_DB_BUFFER_NULL_CHECK(query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + //TRACE_DEBUG("debug query:%s", query); + sqlite3_free(query); + if (order_query != NULL) + sqlite3_free(order_query); + DP_DB_BASIC_EXCEPTION_CHECK; - if ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { - request = dp_request_new(); - if (request == NULL) { - TRACE_ERROR("dp_request_new failed"); - __dp_finalize(stmt); - return NULL; - } - request->id = id; - request->state = sqlite3_column_int(stmt, 0); - request->error = sqlite3_column_int(stmt, 1); - request->startcount = sqlite3_column_int(stmt, 2); - - buffer = (char *)(sqlite3_column_text(stmt, 3)); - if (buffer) { - buffer_length = strlen(buffer); - if (buffer_length > 1) { - request->packagename - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(request->packagename, buffer, - buffer_length * sizeof(char)); - request->packagename[buffer_length] = '\0'; - } + errorcode = sqlite3_bind_int(stmt, 1, limit); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { + if (sqlite3_column_type(stmt, 0) == SQLITE_INTEGER) { + int columnvalue = sqlite3_column_int(stmt, 0); + //TRACE_DEBUG("id(%d):%d", rows_count, columnvalue); + ids[rows_count++] = columnvalue; } - } else { - TRACE_ERROR("sqlite3_step is failed. [%s] errorcode[%d]", - sqlite3_errmsg(g_dp_db_handle), errorcode); - __dp_finalize(stmt); - return NULL; } __dp_finalize(stmt); - return request; + return rows_count; } -int dp_db_remove_all(int id) +int dp_db_get_crashed_ids(void *handle, const char *table, int *ids, const int limit, int *error) { - #if 0 - dp_db_remove(id, DP_DB_TABLE_REQUEST_INFO); - dp_db_remove(id, DP_DB_TABLE_DOWNLOAD_INFO); - dp_db_remove(id, DP_DB_TABLE_HTTP_HEADERS); - dp_db_remove(id, DP_DB_TABLE_NOTIFICATION); - #endif - // apply "ON DELETE CASCADE" - dp_db_remove(id, DP_DB_TABLE_LOG); + // make where. + //get ids if state is QUEUED, CONNECTING or DOWNLOADING with auto_download + char *where = sqlite3_mprintf("WHERE %s IS 1 AND (%s IS %d OR %s IS %d OR %s IS %d)", + DP_DB_COL_AUTO_DOWNLOAD, + DP_DB_COL_STATE, DP_STATE_DOWNLOADING, + DP_DB_COL_STATE, DP_STATE_CONNECTING, + DP_DB_COL_STATE, DP_STATE_QUEUED); + if (where != NULL) { + int rows_count = dp_db_get_ids(handle, table, DP_DB_COL_ID, ids, where, limit, NULL, NULL, error); + sqlite3_free(where); + return rows_count; + } + *error = DP_ERROR_OUT_OF_MEMORY; return -1; } -int dp_db_remove(int id, char *table) + +int dp_db_check_duplicated_int(void *handle, const char *table, const char *column, const int value, int *error) { + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; int errorcode = SQLITE_OK; - int query_len = 0; - int ret = -1; + int count = 0; sqlite3_stmt *stmt = NULL; - char *query_format = NULL; - char *query = NULL; - - if (__dp_sql_open() < 0) { - TRACE_ERROR("__dp_sql_open[%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - query_format = "DELETE FROM %s WHERE id = ? "; - // 2 means the length of one %s - query_len = strlen(query_format) - 2 + strlen(table); - if (query_len < strlen(query_format)) { - TRACE_ERROR("[CHECK QUERY FORMAT] [%s][%s]", - query_format, table); - return -1; - } - - query = (char *)calloc((query_len + 1), sizeof(char)); - if (query == NULL) { - TRACE_STRERROR("[CALLOC]"); - return -1; - } - query[query_len] = '\0'; - - ret = snprintf(query, query_len + 1, query_format, table); - - if (ret < 0) { - TRACE_STRERROR("[CHECK COMBINE] [%s]", query); - free(query); - return -1; - } + char *query = sqlite3_mprintf("SELECT count(*) FROM %s WHERE %s IS ?", table, column); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - // check error of sqlite3_prepare_v2 - if (sqlite3_prepare_v2 - (g_dp_db_handle, query, -1, &stmt, NULL) != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - free(query); - return -1; - } - free(query); + errorcode = sqlite3_bind_int(stmt, 1, value); + DP_DB_BASIC_EXCEPTION_CHECK; - if (sqlite3_bind_int(stmt, 1, id) - != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int[%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + *error = DP_ERROR_NONE; errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; + if (errorcode == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); + } else { + count = 0; } - TRACE_ERROR("[SQL] [%s]", sqlite3_errmsg(g_dp_db_handle)); __dp_finalize(stmt); - return -1; + return count; } -static sqlite3_stmt *__prepare_query(sqlite3 *handle, - db_query_type type, char *table, char *column) +int dp_db_check_duplicated_string(void *handle, const int id, const char *table, const char *column, int is_like, const char *value, int *error) { + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int count = 0; sqlite3_stmt *stmt = NULL; - char *query_format = NULL; - char *query = NULL; - int ret = -1; - - if (type == DP_DB_QUERY_TYPE_GET) { - query_format = DP_DB_BASIC_GET_QUERY_FORMAT; - } else if (type == DP_DB_QUERY_TYPE_SET) { - query_format = DP_DB_BASIC_SET_QUERY_FORMAT; - } else if (type == DP_DB_QUERY_TYPE_INSERT) { - query_format = DP_DB_BASIC_INSERT_QUERY_FORMAT; - } else if (type == DP_DB_QUERY_TYPE_NOW_DATE) { - query_format = DP_DB_BASIC_NOW_DATE_QUERY_FORMAT; - } else { - TRACE_ERROR("[CHECK QUERY TYPE] [%d]", type); - return NULL; - } - if (type == DP_DB_QUERY_TYPE_GET) - query = sqlite3_mprintf(query_format, column, table); - else - query = sqlite3_mprintf(query_format, table, column); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE] [%s]", query_format); - return NULL; + char *id_check = NULL; + if (id >= 0) { + id_check = sqlite3_mprintf("AND %s IS ?", DP_DB_COL_ID); } - - ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + char *query = NULL; + if (is_like > 0) + query = sqlite3_mprintf("SELECT count(*) FROM %s WHERE %s LIKE ? %s", table, column, (id_check == NULL ? "" : id_check)); + else + query = sqlite3_mprintf("SELECT count(*) FROM %s WHERE %s %s ? %s", table, column, (is_like == 0 ? "IS" : "IS NOT"), (id_check == NULL ? "" : id_check)); + if (id_check != NULL) + sqlite3_free(id_check); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); sqlite3_free(query); - if ( ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(handle)); - __dp_finalize(stmt); - return NULL; - } - return stmt; -} - -int dp_db_insert_column(int id, char *table, char *column, - db_column_data_type datatype, void *value) -{ - sqlite3_stmt *stmt = NULL; + DP_DB_BASIC_EXCEPTION_CHECK; - if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return -1; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return -1; - } - - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - stmt = __prepare_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_INSERT, table, column); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - int errorcode = SQLITE_OK; - if (datatype == DP_DB_COL_TYPE_INT) { - int *cast_value = value; - errorcode = sqlite3_bind_int(stmt, 2, *cast_value); - } else if (datatype == DP_DB_COL_TYPE_INT64) { -#ifdef SQLITE_INT64_TYPE - sqlite3_int64 *cast_value = value; - errorcode = sqlite3_bind_int64(stmt, 2, *cast_value); -#else - int *cast_value = value; - errorcode = sqlite3_bind_int(stmt, 2, *cast_value); -#endif - } else if (datatype == DP_DB_COL_TYPE_TEXT) { - errorcode = sqlite3_bind_text(stmt, 2, (char*)value, -1, NULL); - } else { - TRACE_ERROR("[CHECK TYPE] Not Support [%d]", datatype); - __dp_finalize(stmt); - return -1; - } - - if (errorcode != SQLITE_OK) { - TRACE_ERROR("[BIND] [%d] [%s]", - datatype, sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - - // VALUES ( id ) - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; + errorcode = sqlite3_bind_text(stmt, 1, value, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + if (id >= 0) { + errorcode = sqlite3_bind_int(stmt, 2, id); + DP_DB_BASIC_EXCEPTION_CHECK; } + *error = DP_ERROR_NONE; errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; + if (errorcode == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); + } else { + count = 0; } - TRACE_ERROR("[SQL] [%s]", sqlite3_errmsg(g_dp_db_handle)); __dp_finalize(stmt); - return -1; + return count; } -int dp_db_insert_blob_column(int id, char *table, char *column, - void *value, unsigned length) +int dp_db_update_client_info(void *handle, const char *pkgname, const char *smack, const int uid, const int gid, int *error) { - sqlite3_stmt *stmt = NULL; - - if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return -1; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (pkgname == NULL) { + TRACE_ERROR("check pkgname"); return -1; } - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - stmt = __prepare_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_INSERT, table, column); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); + int is_update = dp_db_check_duplicated_string(handle, -1, DP_TABLE_CLIENTS, DP_DB_COL_PACKAGE, 0, pkgname, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; return -1; } int errorcode = SQLITE_OK; - errorcode = sqlite3_bind_blob(stmt, 2, value, (int)length, NULL); + sqlite3_stmt *stmt = NULL; + char *query = NULL; - if (errorcode != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + if (is_update == 0) + query = sqlite3_mprintf( + "INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s) VALUES (?, ?, %d, %d, 0, DATETIME('NOW'), DATETIME('NOW'))", + DP_TABLE_CLIENTS, DP_DB_COL_SMACK_LABEL, DP_DB_COL_PACKAGE, DP_DB_COL_UID, + DP_DB_COL_GID, DP_DB_COL_REQUEST_COUNT, + DP_DB_COL_CREATE_TIME, DP_DB_COL_ACCESS_TIME, uid, gid); + else + query = sqlite3_mprintf("UPDATE %s SET %s = ?, %s = %d, %s = %d, %s = DATETIME('NOW') WHERE %s IS ?", + DP_TABLE_CLIENTS, DP_DB_COL_SMACK_LABEL, DP_DB_COL_UID, + uid, DP_DB_COL_GID, gid, DP_DB_COL_ACCESS_TIME, DP_DB_COL_PACKAGE); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - // VALUES ( id ) - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; + if (smack != NULL) { + errorcode = sqlite3_bind_text(stmt, 1, smack, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; } + errorcode = sqlite3_bind_text(stmt, 2, pkgname, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; - } - TRACE_ERROR("[SQL] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; } -int dp_db_set_column(int id, char *table, char *column, - db_column_data_type datatype, void *value) +int dp_db_get_client_property_string(void *handle, const char *pkgname, const char *column, unsigned char **value, unsigned *length, int *error) { - sqlite3_stmt *stmt = NULL; - - if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return -1; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return -1; - } - - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - stmt = __prepare_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_SET, table, column); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (pkgname == NULL || column == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query"); return -1; } int errorcode = SQLITE_OK; - if (datatype == DP_DB_COL_TYPE_INT) { - int *cast_value = value; - errorcode = sqlite3_bind_int(stmt, 1, *cast_value); - } else if (datatype == DP_DB_COL_TYPE_INT64) { -#ifdef SQLITE_INT64_TYPE - sqlite3_int64 *cast_value = value; - errorcode = sqlite3_bind_int64(stmt, 1, *cast_value); -#else - int *cast_value = value; - errorcode = sqlite3_bind_int(stmt, 1, *cast_value); -#endif - } else if (datatype == DP_DB_COL_TYPE_TEXT) { - errorcode = sqlite3_bind_text(stmt, 1, (char*)value, -1, NULL); - } else { - TRACE_ERROR("[CHECK TYPE] Not Support [%d]", datatype); - __dp_finalize(stmt); - return -1; - } + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ? LIMIT 1", column, DP_TABLE_CLIENTS, DP_DB_COL_PACKAGE); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - if (errorcode != SQLITE_OK) { - TRACE_ERROR("[BIND] [%d] [%s]", - datatype, sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - - // WHERE id = ? - if (sqlite3_bind_int(stmt, 2, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + errorcode = sqlite3_bind_text(stmt, 1, pkgname, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + *error = DP_ERROR_NONE; errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; } - TRACE_ERROR("[SQL] [%s]", sqlite3_errmsg(g_dp_db_handle)); __dp_finalize(stmt); - return -1; + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; } -int dp_db_set_blob_column(int id, char *table, char *column, - void *value, unsigned length) +int dp_db_new_logging(void *handle, const int id, const int state, const int errorvalue, int *error) { - sqlite3_stmt *stmt = NULL; - + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return -1; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); + TRACE_ERROR("check id:%d", id); return -1; } - - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - stmt = __prepare_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_SET, table, column); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - int errorcode = SQLITE_OK; - errorcode = sqlite3_bind_blob(stmt, 1, value, (int)length, NULL); + sqlite3_stmt *stmt = NULL; - if (errorcode != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + char *query = sqlite3_mprintf("INSERT INTO %s (%s, %s, %s, %s, %s) VALUES (?, ?, ?, DATETIME('now'), DATETIME('now'))", + DP_TABLE_LOGGING, DP_DB_COL_ID, DP_DB_COL_STATE, + DP_DB_COL_ERRORCODE, DP_DB_COL_CREATE_TIME, DP_DB_COL_ACCESS_TIME); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - // WHERE id = ? - if (sqlite3_bind_int(stmt, 2, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, state); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 3, errorvalue); + DP_DB_BASIC_EXCEPTION_CHECK; - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; - } - TRACE_ERROR("[SQL] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; } -int dp_db_replace_column(int id, char *table, char *column, - db_column_data_type datatype, void *value) +int dp_db_update_logging(void *handle, const int id, const int state, const int errorvalue, int *error) { + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); + TRACE_ERROR("check id:%d", id); return -1; } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return -1; - } + char *query = sqlite3_mprintf("UPDATE %s SET %s = ?, %s = ?, %s = DATETIME('now') WHERE %s = ?", + DP_TABLE_LOGGING, DP_DB_COL_STATE, DP_DB_COL_ERRORCODE, + DP_DB_COL_ACCESS_TIME, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return -1; - } + errorcode = sqlite3_bind_int(stmt, 1, state); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, errorvalue); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 3, id); + DP_DB_BASIC_EXCEPTION_CHECK; - int check_id = dp_db_get_int_column(id, table, DP_DB_COL_ID); - if (check_id != id) // INSERT - return dp_db_insert_column(id, table, column, datatype, value); - // UPDATE - return dp_db_set_column(id, table, column, datatype, value); + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; } -int dp_db_replace_blob_column(int id, char *table, char *column1, - void *value, unsigned length) +// 0:integer, 1:bigint, 2:string, 3:blob +int dp_db_replace_property(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned length, const unsigned valuetype, int *error) { + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); + TRACE_ERROR("check id:%d", id); return -1; } - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); + if (table == NULL || column == NULL || value == NULL) { + TRACE_ERROR("check materials for query id:%d", id); return -1; } - if (!column1) { - TRACE_ERROR("[CHECK COLUMN NAME]"); + + int is_update = dp_db_check_duplicated_int(handle, table, DP_DB_COL_ID, id, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; return -1; } - int check_id = dp_db_get_int_column(id, table, DP_DB_COL_ID); - if (check_id != id) // INSERT - { - return dp_db_insert_blob_column(id, table, column1, value, length); - } - // UPDATE - return dp_db_set_blob_column(id, table, column1, value, length); -} -// success : 0 -// error : -1 -char *dp_db_get_text_column(int id, char *table, char *column) -{ + int errorcode = SQLITE_OK; sqlite3_stmt *stmt = NULL; + char *query = NULL; - if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return NULL; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return NULL; - } - - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return NULL; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return NULL; - } - - stmt = __prepare_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_GET, table, column); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return NULL; - } + if (is_update == 0) + query = sqlite3_mprintf("INSERT INTO %s (%s, %s) VALUES (?, ?)", table, column, DP_DB_COL_ID); + else + query = sqlite3_mprintf("UPDATE %s SET %s = ? WHERE %s IS ?", table, column, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - // WHERE id = ? - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); + if (valuetype == 0) { + int *cast_value = (int *)value; + errorcode = sqlite3_bind_int(stmt, 1, *cast_value); + } else if (valuetype == 1) { + sqlite_int64 *cast_value = (sqlite_int64 *)value; + errorcode = sqlite3_bind_int64(stmt, 1, *cast_value); + } else if (valuetype == 2) { + errorcode = sqlite3_bind_text(stmt, 1, (char *)value, -1, SQLITE_STATIC); + } else if (valuetype == 3) { + errorcode = sqlite3_bind_blob(stmt, 1, value, (int)length, NULL); + } else { + TRACE_ERROR("invalid type:%d", valuetype); __dp_finalize(stmt); - return NULL; + return -1; } + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, id); + DP_DB_BASIC_EXCEPTION_CHECK; - if (sqlite3_step(stmt) == SQLITE_ROW) { - int buffer_length = 0; - char *columntext = NULL; - char *buffer = (char *)(sqlite3_column_text(stmt, 0)); - if (buffer && (buffer_length = strlen(buffer)) > 1) { - columntext = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(columntext, buffer, buffer_length * sizeof(char)); - columntext[buffer_length] = '\0'; - } - __dp_finalize(stmt); - return columntext; - } - __dp_finalize(stmt); - return NULL; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; } -// success : 0 -// error : -1 -void *dp_db_get_blob_column(int id, char *table, char *column, int *length) +int dp_db_get_property_string(void *handle, const int id, const char *table, const char *column, unsigned char **value, unsigned *length, int *error) { - sqlite3_stmt *stmt = NULL; - + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return NULL; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return NULL; - } - - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return NULL; + TRACE_ERROR("check id:%d", id); + return -1; } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return NULL; + if (table == NULL || column == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; } - stmt = __prepare_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_GET, table, column); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return NULL; - } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ? LIMIT 1", column, table, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - // WHERE id = ? - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return NULL; - } + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; - if (sqlite3_step(stmt) == SQLITE_ROW) { - int blob_length = 0; - void *blob_data = NULL; - blob_length = sqlite3_column_bytes(stmt, 0); - if(blob_length > 0){ - blob_data = (void*)calloc(blob_length, sizeof(unsigned char)); - if(blob_data != NULL){ - memcpy(blob_data, sqlite3_column_blob(stmt, 0), - sizeof(unsigned char)*blob_length); + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } } else { - TRACE_ERROR("[MEM] allocating"); - blob_length = -1; + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else if (data_type == SQLITE_BLOB) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_blob(stmt, 0), getbytes * sizeof(unsigned char)); + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + }else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; } } else { - TRACE_ERROR("NO DATA"); - blob_length = -1; + //TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; } - __dp_finalize(stmt); - *length = blob_length; - return blob_data; + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; } __dp_finalize(stmt); - return NULL; + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; } - -int dp_db_get_int_column(int id, char *table, char *column) +int dp_db_get_property_int(void *handle, const int id, const char *table, const char *column, void *value, int *error) { - sqlite3_stmt *stmt = NULL; - + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return -1; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); + TRACE_ERROR("check id:%d", id); return -1; } - - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); + if (table == NULL || column == NULL || value == NULL) { + TRACE_ERROR("check materials for query id:%d", id); return -1; } - stmt = __prepare_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_GET, table, column); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ? LIMIT 1", column, table, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - // WHERE id = ? - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; - if (sqlite3_step(stmt) == SQLITE_ROW) { - int columnvalue = sqlite3_column_int(stmt, 0); - __dp_finalize(stmt); - return columnvalue; + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_INTEGER) { + int recv_int = sqlite3_column_int(stmt, 0); + int *pvalue = value; + *pvalue = recv_int; + } else if (data_type == SQLITE_FLOAT) { + unsigned long long recv_int = sqlite3_column_int64(stmt, 0); + unsigned long long *pvalue = value; + *pvalue = recv_int; + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_DONE) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; } __dp_finalize(stmt); - return -1; + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; } -long long dp_db_get_int64_column(int id, char *table, char *column) +int dp_db_unset_property_string(void *handle, const int id, const char *table, const char *column, int *error) { - sqlite3_stmt *stmt = NULL; - + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); + TRACE_ERROR("check id:%d", id); return -1; } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); + if (table == NULL || column == NULL) { + TRACE_ERROR("check materials for query id:%d", id); return -1; } - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); + int is_update = dp_db_check_duplicated_int(handle, table, DP_DB_COL_ID, id, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); + } else if (is_update == 0) { + *error = DP_ERROR_ID_NOT_FOUND; return -1; } - stmt = __prepare_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_GET, table, column); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("UPDATE %s SET %s = NULL WHERE %s IS ?", table, column, DP_DB_COL_ID); - // WHERE id = ? - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; - if (sqlite3_step(stmt) == SQLITE_ROW) { - long long columnvalue = sqlite3_column_int64(stmt, 0); - __dp_finalize(stmt); - return columnvalue; - } - __dp_finalize(stmt); - return -1; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; } -int dp_db_update_date(int id, char *table, char *column) +// "DELETE FROM %s WHERE %s NOT IN (SELECT %s FROM %s ORDER BY %s %s LIMIT %d)" +int dp_db_delete(void *handle, const int id, const char *table, int *error) { - int errorcode = SQLITE_OK; - sqlite3_stmt *stmt = NULL; - + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); + TRACE_ERROR("check id:%d", id); return -1; } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("__dp_sql_open [%s]", sqlite3_errmsg(g_dp_db_handle)); + if (table == NULL) { + TRACE_ERROR("check materials for query id:%d", id); return -1; } - stmt = __prepare_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_NOW_DATE, table, column); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); + int is_update = dp_db_check_duplicated_int(handle, table, DP_DB_COL_ID, id, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; return -1; - } - - // WHERE id = ? - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); + } else if (is_update == 0) { + *error = DP_ERROR_ID_NOT_FOUND; return -1; } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; - } - TRACE_ERROR("Failed : [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; -} - -static sqlite3_stmt *__prepare_cond_query(sqlite3 *handle, - db_query_type type, char *table, - char *column, char *cond_column) -{ + int errorcode = SQLITE_OK; sqlite3_stmt *stmt = NULL; - char *query_format = NULL; - char *query = NULL; - int ret = -1; - - if (type == DP_DB_QUERY_TYPE_GET) { - query_format = DP_DB_COND_GET_QUERY_FORMAT; - } else if (type == DP_DB_QUERY_TYPE_SET) { - query_format = DP_DB_COND_SET_QUERY_FORMAT; - } else { - TRACE_ERROR("[CHECK QUERY TYPE] [%d]", type); - return NULL; - } - - if (type == DP_DB_QUERY_TYPE_GET) - query = sqlite3_mprintf(query_format, column, table, cond_column); - else - query = sqlite3_mprintf(query_format, table, column, cond_column); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE] [%s]", query_format); - return NULL; - } + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s IS ?", table, DP_DB_COL_ID); - ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); sqlite3_free(query); - if ( ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(handle)); - __dp_finalize(stmt); - return NULL; - } - return stmt; + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; } -int dp_db_cond_set_column(int id, char *table, char *column, - db_column_data_type datatype, void *value, - char *condcolumn, db_column_data_type condtype, void *condvalue) +int dp_db_new_header(void *handle, const int id, const char *field, const char *value, int *error) { - int errorcode = SQLITE_OK; - sqlite3_stmt *stmt = NULL; - + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return -1; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return -1; - } - - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); + TRACE_ERROR("check id:%d", id); return -1; } - - if (!condcolumn) { - TRACE_ERROR("[CHECK COLUMN NAME]"); + if (field == NULL) { + TRACE_ERROR("check field:%s", field); return -1; } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } + char *query = sqlite3_mprintf("INSERT INTO %s (%s, %s, %s) VALUES (?, ?, ?)", + DP_TABLE_HEADERS, DP_DB_COL_ID, DP_DB_COL_HEADER_FIELD, + DP_DB_COL_HEADER_DATA); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - stmt = __prepare_cond_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_SET, table, column, condcolumn); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 2, (char *)field, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 3, (char *)value, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; - if (datatype == DP_DB_COL_TYPE_INT) { - int *cast_value = value; - errorcode = sqlite3_bind_int(stmt, 1, *cast_value); - } else if (datatype == DP_DB_COL_TYPE_INT64) { -#ifdef SQLITE_INT64_TYPE - sqlite3_int64 *cast_value = value; - errorcode = sqlite3_bind_int64(stmt, 1, *cast_value); -#else - int *cast_value = value; - errorcode = sqlite3_bind_int(stmt, 1, *cast_value); -#endif - } else if (datatype == DP_DB_COL_TYPE_TEXT) { - errorcode = sqlite3_bind_text(stmt, 1, (char*)value, -1, NULL); - } else { - TRACE_ERROR("[CHECK TYPE] Not Support [%d]", datatype); - __dp_finalize(stmt); - return -1; - } - if (errorcode != SQLITE_OK) { - TRACE_ERROR("[BIND] [%d] [%s]", - datatype, sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} - if (condtype == DP_DB_COL_TYPE_INT) { - int *cast_value = condvalue; - errorcode = sqlite3_bind_int(stmt, 3, *cast_value); - } else if (condtype == DP_DB_COL_TYPE_INT64) { -#ifdef SQLITE_INT64_TYPE - sqlite3_int64 *cast_value = condvalue; - errorcode = sqlite3_bind_int64(stmt, 3, *cast_value); -#else - int *cast_value = condvalue; - errorcode = sqlite3_bind_int(stmt, 3, *cast_value); -#endif - } else if (condtype == DP_DB_COL_TYPE_TEXT) { - errorcode = sqlite3_bind_text(stmt, 3, (char*)condvalue, -1, NULL); - } else { - TRACE_ERROR("[CHECK TYPE] Not Support [%d]", condtype); - __dp_finalize(stmt); +int dp_db_update_header(void *handle, const int id, const char *field, const char *value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); return -1; } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; - if (errorcode != SQLITE_OK) { - TRACE_ERROR("[BIND] [%d] [%s]", - datatype, sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + char *query = sqlite3_mprintf("UPDATE %s SET %s = ? WHERE %s IS ? AND %s IS ?", + DP_TABLE_HEADERS, DP_DB_COL_HEADER_DATA, + DP_DB_COL_ID, DP_DB_COL_HEADER_FIELD); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - // WHERE id = ? - if (sqlite3_bind_int(stmt, 2, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + errorcode = sqlite3_bind_text(stmt, 1, (char *)value, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 2, (char *)field, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; - } - __dp_finalize(stmt); - return -1; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; } -char *dp_db_cond_get_text_column(int id, char *table, char *column, - char *condcolumn, db_column_data_type condtype, - void *condvalue) +int dp_db_get_header_value(void *handle, const int id, const char *field, unsigned char **value, unsigned *length, int *error) { - sqlite3_stmt *stmt = NULL; - + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return NULL; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return NULL; - } - - if (!column) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return NULL; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return NULL; + TRACE_ERROR("check id:%d", id); + return -1; } - - stmt = __prepare_cond_query - (g_dp_db_handle, DP_DB_QUERY_TYPE_GET, table, column, condcolumn); - if (stmt == NULL) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return NULL; + if (field == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; } int errorcode = SQLITE_OK; - if (condtype == DP_DB_COL_TYPE_INT) { - int *cast_value = condvalue; - errorcode = sqlite3_bind_int(stmt, 2, *cast_value); - } else if (condtype == DP_DB_COL_TYPE_INT64) { -#ifdef SQLITE_INT64_TYPE - sqlite3_int64 *cast_value = condvalue; - errorcode = sqlite3_bind_int64(stmt, 2, *cast_value); -#else - int *cast_value = condvalue; - errorcode = sqlite3_bind_int(stmt, 2, *cast_value); -#endif - } else if (condtype == DP_DB_COL_TYPE_TEXT) { - errorcode = sqlite3_bind_text(stmt, 2, (char*)condvalue, -1, NULL); - } else { - TRACE_ERROR("[CHECK TYPE] Not Support [%d]", condtype); - __dp_finalize(stmt); - return NULL; - } - if (errorcode != SQLITE_OK) { - TRACE_ERROR("[BIND] [%d] [%s]", - condtype, sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return NULL; - } + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ? AND %s IS ? LIMIT 1", DP_DB_COL_HEADER_DATA, DP_TABLE_HEADERS, DP_DB_COL_ID, DP_DB_COL_HEADER_FIELD); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - // WHERE id = ? - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return NULL; - } + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 2, (char *)field, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; - if (sqlite3_step(stmt) == SQLITE_ROW) { - int buffer_length = 0; - char *columntext = NULL; - char *buffer = (char *)(sqlite3_column_text(stmt, 0)); - if (buffer && (buffer_length = strlen(buffer)) > 1) { - columntext = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(columntext, buffer, buffer_length * sizeof(char)); - columntext[buffer_length] = '\0'; + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; } - __dp_finalize(stmt); - return columntext; + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; } - TRACE_ERROR("[SQL] [%s]", sqlite3_errmsg(g_dp_db_handle)); __dp_finalize(stmt); - return NULL; + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; } -int dp_db_cond_remove(int id, char *table, - char *condcolumn, db_column_data_type condtype, - void *condvalue) +// not supprot blob as column & value for additional condition +int dp_db_cond_delete(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned valuetype, int *error) { - int errorcode = SQLITE_OK; - int ret = -1; - sqlite3_stmt *stmt = NULL; - char *query_format = NULL; - char *query = NULL; - + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return -1; - } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); + TRACE_ERROR("check id:%d", id); return -1; } - - if (!condcolumn) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("__dp_sql_open[%s]", sqlite3_errmsg(g_dp_db_handle)); + if (table == NULL || column == NULL || value == NULL) { + TRACE_ERROR("check materials for query id:%d", id); return -1; } - query_format = "DELETE FROM %s WHERE id = ? AND %s = ?"; - - query = sqlite3_mprintf(query_format, table, condcolumn); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE] [%s]", query_format); - return -1; - } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s IS ? AND %s IS ?", table, DP_DB_COL_ID, column); - ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); sqlite3_free(query); - if ( ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; - if (condtype == DP_DB_COL_TYPE_INT) { - int *cast_value = condvalue; + if (valuetype == 0) { + int *cast_value = (int *)value; errorcode = sqlite3_bind_int(stmt, 2, *cast_value); - } else if (condtype == DP_DB_COL_TYPE_INT64) { -#ifdef SQLITE_INT64_TYPE - sqlite3_int64 *cast_value = condvalue; + } else if (valuetype == 1) { + sqlite_int64 *cast_value = (sqlite_int64 *)value; errorcode = sqlite3_bind_int64(stmt, 2, *cast_value); -#else - int *cast_value = condvalue; - errorcode = sqlite3_bind_int(stmt, 2, *cast_value); -#endif - } else if (condtype == DP_DB_COL_TYPE_TEXT) { - errorcode = sqlite3_bind_text(stmt, 2, (char*)condvalue, -1, NULL); - } else { - TRACE_ERROR("[CHECK TYPE] Not Support [%d]", condtype); - __dp_finalize(stmt); - return -1; - } - if (errorcode != SQLITE_OK) { - TRACE_ERROR("[BIND] [%d] [%s]", - condtype, sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; + } else if (valuetype == 2) { + errorcode = sqlite3_bind_text(stmt, 2, (char *)value, -1, SQLITE_STATIC); } + DP_DB_BASIC_EXCEPTION_CHECK; - if (sqlite3_bind_int(stmt, 1, id) - != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int[%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; - } - TRACE_ERROR("[SQL] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; -} - -static int __dp_sql_bind_value(sqlite3_stmt *stmt, - db_column_data_type condtype, void *value, int index) -{ - int errorcode = SQLITE_ERROR; - int *cast_value = 0; - - if (stmt == NULL) - return SQLITE_ERROR; - - switch (condtype) { - case DP_DB_COL_TYPE_INT: - cast_value = value; - errorcode = sqlite3_bind_int(stmt, index, *cast_value); - break; - case DP_DB_COL_TYPE_INT64: -#ifdef SQLITE_INT64_TYPE - sqlite3_int64 *cast_value = value; - errorcode = sqlite3_bind_int64(stmt, index, *cast_value); -#else - cast_value = value; - errorcode = sqlite3_bind_int(stmt, index, *cast_value); -#endif - break; - case DP_DB_COL_TYPE_TEXT: - errorcode = - sqlite3_bind_text(stmt, index, (char *)value, -1, SQLITE_STATIC); - break; - default: - errorcode = SQLITE_ERROR; - break; - } - return errorcode; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; } -char *dp_db_cond_get_text(char *table, char *column, char *condcolumn, - db_column_data_type condtype, void *condvalue) +int dp_db_get_cond_ids(void *handle, const char *table, const char *getcolumn, const char *column, const int value, int *ids, const int limit, int *error) { + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int rows_count = 0; sqlite3_stmt *stmt = NULL; - char *query = NULL; - int ret = -1; - - if (table == NULL) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return NULL; - } - - if (column == NULL) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return NULL; - } - if (condcolumn == NULL) { - TRACE_ERROR("[CHECK Condition]"); - return NULL; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("__dp_sql_open[%s]", sqlite3_errmsg(g_dp_db_handle)); - return NULL; - } - - query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ?", - column, table, condcolumn); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return NULL; - } - ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL); + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ?", getcolumn, table, column); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); sqlite3_free(query); - if ( ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return NULL; - } + DP_DB_BASIC_EXCEPTION_CHECK; - if (__dp_sql_bind_value(stmt, condtype, condvalue, 1) != SQLITE_OK) { - TRACE_ERROR - ("[BIND][%d][%s]", condtype, sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return NULL; - } - if (sqlite3_step(stmt) == SQLITE_ROW && - sqlite3_column_type(stmt, 0) == SQLITE_TEXT) { - int getbytes = sqlite3_column_bytes(stmt, 0); - if (getbytes > 0) { - char *getstr = (char *)calloc(getbytes + 1, sizeof(char)); - if (getstr != NULL) { - memcpy(getstr, sqlite3_column_text(stmt, 0), - getbytes * sizeof(char)); - getstr[getbytes] = '\0'; - } - __dp_finalize(stmt); - return getstr; + errorcode = sqlite3_bind_int(stmt, 1, value); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { + if (sqlite3_column_type(stmt, 0) == SQLITE_INTEGER) { + int columnvalue = sqlite3_column_int(stmt, 0); + //TRACE_DEBUG("id(%d):%d", rows_count, columnvalue); + ids[rows_count++] = columnvalue; } } __dp_finalize(stmt); - return NULL; + return rows_count; } -int dp_db_cond_get_int(char *table, char *column, char *condcolumn, - db_column_data_type condtype, void *condvalue) +int dp_db_get_cond_string(void *handle, const char *table, char *wherecolumn, const int wherevalue, const char *getcolumn, unsigned char **value, unsigned *length, int *error) { - sqlite3_stmt *stmt = NULL; - char *query = NULL; - int ret = -1; - - if (table == NULL) { - TRACE_ERROR("[CHECK TABLE NAME]"); + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (table == NULL || getcolumn == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query"); return -1; } - if (column == NULL) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return -1; - } - if (condcolumn == NULL) { - TRACE_ERROR("[CHECK Condition]"); - return -1; - } + if (wherecolumn == NULL) + wherecolumn = DP_DB_COL_ID; - if (__dp_sql_open() < 0) { - TRACE_ERROR("__dp_sql_open[%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ?", - column, table, condcolumn); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return -1; - } - ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL); + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ? LIMIT 1", getcolumn, table, wherecolumn); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); sqlite3_free(query); - if ( ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + DP_DB_BASIC_EXCEPTION_CHECK; - if (__dp_sql_bind_value(stmt, condtype, condvalue, 1) != SQLITE_OK) { - TRACE_ERROR - ("[BIND][%d][%s]", condtype, sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - if (sqlite3_step(stmt) == SQLITE_ROW && - sqlite3_column_type(stmt, 0) == SQLITE_INTEGER) { - int columnvalue = sqlite3_column_int(stmt, 0); - __dp_finalize(stmt); - return columnvalue; + errorcode = sqlite3_bind_int(stmt, 1, wherevalue); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else if (data_type == SQLITE_BLOB) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_blob(stmt, 0), getbytes * sizeof(unsigned char)); + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + }else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; } __dp_finalize(stmt); - return -1; + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; } -int dp_db_get_cond_rows_count(int id, char *table, - char *condcolumn, db_column_data_type condtype, - void *condvalue) +int dp_db_limit_rows(void *handle, const char *table, int limit, int *error) { - int errorcode = SQLITE_OK; - int ret = -1; - sqlite3_stmt *stmt = NULL; - char *query = NULL; - - if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (table == NULL) { + TRACE_ERROR("check materials for query"); return -1; } - - if (!table) { - TRACE_ERROR("[CHECK TABLE NAME]"); + if (limit < 0) { + TRACE_ERROR("check limitation:%d", limit); return -1; } - if (__dp_sql_open() < 0) { - TRACE_ERROR("db_util_open is failed [%s]", - sqlite3_errmsg(g_dp_db_handle)); - return -1; - } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s NOT IN (SELECT %s FROM %s ORDER BY %s ASC LIMIT ?)", table, DP_DB_COL_ID, DP_DB_COL_ID, table, DP_DB_COL_CREATE_TIME); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; - if (condcolumn) - query = - sqlite3_mprintf - ("SELECT count(id) FROM %s WHERE id = ? AND %s = ?", - table, condcolumn); - else - query = - sqlite3_mprintf - ("SELECT count(id) FROM %s WHERE id = ?", table); + errorcode = sqlite3_bind_int(stmt, 1, limit); + DP_DB_BASIC_EXCEPTION_CHECK; - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return -1; - } + // apply "ON DELETE CASCADE" - ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL); - sqlite3_free(query); - if (ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} - if (condcolumn) { - if (condtype == DP_DB_COL_TYPE_INT) { - int *cast_value = condvalue; - errorcode = sqlite3_bind_int(stmt, 2, *cast_value); - } else if (condtype == DP_DB_COL_TYPE_INT64) { -#ifdef SQLITE_INT64_TYPE - sqlite3_int64 *cast_value = condvalue; - errorcode = sqlite3_bind_int64(stmt, 2, *cast_value); -#else - int *cast_value = condvalue; - errorcode = sqlite3_bind_int(stmt, 2, *cast_value); -#endif - } else if (condtype == DP_DB_COL_TYPE_TEXT) { - errorcode = sqlite3_bind_text(stmt, 2, (char*)condvalue, -1, NULL); - } else { - TRACE_ERROR("[CHECK TYPE] Not Support [%d]", condtype); - __dp_finalize(stmt); - return -1; - } - if (errorcode != SQLITE_OK) { - TRACE_ERROR("[BIND] [%d] [%s]", - condtype, sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } +int dp_db_limit_time(void *handle, const char *table, int hours, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (table == NULL) { + TRACE_ERROR("check materials for query"); + return -1; } - - if (sqlite3_bind_int(stmt, 1, id) - != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int[%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); + if (hours <= 0) { + TRACE_ERROR("check limit time:%d", hours); return -1; } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_ROW) { - int count = sqlite3_column_int(stmt, 0); - __dp_finalize(stmt); - return count; - } - __dp_finalize(stmt); + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s < DATETIME('now','-%d hours')", table, DP_DB_COL_CREATE_TIME, hours); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; return 0; } -int dp_db_get_http_headers_list(int id, char **headers) +int dp_db_get_http_headers_list(void *handle, int id, char **headers, int *error) { int errorcode = SQLITE_OK; - int i = 0; int headers_index = 0; sqlite3_stmt *stmt = NULL; + *error = DP_ERROR_NONE; + DP_DB_PARAM_NULL_CHECK; if (id <= 0) { TRACE_ERROR("[CHECK ID]"); - return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("db_util_open is failed [%s]", - sqlite3_errmsg(g_dp_db_handle)); + *error = DP_ERROR_INVALID_PARAMETER; return -1; } errorcode = - sqlite3_prepare_v2(g_dp_db_handle, - "SELECT header_field, header_data FROM httpheaders WHERE id = ?", + sqlite3_prepare_v2(handle, + "SELECT header_field, header_data FROM header WHERE id = ?", -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("sqlite3_bind_int [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } + + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + + DP_DB_BASIC_EXCEPTION_CHECK; while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { int buffer_length = 0; char *header_field = (char *)(sqlite3_column_text(stmt, 0)); char *header_data = (char *)(sqlite3_column_text(stmt, 1)); - i++; + // REF : http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 buffer_length = strlen(header_field) + strlen(header_data) + 1; char *headers_buffer = calloc(buffer_length + 1, sizeof(char)); @@ -1750,600 +1316,7 @@ int dp_db_get_http_headers_list(int id, char **headers) } __dp_finalize(stmt); - return headers_index; -} - -static char *__merge_strings(char *dest, const char *src, char sep) -{ - int dest_length = 0; - int src_length = 0; - char *temp_dest = NULL; - - if (dest == NULL || src == NULL) - return NULL; - - dest_length = strlen(dest); - src_length = strlen(src); - - temp_dest = sqlite3_realloc(dest, dest_length + src_length + 1); - if (temp_dest == NULL) { - free(dest); - return NULL; - } - temp_dest = strncat(temp_dest, &sep, 1); - temp_dest = strncat(temp_dest, src, src_length); - return temp_dest; -} - -static char *__get_conds_query(int count, db_conds_list_fmt *conds, char *op) -{ - char *conditions = NULL; - int i = 0; - - if (count > 0 && conds != NULL) { - conditions = sqlite3_mprintf("WHERE"); - for (i = 0; i < count; i++) { - char *token = - sqlite3_mprintf("%s %s ?", conds[i].column, - (conds[i].is_like == 1 ? "LIKE" : "=")); - if (token != NULL) { - conditions = __merge_strings(conditions, token, ' '); - sqlite3_free(token); - token = NULL; - } - if (i < count - 1 && op) - conditions = __merge_strings(conditions, op, ' '); - } - } - return conditions; -} - -static int __bind_value(sqlite3_stmt *stmt, - db_column_data_type condtype, void *value, int index) -{ - int errorcode = SQLITE_ERROR; - int *cast_value = 0; - - if (stmt == NULL) - return SQLITE_ERROR; - - switch (condtype) { - case DP_DB_COL_TYPE_INT: - cast_value = value; - errorcode = sqlite3_bind_int(stmt, index, *cast_value); - break; - case DP_DB_COL_TYPE_INT64: -#ifdef SQLITE_INT64_TYPE - sqlite3_int64 *cast_value = value; - errorcode = sqlite3_bind_int64(stmt, index, *cast_value); -#else - cast_value = value; - errorcode = sqlite3_bind_int(stmt, index, *cast_value); -#endif - break; - case DP_DB_COL_TYPE_TEXT: - errorcode = - sqlite3_bind_text(stmt, index, (char *)value, -1, SQLITE_STATIC); - break; - default: - errorcode = SQLITE_ERROR; - break; - } - return errorcode; -} - -int dp_db_insert_columns(char *table, int column_count, - db_conds_list_fmt *columns) -{ - int errorcode = SQLITE_OK; - int ret = -1; - sqlite3_stmt *stmt = NULL; - char *query = NULL; - int i = 0; - - if (table == NULL) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return -1; - } - if (column_count <= 0) { - TRACE_ERROR("[CHECK db_conds_list_fmt count]"); - return -1; - } - if (__dp_sql_open() < 0) { - TRACE_ERROR("[SQL HANDLE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - query = - sqlite3_mprintf("INSERT INTO %s ", table); - query = __merge_strings(query, columns[0].column, '('); - for (i = 1; i < column_count; i++) { - char *column_query = NULL; - column_query = sqlite3_mprintf(", %s", columns[i].column); - query = __merge_strings(query, column_query, ' '); - sqlite3_free(column_query); - } - query = __merge_strings(query, " VALUES ", ')'); - query = __merge_strings(query, "?", '('); - for (i = 1; i < column_count; i++) { - query = __merge_strings(query, ", ?", ' '); - } - query = __merge_strings(query, ")", ' '); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return -1; - } - TRACE_DEBUG("query:%s", query); - - ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL); - sqlite3_free(query); - if ( ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - - for (i = 0; i < column_count; i++) { - if (__bind_value - (stmt, columns[i].type, columns[i].value, (i + 1)) != - SQLITE_OK) { - TRACE_ERROR("[BIND][%d][%s]", columns[i].type, - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - } - - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; - } - TRACE_ERROR("[SQL] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; -} - -int dp_db_update_columns(int id, char *table, int column_count, - db_conds_list_fmt *columns) -{ - int errorcode = SQLITE_OK; - int ret = -1; - sqlite3_stmt *stmt = NULL; - char *query = NULL; - int i = 0; - - if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return -1; - } - if (table == NULL) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return -1; - } - if (column_count <= 0) { - TRACE_ERROR("[CHECK db_conds_list_fmt count]"); - return -1; - } - if (__dp_sql_open() < 0) { - TRACE_ERROR("[SQL HANDLE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - query = - sqlite3_mprintf("UPDATE %s SET %s = ?", table, columns[0].column); - for (i = 1; i < column_count; i++) { - char *column_query = NULL; - column_query = sqlite3_mprintf("%s = ?", columns[i].column); - query = __merge_strings(query, column_query, ','); - sqlite3_free(column_query); - } - query = __merge_strings(query, "WHERE id = ?", ' '); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return -1; - } - TRACE_DEBUG("query:%s", query); - - ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL); - sqlite3_free(query); - if ( ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - - for (i = 0; i < column_count; i++) { - if (__bind_value - (stmt, columns[i].type, columns[i].value, (i + 1)) != - SQLITE_OK) { - TRACE_ERROR("[BIND][%d][%s]", columns[i].type, - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - } - if (sqlite3_bind_int(stmt, column_count + 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] ID [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - __dp_finalize(stmt); - return 0; - } - TRACE_ERROR("[SQL] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; -} - -int dp_db_get_conds_rows_count(char *table, - char *getcolumn, char *op, - int conds_count, db_conds_list_fmt *conds) -{ - int errorcode = SQLITE_OK; - int ret = -1; - sqlite3_stmt *stmt = NULL; - char *query = NULL; - int i = 0; - - if (table == NULL) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return -1; - } - if (getcolumn == NULL) { - TRACE_ERROR("[CHECK RESULT COLUMN]"); - return -1; - } - if (op == NULL) { - TRACE_ERROR("[CHECK OPERATOR] AND or OR"); - return -1; - } - if (conds_count <= 0) { - TRACE_ERROR("[CHECK db_conds_list_fmt count]"); - return -1; - } - if (__dp_sql_open() < 0) { - TRACE_ERROR("[SQL HANDLE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - query = - sqlite3_mprintf("SELECT count(%s) FROM %s", getcolumn, table); - - char *conditions = __get_conds_query(conds_count, conds, op); - if (conditions != NULL) { - query = __merge_strings(query, conditions, ' '); - sqlite3_free(conditions); - } - - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return -1; - } - - ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL); - sqlite3_free(query); - if (ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - for (i = 0; i < conds_count; i++) { - if (__bind_value - (stmt, conds[i].type, conds[i].value, (i + 1)) != - SQLITE_OK) { - TRACE_ERROR("[BIND][%d][%s]", conds[i].type, - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_ROW) { - int count = sqlite3_column_int(stmt, 0); - __dp_finalize(stmt); - return count; - } - __dp_finalize(stmt); - return 0; -} -int dp_db_get_conds_list(char *table, char *getcolumn, - db_column_data_type gettype, void **list, - int rowslimit, int rowsoffset, - char *ordercolumn, char *ordering, - char *op, int conds_count, - db_conds_list_fmt *conds) -{ - int errorcode = SQLITE_OK; - int rows_count = 0; - sqlite3_stmt *stmt = NULL; - int i = 0; - - if (table == NULL) { - TRACE_ERROR("[CHECK TABLE NAME]"); - return -1; - } - if (op == NULL) { - TRACE_ERROR("[CHECK OPERATOR] AND or OR"); - return -1; - } - if (getcolumn == NULL) { - TRACE_ERROR("[CHECK COLUMN NAME]"); - return -1; - } - if (conds_count <= 0) { - TRACE_ERROR("[CHECK db_conds_list_fmt count]"); - return -1; - } - if (__dp_sql_open() < 0) { - TRACE_ERROR("[SQL HANDLE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - char *limit = NULL; - char *order = NULL; - char *query = sqlite3_mprintf("SELECT %s FROM %s", getcolumn, table); - char *conditions = __get_conds_query(conds_count, conds, op); - if (conditions != NULL) { - query = __merge_strings(query, conditions, ' '); - sqlite3_free(conditions); - } - - if (ordercolumn != NULL) { - order = - sqlite3_mprintf - ("ORDER BY %s %s", ordercolumn, - (ordering == NULL ? "ASC" : ordering)); - if (order != NULL) { - query = __merge_strings(query, order, ' '); - sqlite3_free(order); - } - } - if (rowslimit > 0) { // 0 or negative : no limitation - if (rowsoffset >= 0) - limit = - sqlite3_mprintf("LIMIT %d OFFSET %d", rowslimit, - rowsoffset); - else - limit = sqlite3_mprintf("LIMIT %d", rowslimit); - if (limit != NULL) { - query = __merge_strings(query, limit, ' '); - sqlite3_free(limit); - } - } - - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return -1; - } - - errorcode = - sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL); - sqlite3_free(query); - if (errorcode != SQLITE_OK) { - TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - for (i = 0; i < conds_count; i++) { - if (__bind_value - (stmt, conds[i].type, conds[i].value, (i + 1)) != - SQLITE_OK) { - TRACE_ERROR - ("[BIND][%d][%s]", conds[i].type, - sqlite3_errmsg(g_dp_db_handle)); - __dp_finalize(stmt); - return -1; - } - } - while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { - switch (gettype) { - case DP_DB_COL_TYPE_INT: - { - int **list_int_p = (int **)list; - *list_int_p[rows_count++] = sqlite3_column_int(stmt, 0); - break; - } - case DP_DB_COL_TYPE_INT64: - { -#ifdef SQLITE_INT64_TYPE - long long **list_long_p = (long long **)list; - *list_long_p[rows_count++] = sqlite3_column_int64(stmt, 0); -#else - int **list_int_p = (int **)list; - *list_int_p[rows_count++] = sqlite3_column_int(stmt, 0); -#endif - break; - } - case DP_DB_COL_TYPE_TEXT: - { - int getbytes = sqlite3_column_bytes(stmt, 0); - if (getbytes > 0) { - char *getstr = (char *)calloc((getbytes + 1), sizeof(char)); - if (getstr != NULL) { - memcpy(getstr, sqlite3_column_text(stmt, 0), - getbytes * sizeof(char)); - getstr[getbytes] = '\0'; - list[rows_count++] = getstr; - } - } - break; - } - default: - break; - } - if (rows_count >= rowslimit) - break; - } - __dp_finalize(stmt); - return rows_count; -} - -static void __dp_db_reset(sqlite3_stmt *stmt) -{ - if (stmt != 0) { - sqlite3_clear_bindings(stmt); - if (sqlite3_reset(stmt) != SQLITE_OK) { - sqlite3 *handle = sqlite3_db_handle(stmt); - TRACE_ERROR("failed sqlite3_reset [%s]", - sqlite3_errmsg(handle)); - } - } -} - -int dp_db_request_new_logging(const int id, const int state, const char *pkgname) -{ - int errorcode = SQLITE_OK; - int ret = -1; - char *query = NULL; - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[SQL HANDLE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - if (g_dp_db_logging_new_stmt == NULL) { - query = - sqlite3_mprintf("INSERT INTO %s (%s, %s, %s, %s) VALUES (?, ?, ?, DATETIME('now'))", - DP_DB_TABLE_LOG, DP_DB_COL_ID, DP_DB_COL_STATE, - DP_DB_COL_PACKAGENAME, DP_DB_COL_CREATE_TIME); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return -1; - } - - TRACE_DEBUG("query:%s", query); - - ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &g_dp_db_logging_new_stmt, NULL); - sqlite3_free(query); - if (ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - } - if (sqlite3_bind_int(g_dp_db_logging_new_stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_db_reset(g_dp_db_logging_new_stmt); - return -1; - } - if (sqlite3_bind_int(g_dp_db_logging_new_stmt, 2, state) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_db_reset(g_dp_db_logging_new_stmt); - return -1; - } - if (sqlite3_bind_text(g_dp_db_logging_new_stmt, 3, pkgname, -1, SQLITE_STATIC) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_db_reset(g_dp_db_logging_new_stmt); - return -1; - } - - errorcode = sqlite3_step(g_dp_db_logging_new_stmt); - __dp_db_reset(g_dp_db_logging_new_stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - return 0; - } - return -1; -} - -int dp_db_request_update_status(const int id, const int state, const int download_error) -{ - int errorcode = SQLITE_OK; - int ret = -1; - char *query = NULL; - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[SQL HANDLE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - if (g_dp_db_logging_status_stmt == NULL) { - query = - sqlite3_mprintf("UPDATE %s SET %s = ?, %s = ?, %s = DATETIME('now') WHERE %s = ?", - DP_DB_TABLE_LOG, DP_DB_COL_STATE, DP_DB_COL_ERRORCODE, - DP_DB_COL_ACCESS_TIME, DP_DB_COL_ID); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return -1; - } - - TRACE_DEBUG("query:%s", query); - - ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &g_dp_db_logging_status_stmt, NULL); - sqlite3_free(query); - if (ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - } - if (sqlite3_bind_int(g_dp_db_logging_status_stmt, 1, state) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_db_reset(g_dp_db_logging_status_stmt); - return -1; - } - if (sqlite3_bind_int(g_dp_db_logging_status_stmt, 2, download_error) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_db_reset(g_dp_db_logging_status_stmt); - return -1; - } - if (sqlite3_bind_int(g_dp_db_logging_status_stmt, 3, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_db_reset(g_dp_db_logging_status_stmt); - return -1; - } - - errorcode = sqlite3_step(g_dp_db_logging_status_stmt); - __dp_db_reset(g_dp_db_logging_status_stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - return 0; - } - return -1; + return headers_index; } -int dp_db_get_state(int id) -{ - if (id <= 0) { - TRACE_ERROR("[CHECK ID]"); - return -1; - } - - if (__dp_sql_open() < 0) { - TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - - if (g_dp_db_logging_get_state_stmt == NULL) { - char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ?", - DP_DB_COL_STATE, DP_DB_TABLE_LOG, DP_DB_COL_ID); - if (query == NULL) { - TRACE_ERROR("[CHECK COMBINE]"); - return -1; - } - - TRACE_DEBUG("query:%s", query); - - int ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &g_dp_db_logging_get_state_stmt, NULL); - sqlite3_free(query); - if (ret != SQLITE_OK) { - TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle)); - return -1; - } - } - - if (sqlite3_bind_int(g_dp_db_logging_get_state_stmt, 1, id) != SQLITE_OK) { - TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle)); - __dp_db_reset(g_dp_db_logging_get_state_stmt); - return -1; - } - - int state = DP_STATE_NONE; - if (sqlite3_step(g_dp_db_logging_get_state_stmt) == SQLITE_ROW) { - state = sqlite3_column_int(g_dp_db_logging_get_state_stmt, 0); - } - __dp_db_reset(g_dp_db_logging_get_state_stmt); - return state; -} diff --git a/provider/download-provider-ipc.c b/provider/download-provider-ipc.c new file mode 100644 index 0000000..e79a6f7 --- /dev/null +++ b/provider/download-provider-ipc.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013 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 <time.h> + +#include <sys/socket.h> // shutdown + +#include "download-provider-log.h" +#include "download-provider-ipc.h" + +int dp_ipc_check_stderr(int basecode) +{ + int errorcode = basecode; + if (errno == EPIPE) { + TRACE_STRERROR("[EPIPE:%d] Broken Pipe", errno); + errorcode = DP_ERROR_IO_ERROR; + } else if (errno == EAGAIN) { + TRACE_STRERROR("[EAGAIN:%d]", errno); + errorcode = DP_ERROR_IO_EAGAIN; + } else if (errno == EINTR) { + TRACE_STRERROR("[EINTR:%d]", errno); + errorcode = DP_ERROR_IO_EINTR; + } else if (errno == ENOENT) { + TRACE_STRERROR("[ENOENT:%d]", errno); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_STRERROR("[errno:%d]", errno); + } + return errorcode; +} + +int dp_ipc_write(int sock, void *value, size_t type_size) +{ + if (sock < 0) { + TRACE_ERROR("[ERROR] check sock:%d", sock); + return -1; + } else if (value == NULL) { + TRACE_ERROR("[ERROR] check buffer sock:%d", sock); + return -1; + } else if (write(sock, value, type_size) <= 0) { + TRACE_STRERROR("[IPC.Write] exception sock:%d", sock); + return -1; + } + return 0; +} + +ssize_t dp_ipc_read(int sock, void *value, size_t type_size, + const char *func) +{ + int errorcode = DP_ERROR_NONE; + ssize_t recv_bytes = 0; + + if (sock < 0) { + TRACE_ERROR("[ERROR] %s check sock:%d", func, sock); + return -1; + } + if (value == NULL) { + TRACE_ERROR("[ERROR] %s check buffer sock:%d", func, sock); + return -1; + } + + int tryagain = 3; + do { + errorcode = DP_ERROR_NONE; + recv_bytes = read(sock, value, type_size); + if (recv_bytes < 0) { + TRACE_ERROR("[IPC.Read] %s exception sock:%d", func, sock); + errorcode = dp_ipc_check_stderr(DP_ERROR_IO_ERROR); + } else if (recv_bytes == 0) { + TRACE_ERROR("[ERROR] %s closed peer sock:%d", func, sock); + errorcode = DP_ERROR_IO_ERROR; + } + } while (sock >= 0 && (errorcode == DP_ERROR_IO_EAGAIN || + errorcode == DP_ERROR_IO_EINTR) && (--tryagain > 0)); + return recv_bytes; +} + +dp_ipc_fmt *dp_ipc_get_fmt(int sock) +{ + dp_ipc_fmt *ipc_info = malloc(sizeof(dp_ipc_fmt)); + if (ipc_info == NULL) { + TRACE_ERROR("[ERROR] Fail to malloc"); + return NULL; + } + memset(ipc_info, 0x00, sizeof(dp_ipc_fmt)); + ssize_t recv_size = read(sock, ipc_info, sizeof(dp_ipc_fmt)); + if (recv_size <= 0 || recv_size != sizeof(dp_ipc_fmt)) { + TRACE_STRERROR("socket read ipcinfo read size:%d", recv_size); + free(ipc_info); + return NULL; + } + return ipc_info; +} + +int dp_ipc_query(int sock, int download_id, short section, + unsigned property, int error, size_t size) +{ + dp_ipc_fmt ipc_info; + memset(&ipc_info, 0x00, sizeof(dp_ipc_fmt)); + ipc_info.section = section; + ipc_info.property = property; + ipc_info.id = download_id; + ipc_info.errorcode = error; + ipc_info.size = size; + if (dp_ipc_write(sock, &ipc_info, sizeof(dp_ipc_fmt)) < 0) + return -1; + return 0; +} + +int dp_ipc_socket_free(int sockfd) +{ + if (sockfd < 0) + return -1; + close(sockfd); + return 0; +} diff --git a/provider/download-provider-main.c b/provider/download-provider-main.c index 6e71cb5..ded45db 100755 --- a/provider/download-provider-main.c +++ b/provider/download-provider-main.c @@ -17,295 +17,50 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <glib.h> -#include <glib-object.h> #include <pthread.h> -#include <locale.h> -#include <libintl.h> -#include <systemd/sd-daemon.h> -#include "vconf.h" +#include <systemd/sd-daemon.h> +#include <glib-object.h> #include "download-provider-config.h" #include "download-provider-log.h" -#include "download-provider-socket.h" -#include "download-provider-pthread.h" -#include "download-provider-slots.h" -#include "download-provider-db.h" +#include "download-provider-client-manager.h" #include "download-provider-network.h" -#include "download-provider-queue.h" -#include "download-provider-notification.h" -#include "download-provider-da-interface.h" - -// declare functions -int dp_lock_pid(char *path); -void *dp_thread_requests_manager(void *arg); -static pthread_t g_dp_thread_queue_manager_pid = 0; - -// declare global variables -// need for libsoup, decided the life-time by mainloop. -GMainLoop *g_main_loop_handle = 0; - -void dp_terminate(int signo) -{ - TRACE_DEBUG("Received SIGTERM:%d", signo); - if (g_main_loop_is_running(g_main_loop_handle)) - g_main_loop_quit(g_main_loop_handle); -} - -static gboolean __dp_idle_start_service(void *data) -{ - // declare all resources - pthread_t thread_pid; - pthread_attr_t thread_attr; - - // initialize - if (pthread_attr_init(&thread_attr) != 0) { - TRACE_STRERROR("failed to init pthread attr"); - dp_terminate(SIGTERM); - return FALSE; - } - if (pthread_attr_setdetachstate(&thread_attr, - PTHREAD_CREATE_DETACHED) != 0) { - TRACE_STRERROR("failed to set detach option"); - dp_terminate(SIGTERM); - return FALSE; - } - - // create thread for managing QUEUEs - if (pthread_create - (&g_dp_thread_queue_manager_pid, NULL, dp_thread_queue_manager, - data) != 0) { - TRACE_STRERROR - ("failed to create pthread for run_manage_download_server"); - dp_terminate(SIGTERM); - } - // start service, accept url-download ( client package ) - if (pthread_create - (&thread_pid, &thread_attr, dp_thread_requests_manager, - data) != 0) { - TRACE_STRERROR - ("failed to create pthread for run_manage_download_server"); - dp_terminate(SIGTERM); - } - return FALSE; -} - -void __set_locale() -{ - char *str = NULL; - str = vconf_get_str(VCONFKEY_LANGSET); - if (str != NULL) { - setlocale(LC_ALL, str); - bindtextdomain(PKG_NAME, LOCALE_DIR); - textdomain(PKG_NAME); - } - free(str); -} -void __lang_changed_cb(keynode_t *key, void* data) -{ - __set_locale(); -} +void *dp_client_manager(void *arg); int main(int argc, char **argv) { - dp_privates *privates = NULL; - int lock_fd = -1; - - if (chdir("/") < 0) { - TRACE_STRERROR("failed to call setsid or chdir"); - exit(EXIT_FAILURE); - } - -#if 0 - // close all console I/O - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); -#endif - - if (signal(SIGTERM, dp_terminate) == SIG_ERR) { - TRACE_ERROR("failed to register signal callback"); - exit(EXIT_FAILURE); - } - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { - TRACE_ERROR("failed to register signal callback"); - exit(EXIT_FAILURE); - } - if (signal(SIGINT, dp_terminate) == SIG_ERR) { - TRACE_ERROR("failed to register signal callback"); - exit(EXIT_FAILURE); - } - // write IPC_FD_PATH. and lock - if ((lock_fd = dp_lock_pid(DP_LOCK_PID)) < 0) { - TRACE_ERROR - ("It need to check download-provider is already alive"); - TRACE_ERROR("Or fail to create pid file in (%s)", - DP_LOCK_PID); - exit(EXIT_FAILURE); - } + GMainLoop *event_loop; + pthread_t tid; + TRACE_INFO("download-provider's working is started"); g_type_init(); - // locale - __set_locale(); - if (vconf_notify_key_changed(VCONFKEY_LANGSET, __lang_changed_cb, NULL) != 0) - TRACE_ERROR("Fail to set language changed vconf callback"); - - privates = (dp_privates *) calloc(1, sizeof(dp_privates)); - if (!privates) { - TRACE_ERROR("[CRITICAL] failed to alloc for private info"); - goto DOWNLOAD_EXIT; - } - privates->groups = dp_client_group_slots_new(DP_MAX_GROUP); - if (privates->groups == NULL) { - TRACE_ERROR("[CRITICAL] failed to alloc for groups"); - goto DOWNLOAD_EXIT; + event_loop = g_main_loop_new(NULL, FALSE); + if (!event_loop) { + TRACE_ERROR("Failed to create g main loop handle"); + return 0; } - privates->requests = dp_request_slots_new(DP_MAX_REQUEST); - if (privates->requests == NULL) { - TRACE_ERROR("[CRITICAL] failed to alloc for requests"); - goto DOWNLOAD_EXIT; + // check network status + if (dp_network_connection_init() < 0) { + TRACE_ERROR("failed to init network-manager"); + return 0; } - - // ready socket ( listen ) - privates->listen_fd = dp_accept_socket_new(); - if (privates->listen_fd < 0) { - TRACE_ERROR("[CRITICAL] failed to bind SOCKET"); - goto DOWNLOAD_EXIT; + // create a thread for main thread + if (pthread_create(&tid, NULL, dp_client_manager, (void *)event_loop) != 0) { + TRACE_ERROR("failed to create main thread"); + return 0; + } else { + pthread_detach(tid); + TRACE_INFO("download main thread is created[%lu]", tid); } - dp_db_open(); - - // convert to request type, insert all to privates->requests - // timeout of request thread will start these jobs by queue thread - // load all list from (queue table) - if (dp_db_crashed_list(privates->requests, DP_MAX_REQUEST) > 0) { - int i = 0; - for (i = 0; i < DP_MAX_REQUEST; i++) { - if (!privates->requests[i].request) - continue; - dp_request *request = privates->requests[i].request; - TRACE_DEBUG - ("ID [%d] state[%d]", request->id, request->state); - - // load to memory, Can be started automatically. - if (request->state == DP_STATE_DOWNLOADING || - request->state == DP_STATE_CONNECTING) { - request->state = DP_STATE_QUEUED; - if (dp_db_set_column - (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE, - DP_DB_COL_TYPE_INT, &request->state) < 0) { - TRACE_ERROR("[CHECK SQL]"); - } - } - - if (request->state == DP_STATE_QUEUED) { - int auto_download = dp_db_get_int_column(request->id, - DP_DB_TABLE_REQUEST_INFO, - DP_DB_COL_AUTO_DOWNLOAD); - if (auto_download == 1) { - // auto retry... defaultly, show notification - request->auto_notification = 1; - request->start_time = (int)time(NULL); - continue; - } - // do not retry this request - request->state = DP_STATE_FAILED; - request->error = DP_ERROR_SYSTEM_DOWN; - if (dp_db_set_column - (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE, - DP_DB_COL_TYPE_INT, &request->state) < 0) { - TRACE_ERROR("[CHECK SQL]"); - } - if (dp_db_set_column - (request->id, DP_DB_TABLE_LOG, - DP_DB_COL_ERRORCODE, DP_DB_COL_TYPE_INT, - &request->error) < 0) { - TRACE_ERROR("[CHECK SQL]"); - } - } + TRACE_INFO("g main loop is started"); + g_main_loop_run(event_loop); + dp_network_connection_destroy(); + g_main_loop_unref(event_loop); - // if wanna restart, call continue before this line. - // default. update state/error. move to history. unload memory - // remove from memory - dp_request_free(request); - privates->requests[i].request = NULL; - } - } // query crashed_list - -#if 0 - if (argc != 2 || memcmp(argv[1], "service", 7) != 0) { - // in first launch in booting time, not request. terminate by self - if (dp_get_request_count(privates->requests) <= 0) { - TRACE_DEBUG("First Boot, No Request"); - goto DOWNLOAD_EXIT; - } - } -#endif - - dp_clear_downloadinginfo_notification(); - - if (dp_init_agent() != DP_ERROR_NONE) { - TRACE_ERROR("[CRITICAL] failed to init agent"); - goto DOWNLOAD_EXIT; - } - - privates->connection = 0; - privates->network_status = DP_NETWORK_TYPE_OFF; - if (dp_network_connection_init(privates) < 0) { - TRACE_DEBUG("use instant network check"); - privates->connection = 0; - } - - // libsoup need mainloop. - g_main_loop_handle = g_main_loop_new(NULL, 0); - - g_idle_add(__dp_idle_start_service, privates); - - sd_notify(0, "READY=1"); - - g_main_loop_run(g_main_loop_handle); - -DOWNLOAD_EXIT : - - TRACE_DEBUG("Download-Provider will be terminated."); - if (vconf_ignore_key_changed(VCONFKEY_LANGSET, __lang_changed_cb) != 0) - TRACE_ERROR("Fail to unset language changed vconf callback"); - - dp_deinit_agent(); - - if (privates != NULL) { - - if (privates->connection) - dp_network_connection_destroy(privates->connection); - - if (privates->listen_fd >= 0) - privates->listen_fd = -1; - - if (g_dp_thread_queue_manager_pid > 0 && - pthread_kill(g_dp_thread_queue_manager_pid, 0) != ESRCH) { - //pthread_cancel(g_dp_thread_queue_manager_pid); - //send signal to queue thread - dp_thread_queue_manager_wake_up(); - int status; - pthread_join(g_dp_thread_queue_manager_pid, (void **)&status); - g_dp_thread_queue_manager_pid = 0; - } - dp_request_slots_free(privates->requests, DP_MAX_REQUEST); - privates->requests = NULL; - dp_client_group_slots_free(privates->groups, DP_MAX_GROUP); - privates->groups = NULL; - free(privates); - privates = NULL; - } - dp_db_close(); - - // delete pid file - if (access(DP_LOCK_PID, F_OK) == 0) { - close(lock_fd); - unlink(DP_LOCK_PID); - } - exit(EXIT_SUCCESS); + TRACE_INFO("download-provider's working is done"); + return 0; } diff --git a/provider/download-provider-network.c b/provider/download-provider-network.c index ac3fc5b..5fafe2c 100755 --- a/provider/download-provider-network.c +++ b/provider/download-provider-network.c @@ -14,224 +14,130 @@ * limitations under the License. */ +#include "download-provider.h" #include "download-provider-log.h" -#include "download-provider-config.h" #include "download-provider-pthread.h" #include "download-provider-network.h" +#include "download-provider-client-manager.h" + +#include <net_connection.h> #ifdef SUPPORT_WIFI_DIRECT #include <wifi-direct.h> #endif -extern pthread_mutex_t g_dp_queue_mutex; -extern pthread_cond_t g_dp_queue_cond; - -#if 0 -typedef enum -{ - CONNECTION_TYPE_DISCONNECTED = 0, /**< Disconnected */ - CONNECTION_TYPE_WIFI = 1, /**< Wi-Fi type */ - CONNECTION_TYPE_CELLULAR = 2, /**< Cellular type */ - CONNECTION_TYPE_ETHERNET = 3, /**< Ethernet type */ - CONNECTION_TYPE_BT = 4, /**< Bluetooth type */ -} connection_type_e; -typedef enum -{ - CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE = 0, /**< Out of service */ - CONNECTION_CELLULAR_STATE_FLIGHT_MODE = 1, /**< Flight mode */ - CONNECTION_CELLULAR_STATE_ROAMING_OFF = 2, /**< Roaming is turned off */ - CONNECTION_CELLULAR_STATE_CALL_ONLY_AVAILABLE = 3, /**< Call is only available */ - CONNECTION_CELLULAR_STATE_AVAILABLE = 4, /**< Available but not connected yet */ - CONNECTION_CELLULAR_STATE_CONNECTED = 5, /**< Connected */ -} connection_cellular_state_e -typedef enum -{ - CONNECTION_WIFI_STATE_DEACTIVATED = 0, /**< Deactivated state */ - CONNECTION_WIFI_STATE_DISCONNECTED = 1, /**< disconnected state */ - CONNECTION_WIFI_STATE_CONNECTED = 2, /**< Connected state */ -} connection_wifi_state_e; -typedef enum -{ - CONNECTION_ETHERNET_STATE_DEACTIVATED = 0, /**< Deactivated state */ - CONNECTION_ETHERNET_STATE_DISCONNECTED = 1, /**< disconnected state */ - CONNECTION_ETHERNET_STATE_CONNECTED = 2, /**< Connected state */ -} connection_ethernet_state_e; -typedef enum -{ - CONNECTION_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ - CONNECTION_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ - CONNECTION_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory error */ - CONNECTION_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid Operation */ - CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED = TIZEN_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED, /**< Address family not supported */ - CONNECTION_ERROR_OPERATION_FAILED = TIZEN_ERROR_NETWORK_CLASS|0x0401, /**< Operation failed */ - CONNECTION_ERROR_ITERATOR_END = TIZEN_ERROR_NETWORK_CLASS|0x0402, /**< End of iteration */ - CONNECTION_ERROR_NO_CONNECTION = TIZEN_ERROR_NETWORK_CLASS|0x0403, /**< There is no connection */ - CONNECTION_ERROR_NOW_IN_PROGRESS = TIZEN_ERROR_NOW_IN_PROGRESS, /** Now in progress */ - CONNECTION_ERROR_ALREADY_EXISTS = TIZEN_ERROR_NETWORK_CLASS|0x0404, /**< Already exists */ - CONNECTION_ERROR_OPERATION_ABORTED = TIZEN_ERROR_NETWORK_CLASS|0x0405, /**< Operation is aborted */ - CONNECTION_ERROR_DHCP_FAILED = TIZEN_ERROR_NETWORK_CLASS|0x0406, /**< DHCP failed */ - CONNECTION_ERROR_INVALID_KEY = TIZEN_ERROR_NETWORK_CLASS|0x0407, /**< Invalid key */ - CONNECTION_ERROR_NO_REPLY = TIZEN_ERROR_NETWORK_CLASS|0x0408, /**< No reply */ -} connection_error_e; - +pthread_mutex_t g_dp_network_mutex = PTHREAD_MUTEX_INITIALIZER; +int g_network_status = DP_NETWORK_OFF; +connection_h g_network_connection = 0; +int g_network_is_wifi_direct = 0; -static void __print_connection_errorcode_to_string(connection_error_e errorcode) -{ - switch(errorcode) - { - case CONNECTION_ERROR_INVALID_PARAMETER : - TRACE_DEBUG("CONNECTION_ERROR_INVALID_PARAMETER"); - break; - case CONNECTION_ERROR_OUT_OF_MEMORY : - TRACE_DEBUG("CONNECTION_ERROR_OUT_OF_MEMORY"); - break; - case CONNECTION_ERROR_INVALID_OPERATION : - TRACE_DEBUG("CONNECTION_ERROR_INVALID_OPERATION"); - break; - case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED : - TRACE_DEBUG("CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED"); - break; - case CONNECTION_ERROR_OPERATION_FAILED : - TRACE_DEBUG("CONNECTION_ERROR_OPERATION_FAILED"); - break; - case CONNECTION_ERROR_ITERATOR_END : - TRACE_DEBUG("CONNECTION_ERROR_ITERATOR_END"); - break; - case CONNECTION_ERROR_NO_CONNECTION : - TRACE_DEBUG("CONNECTION_ERROR_NO_CONNECTION"); - break; - case CONNECTION_ERROR_NOW_IN_PROGRESS : - TRACE_DEBUG("CONNECTION_ERROR_NOW_IN_PROGRESS"); - break; - case CONNECTION_ERROR_ALREADY_EXISTS : - TRACE_DEBUG("CONNECTION_ERROR_ALREADY_EXISTS"); - break; - case CONNECTION_ERROR_OPERATION_ABORTED : - TRACE_DEBUG("CONNECTION_ERROR_OPERATION_ABORTED"); - break; - case CONNECTION_ERROR_DHCP_FAILED : - TRACE_DEBUG("CONNECTION_ERROR_DHCP_FAILED"); - break; - case CONNECTION_ERROR_INVALID_KEY : - TRACE_DEBUG("CONNECTION_ERROR_INVALID_KEY"); - break; - case CONNECTION_ERROR_NO_REPLY : - TRACE_DEBUG("CONNECTION_ERROR_NO_REPLY"); - break; - default : - TRACE_DEBUG("CONNECTION_ERROR_NONE"); - break; - } -} +#ifdef SUPPORT_COMPANION_MODE +// support B3 companion mode +#include "vconf.h" +#include "vconf-keys.h" +#include "SAPInterface.h" +#define VCONFKEY_SAP_CONNECTION_NOTIFICATION VCONFKEY_WMS_WMANAGER_CONNECTED +#define VCONFKEY_SAP_CONNECTION_TYPE "memory/private/sap/conn_type" #endif - -#ifdef SUPPORT_WIFI_DIRECT -// support WIFI-Direct -static void __dp_network_wifi_direct_connection_state_changed_cb(wifi_direct_error_e error_code, wifi_direct_connection_state_e connection_state, const char *mac_address, void *data) +static int __dp_network_is_companion_mode() { - dp_privates *privates = (dp_privates*)data; - if (privates == NULL) { - TRACE_ERROR("[CRITICAL] Invalid data"); - return ; - } +#ifdef SUPPORT_COMPANION_MODE + int wms_connected = 0; + int companion_mode = 0; + vconf_get_int(VCONFKEY_SAP_CONNECTION_NOTIFICATION, &wms_connected); + vconf_get_int(VCONFKEY_SAP_CONNECTION_TYPE, &companion_mode); + TRACE_INFO("wms_connected:%d, companion_mode:%d", wms_connected, companion_mode); + if (wms_connected == 1 && (companion_mode & SAP_BT)) + return 1; - if (connection_state == WIFI_DIRECT_CONNECTION_RSP) { - TRACE_DEBUG("WIFI_DIRECT_CONNECTION_RSP"); - privates->is_connected_wifi_direct = 1; - return ; - } - privates->is_connected_wifi_direct = 0; +#endif + return 0; } -//return 0 : connected -int dp_network_wifi_direct_is_connected() +#ifdef SUPPORT_WIFI_DIRECT + +static int __dp_network_wifi_direct_status() { - int is_connected = -1; + int is_connected = 0; wifi_direct_state_e wifi_state = WIFI_DIRECT_STATE_DEACTIVATED; if (wifi_direct_get_state(&wifi_state) == 0) { - switch (wifi_state) - { - case WIFI_DIRECT_STATE_DEACTIVATED : - TRACE_DEBUG("WIFI_DIRECT_STATE_DEACTIVATED"); - break; - case WIFI_DIRECT_STATE_DEACTIVATING : - TRACE_DEBUG("WIFI_DIRECT_STATE_DEACTIVATING"); - break; - case WIFI_DIRECT_STATE_ACTIVATING : - TRACE_DEBUG("WIFI_DIRECT_STATE_ACTIVATING"); - break; - case WIFI_DIRECT_STATE_ACTIVATED : - TRACE_DEBUG("WIFI_DIRECT_STATE_ACTIVATED"); - break; - case WIFI_DIRECT_STATE_DISCOVERING : - TRACE_DEBUG("WIFI_DIRECT_STATE_DISCOVERING"); - break; - case WIFI_DIRECT_STATE_CONNECTING : - TRACE_DEBUG("WIFI_DIRECT_STATE_CONNECTING"); - break; - case WIFI_DIRECT_STATE_DISCONNECTING : - TRACE_DEBUG("WIFI_DIRECT_STATE_DISCONNECTING"); - break; - case WIFI_DIRECT_STATE_CONNECTED : - is_connected = 0; - TRACE_DEBUG("WIFI_DIRECT_STATE_CONNECTED"); - break; - default : - break; + if (wifi_state == WIFI_DIRECT_STATE_CONNECTED) { + TRACE_INFO("WIFI_DIRECT_STATE_CONNECTED"); + is_connected = 1; } } return is_connected; } -#endif +// support WIFI-Direct +static void __dp_network_wifi_direct_changed_cb + (wifi_direct_error_e error_code, + wifi_direct_connection_state_e connection_state, + const char *mac_address, void *data) +{ + pthread_mutex_lock(&g_dp_network_mutex); + if (connection_state == WIFI_DIRECT_CONNECTION_RSP) { + TRACE_INFO("WIFI_DIRECT_CONNECTION_RSP"); + g_network_is_wifi_direct = __dp_network_wifi_direct_status(); + } else { + TRACE_INFO("WIFI_DIRECT_DISCONNECTION"); + g_network_is_wifi_direct = 0; + } + pthread_mutex_unlock(&g_dp_network_mutex); +} +#endif ////////////////////////////////////////////////////////////////////////// /// @brief check the status in more detail by connection type /// @return dp_network_type -static dp_network_type __dp_get_network_connection_status(connection_h connection, connection_type_e type) +static int __dp_get_network_connection_status(connection_h connection, connection_type_e type) { - dp_network_type network_type = DP_NETWORK_TYPE_OFF; - if (type == CONNECTION_TYPE_WIFI) { + int network_type = DP_NETWORK_OFF; + if (__dp_network_is_companion_mode() == 1) { + network_type = DP_NETWORK_ALL; + TRACE_INFO("COMPANION MODE"); + } else if (type == CONNECTION_TYPE_WIFI) { connection_wifi_state_e wifi_state; wifi_state = CONNECTION_WIFI_STATE_DEACTIVATED; - if (connection_get_wifi_state - (connection, &wifi_state) != CONNECTION_ERROR_NONE) + if (connection_get_wifi_state(connection, &wifi_state) != + CONNECTION_ERROR_NONE) { TRACE_ERROR("Failed connection_get_wifi_state"); - if (wifi_state == CONNECTION_WIFI_STATE_CONNECTED) { - TRACE_DEBUG("[CONNECTION_WIFI] CONNECTED"); - network_type = DP_NETWORK_TYPE_WIFI; } else { - TRACE_DEBUG("[CONNECTION_WIFI] [%d]", wifi_state); + if (wifi_state == CONNECTION_WIFI_STATE_CONNECTED) { + TRACE_INFO("WIFI CONNECTED"); + network_type = DP_NETWORK_WIFI; + } } } else if (type == CONNECTION_TYPE_CELLULAR) { connection_cellular_state_e cellular_state; cellular_state = CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE; - if (connection_get_cellular_state - (connection, &cellular_state) != CONNECTION_ERROR_NONE) + if (connection_get_cellular_state(connection, + &cellular_state) != CONNECTION_ERROR_NONE) { TRACE_ERROR("Failed connection_get_cellular_state"); - if (cellular_state == CONNECTION_CELLULAR_STATE_CONNECTED) { - TRACE_DEBUG("[CONNECTION_CELLULAR] DATA NETWORK CONNECTED"); - network_type = DP_NETWORK_TYPE_DATA_NETWORK; } else { - TRACE_DEBUG("[CONNECTION_CELLULAR] [%d]", cellular_state); + if (cellular_state == CONNECTION_CELLULAR_STATE_CONNECTED) { + TRACE_INFO("DATA NETWORK CONNECTED"); + network_type = DP_NETWORK_DATA_NETWORK; + } } } else if (type == CONNECTION_TYPE_ETHERNET) { connection_ethernet_state_e ethernet_state; ethernet_state = CONNECTION_ETHERNET_STATE_DISCONNECTED; - if (connection_get_ethernet_state - (connection, ðernet_state) != CONNECTION_ERROR_NONE) + if (connection_get_ethernet_state(connection, + ðernet_state) != CONNECTION_ERROR_NONE) { TRACE_ERROR("Failed connection_get_ethernet_state"); - if (ethernet_state == CONNECTION_ETHERNET_STATE_CONNECTED) { - TRACE_DEBUG("[CONNECTION_ETHERNET] ETHERNET CONNECTED"); - network_type = DP_NETWORK_TYPE_ETHERNET; } else { - TRACE_DEBUG("[CONNECTION_ETHERNET] [%d]", ethernet_state); + if (ethernet_state == CONNECTION_ETHERNET_STATE_CONNECTED) { + TRACE_INFO("ETHERNET CONNECTED"); + network_type = DP_NETWORK_WIFI; + } } } else { - TRACE_DEBUG("[DISCONNECTED]"); - network_type = DP_NETWORK_TYPE_OFF; + TRACE_INFO("DISCONNECTED"); + network_type = DP_NETWORK_OFF; } + g_network_status = network_type; return network_type; } @@ -240,33 +146,25 @@ static dp_network_type __dp_get_network_connection_status(connection_h connectio /// @todo care requests by network status static void __dp_network_connection_type_changed_cb(connection_type_e type, void *data) { - dp_privates *privates = (dp_privates*)data; - if (privates == NULL) { - TRACE_ERROR("[CRITICAL] Invalid data"); - return ; - } - CLIENT_MUTEX_LOCK(&(g_dp_queue_mutex)); - #if 1 // this callback guarantee that already connectdd - if (type == CONNECTION_TYPE_WIFI) { - TRACE_DEBUG("[CONNECTION_WIFI] CONNECTED"); - privates->network_status = DP_NETWORK_TYPE_WIFI; + pthread_mutex_lock(&g_dp_network_mutex); + // this callback guarantee that already connected + if (__dp_network_is_companion_mode() == 1) { + TRACE_INFO("COMPANION MODE"); + g_network_status = DP_NETWORK_ALL; + } else if (type == CONNECTION_TYPE_WIFI) { + TRACE_INFO("WIFI CONNECTED"); + g_network_status = DP_NETWORK_WIFI; } else if (type == CONNECTION_TYPE_CELLULAR) { - TRACE_DEBUG("[CONNECTION_CELLULAR] DATA NETWORK CONNECTED"); - privates->network_status = DP_NETWORK_TYPE_DATA_NETWORK; + TRACE_INFO("DATA NETWORK CONNECTED"); + g_network_status = DP_NETWORK_DATA_NETWORK; } else if (type == CONNECTION_TYPE_ETHERNET) { - TRACE_DEBUG("[CONNECTION_ETHERNET] ETHERNET CONNECTED"); - privates->network_status = DP_NETWORK_TYPE_ETHERNET; + TRACE_INFO("ETHERNET CONNECTED"); + g_network_status = DP_NETWORK_WIFI; } else { - TRACE_DEBUG("[DISCONNECTED]"); - privates->network_status = DP_NETWORK_TYPE_OFF; + TRACE_INFO("DISCONNECTED"); + g_network_status = DP_NETWORK_OFF; } - if (privates->network_status != DP_NETWORK_TYPE_OFF) - pthread_cond_signal(&g_dp_queue_cond); - #else - privates->network_status = - __dp_get_network_connection_status(privates->connection, type); - #endif - CLIENT_MUTEX_UNLOCK(&(g_dp_queue_mutex)); + pthread_mutex_unlock(&g_dp_network_mutex); } ////////////////////////////////////////////////////////////////////////// @@ -274,124 +172,96 @@ static void __dp_network_connection_type_changed_cb(connection_type_e type, void /// @todo auto resume feature static void __dp_network_connection_ip_changed_cb(const char *ip, const char *ipv6, void *data) { - dp_privates *privates = (dp_privates*)data; - if (privates == NULL) { - TRACE_ERROR("[CRITICAL] Invalid data"); - return ; - } - if (privates->network_status != DP_NETWORK_TYPE_OFF) { - dp_request_slots *requests = privates->requests; - int i = 0; - for (i = 0; i < DP_MAX_REQUEST; i++) { - int locked = pthread_mutex_trylock(&requests[i].mutex); - // locking failure means it used by other thread. - if (locked == 0) { - if (requests[i].request != NULL) { - if (requests[i].request->state == DP_STATE_DOWNLOADING || - (requests[i].request->state == DP_STATE_FAILED && - requests[i].request->error == DP_ERROR_CONNECTION_FAILED)) { - requests[i].request->ip_changed = 1; - } - } - CLIENT_MUTEX_UNLOCK(&requests[i].mutex); - } - } + if (dp_network_get_status() != DP_NETWORK_OFF) { + TRACE_DEBUG("[CONNECTION] IP CHANGED"); + // broadcast to all thread for clients + dp_broadcast_signal(); } } +int dp_network_get_status() +{ + int status = DP_NETWORK_OFF; + pthread_mutex_lock(&g_dp_network_mutex); + status = g_network_status; + pthread_mutex_unlock(&g_dp_network_mutex); + return status; +} + +int dp_network_is_wifi_direct() +{ + pthread_mutex_lock(&g_dp_network_mutex); + int status = g_network_is_wifi_direct; + pthread_mutex_unlock(&g_dp_network_mutex); + return status; +} + ////////////////////////////////////////////////////////////////////////// /// @brief create connection handle & regist callback /// @return 0 : success -1 : failed -int dp_network_connection_init(dp_privates *privates) +int dp_network_connection_init() { int retcode = 0; - if (!privates) { - TRACE_ERROR("[CRITICAL] Invalid data"); - return -1; - } - #ifdef SUPPORT_WIFI_DIRECT if (wifi_direct_initialize() == 0) { wifi_direct_set_connection_state_changed_cb - (__dp_network_wifi_direct_connection_state_changed_cb, privates); - if (dp_network_wifi_direct_is_connected() == 0) - privates->is_connected_wifi_direct = 1; + (__dp_network_wifi_direct_changed_cb, NULL); + g_network_is_wifi_direct = __dp_network_wifi_direct_status(); } #endif - if ((retcode = connection_create(&privates->connection)) != + if ((retcode = connection_create(&g_network_connection)) != CONNECTION_ERROR_NONE) { TRACE_ERROR("Failed connection_create [%d]", retcode); return -1; } - if ((retcode = connection_set_type_changed_cb - (privates->connection, __dp_network_connection_type_changed_cb, - privates)) != CONNECTION_ERROR_NONE) { + if ((retcode = connection_set_type_changed_cb(g_network_connection, + __dp_network_connection_type_changed_cb, NULL)) != + CONNECTION_ERROR_NONE) { TRACE_ERROR("Failed connection_set_type_changed_cb [%d]", retcode); - connection_destroy(privates->connection); + connection_destroy(g_network_connection); + g_network_connection = 0; return -1; } + if ((retcode = connection_set_ip_address_changed_cb - (privates->connection, __dp_network_connection_ip_changed_cb, - privates)) != CONNECTION_ERROR_NONE) { + (g_network_connection, __dp_network_connection_ip_changed_cb, + NULL)) != CONNECTION_ERROR_NONE) { TRACE_ERROR("Failed __dp_network_connection_ip_changed_cb [%d]", retcode); - connection_destroy(privates->connection); + connection_destroy(g_network_connection); + g_network_connection = 0; return -1; } + connection_type_e type = CONNECTION_TYPE_DISCONNECTED; - if ((retcode = connection_get_type(privates->connection, &type)) != + if ((retcode = connection_get_type(g_network_connection, &type)) != CONNECTION_ERROR_NONE) { TRACE_ERROR("Failed connection_get_type [%d]", retcode); - connection_destroy(privates->connection); + connection_destroy(g_network_connection); + g_network_connection = 0; return -1; } - privates->network_status = - __dp_get_network_connection_status(privates->connection, type); + g_network_status = + __dp_get_network_connection_status(g_network_connection, type); return 0; } ////////////////////////////////////////////////////////////////////////// /// @brief destroy connection handle -void dp_network_connection_destroy(connection_h connection) +void dp_network_connection_destroy() { + pthread_mutex_lock(&g_dp_network_mutex); #ifdef SUPPORT_WIFI_DIRECT wifi_direct_unset_connection_state_changed_cb(); wifi_direct_deinitialize(); #endif - connection_unset_type_changed_cb(connection); - connection_unset_ip_address_changed_cb(connection); - connection_destroy(connection); -} - -////////////////////////////////////////////////////////////////////////// -/// @brief check network status using connection API -/// @todo the standard of enabled networking can be changed later -/// @return Network type -dp_network_type dp_get_network_connection_instant_status() -{ - int retcode = 0; - connection_h network_handle = NULL; - dp_network_type network_type = DP_NETWORK_TYPE_OFF; - if ((retcode = connection_create(&network_handle)) != - CONNECTION_ERROR_NONE) { - TRACE_ERROR("Failed connection_create [%d]", retcode); - return DP_NETWORK_TYPE_OFF; + if (g_network_connection != 0) { + connection_unset_type_changed_cb(g_network_connection); + connection_unset_ip_address_changed_cb(g_network_connection); + connection_destroy(g_network_connection); } - - connection_type_e type = CONNECTION_TYPE_DISCONNECTED; - if ((retcode = connection_get_type(network_handle, &type)) != - CONNECTION_ERROR_NONE) { - TRACE_ERROR("Failed connection_get_type [%d]", retcode); - connection_destroy(network_handle); - return DP_NETWORK_TYPE_OFF; - } - network_type = - __dp_get_network_connection_status(network_handle, type); - - if (connection_destroy(network_handle) != CONNECTION_ERROR_NONE) - TRACE_ERROR("Failed connection_destroy"); - - return network_type; + g_network_connection = 0; + pthread_mutex_unlock(&g_dp_network_mutex); } diff --git a/provider/download-provider-notification-manager.c b/provider/download-provider-notification-manager.c new file mode 100644 index 0000000..ea89c0c --- /dev/null +++ b/provider/download-provider-notification-manager.c @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2013 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. + */ + +#ifdef SUPPORT_NOTIFICATION +#include <stdlib.h> +#include <signal.h> // pthread_kill +#include <errno.h> // ESRCH + +#include "download-provider-log.h" +#include "download-provider-pthread.h" +#include "download-provider-client.h" +#include "download-provider-client-manager.h" +#include "download-provider-notification.h" +#include "download-provider-db-defs.h" +#include "download-provider-db.h" +#endif +#include "download-provider-notification-manager.h" + +#ifdef SUPPORT_NOTIFICATION +typedef struct { // manage clients without mutex + int id; + int state; + int noti_priv_id; + double received_size; + double file_size; + dp_noti_type type; + void *slot; // client can not be NULL. it will exist in dummy + void *request; // this can be NULL after destroy + void *next; +} dp_notification_queue_fmt; + + +pthread_mutex_t g_dp_notification_manager_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t g_dp_notification_manager_cond = PTHREAD_COND_INITIALIZER; +pthread_t g_dp_notification_manager_tid = 0; + +static dp_notification_queue_fmt *g_dp_notification_clear = NULL; +static dp_notification_queue_fmt *g_dp_notification_ongoing = NULL; +static dp_notification_queue_fmt *g_dp_notification = NULL; + +pthread_mutex_t g_dp_notification_queue_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t g_dp_notification_queue_ongoing_mutex = PTHREAD_MUTEX_INITIALIZER; + +// normal . push at the tail of queue. +static int __dp_notification_queue_push(dp_notification_queue_fmt **queue, void *slot, void *request, const int id, const int state, const int noti_priv_id, const double received_size, const double file_size, const dp_noti_type type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (id <= 0) { + TRACE_ERROR("check slot or download id", id); + return -1; + } + + int ret = -1; + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_mutex); + // search the tail of queue + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + prevp = tailp; + tailp = tailp->next; + } + dp_notification_queue_fmt *new_queue = (dp_notification_queue_fmt *)malloc(sizeof(dp_notification_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->id = id; + new_queue->state = state; + new_queue->noti_priv_id = noti_priv_id; + new_queue->received_size = received_size; + new_queue->file_size = file_size; + new_queue->type = type; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + ret = 0; + } + //TRACE_DEBUG("queue push %d id:%d", i, id); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return ret; +} + +int __dp_notification_queue_pop(dp_notification_queue_fmt **queue, void **slot, void **request, int *id, int *state, int *noti_priv_id, double *received_size, double *file_size, dp_noti_type *type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL) { + TRACE_ERROR("check client memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_queue_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (queue == NULL || *queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return -1; + } + // get a head of queue + int ret = -1; + do { + dp_notification_queue_fmt *popp = *queue; + *queue = popp->next; + if (popp->slot == NULL) { + TRACE_DEBUG("queue error slot:%p id:%d", popp->slot, popp->id); + } else { + *slot = popp->slot; + if (request != NULL) { + *request = popp->request; + } + *id = popp->id; + *state = popp->state; + if (noti_priv_id != NULL) + *noti_priv_id = popp->noti_priv_id; + if (received_size != NULL) + *received_size = popp->received_size; + if (file_size != NULL) + *file_size = popp->file_size; + *type = popp->type; + ret = 0; + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return ret; +} + +int __dp_notification_queue_ongoing_pop(dp_notification_queue_fmt **queue, void **slot, void **request, int *id, int *state, double *received_size, double *file_size, dp_noti_type *type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL) { + TRACE_ERROR("check client memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_queue_ongoing_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (queue == NULL || *queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return -1; + } + // get a head of queue + int ret = -1; + do { + dp_notification_queue_fmt *popp = *queue; + *queue = popp->next; + if (popp->slot == NULL) { + TRACE_DEBUG("queue error slot:%p id:%d", popp->slot, popp->id); + } else { + *slot = popp->slot; + if (request != NULL) { + *request = popp->request; + } + *id = popp->id; + *state = popp->state; + if (received_size != NULL) + *received_size = popp->received_size; + if (file_size != NULL) + *file_size = popp->file_size; + *type = popp->type; + ret = 0; + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return ret; +} + +static int __dp_notification_queue_ongoing_push(dp_notification_queue_fmt **queue, void *slot, void *request, const int id, const int state, const double received_size, const double file_size, const dp_noti_type type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (id <= 0) { + TRACE_ERROR("check slot or download id", id); + return -1; + } + + int ret = -1; + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_ongoing_mutex); + // search the tail of queue + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->slot == slot && tailp->request == request) { + if (tailp->id == id && tailp->state == state && tailp->type == type) { + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return 0; + } + } + prevp = tailp; + tailp = tailp->next; + } + dp_notification_queue_fmt *new_queue = (dp_notification_queue_fmt *)malloc(sizeof(dp_notification_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->id = id; + new_queue->state = state; + new_queue->received_size = received_size; + new_queue->file_size = file_size; + new_queue->type = type; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + ret = 0; + } + //TRACE_DEBUG("queue push %d id:%d", i, id); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return ret; +} + +void __dp_notification_queue_clear(dp_notification_queue_fmt **queue, const int id) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_mutex); + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->id == id) { + // clear. + if (prevp == NULL) + *queue = tailp->next; + else + prevp->next = tailp->next; + TRACE_DEBUG("queue clear this %d id:%d", i, tailp->id); + free(tailp); + break; + } + prevp = tailp; + tailp = tailp->next; + } + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); +} + +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type) +{ + dp_request_fmt *requestp = request; + if (request == NULL) { + TRACE_DEBUG("check address request:%p id:%d", + request, (request == NULL ? 0 : requestp->id)); + return -1; + } + __dp_notification_queue_clear(&g_dp_notification, requestp->id); + TRACE_DEBUG("push clear id:%d noti_priv_id:%d", requestp->id, requestp->noti_priv_id); + if (__dp_notification_queue_push(&g_dp_notification_clear, slot, request, requestp->id, requestp->state, -1, 0, 0, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + dp_notification_manager_wake_up(); + return 0; +} + +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type) +{ + dp_request_fmt *requestp = request; + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : requestp->id)); + return -1; + } +// TRACE_DEBUG("push noti id:%d noti_priv_id:%d type:%d", requestp->id, requestp->noti_priv_id, type); + if (type == DP_NOTIFICATION) { + __dp_notification_queue_clear(&g_dp_notification_ongoing, requestp->id); + if (__dp_notification_queue_push(&g_dp_notification, slot, request, requestp->id, requestp->state, requestp->noti_priv_id, 0, (double)requestp->file_size, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + } else { + __dp_notification_queue_clear(&g_dp_notification, requestp->id); + if (__dp_notification_queue_ongoing_push(&g_dp_notification_ongoing, slot, request, requestp->id, requestp->state, (double)requestp->received_size, (double)requestp->file_size, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + } + dp_notification_manager_wake_up(); + return 0; +} + +static void __dp_notification_manager_check_notification() +{ + int pop_queue = 0; + do { + int errorcode = DP_ERROR_NONE; + int download_id = -1; + int state = -1; + dp_noti_type noti_type = -1; + dp_client_slots_fmt *slot = NULL; + dp_request_fmt *request = NULL; + pop_queue = 0; + if (__dp_notification_queue_pop(&g_dp_notification_clear, (void *)&slot, (void *)&request, &download_id, &state, NULL, NULL, NULL, ¬i_type) == 0) { + if (slot != NULL) { + int noti_priv_id = -1; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL && request->id == download_id && request->noti_priv_id >= 0) { + noti_priv_id = request->noti_priv_id; + request->noti_priv_id = -1; + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)&request->noti_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + TRACE_DEBUG("clear ongoing id:%d noti_priv_id:%d type:%d", download_id, noti_priv_id, noti_type); + if (noti_priv_id >= 0) { + if (noti_type > DP_NOTIFICATION) + dp_notification_delete_ongoing(noti_priv_id); + else + dp_notification_delete(noti_priv_id); + } + } + pop_queue++; + continue; + } + int noti_priv_id = -1; + if (__dp_notification_queue_pop(&g_dp_notification, (void *)&slot, (void *)&request, &download_id, &state, ¬i_priv_id, NULL, NULL, ¬i_type) == 0) { + if (slot != NULL) { + __dp_notification_queue_clear(&g_dp_notification_ongoing, download_id); // prevent new ongoing + if (noti_priv_id >= 0) { + TRACE_DEBUG("clear ongoing(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + dp_notification_delete_ongoing(noti_priv_id); + noti_priv_id = -1; + } + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + TRACE_DEBUG("notification id:%d type:%d state:%d", download_id, noti_type, state); + if (request != NULL && request->id == download_id && request->noti_priv_id >= 0) { + dp_notification_delete_ongoing(request->noti_priv_id); + request->noti_priv_id = -1; + } + dp_content_type content_type = DP_CONTENT_UNKNOWN; + if (request != NULL) + content_type = request->content_type; + noti_priv_id = dp_notification_new(slot->client.dbhandle, download_id, state, content_type, slot->pkgname); // lazy API + TRACE_DEBUG("new notification(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + if (noti_priv_id < 0) { + TRACE_ERROR("failed to register notification for id:%d", download_id); + } else { + if (request != NULL && request->id == download_id) { + request->noti_priv_id = noti_priv_id; + } + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)¬i_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + pop_queue++; + } + double received_size = 0; + double file_size = 0; + if (__dp_notification_queue_ongoing_pop(&g_dp_notification_ongoing, (void *)&slot, (void *)&request, &download_id, &state, &received_size, &file_size, ¬i_type) == 0) { + if (slot != NULL) { + int noti_priv_id = -1; + int request_id = -1; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL && request->id == download_id) { + request_id = download_id; + if (request->noti_priv_id >= 0) { + noti_priv_id = request->noti_priv_id; + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } else { + TRACE_ERROR("ongoing wrong address id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + continue; + } + + if (request_id < 0) { + TRACE_ERROR("ongoing wrong info id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + slot = NULL; + request = NULL; + continue; + } + if (noti_priv_id < 0 && noti_type > DP_NOTIFICATION_ONGOING) { + TRACE_DEBUG("ongoing precheck id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + noti_type = DP_NOTIFICATION_ONGOING; + } + + TRACE_DEBUG("ongoing id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + + char *subject = NULL; + if (noti_type == DP_NOTIFICATION || noti_type == DP_NOTIFICATION_ONGOING_UPDATE) { + unsigned length = 0; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL) { + if (dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&subject, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get subject id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } else if (subject == NULL && dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&subject, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get content_name id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + + if (noti_type > DP_NOTIFICATION_ONGOING) { // update + if (noti_priv_id >= 0 && dp_notification_ongoing_update(noti_priv_id, received_size, file_size, subject) < 0) { + TRACE_ERROR("failed to update ongoing for id:%d", download_id); + } + } else { // new ongoing + if (noti_priv_id >= 0) { + TRACE_DEBUG("clear ongoing id:%d noti_priv_id:%d", download_id, noti_priv_id); + dp_notification_delete(noti_priv_id); + dp_notification_delete_ongoing(noti_priv_id); + noti_priv_id = -1; + } + unsigned char *raws_buffer = NULL; + unsigned length = 0; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_ONGOING, &raws_buffer, &length, &errorcode) < 0) { + TRACE_DEBUG("failed to get bundle raws id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + noti_priv_id = dp_notification_ongoing_new(slot->pkgname, subject, raws_buffer, length); + TRACE_DEBUG("new ongoing(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + free(raws_buffer); + if (noti_priv_id < 0) { + TRACE_ERROR("failed to update ongoing for id:%d", download_id); + } else { + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL) + request->noti_priv_id = noti_priv_id; + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)¬i_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + } + free(subject); + } + pop_queue++; + } + } while (pop_queue > 0); +} + +static void *__dp_notification_manager(void *arg) +{ + pthread_cond_init(&g_dp_notification_manager_cond, NULL); + + dp_notification_set_locale(); + + while (g_dp_notification_manager_tid > 0) { + + if (g_dp_notification_manager_tid <= 0) { + TRACE_DEBUG("notification-manager is closed by other thread"); + break; + } + + // check wifi_direct first + __dp_notification_manager_check_notification(); + + CLIENT_MUTEX_LOCK(&g_dp_notification_manager_mutex); + pthread_cond_wait(&g_dp_notification_manager_cond, &g_dp_notification_manager_mutex); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + } + + TRACE_DEBUG("notification-manager's working is done"); + dp_notification_clear_locale(); + pthread_cond_destroy(&g_dp_notification_manager_cond); + pthread_exit(NULL); + return 0; +} + +static int __dp_notification_manager_start() +{ + if (g_dp_notification_manager_tid == 0 || + pthread_kill(g_dp_notification_manager_tid, 0) == ESRCH) { + TRACE_DEBUG("try to create notification-manager"); + if (pthread_create(&g_dp_notification_manager_tid, NULL, + __dp_notification_manager, NULL) != 0) { + TRACE_STRERROR("failed to create notification-manager"); + return -1; + } + } + return 0; +} + +void dp_notification_manager_wake_up() +{ + if (g_dp_notification_manager_tid > 0) { + int locked = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_manager_mutex); + if (locked == 0) { + pthread_cond_signal(&g_dp_notification_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + } + } else { + __dp_notification_manager_start(); + } +} + +void dp_notification_manager_kill() +{ + if (g_dp_notification_manager_tid > 0 && + pthread_kill(g_dp_notification_manager_tid, 0) != ESRCH) { + //send signal to notification thread + g_dp_notification_manager_tid = 0; + CLIENT_MUTEX_LOCK(&g_dp_notification_manager_mutex); + pthread_cond_signal(&g_dp_notification_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + pthread_cancel(g_dp_notification_manager_tid); + int status; + pthread_join(g_dp_notification_manager_tid, (void **)&status); + } +} +#else + +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type) +{ + return 0; +} + +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type) +{ + return 0; +} + +void dp_notification_manager_wake_up() +{ + return; +} + +void dp_notification_manager_kill() +{ + return; +} +#endif diff --git a/provider/download-provider-notification.c b/provider/download-provider-notification.c index f6e2f8b..521cb44 100755 --- a/provider/download-provider-notification.c +++ b/provider/download-provider-notification.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2013 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. @@ -14,39 +14,124 @@ * limitations under the License. */ +#ifdef SUPPORT_NOTIFICATION #include <time.h> #include <sys/time.h> #include <stdlib.h> #include <stdio.h> -#include "bundle.h" -#include "notification.h" -#include "appsvc.h" - -#include "download-provider-defs.h" - +#include "download-provider.h" #include "download-provider-notification.h" -#include "download-provider-request.h" +#include "download-provider-db-defs.h" #include "download-provider-db.h" #include "download-provider-log.h" +#include "download-provider-client.h" +#include "download-provider-utils.h" +#include <bundle.h> +#include <notification.h> +#include <notification_internal.h> +#include <appsvc.h> + +#include <vconf.h> +#include <locale.h> #include <libintl.h> -#define S_(s) dgettext("sys_string", s) #define __(s) dgettext(PKG_NAME, s) -#define DP_NOTIFICATION_ICON_PATH IMAGE_DIR"/Q02_Notification_download_complete.png" -#define DP_NOTIFICATION_ONGOING_ICON_PATH IMAGE_DIR"/Notification_download_animation.gif" +#define DP_DOMAIN PKG_NAME +#define DP_LOCALEDIR LOCALE_DIR +#define DP_NOTIFICATION_NO_SUBJECT "No Name" + +#ifdef _TIZEN_2_3_UX +#define DP_NOTIFICATION_DRM_ICON_PATH IMAGE_DIR"/download_manager_icon_drm.png" +#define DP_NOTIFICATION_UNKNOWN_ICON_PATH IMAGE_DIR"/download_manager_icon_unknown.png" +#define DP_NOTIFICATION_EXCEL_ICON_PATH IMAGE_DIR"/download_manager_icon_xls.png" +#define DP_NOTIFICATION_HTML_ICON_PATH IMAGE_DIR"/download_manager_icon_html.png" +#define DP_NOTIFICATION_MUSIC_ICON_PATH IMAGE_DIR"/download_manager_icon_music.png" +#define DP_NOTIFICATION_PDF_ICON_PATH IMAGE_DIR"/download_manager_icon_pdf.png" +#define DP_NOTIFICATION_PPT_ICON_PATH IMAGE_DIR"/download_manager_icon_ppt.png" +#define DP_NOTIFICATION_TEXT_ICON_PATH IMAGE_DIR"/download_manager_icon_text.png" +#define DP_NOTIFICATION_WORD_ICON_PATH IMAGE_DIR"/download_manager_icon_word.png" +#define DP_NOTIFICATION_VIDEO_ICON_PATH IMAGE_DIR"/download_manager_icon_movie.png" +#define DP_NOTIFICATION_IMAGE_ICON_PATH IMAGE_DIR"/download_manager_icon_img.png" +#define DP_NOTIFICATION_FALSH_ICON_PATH IMAGE_DIR"/download_manager_icon_swf.png" +#define DP_NOTIFICATION_TPK_ICON_PATH IMAGE_DIR"/download_manager_icon_tpk.png" +#define DP_NOTIFICATION_VCAL_ICON_PATH IMAGE_DIR"/download_manager_icon_date.png" + +// base path +#define QP_PRELOAD_NOTI_ICON_PATH "/usr/apps/com.samsung.quickpanel/shared/res/noti_icons" +// each application path +#define QP_PRELOAD_COMMON_PATH QP_PRELOAD_NOTI_ICON_PATH"/Common" +#define DP_NOTIFICATION_COMPLETED_ICON_PATH QP_PRELOAD_COMMON_PATH"/noti_download_complete.png" +#define DP_NOTIFICATION_FAILED_ICON_PATH QP_PRELOAD_COMMON_PATH"/noti_download_failed.png" + +#define DP_NOTIFICATION_ONGOING_ICON_PATH "reserved://quickpanel/ani/downloading" #define DP_NOTIFICATION_DOWNLOADING_ICON_PATH "reserved://indicator/ani/downloading" -#define DP_NOTIFICATION_FAILED_ICON_PATH IMAGE_DIR"/Q02_Notification_download_failed.png" - -static const char *__noti_error_str( - notification_error_e err) +#define DP_NOTIFICATION_FAILED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_Processing_download_failed.png" +#define DP_NOTIFICATION_COMPLETED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_Processing_download_complete.png" +#else +#define DP_NOTIFICATION_DRM_ICON_PATH IMAGE_DIR"/U01_icon_drm.png" +#define DP_NOTIFICATION_UNKNOWN_ICON_PATH IMAGE_DIR"/U01_icon_unkown.png" +#define DP_NOTIFICATION_EXCEL_ICON_PATH IMAGE_DIR"/U01_icon_excel.png" +#define DP_NOTIFICATION_HTML_ICON_PATH IMAGE_DIR"/U01_icon_html.png" +#define DP_NOTIFICATION_MUSIC_ICON_PATH IMAGE_DIR"/U01_list_icon_mp3.png" +#define DP_NOTIFICATION_PDF_ICON_PATH IMAGE_DIR"/U01_icon_pdf.png" +#define DP_NOTIFICATION_PPT_ICON_PATH IMAGE_DIR"/U01_icon_ppt.png" +#define DP_NOTIFICATION_TEXT_ICON_PATH IMAGE_DIR"/U01_icon_text.png" +#define DP_NOTIFICATION_WORD_ICON_PATH IMAGE_DIR"/U01_icon_word.png" +#define DP_NOTIFICATION_VIDEO_ICON_PATH IMAGE_DIR"/U01_list_icon_mp4.png" +#define DP_NOTIFICATION_IMAGE_ICON_PATH IMAGE_DIR"/U01_list_icon_image.png" +#define DP_NOTIFICATION_FALSH_ICON_PATH IMAGE_DIR"/U01_icon_swf.png" +#define DP_NOTIFICATION_TPK_ICON_PATH IMAGE_DIR"/U01_icon_tpk.png" +#define DP_NOTIFICATION_VCAL_ICON_PATH IMAGE_DIR"/U01_icon_vcs.png" + +#define DP_NOTIFICATION_FAILED_ICON_PATH IMAGE_DIR"/noti_download_failed.png" +#define DP_NOTIFICATION_COMPLETED_ICON_PATH IMAGE_DIR"/noti_download_complete.png" + +#define DP_NOTIFICATION_ONGOING_ICON_PATH "reserved://quickpanel/ani/downloading" +#define DP_NOTIFICATION_DOWNLOADING_ICON_PATH "reserved://indicator/ani/downloading" +#define DP_NOTIFICATION_FAILED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_processing_download_fail.png" +#define DP_NOTIFICATION_COMPLETED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_processing_download_complete.png" +#endif + +#define DP_MAX_ICONS_TABLE_COUNT 15 + +char *file_icons_table[DP_MAX_ICONS_TABLE_COUNT]={ + //unknown file type + DP_NOTIFICATION_UNKNOWN_ICON_PATH, + //image + DP_NOTIFICATION_IMAGE_ICON_PATH, + //video + DP_NOTIFICATION_VIDEO_ICON_PATH, + // audio /music + DP_NOTIFICATION_MUSIC_ICON_PATH, + // PDF + DP_NOTIFICATION_PDF_ICON_PATH, + // word + DP_NOTIFICATION_WORD_ICON_PATH, + // ppt + DP_NOTIFICATION_PPT_ICON_PATH, + // excel + DP_NOTIFICATION_EXCEL_ICON_PATH, + // html + DP_NOTIFICATION_HTML_ICON_PATH, + // txt + DP_NOTIFICATION_TEXT_ICON_PATH, + // DRM + DP_NOTIFICATION_DRM_ICON_PATH, + DP_NOTIFICATION_DRM_ICON_PATH, + DP_NOTIFICATION_FALSH_ICON_PATH, + DP_NOTIFICATION_TPK_ICON_PATH, + DP_NOTIFICATION_VCAL_ICON_PATH, +}; + +static const char *__dp_noti_error_str(int err) { switch (err) { - case NOTIFICATION_ERROR_INVALID_DATA: - return "NOTIFICATION_ERROR_INVALID_DATA"; - case NOTIFICATION_ERROR_NO_MEMORY: - return "NOTIFICATION_ERROR_NO_MEMORY"; + case NOTIFICATION_ERROR_INVALID_PARAMETER: + return "NOTIFICATION_ERROR_INVALID_PARAMETER"; + case NOTIFICATION_ERROR_OUT_OF_MEMORY: + return "NOTIFICATION_ERROR_OUT_OF_MEMORY"; case NOTIFICATION_ERROR_FROM_DB: return "NOTIFICATION_ERROR_FROM_DB"; case NOTIFICATION_ERROR_ALREADY_EXIST_ID: @@ -61,7 +146,7 @@ static const char *__noti_error_str( return "Unknown error"; } -static char *__get_string_sender(char *url) +char *__dp_noti_get_sender(char *url) { char *temp = NULL; char *found = NULL; @@ -73,13 +158,13 @@ static char *__get_string_sender(char *url) return NULL; found = strstr(url, "://"); - if (found) { + if (found != NULL) { temp = found + 3; } else { temp = url; } found = strchr(temp, '/'); - if (found) { + if (found != NULL) { int len = 0; len = found - temp; sender = calloc(len + 1, sizeof(char)); @@ -93,7 +178,7 @@ static char *__get_string_sender(char *url) // For credential URL found = strchr(sender, '@'); found1 = strchr(sender, ':'); - if (found && found1 && found1 < found) { + if (found != NULL && found1 != NULL && found1 < found) { int len = 0; found = found + 1; len = strlen(found); @@ -110,47 +195,16 @@ static char *__get_string_sender(char *url) } } -static char *__get_string_size(long long file_size) -{ - const char *unitStr[4] = {"B", "KB", "MB", "GB"}; - double doubleTypeBytes = 0.0; - int unit = 0; - long long bytes = file_size; - long long unitBytes = bytes; - char *temp = NULL; - - /* using bit operation to avoid floating point arithmetic */ - for (unit = 0; (unitBytes > 1024 && unit < 4); unit++) { - unitBytes = unitBytes >> 10; - } - unitBytes = 1 << (10 * unit); - - if (unit > 3) - unit = 3; - - char str[64] = {0}; - if (unit == 0) { - snprintf(str, sizeof(str), "%lld %s", bytes, unitStr[unit]); - } else { - doubleTypeBytes = ((double)bytes / (double)unitBytes); - snprintf(str, sizeof(str), "%.2f %s", doubleTypeBytes, unitStr[unit]); - } - - str[63] = '\0'; - temp = dp_strdup(str); - return temp; -} - -static char *__get_string_status(dp_state_type state) +static char *__dp_noti_status(dp_state_type state) { char *message = NULL; switch (state) { case DP_STATE_COMPLETED: - message = __("IDS_DM_HEADER_DOWNLOAD_COMPLETE"); + message = "IDS_DM_HEADER_DOWNLOAD_COMPLETE"; break; case DP_STATE_CANCELED: case DP_STATE_FAILED: - message = S_("IDS_COM_POP_DOWNLOAD_FAILED"); + message = "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB"; break; default: break; @@ -158,459 +212,414 @@ static char *__get_string_status(dp_state_type state) return message; } -int dp_set_downloadinginfo_notification(int id, char *packagename) +void __lang_changed_cb(keynode_t *key, void* data) { - notification_h noti_handle = NULL; - notification_error_e err = NOTIFICATION_ERROR_NONE; - int privId = 0; - bundle *b = NULL; - void *blob_data = NULL; - bundle_raw* b_raw = NULL; - int length; + char *str = NULL; + str = vconf_get_str(VCONFKEY_LANGSET); + if (str != NULL) { + setlocale(LC_ALL, str); + bindtextdomain(PKG_NAME, LOCALE_DIR); + textdomain(PKG_NAME); + } + free(str); +} + +void dp_notification_set_locale() +{ + // move to notification.c + // locale + __lang_changed_cb(NULL, NULL); + if (vconf_notify_key_changed(VCONFKEY_LANGSET, __lang_changed_cb, NULL) != 0) + TRACE_ERROR("Fail to set language changed vconf callback"); +} + +void dp_notification_clear_locale() +{ + // move to notification.c + if (vconf_ignore_key_changed(VCONFKEY_LANGSET, __lang_changed_cb) != 0) + TRACE_ERROR("Fail to unset language changed vconf callback"); +} +void dp_notification_clear_ongoings() +{ + int err = NOTIFICATION_ERROR_NONE; + err = notification_delete_all_by_type(NULL, NOTIFICATION_TYPE_ONGOING); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("[FAIL] clear noti [%s]", __dp_noti_error_str(err)); + } + return; +} + +int dp_notification_ongoing_new(const char *pkgname, const char *subject, unsigned char *raws_buffer, const int raws_length) +{ + int err = NOTIFICATION_ERROR_NONE; + notification_h noti_handle = NULL; noti_handle = notification_create(NOTIFICATION_TYPE_ONGOING); - if (!noti_handle) { - TRACE_ERROR("[FAIL] create notification handle"); + if (noti_handle == NULL) { + TRACE_ERROR("failed to create notification handle"); return -1; } - char *title = dp_db_get_text_column(id, - DP_DB_TABLE_NOTIFICATION, DP_DB_COL_TITLE); - if(title != NULL) { - err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, - title, NULL, NOTIFICATION_VARIABLE_TYPE_NONE); - free(title); - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set title [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; - } + if (subject != NULL) { + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, subject, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); } else { - char *content_name = - dp_db_get_text_column - (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_NAME); - - if (content_name == NULL) - content_name = strdup("No Name"); - err = notification_set_text(noti_handle, - NOTIFICATION_TEXT_TYPE_TITLE, content_name, NULL, + NOTIFICATION_TEXT_TYPE_TITLE, DP_NOTIFICATION_NO_SUBJECT, NULL, NOTIFICATION_VARIABLE_TYPE_NONE); - if (content_name) - free(content_name); } - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set title [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set subject error:%s", __dp_noti_error_str(err)); } err = notification_set_image(noti_handle, - NOTIFICATION_IMAGE_TYPE_ICON, DP_NOTIFICATION_ONGOING_ICON_PATH); + NOTIFICATION_IMAGE_TYPE_ICON, + DP_NOTIFICATION_ONGOING_ICON_PATH); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set icon [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set icon error:%s", __dp_noti_error_str(err)); } - blob_data = dp_db_get_blob_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_RAW_BUNDLE_ONGOING, &length); - if (blob_data != NULL) { - b_raw = (bundle_raw*)blob_data; - if (b_raw != NULL) { - b = bundle_decode_raw(b_raw, length); - if (b != NULL) { - err = notification_set_execute_option(noti_handle, - NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); - - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set execute option [%s]", __noti_error_str(err)); - bundle_free_encoded_rawdata(&b_raw); - bundle_free(b); - notification_free(noti_handle); - return -1; + if (raws_buffer != NULL && raws_length > 0) { + bundle *b = NULL; + b = bundle_decode_raw((bundle_raw *)raws_buffer, raws_length); + if (b != NULL) { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } else { + b = bundle_create(); + if (b != NULL && pkgname != NULL) { + if (appsvc_set_pkgname(b, pkgname) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set set pkgname"); + } else { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); } - bundle_free_encoded_rawdata(&b_raw); - bundle_free(b); + } else { + TRACE_ERROR("failed to create bundle"); } } - } else { - b = bundle_create(); - if (!b) { - TRACE_ERROR("[FAIL] create bundle"); - notification_free(noti_handle); - return -1; - } - - if (packagename && - appsvc_set_pkgname(b, packagename) != APPSVC_RET_OK) { - TRACE_ERROR("[FAIL] set pkg name"); - bundle_free(b); - notification_free(noti_handle); - return -1; - } - err = notification_set_execute_option(noti_handle, - NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set execute option [%s]", __noti_error_str(err)); - bundle_free(b); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set service error:%s", __dp_noti_error_str(err)); } - bundle_free(b); + if (b != NULL) + bundle_free(b); } + err = notification_set_property(noti_handle, NOTIFICATION_PROP_DISABLE_TICKERNOTI); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set property [%s]", __noti_error_str(err)); + TRACE_ERROR("failed to set property error:%s", __dp_noti_error_str(err)); notification_free(noti_handle); return -1; } - err = notification_set_image(noti_handle, - NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, DP_NOTIFICATION_DOWNLOADING_ICON_PATH); + NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + DP_NOTIFICATION_DOWNLOADING_ICON_PATH); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set icon indicator [%s]", __noti_error_str(err)); + TRACE_ERROR("failed to set icon indicator error:%s", __dp_noti_error_str(err)); notification_free(noti_handle); return -1; } - - err = notification_set_display_applist(noti_handle, NOTIFICATION_DISPLAY_APP_ALL); + err = notification_set_display_applist(noti_handle, + NOTIFICATION_DISPLAY_APP_ALL); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set disable icon [%s]", __noti_error_str(err)); + TRACE_ERROR("failed to set display app all error:%s", __dp_noti_error_str(err)); notification_free(noti_handle); return -1; } - err = notification_insert(noti_handle, &privId); + int priv_id = 0; + err = notification_insert(noti_handle, &priv_id); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set insert [%s]", __noti_error_str(err)); + TRACE_ERROR("failed to set priv_id error:%s", __dp_noti_error_str(err)); notification_free(noti_handle); return -1; } - TRACE_DEBUG("m_noti_id [%d]", privId); + //TRACE_DEBUG("m_noti_id [%d]", priv_id); notification_free(noti_handle); - return privId; + + return priv_id; // store on memory for reuse it } -int dp_set_downloadedinfo_notification(int priv_id, int id, char *packagename, dp_state_type state) -{ - notification_h noti_handle = NULL; - notification_error_e err = NOTIFICATION_ERROR_NONE; - int privId = 0; - bundle *b = NULL; - void *blob_data = NULL; - bundle_raw* b_raw = NULL; - int length = 0; - if (priv_id >= 0) { - err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_ONGOING, - priv_id); + +int dp_notification_ongoing_update(const int noti_priv_id, const double received_size, const double file_size, const char *subject) +{ + if (noti_priv_id > 0) { + int err = NOTIFICATION_ERROR_NONE; + if (file_size > 0) + err = notification_update_progress(NULL, noti_priv_id, (received_size / file_size)); + else + err = notification_update_size(NULL, noti_priv_id, received_size); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] delete notification handle [%s]", - __noti_error_str(err)); + TRACE_ERROR("failed to update error:%s", __dp_noti_error_str(err)); + // return 0 because progress is called frequently + } + if (subject != NULL) { + notification_h noti_handle = NULL; + noti_handle = notification_load(NULL, noti_priv_id); + if (noti_handle != NULL) { + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, subject, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + err = notification_update(noti_handle); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to update by priv_id:%d", noti_priv_id); + } + notification_free(noti_handle); + } else { + TRACE_ERROR("failed to load handle by priv_id:%d", noti_priv_id); + return -1; + } } } + return 0; +} - noti_handle = notification_create(NOTIFICATION_TYPE_NOTI); - if (!noti_handle) { - TRACE_ERROR("[FAIL] create notification handle"); +int dp_notification_delete_ongoing(const int noti_priv_id) +{ + int err = NOTIFICATION_ERROR_NONE; + err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_ONGOING, noti_priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to delete notification by priv_id:%d error:%s", noti_priv_id, __dp_noti_error_str(err)); + } + return 0; +} + +int dp_notification_delete(const int noti_priv_id) +{ + int err = NOTIFICATION_ERROR_NONE; + err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NOTI, noti_priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to delete notification by priv_id:%d error:%s", noti_priv_id, __dp_noti_error_str(err)); + } + return 0; +} + + +int dp_notification_new(void *dbhandle, const int download_id, const int state, int content_type, const char *pkgname) +{ + int errorcode = DP_ERROR_NONE; + int err = NOTIFICATION_ERROR_NONE; + + if (state != DP_STATE_COMPLETED && + state != DP_STATE_CANCELED && + state != DP_STATE_FAILED) { + TRACE_ERROR("deny by invalid state:%d id:%d", state, download_id); + return -1; + } + + + notification_h noti_handle = NULL; + noti_handle = notification_create(NOTIFICATION_TYPE_NOTI); + if (noti_handle == NULL) { + TRACE_ERROR("failed to create notification handle"); return -1; } + err = notification_set_layout(noti_handle, NOTIFICATION_LY_NOTI_EVENT_SINGLE); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set title [%s]", __noti_error_str(err)); + TRACE_ERROR("Fail to set notification layout [%d]", err); notification_free(noti_handle); return -1; } - err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, - __get_string_status(state), NULL, NOTIFICATION_VARIABLE_TYPE_NONE); + err = notification_set_text_domain(noti_handle, DP_DOMAIN, DP_LOCALEDIR); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set title [%s]", __noti_error_str(err)); + TRACE_ERROR("Fail to set text domain [%d]", err); notification_free(noti_handle); return -1; } - char *description = - dp_db_get_text_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_DESCRIPTION); - if(description != NULL) { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get description id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + if (string != NULL) { +#ifdef _TIZEN_2_3_UX + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_CONTENT, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#else err = notification_set_text(noti_handle, - NOTIFICATION_TEXT_TYPE_INFO_2, description, - NULL, NOTIFICATION_VARIABLE_TYPE_NONE); - free(description); + NOTIFICATION_TEXT_TYPE_TITLE, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#endif + free(string); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set description [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set state id:%d error:%s", download_id, __dp_noti_error_str(err)); } } else { - char *url = NULL; - url = dp_db_get_text_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_URL); - if (url) { - char *sender_str = __get_string_sender(url); - err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_2, - sender_str, NULL, NOTIFICATION_VARIABLE_TYPE_NONE); - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set title [%s]", __noti_error_str(err)); - free(sender_str); - free(url); - notification_free(noti_handle); - return -1; - } - free(sender_str); - free(url); + string = __dp_noti_status(state); +#ifdef _TIZEN_2_3_UX + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_CONTENT, __(string), string, + NOTIFICATION_VARIABLE_TYPE_NONE); +#else + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, __(string), string, + NOTIFICATION_VARIABLE_TYPE_NONE); +#endif + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set state id:%d error:%s", download_id, __dp_noti_error_str(err)); } } - char *title = dp_db_get_text_column(id, - DP_DB_TABLE_NOTIFICATION, DP_DB_COL_TITLE); - if(title != NULL) { - err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT, - title, NULL, NOTIFICATION_VARIABLE_TYPE_NONE); - free(title); + string = NULL; + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get subject id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + err = NOTIFICATION_ERROR_NONE; + if (string == NULL && dp_db_get_property_string(dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get content_name id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + if (string == NULL) + string = dp_strdup(DP_NOTIFICATION_NO_SUBJECT); + if (string != NULL) { +#ifdef _TIZEN_2_3_UX + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#else + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_CONTENT, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#endif + free(string); + string = NULL; if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set title [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set state id:%d error:%s", download_id, __dp_noti_error_str(err)); } - } else { - char *content_name = - dp_db_get_text_column - (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_NAME); - if (content_name == NULL) - content_name = strdup("No Name"); - - err = notification_set_text(noti_handle, - NOTIFICATION_TEXT_TYPE_CONTENT, content_name, - NULL, NOTIFICATION_VARIABLE_TYPE_NONE); - free(content_name); } - - time_t tt = time(NULL); - err = notification_set_time_to_text(noti_handle, - NOTIFICATION_TEXT_TYPE_INFO_SUB_1, tt); + err = notification_set_time(noti_handle, time(NULL)); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set time [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set time id:%d error:%s", download_id, __dp_noti_error_str(err)); } + + bundle *b = NULL; + bundle_raw *raws_buffer = NULL; if (state == DP_STATE_COMPLETED) { - blob_data = dp_db_get_blob_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_RAW_BUNDLE_COMPLETE, &length); - if (blob_data != NULL) { - b_raw = (bundle_raw*)blob_data; - if (b_raw != NULL) { - b = bundle_decode_raw(b_raw, length); - if (b != NULL) { - err = notification_set_execute_option(noti_handle, - NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); - - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set execute option [%s]", __noti_error_str(err)); - bundle_free_encoded_rawdata(&b_raw); - bundle_free(b); - notification_free(noti_handle); - return -1; - } - bundle_free_encoded_rawdata(&b_raw); - } - } + + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_COMPLETE, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get bundle raws id:%d", download_id); + } + if (raws_buffer != NULL) { + b = bundle_decode_raw(raws_buffer, length); + bundle_free_encoded_rawdata(&raws_buffer); + } + if (b != NULL) { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); } else { - char *file_path = NULL; b = bundle_create(); - if (!b) { - TRACE_ERROR("[FAIL] create bundle"); - notification_free(noti_handle); - return -1; - } - if (appsvc_set_operation(b, APPSVC_OPERATION_VIEW) != APPSVC_RET_OK) { - TRACE_ERROR("[FAIL] appsvc set operation"); - bundle_free(b); - notification_free(noti_handle); - return -1; - } - file_path = dp_db_get_text_column - (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_SAVED_PATH); - if (file_path == NULL) { - TRACE_ERROR("[FAIL] get file path"); - bundle_free(b); - notification_free(noti_handle); - return -1; - + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get saved_path id:%d error:%s", download_id, dp_print_errorcode(errorcode)); } - if (appsvc_set_uri(b, file_path) != APPSVC_RET_OK) { - TRACE_ERROR("[FAIL] appsvc set uri"); - bundle_free(b); - notification_free(noti_handle); - free(file_path); - return -1; - } - free(file_path); - err = notification_set_execute_option(noti_handle, - NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set execute option[%s]", __noti_error_str(err)); - bundle_free(b); - notification_free(noti_handle); - return -1; + if (b != NULL && string != NULL) { + if (appsvc_set_operation(b, APPSVC_OPERATION_VIEW) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set service operation id:%d", download_id); + } else { + if (appsvc_set_uri(b, string) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set service uri id:%d", download_id); + } else { + err = notification_set_execute_option(noti_handle, + NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } + } + } else { + TRACE_SECURE_ERROR("failed to create bundle id:%d path:%s", download_id, string); } + free(string); + string = NULL; + } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set service id:%d error:%s", download_id, __dp_noti_error_str(err)); } - long long file_size = dp_db_get_int64_column(id, - DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_SIZE); - char *size_str = __get_string_size(file_size); - err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_1, - size_str, NULL, NOTIFICATION_VARIABLE_TYPE_NONE); + char *file_type_icon = DP_NOTIFICATION_UNKNOWN_ICON_PATH; + if (content_type > 0 && content_type < DP_MAX_ICONS_TABLE_COUNT) + file_type_icon = file_icons_table[content_type]; + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, file_type_icon); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set title [%s]", __noti_error_str(err)); - free(size_str); - bundle_free(b); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); } - free(size_str); - - err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, - DP_NOTIFICATION_ICON_PATH); + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + DP_NOTIFICATION_COMPLETED_INDICATOR_ICON_PATH); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set icon [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); } + } else if (state == DP_STATE_CANCELED || state == DP_STATE_FAILED) { - blob_data = dp_db_get_blob_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_RAW_BUNDLE_FAIL, &length); - if (blob_data != NULL) { - b_raw = (bundle_raw *)blob_data; - if (b_raw != NULL) { - b = bundle_decode_raw(b_raw, length); - if (b != NULL) { - err = notification_set_execute_option(noti_handle, - NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); - - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set execute option [%s]", __noti_error_str(err)); - bundle_free_encoded_rawdata(&b_raw); - bundle_free(b); - notification_free(noti_handle); - return -1; - } - bundle_free_encoded_rawdata(&b_raw); - } - } + + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_FAIL, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get bundle raws id:%d", download_id); + } + if (raws_buffer != NULL) { + b = bundle_decode_raw(raws_buffer, length); + bundle_free_encoded_rawdata(&raws_buffer); + } + if (b != NULL) { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); } else { b = bundle_create(); - if (!b) { - TRACE_ERROR("[FAIL] create bundle"); - notification_free(noti_handle); - return -1; - } - if (packagename && - appsvc_set_pkgname(b, packagename) != - APPSVC_RET_OK) { - TRACE_ERROR("[FAIL] set pkg name"); - bundle_free(b); - notification_free(noti_handle); - return -1; - } - err = notification_set_execute_option(noti_handle, - NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set execute option[%s]", __noti_error_str(err)); - bundle_free(b); - notification_free(noti_handle); - return -1; + if (b != NULL && pkgname != NULL) { + if (appsvc_set_pkgname(b, pkgname) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set set pkgname id:%d", download_id); + } else { + err = notification_set_execute_option(noti_handle, + NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } + } else { + TRACE_ERROR("failed to create bundle id:%d", download_id); } } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set service id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, DP_NOTIFICATION_FAILED_ICON_PATH); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set icon [%s]", __noti_error_str(err)); - bundle_free(b); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + DP_NOTIFICATION_FAILED_INDICATOR_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); } - } else { - TRACE_ERROR("[CRITICAL] invalid state"); - bundle_free(b); - notification_free(noti_handle); - return -1; - } - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set time [%s]", __noti_error_str(err)); - notification_free(noti_handle); - bundle_free(b); - return -1; } - bundle_free(b); + if (b != NULL) + bundle_free(b); err = notification_set_property(noti_handle, NOTIFICATION_PROP_DISABLE_TICKERNOTI); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set property [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set property id:%d error:%s", download_id, __dp_noti_error_str(err)); } - err = notification_set_display_applist(noti_handle, NOTIFICATION_DISPLAY_APP_ALL ^ NOTIFICATION_DISPLAY_APP_INDICATOR); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set disable icon [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set display app all id:%d error:%s", download_id, __dp_noti_error_str(err)); } - err = notification_insert(noti_handle, &privId); + int priv_id = 0; + err = notification_insert(noti_handle, &priv_id); if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] set insert [%s]", __noti_error_str(err)); - notification_free(noti_handle); - return -1; + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, __dp_noti_error_str(err)); } - TRACE_DEBUG("m_noti_id [%d]", privId); + //TRACE_DEBUG("m_noti_id [%d]", priv_id); notification_free(noti_handle); - return privId; -} -void dp_update_downloadinginfo_notification(int priv_id, double received_size, double file_size) -{ - notification_error_e err = NOTIFICATION_ERROR_NONE; - if (priv_id < 0) { - TRACE_ERROR("[FAIL] Invalid priv_id[%d]", priv_id); - return; - } - - if (file_size > 0) { - double progress; - progress = received_size / file_size; - err = notification_update_progress(NULL, priv_id, progress); - if (err != NOTIFICATION_ERROR_NONE) - TRACE_ERROR("[FAIL] update noti progress[%s]", - __noti_error_str(err)); - } else { - err = notification_update_size(NULL, priv_id, received_size); - if (err != NOTIFICATION_ERROR_NONE) - TRACE_ERROR("[FAIL] update noti progress[%s]", - __noti_error_str(err)); - } + return priv_id; } - -void dp_clear_downloadinginfo_notification() +#else +void dp_notification_clear_ongoings() { - notification_error_e err = NOTIFICATION_ERROR_NONE; - err = notification_delete_all_by_type(NULL, NOTIFICATION_TYPE_ONGOING); - if (err != NOTIFICATION_ERROR_NONE) { - TRACE_ERROR("[FAIL] clear noti [%s]", __noti_error_str(err)); - } return; } +#endif diff --git a/provider/download-provider-notify.c b/provider/download-provider-notify.c new file mode 100644 index 0000000..3288fde --- /dev/null +++ b/provider/download-provider-notify.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013 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 <fcntl.h> + +#include <download-provider-log.h> +#include <download-provider-client.h> +#include <download-provider-client-manager.h> +#include <download-provider-ipc.h> + +static char *__dp_notify_get_path(pid_t pid) +{ + size_t path_size = sizeof(NOTIFY_DIR) + 21; + char *notify_fifo = (char *)calloc(path_size, sizeof(char)); + if (notify_fifo == NULL) { + TRACE_STRERROR("failed to alocalte fifo path pid:%d", (int)pid); + return NULL; + } + if (snprintf(notify_fifo, path_size,"%s/%d", NOTIFY_DIR, pid) < 0) { + TRACE_STRERROR("failed to make fifo path pid:%d", (int)pid); + free(notify_fifo); + return NULL; + } + return notify_fifo; +} + +int dp_notify_init(pid_t pid) +{ + char *notify_fifo = __dp_notify_get_path(pid); + if (notify_fifo == NULL) + return -1; + int notify_fd = -1; + struct stat fifo_state; + if (stat(notify_fifo, &fifo_state) == 0) // found + unlink(notify_fifo); + if (mkfifo(notify_fifo, 0644/*-rwrr*/) < 0) { + TRACE_STRERROR("failed to make fifo %s", notify_fifo); + } else { + notify_fd = open(notify_fifo, O_RDWR | O_NONBLOCK, 0644); + } + free(notify_fifo); + return notify_fd; +} + +void dp_notify_deinit(pid_t pid) +{ + char *notify_fifo = __dp_notify_get_path(pid); + if (notify_fifo == NULL) + return ; + struct stat fifo_state; + if (stat(notify_fifo, &fifo_state) == 0) // found + unlink(notify_fifo); + free(notify_fifo); +} + +static int __dp_notify_feedback(int sock, int id, int state, int errorcode, unsigned long long received_size) +{ + dp_ipc_event_fmt eventinfo; + memset(&eventinfo, 0x00, sizeof(dp_ipc_event_fmt)); + eventinfo.id = id; + eventinfo.state = state; + eventinfo.errorcode = errorcode; + eventinfo.received_size = received_size; + if (dp_ipc_write(sock, &eventinfo, sizeof(dp_ipc_event_fmt)) < 0) { + // failed to read from socket // ignore this status + return -1; + } + return 0; +} + +int dp_notify_feedback(int sock, void *slot, int id, int state, int errorcode, unsigned long long received_size) +{ + if (__dp_notify_feedback(sock, id, state, errorcode, received_size) < 0) { + TRACE_ERROR("notify failure by IO_ERROR"); + if (slot != NULL) { + dp_client_slots_fmt *base_slot = slot; + if (base_slot->client.notify >= 0) + close(base_slot->client.notify); + base_slot->client.notify = -1; + dp_notify_deinit(base_slot->credential.pid); + TRACE_ERROR("disable notify channel by IO_ERROR"); + } + return -1; + } + return 0; +} diff --git a/provider/download-provider-plugin-download-agent.c b/provider/download-provider-plugin-download-agent.c new file mode 100644 index 0000000..5522510 --- /dev/null +++ b/provider/download-provider-plugin-download-agent.c @@ -0,0 +1,989 @@ +/* + * Copyright (c) 2013 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 <fcntl.h> + +#include <download-provider.h> +#include <download-provider-log.h> +#include <download-provider-pthread.h> +#include <download-provider-ipc.h> +#include <download-provider-db-defs.h> +#include <download-provider-db.h> +#include <download-provider-utils.h> +#include <download-provider-notify.h> +#include <download-provider-smack.h> +#include <download-provider-client.h> +#include <download-provider-client-manager.h> +#include <download-provider-plugin-download-agent.h> +#include <download-provider-notification-manager.h> +#include <download-provider-queue-manager.h> + +#include <download-agent-defs.h> +#include <download-agent-interface.h> +#include "xdgmime.h" +#include "content/mime_type.h" + +#define DP_SDCARD_MNT_POINT "/opt/storage/sdcard" +#define DP_MAX_FILE_PATH_LEN 256 +#define DP_MAX_MIME_TABLE_NUM 15 + +typedef struct { + const char *mime; + int content_type; +}mime_table_type; + +const char *ambiguous_mime_type_list[] = { + "text/plain", + "application/octet-stream" +}; + +mime_table_type mime_table[]={ + // PDF + {"application/pdf",DP_CONTENT_PDF}, + // word + {"application/msword",DP_CONTENT_WORD}, + {"application/vnd.openxmlformats-officedocument.wordprocessingml.document",DP_CONTENT_WORD}, + // ppt + {"application/vnd.ms-powerpoint",DP_CONTENT_PPT}, + {"application/vnd.openxmlformats-officedocument.presentationml.presentation",DP_CONTENT_PPT}, + // excel + {"application/vnd.ms-excel",DP_CONTENT_EXCEL}, + {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",DP_CONTENT_EXCEL}, + // html + {"text/html",DP_CONTENT_HTML}, + // txt + {"text/txt",DP_CONTENT_TEXT}, + {"text/plain",DP_CONTENT_TEXT}, + // DRM + {"application/vnd.oma.drm.content",DP_CONTENT_SD_DRM}, + {"application/vnd.oma.drm.message",DP_CONTENT_DRM}, + {"application/x-shockwave-flash", DP_CONTENT_FLASH}, + {"application/vnd.tizen.package", DP_CONTENT_TPK}, + {"text/calendar",DP_CONTENT_VCAL}, +}; + +static void *g_da_handle = NULL; +static int (*download_agent_init)(void) = NULL; // int da_init(da_client_cb_t *da_client_callback); +static int (*download_agent_deinit)(void) = 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_suspend_without_update)(int) = NULL; // int da_suspend_download_without_update(int download_id); +static int (*download_agent_cancel_without_update)(int) = NULL; // int da_cancel_download_without_update(int download_id); +static int (*download_agent_start)(const char *url, req_data_t *ext_data, da_cb_t *da_cb_data, int *download_id) = NULL; // int da_start_download_with_extension(const char *url, extension_data_t *ext_data, int *download_id); +static dp_content_type __dp_get_content_type(const char *mime, const char *file_path); + +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_NETWORK_ERROR; + break; + case DA_ERR_CONNECTION_FAIL: + case DA_ERR_NETWORK_UNAUTHORIZED: + 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_ACCESS_FILE: + default: + ret = DP_ERROR_IO_ERROR; + break; + } + return ret; +} + +static int __dp_da_state_feedback(dp_client_slots_fmt *slot, dp_request_fmt *request) +{ + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address"); + return -1; // try cancel + } + + TRACE_INFO("[INFO][%d] state:%s error:%s", request->id, + dp_print_state(request->state), dp_print_errorcode(request->error)); + + int errorcode = DP_ERROR_NONE; + if (dp_db_update_logging(slot->client.dbhandle, request->id, + request->state, request->error, &errorcode) < 0) { + TRACE_ERROR("logging failure id:%d error:%d", request->id, errorcode); + return -1; // try cancel + } + + request->access_time = (int)time(NULL); + + if (request->state_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, request->id, request->state, request->error, 0) < 0) { + TRACE_ERROR("id:%d disable state callback by IO_ERROR", request->id); + request->state_cb = 0; + } + } + + return 0; +} + +static int __precheck_request(dp_request_fmt *request, int agentid) +{ + if (request == NULL) { + TRACE_ERROR("null-check request req_id:%d", agentid); + return -1; + } + if (request->id < 0 || (request->agent_id != agentid)) { + TRACE_ERROR("id-check request_id:%d agent_id:%d req_id:%d", + request->id, request->agent_id, agentid); + return -1; + } + return 0; +} + +static int __set_file_permission_to_client(dp_client_slots_fmt *slot, dp_request_fmt *request, char *saved_path) +{ + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), (request == NULL ? 0 : request->agent_id)); + return DP_ERROR_INVALID_PARAMETER; + } else if (saved_path == NULL) { + TRACE_ERROR("check null saved path"); + return DP_ERROR_INVALID_PARAMETER; + } + + struct stat lstat_info; + struct stat fstat_info; + int fd; + int errorcode = DP_ERROR_NONE; + char *str = NULL; + str = strrchr(saved_path, '/'); + dp_credential cred = slot->credential; + if (lstat(saved_path, &lstat_info) != -1) { + fd = open (saved_path, O_RDONLY); + if (fd != -1) { + if (fstat(fd, &fstat_info) != -1) { + if (lstat_info.st_mode == fstat_info.st_mode && + lstat_info.st_ino == fstat_info.st_ino && + lstat_info.st_dev == fstat_info.st_dev) { + if ((fchown(fd, cred.uid, cred.gid) != 0) || + (fchmod(fd, S_IRUSR | S_IWUSR | + S_IRGRP | S_IROTH) != 0)) { + TRACE_STRERROR("[ERROR][%d] permission user:%d group:%d", + request->id, cred.uid, cred.gid); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + } else { + TRACE_STRERROR("fstat & lstat info have not matched"); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + } else { + TRACE_STRERROR("fstat call failed"); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + close(fd); + } else { + TRACE_SECURE_ERROR("open failed for file : %s", saved_path); + errorcode = DP_ERROR_IO_ERROR; + } + } else { + TRACE_STRERROR("lstat call failed"); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + if (errorcode == DP_ERROR_NONE && dp_smack_is_mounted() == 1) { + // get smack_label from sql + char *smack_label = dp_db_get_client_smack_label(slot->pkgname); + 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 = dp_smack_set_label(smack_label, dir_path, saved_path); + free(dir_path); + } else { + TRACE_STRERROR("[ERROR] calloc"); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } + free(smack_label); + } + } + return errorcode; +} + +static void __finished_cb(finished_info_t *info, void *user_req_data, + void *user_client_data) +{ + if (info == NULL) { + TRACE_ERROR("check download info address"); + return ; + } + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), info->download_id); + free(info->etag); + free(info->saved_path); + free(info); + return ; + } + CLIENT_MUTEX_LOCK(&slot->mutex); + if (__precheck_request(request, info->download_id) < 0) { + TRACE_ERROR("error request agent_id:%d", info->download_id); + if (dp_cancel_agent_download(info->download_id) < 0) + TRACE_ERROR("failed to call cancel_download(%d)", info->download_id); + free(info->etag); + free(info->saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return ; + } + + int state = DP_STATE_NONE; + int errorcode = DP_ERROR_NONE; + + if (info->http_status > 0) { + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_HTTP_STATUS, (void *)&info->http_status, 0, 0, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set http_status(%d)", request->id, info->http_status); + } + } + + TRACE_SECURE_DEBUG("[FINISH][%d][%s]", request->id, info->saved_path); + if (info->err == DA_RESULT_OK) { + if (info->saved_path != NULL) { + if(strncmp(DP_SDCARD_MNT_POINT, info->saved_path, strlen(DP_SDCARD_MNT_POINT)) != 0) { + errorcode = __set_file_permission_to_client(slot, request, info->saved_path); + } + } else { + TRACE_ERROR("[ERROR][%d] No SavedPath", request->id); + errorcode = DP_ERROR_INVALID_DESTINATION; + } + if (errorcode == DP_ERROR_NONE) + state = DP_STATE_COMPLETED; + else + state = DP_STATE_FAILED; + } else { + if (info->err == DA_RESULT_USER_CANCELED) { + + TRACE_INFO("[CANCELED][%d]", request->id); + + // if state is canceled and error is DP_ERROR_IO_EAGAIN mean ip_changed + if (request->error == DP_ERROR_IO_EAGAIN) { + request->error = DP_ERROR_NONE; + } else { + state = DP_STATE_CANCELED; + errorcode = request->error; + } + + } else { + state = DP_STATE_FAILED; + errorcode = __change_error(info->err); + TRACE_ERROR("[FAILED][%d][%s] agent error:%d", request->id, + dp_print_errorcode(errorcode), info->err); + } + + } + + if (errorcode == DP_ERROR_NONE && info->saved_path != NULL) { + + char *content_name = NULL; + char *str = NULL; + str = strrchr(info->saved_path, '/'); + if (str != NULL) { + str++; + content_name = dp_strdup(str); + } + if (request->file_size == 0) {// missed in download_cb + request->file_size = request->received_size; + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, (void *)&request->file_size, 0, 1, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set content_size(%ld)", request->id, request->file_size); + } + } + // update contentname, savedpath + if (content_name != NULL) { + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (void *)content_name, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set content_name", request->id); + } + } + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (void *)info->saved_path, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set saved_path", request->id); + } + free(content_name); + /* update the received file size. + * The last received file size cannot update + * because of reducing update algorithm*/ + if (request->progress_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, request->id, DP_STATE_DOWNLOADING, DP_ERROR_NONE, request->received_size) < 0) { + TRACE_ERROR("id:%d disable progress callback by IO_ERROR", request->id); + request->progress_cb = 0; + } + } + } + + request->state = state; + request->error = errorcode; + + if (__dp_da_state_feedback(slot, request) < 0) { + TRACE_ERROR("id:%d check notify channel", request->id); + if (dp_cancel_agent_download_without_update(request->agent_id) < 0) + TRACE_ERROR("[fail][%d]cancel_agent", request->id); + } + if (request->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + request->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, request, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + } + free(info->etag); + free(info->saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); +} + +static void __paused_cb(int download_id, void *user_req_data, void *user_client_data) +{ + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), download_id); + return ; + } + dp_queue_manager_wake_up(); +} + +static void __download_info_cb(download_info_t *info, void *user_req_data, void *user_client_data) +{ + if (info == NULL) { + TRACE_ERROR("check download info address"); + return ; + } + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), info->download_id); + free(info->content_name); + free(info->etag); + free(info->file_type); + free(info->tmp_saved_path); + free(info); + return ; + } + CLIENT_MUTEX_LOCK(&slot->mutex); + if (__precheck_request(request, info->download_id) < 0) { + TRACE_ERROR("error request agent_id:%d", info->download_id); + if (dp_cancel_agent_download(info->download_id) < 0) + TRACE_ERROR("failed to call cancel_download(%d)", info->download_id); + free(info->content_name); + free(info->etag); + free(info->file_type); + free(info->tmp_saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return ; + } + + // update info before sending event + TRACE_SECURE_DEBUG("[DOWNLOAD][%d][%s]", request->id, info->tmp_saved_path); + if (info->tmp_saved_path != NULL) { + int errorcode = DP_ERROR_NONE; + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_MIMETYPE, (void *)info->file_type, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set mimetype", request->id); + } + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (void *)info->content_name, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set contentname", request->id); + } + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (void *)info->tmp_saved_path, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set tmp_saved_path", request->id); + } + if (info->file_size > 0 && dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, (void *)&(info->file_size), 0, 1, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set file size", request->id); + } + if (info->etag && dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (void *)info->etag, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set etag", request->id); + } + if(strncmp(DP_SDCARD_MNT_POINT, info->tmp_saved_path, strlen(DP_SDCARD_MNT_POINT)) != 0) { + errorcode = __set_file_permission_to_client(slot, request, info->tmp_saved_path); + } + request->error = errorcode; + } else { + request->error = DP_ERROR_IO_ERROR; + } + + if (request->error != DP_ERROR_NONE) { + request->state = DP_STATE_FAILED; + TRACE_ERROR("id:%d try to cancel(%d)", request->id, info->download_id); + if (dp_cancel_agent_download(request->agent_id) < 0) { + TRACE_ERROR("[fail][%d] cancel_agent:%d", request->id, + info->download_id); + } + } else { + request->state = DP_STATE_DOWNLOADING; + request->file_size = info->file_size; // unsigned + TRACE_DEBUG("[STARTED] id:%d agentid:%d", request->id, info->download_id); + } + + if (__dp_da_state_feedback(slot, request) < 0) { + TRACE_ERROR("id:%d check notify channel", request->id); + if (dp_cancel_agent_download(request->agent_id) < 0) + TRACE_ERROR("[fail][%d]cancel_agent", request->id); + } + // notification + if (request->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, request, DP_NOTIFICATION_ONGOING_UPDATE) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + } + //get the mime type for dp notification + if (request->noti_type > DP_NOTIFICATION_TYPE_NONE) { + request->content_type = __dp_get_content_type(info->file_type, info->tmp_saved_path); + } + free(info->content_name); + free(info->etag); + free(info->file_type); + free(info->tmp_saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); +} + +static void __progress_cb(int download_id, unsigned long long received_size, + void *user_req_data, void *user_client_data) +{ + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), download_id); + return ; + } + CLIENT_MUTEX_LOCK(&slot->mutex); + /* + if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) != 0) { + TRACE_ERROR("slot busy agent_id:%d", download_id); + return ; + } + */ + if (__precheck_request(request, download_id) < 0) { + TRACE_ERROR("error request agent_id:%d", download_id); + if (dp_cancel_agent_download(download_id) < 0) + TRACE_ERROR("failed to call cancel_download(%d)", download_id); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return ; + } + + // For resume case after pause, it change state from connecting to downloading + if (request->state == DP_STATE_CONNECTING) { + request->state = DP_STATE_DOWNLOADING; + if (__dp_da_state_feedback(slot, request) < 0) { + TRACE_ERROR("id:%d check notify channel", request->id); + if (dp_cancel_agent_download(request->agent_id) < 0) + TRACE_ERROR("[fail][%d]cancel_agent", request->id); + } + } + + if (request->state == DP_STATE_DOWNLOADING) { + request->received_size = 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->progress_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, + request->id, DP_STATE_DOWNLOADING, DP_ERROR_NONE, received_size) < 0) { + // failed to read from socket // ignore this status + TRACE_ERROR("id:%d disable progress callback by IO_ERROR", request->id); + request->progress_cb = 0; + } + } + + if (request->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, request, DP_NOTIFICATION_ONGOING_PROGRESS) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + } + + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); +} + +static int __dp_is_ambiguous_mime_type(const char *mime_type) +{ + if (mime_type == NULL) + return -1; + + int index = 0; + int listSize = sizeof(ambiguous_mime_type_list) / sizeof(const char *); + for (index = 0; index < listSize; index++) { + if (0 == strncmp(mime_type, ambiguous_mime_type_list[index], + strlen(ambiguous_mime_type_list[index]))) { + TRACE_DEBUG("It is ambiguous"); + return 0; + } + } + return -1; +} + +static dp_content_type __dp_get_content_type(const char *mime, const char *file_path) +{ + int i = 0; + int type = DP_CONTENT_UNKNOWN; + char *temp_mime = NULL; + if (mime == NULL || strlen(mime) < 1) + return DP_CONTENT_UNKNOWN; + + if ((file_path != NULL) && (strlen(file_path) > 0) && + (__dp_is_ambiguous_mime_type(mime) == 0)) { + const char *ext = strrchr(file_path, '.'); + if (ext == NULL) { + TRACE_ERROR("File Extension is NULL"); + return type; + } + mime_type_get_mime_type(ext + 1, &temp_mime); + } + if (temp_mime == NULL) { + temp_mime = (char *)calloc(1, DP_MAX_FILE_PATH_LEN); + if (temp_mime == NULL) { + TRACE_ERROR("Fail to call calloc"); + return type; + } + strncpy(temp_mime, mime, DP_MAX_FILE_PATH_LEN - 1); + } + TRACE_SECURE_DEBUG("mime type [%s]", temp_mime); + + /* Search a content type from mime table. */ + for (i = 0; i < DP_MAX_MIME_TABLE_NUM; i++) { + if (strncmp(mime_table[i].mime, temp_mime, strlen(temp_mime)) == 0){ + type = mime_table[i].content_type; + break; + } + } + if (type == DP_CONTENT_UNKNOWN) { + const char *unaliased_mime = NULL; + /* unaliased_mimetype means representative mime among similar types */ + unaliased_mime = xdg_mime_unalias_mime_type(temp_mime); + + if (unaliased_mime != NULL) { + TRACE_SECURE_DEBUG("unaliased mime type[%s]",unaliased_mime); + if (strstr(unaliased_mime,"video/") != NULL) + type = DP_CONTENT_VIDEO; + else if (strstr(unaliased_mime,"audio/") != NULL) + type = DP_CONTENT_MUSIC; + else if (strstr(unaliased_mime,"image/") != NULL) + type = DP_CONTENT_IMAGE; + } + } + free(temp_mime); + TRACE_DEBUG("type[%d]", type); + return type; +} + + +int dp_init_agent() +{ + + g_da_handle = dlopen("/usr/lib/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_without_update"); + *(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"); + if (download_agent_start == NULL) { + TRACE_ERROR("[dlsym] da_start_download:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_cancel_without_update) = dlsym(g_da_handle, "da_cancel_download_without_update"); + if (download_agent_cancel_without_update == NULL) { + TRACE_ERROR("[dlsym] da_cancel_download_without_update:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_suspend_without_update) = dlsym(g_da_handle, "da_suspend_download_without_update"); + if (download_agent_suspend_without_update == NULL) { + TRACE_ERROR("[dlsym] da_suspend_download_without_update:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + int da_ret = -1; + da_ret = (*download_agent_init)(); + 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) + return 0; + if (download_agent_is_alive != NULL) + da_ret = (*download_agent_is_alive)(req_id); + return da_ret; +} + +// 0 : success +// -1 : failed +int 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 +int 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 +int dp_cancel_agent_download_without_update(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_without_update != NULL) { + if ((*download_agent_cancel_without_update)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + +// 0 : success +// -1 : failed +int dp_pause_agent_download_without_update(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_without_update != NULL) { + if ((*download_agent_suspend_without_update)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + +// 0 : success +// -1 : failed +// -2 : pended +int dp_start_agent_download(void *slot, void *request) +{ + int da_ret = -1; + int req_dl_id = -1; + req_data_t *req_data = NULL; + + dp_client_slots_fmt *base_slot = slot; + dp_request_fmt *base_req = request; + + if (slot == NULL || request == NULL) { + TRACE_ERROR("check slot or request address"); + return DP_ERROR_INVALID_PARAMETER; + } + + da_cb_t da_cb = { + __download_info_cb, + __progress_cb, + __finished_cb, + __paused_cb + }; + + req_data = (req_data_t *)calloc(1, sizeof(req_data_t)); + if (req_data == NULL) { + TRACE_ERROR("[ERROR] calloc"); + return DP_ERROR_OUT_OF_MEMORY; + } + + int errorcode = DP_ERROR_NONE; + unsigned length = 0; + char *url = NULL; + char *destination = NULL; + char *tmp_saved_path = NULL; + char *user_tmp_file_path = NULL; + char *filename = NULL; + char *etag = NULL; + int user_network_bonding = 0; + + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (unsigned char **)&url, &length, &errorcode) < 0 || + url == NULL) { + free(req_data); + if (errorcode == DP_ERROR_NO_DATA) { + TRACE_ERROR("url id:%d NO_DATA", base_req->id); + return DP_ERROR_INVALID_URL; + } else { + TRACE_ERROR("url id:%d DISK_BUSY", base_req->id); + return DP_ERROR_DISK_BUSY; + } + } + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_TEMP_FILE_PATH, (unsigned char **)&user_tmp_file_path, &length, &errorcode) < 0 || + user_tmp_file_path == NULL) { + TRACE_DEBUG("user_tmp_file_path id:%d NO_DATA", base_req->id); + } + + if (user_tmp_file_path != NULL) + req_data->temp_file_path = user_tmp_file_path; + else { + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (unsigned char **)&filename, &length, &errorcode) < 0 || + filename == NULL) { + TRACE_DEBUG("filename id:%d NO_DATA", base_req->id); + } else + req_data->file_name = filename; + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (unsigned char **)&destination, &length, &errorcode) < 0 || + destination == NULL) { + TRACE_DEBUG("destination id:%d NO_DATA", base_req->id); + } else + req_data->install_path = destination; + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (unsigned char **)&tmp_saved_path, &length, &errorcode) < 0 || + tmp_saved_path == NULL) { + TRACE_DEBUG("tmp_saved_path id:%d NO_DATA", base_req->id); + } + } + + if (tmp_saved_path != NULL) { + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (unsigned char **)&etag, &length, &errorcode) < 0 || + etag == NULL) { + TRACE_DEBUG("etag id:%d NO_DATA", base_req->id); + } + if (etag != NULL) { + TRACE_DEBUG("try to resume id:%d", base_req->id); + req_data->etag = etag; + req_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("try to restart id:%d remove tmp file:%s", + base_req->id, tmp_saved_path); + if (dp_is_file_exist(tmp_saved_path) == 0) { + if (unlink(tmp_saved_path) != 0) + TRACE_STRERROR("failed to remove file id:%d", base_req->id); + } + } + } + if( dp_db_get_property_int(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, (int *)&user_network_bonding, &errorcode) < 0 || + user_network_bonding < 0) { + TRACE_DEBUG("unable to get network bonding value for id:%d", base_req->id); + } else + req_data->network_bonding = user_network_bonding; + + req_data->pkg_name = base_slot->pkgname; + + // get headers list from header table(DB) + int headers_count = dp_db_check_duplicated_int(base_slot->client.dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ID, base_req->id, &errorcode); + if (headers_count > 0) { + req_data->request_header = calloc(headers_count, sizeof(char *)); + if (req_data->request_header != NULL) { + headers_count = dp_db_get_http_headers_list(base_slot->client.dbhandle, base_req->id, (char **)req_data->request_header, &errorcode); + if (headers_count > 0) + req_data->request_header_count = headers_count; + } + } + + req_data->user_client_data = (void *)slot; + req_data->user_req_data = (void *)request; + + // call start API of agent lib + if (download_agent_start != NULL) + da_ret = (*download_agent_start)(url, req_data, &da_cb, &req_dl_id); + if (req_data->request_header_count > 0) { + int len = 0; + int i = 0; + len = req_data->request_header_count; + for (i = 0; i < len; i++) + free((void *)(req_data->request_header[i])); + free(req_data->request_header); + } + free(url); + free(destination); + free(tmp_saved_path); + free(user_tmp_file_path); + free(filename); + free(etag); + free(req_data); + + if (da_ret == DA_RESULT_OK) { + TRACE_DEBUG("request id :%d SUCCESS agent_id:%d", base_req->id, req_dl_id); + base_req->agent_id = req_dl_id; + } + return __change_error(da_ret); +} + +int 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); +} + diff --git a/provider/download-provider-pthread.c b/provider/download-provider-pthread.c new file mode 100644 index 0000000..3ef2816 --- /dev/null +++ b/provider/download-provider-pthread.c @@ -0,0 +1,110 @@ +/* + * 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 <unistd.h> +#include <time.h> +#include <errno.h> + +#include "download-provider-log.h" +#include "download-provider-pthread.h" + +static char *__print_pthread_error(int code) +{ + switch(code) + { + case 0: + return "NONE"; + case EINVAL: + return "EINVAL"; + case ENOMEM: + return "ENOMEM"; + case EBUSY: + return "EBUSY"; + case EDEADLK: + return "EDEADLK"; + } + return "UNKNOWN"; +} + +int dp_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + int ret = pthread_mutex_init(mutex, attr); + if (0 == ret || EBUSY == ret) + return 0; + else + TRACE_STRERROR("error:%d.%s", ret, __print_pthread_error(ret)); + return -1; +} + +void dp_mutex_lock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_lock(mutex); + if (ret != 0) + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); +} + +int dp_mutex_check_lock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_lock(mutex); + if (ret != 0) + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); + return ret; +} + +int dp_mutex_trylock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_trylock(mutex); + if (ret != 0 && ret != EINVAL) { + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); + } + return ret; +} + +int dp_mutex_timedlock(pthread_mutex_t *mutex, int sec, const char *func, int line) +{ + struct timespec deltatime; + deltatime.tv_sec = sec; + deltatime.tv_nsec = 0; + int ret = pthread_mutex_timedlock(mutex, &deltatime); + if (ret != 0) { + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); + } + return ret; +} + +void dp_mutex_unlock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_unlock(mutex); + if (ret != 0) + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); +} + +void dp_mutex_destroy(pthread_mutex_t *mutex) +{ + int ret = pthread_mutex_destroy(mutex); + if (ret != 0) { + TRACE_STRERROR("error:%d.%s", ret, __print_pthread_error(ret)); + if(EBUSY == ret) { + if (pthread_mutex_unlock(mutex) == 0) + pthread_mutex_destroy(mutex); + } + } +} diff --git a/provider/download-provider-queue-manager.c b/provider/download-provider-queue-manager.c new file mode 100644 index 0000000..41f4a36 --- /dev/null +++ b/provider/download-provider-queue-manager.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2013 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 <stdlib.h> +#include <signal.h> // pthread_kill +#include <errno.h> // ESRCH + +#include <download-provider-log.h> +#include <download-provider-pthread.h> + +#include <download-provider-db-defs.h> +#include <download-provider-db.h> +#include <download-provider-queue.h> +#include <download-provider-network.h> +#include <download-provider-notify.h> +#include <download-provider-client.h> +#include <download-provider-client-manager.h> +#include <download-provider-plugin-download-agent.h> + +pthread_mutex_t g_dp_queue_manager_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t g_dp_queue_manager_cond = PTHREAD_COND_INITIALIZER; +pthread_t g_dp_queue_manager_tid = 0; + +static dp_queue_fmt *g_dp_queue_network_all = NULL; +static dp_queue_fmt *g_dp_queue_network_wifi = NULL; +static dp_queue_fmt *g_dp_queue_network_data_network = NULL; +static dp_queue_fmt *g_dp_queue_network_wifi_direct = NULL; + +static dp_queue_fmt **__dp_queue_manager_get_queue(int network) +{ + switch(network) { + case DP_NETWORK_ALL: + //TRACE_DEBUG("network all"); + return &g_dp_queue_network_all; + case DP_NETWORK_WIFI: + //TRACE_DEBUG("network wifi only"); + return &g_dp_queue_network_wifi; + case DP_NETWORK_DATA_NETWORK: + //TRACE_DEBUG("network data network only"); + return &g_dp_queue_network_data_network; + case DP_NETWORK_WIFI_DIRECT: + //TRACE_DEBUG("network wifi-direct"); + return &g_dp_queue_network_wifi_direct; + default: + break; + } + return NULL; +} +int dp_queue_manager_push_queue(void *slot, void *request) +{ + dp_request_fmt *requestp = request; + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : requestp->id)); + return -1; + } + dp_queue_fmt **queue = __dp_queue_manager_get_queue(requestp->network_type); + if (requestp->state != DP_STATE_QUEUED) { + TRACE_ERROR("check id:%d state:%s", requestp->id, dp_print_state(requestp->state)); + return -1; + } + if (dp_queue_push(queue, slot, request) < 0) { + TRACE_ERROR("failed to push to queue id:%d", requestp->id); + return -1; + } + return 0; +} + +void dp_queue_manager_clear_queue(void *request) +{ + dp_request_fmt *requestp = request; + if (request == NULL) { + TRACE_DEBUG("check address request:%p id:%d", + request, (request == NULL ? 0 : requestp->id)); + return ; + } + dp_queue_fmt **queue = __dp_queue_manager_get_queue(requestp->network_type); + dp_queue_clear(queue, request); +} + +// if return negative, queue-manager try again. +static int __dp_queue_manager_try_download(dp_client_slots_fmt *slot, dp_request_fmt *request) +{ + int errorcode = DP_ERROR_NONE; + int result = 0; + + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : request->id)); + // return 0 to ignore this call. + return 0; + } + + if (request->state != DP_STATE_QUEUED) { + TRACE_ERROR("check id %d state:%d", request->id, request->state); + return 0; + } + + // check startcount + + request->startcount++; + request->access_time = (int)time(NULL); + + if (dp_db_replace_property(slot->client.dbhandle, request->id, + DP_TABLE_LOGGING, DP_DB_COL_STARTCOUNT, + (void *)&request->startcount, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set startcount"); + return -1; + } + + errorcode = DP_ERROR_NONE; + + if (dp_is_alive_download(request->agent_id) > 0) + errorcode = dp_resume_agent_download(request->agent_id); + else + // call agent start function + errorcode = dp_start_agent_download(slot, request); + + if (errorcode == DP_ERROR_NONE) { + request->state = DP_STATE_CONNECTING; + } else if (errorcode == DP_ERROR_TOO_MANY_DOWNLOADS || + errorcode == DP_ERROR_DISK_BUSY || + errorcode == DP_ERROR_OUT_OF_MEMORY) { + TRACE_ERROR("push queue id:%d error:%s", request->id, dp_print_errorcode(errorcode)); + // PENDED + request->state = DP_STATE_QUEUED; + result = -1; // try again. + } else if (errorcode == DP_ERROR_INVALID_STATE) { // by resume + // ignore this request + result = -1; + TRACE_ERROR("failed to resume id:%d", request->id); + request->agent_id = -1; // workaround. da_agent will an object for this agent_id later + } else if (errorcode != DP_ERROR_NONE) { + request->state = DP_STATE_FAILED; + } + + request->error = errorcode; + + if (result == 0) { // it's not for retrying + int sqlerror = DP_ERROR_NONE; + if (dp_db_update_logging(slot->client.dbhandle, request->id, + request->state, request->error, &sqlerror) < 0) { + TRACE_ERROR("logging failure id:%d error:%d", request->id, sqlerror); + } + if (errorcode != DP_ERROR_NONE && request->state_cb == 1) { // announce state + + TRACE_ERROR("notify id:%d error:%s", request->id, dp_print_errorcode(errorcode)); + if (dp_notify_feedback(slot->client.notify, slot, + request->id, request->state, request->error, 0) < 0) { + TRACE_ERROR("disable state callback by IO_ERROR id:%d", request->id); + request->state_cb = 0; + } + } + } + + return result; + +} + +static int __dp_queue_manager_check_queue(dp_queue_fmt **queue) +{ + dp_client_slots_fmt *slot = NULL; + dp_request_fmt *request = NULL; + while (dp_queue_pop(queue, (void *)&slot, (void *)&request) == 0) { // pop a request from queue. + TRACE_DEBUG("queue-manager pop a request"); + if (slot == NULL || request == NULL) { + TRACE_DEBUG("queue error client:%p request:%p id:%d", slot, request, (request == NULL ? 0 : request->id)); + continue; + } + + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_DEBUG("queue info slot:%p request:%p id:%d", slot, request, (request == NULL ? 0 : request->id)); + + int errorcode = DP_ERROR_NONE; + int download_state = DP_STATE_NONE; + if (slot != NULL && request != NULL && + dp_db_get_property_int(slot->client.dbhandle, request->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("deny checking id:%d db state:%s memory:%s", request->id, dp_print_state(download_state), dp_print_state(request->state)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + + if (download_state == DP_STATE_QUEUED && __dp_queue_manager_try_download(slot, request) < 0) { + // if failed to start, push at the tail of queue. try again. + if (dp_queue_push(queue, slot, request) < 0) { + TRACE_ERROR("failed to push to queue id:%d", request->id); + int errorcode = DP_ERROR_NONE; + if (dp_db_update_logging(slot->client.dbhandle, request->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("failed to update log id:%d", request->id); + } + request->state = DP_STATE_FAILED; + request->error = DP_ERROR_QUEUE_FULL; + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return -1; // return negative for taking a break + } + + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + slot = NULL; + request = NULL; + } + return 0; +} + +static void *__dp_queue_manager(void *arg) +{ + pthread_cond_init(&g_dp_queue_manager_cond, NULL); + + if (dp_init_agent() != DP_ERROR_NONE) { + TRACE_ERROR("failed to init agent"); + pthread_cond_destroy(&g_dp_queue_manager_cond); + pthread_exit(NULL); + return 0; + } + + do { + + if (g_dp_queue_manager_tid <= 0) { + TRACE_INFO("queue-manager is closed by other thread"); + break; + } + + // check wifi_direct first + if (dp_network_is_wifi_direct() == 1 && __dp_queue_manager_check_queue(&g_dp_queue_network_wifi_direct) < 0) { + TRACE_ERROR("download-agent is busy, try again after 15 seconds"); + } else { // enter here if disable wifi-direct or download-agent is available + int network_status = dp_network_get_status(); + if (network_status != DP_NETWORK_OFF) { + TRACE_INFO("queue-manager try to check queue network:%d", network_status); + if (g_dp_queue_network_all != NULL && __dp_queue_manager_check_queue(&g_dp_queue_network_all) < 0) { + TRACE_ERROR("download-agent is busy, try again after 15 seconds"); + } else { + dp_queue_fmt **queue = __dp_queue_manager_get_queue(network_status); + if (__dp_queue_manager_check_queue(queue) < 0) { + TRACE_ERROR("download-agent is busy, try again after 15 seconds"); + } + } + } + } + + struct timeval now; + struct timespec ts; + gettimeofday(&now, NULL); + ts.tv_sec = now.tv_sec + 5; + ts.tv_nsec = now.tv_usec * 1000; + CLIENT_MUTEX_LOCK(&g_dp_queue_manager_mutex); + pthread_cond_timedwait(&g_dp_queue_manager_cond, &g_dp_queue_manager_mutex, &ts); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_manager_mutex); + + } while (g_dp_queue_manager_tid > 0); + + TRACE_DEBUG("queue-manager's working is done"); + dp_deinit_agent(); + dp_queue_clear_all(&g_dp_queue_network_all); + pthread_cond_destroy(&g_dp_queue_manager_cond); + pthread_exit(NULL); + return 0; +} + +static int __dp_queue_manager_start() +{ + if (g_dp_queue_manager_tid == 0 || + pthread_kill(g_dp_queue_manager_tid, 0) == ESRCH) { + TRACE_DEBUG("try to create queue-manager"); + if (pthread_create(&g_dp_queue_manager_tid, NULL, + __dp_queue_manager, NULL) != 0) { + TRACE_STRERROR("failed to create queue-manager"); + return -1; + } + } + return 0; +} + +void dp_queue_manager_wake_up() +{ + if (g_dp_queue_manager_tid > 0 && + pthread_kill(g_dp_queue_manager_tid, 0) != ESRCH) { + int locked = CLIENT_MUTEX_TRYLOCK(&g_dp_queue_manager_mutex); + if (locked == 0) { + pthread_cond_signal(&g_dp_queue_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_manager_mutex); + } + } else { + __dp_queue_manager_start(); + } +} + +void dp_queue_manager_kill() +{ + if (g_dp_queue_manager_tid > 0 && + pthread_kill(g_dp_queue_manager_tid, 0) != ESRCH) { + //send signal to queue thread + g_dp_queue_manager_tid = 0; + CLIENT_MUTEX_LOCK(&g_dp_queue_manager_mutex); + pthread_cond_signal(&g_dp_queue_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_manager_mutex); + pthread_cancel(g_dp_queue_manager_tid); + int status; + pthread_join(g_dp_queue_manager_tid, (void **)&status); + } +} diff --git a/provider/download-provider-queue.c b/provider/download-provider-queue.c new file mode 100644 index 0000000..ad038fd --- /dev/null +++ b/provider/download-provider-queue.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2013 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 <stdlib.h> + +#include <download-provider-queue.h> +#include <download-provider-log.h> +#include <download-provider-pthread.h> +#include <download-provider-client.h> +#include <download-provider-client-manager.h> + +/* queue + * 1. push : at the tail of linked list + * 2. pop : at the head of linked list + * 3. priority push : at the head of linked list + * 4. in pop, check client of slot, search request by download_id + */ + +//dp_queue_fmt *g_dp_queue = NULL; // head of linked list +pthread_mutex_t g_dp_queue_mutex = PTHREAD_MUTEX_INITIALIZER; + +// normal . push at the tail of queue. +int dp_queue_push(dp_queue_fmt **queue, void *slot, void *request) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + dp_client_slots_fmt *baseslot = slot; + dp_request_fmt *new_request = request; + if (slot == NULL || request == NULL || new_request->id <= 0) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (new_request->id <= 0) { + TRACE_ERROR("check slot or download id", new_request->id); + return -1; + } else if (new_request->state != DP_STATE_QUEUED) { + TRACE_ERROR("check id:%d state:%s", new_request->id, dp_print_state(new_request->state)); + return -1; + } + + CLIENT_MUTEX_LOCK(&g_dp_queue_mutex); + // search the tail of queue + int i = 0; + dp_queue_fmt *tailp = *queue; + dp_queue_fmt *prevp = NULL; + TRACE_DEBUG("queue req slot:%p request:%p id:%d", slot, request, (request == NULL ? 0 : new_request->id)); + for (; tailp != NULL; i++) { + dp_request_fmt *qrequestp = tailp->request; + if (tailp->slot == NULL || tailp->request == NULL || + qrequestp->state != DP_STATE_QUEUED) { + TRACE_DEBUG("queue error %d slot:%p request:%p id:%d", i, tailp->slot, tailp->request, (tailp->request == NULL ? 0 : ((dp_request_fmt *)tailp->request)->id)); + } else if (tailp->slot == slot && tailp->request == request && qrequestp->id == new_request->id) { + TRACE_INFO("queue duplicte %d slot:%p request:%p id:%d", i, slot, request, new_request->id); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return 0; + } else { + TRACE_INFO("queue info %d slot:%p request:%p id:%d %s", i, tailp->slot, tailp->request, ((dp_request_fmt *)tailp->request)->id, ((dp_client_slots_fmt *)tailp->slot)->pkgname); + } + prevp = tailp; + tailp = tailp->next; + } + dp_queue_fmt *new_queue = (dp_queue_fmt *)malloc(sizeof(dp_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + } else { + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return -1; + } + TRACE_DEBUG("queue push %d info:%s id:%d", i, baseslot->pkgname, new_request->id); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return 0; +} + +int dp_queue_pop(dp_queue_fmt **queue, void **slot, void **request) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_queue_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (*queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return -1; + } + // get a head of queue + int ret = -1; + dp_queue_fmt *popp; + do { + popp = *queue; + *queue = popp->next; + dp_client_slots_fmt *slotp = popp->slot; + dp_request_fmt *requestp = popp->request; + if (slotp == NULL || requestp == NULL || + requestp->state != DP_STATE_QUEUED) { + TRACE_DEBUG("queue error slot:%p request:%p id:%d", popp->slot, popp->request, (requestp == NULL ? 0 : requestp->id)); + free(popp); + } else { + TRACE_INFO("queue pop slot:%p request:%p id:%d %s", popp->slot, popp->request, requestp->id, slotp->pkgname); + *slot = popp->slot; + *request = popp->request; + ret = 0; + free(popp); + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return ret; +} + +void dp_queue_clear(dp_queue_fmt **queue, void *request) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + if (request == NULL) { + TRACE_ERROR("check client and request memory address"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_queue_mutex); + int i = 0; + dp_queue_fmt *tailp = *queue; + dp_queue_fmt *prevp = NULL; + TRACE_DEBUG("queue clear req request:%p id:%d", request, (request == NULL ? 0 : ((dp_request_fmt *)request)->id)); + for (; tailp != NULL; i++) { + dp_request_fmt *requestp = tailp->request; + TRACE_DEBUG("queue info %d request:%p id:%d", i, requestp, (requestp == NULL ? 0 : requestp->id)); + if (requestp == request) { + // clear. + if (prevp == NULL) + *queue = tailp->next; + else + prevp->next = tailp->next; + TRACE_DEBUG("queue clear this %d request:%p id:%d", i, requestp, (requestp == NULL ? 0 : requestp->id)); + free(tailp); + break; + } + prevp = tailp; + tailp = tailp->next; + } + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); +} + +void dp_queue_clear_all(dp_queue_fmt **queue) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_queue_mutex); + if (queue == NULL || *queue == NULL) { + TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return ; + } + // get a head of queue + do { + dp_queue_fmt *popp = *queue; + *queue = popp->next; + TRACE_DEBUG("queue clear slot:%p request:%p id:%d", popp->slot, popp->request, (popp->request == NULL ? 0 : ((dp_request_fmt *)popp->request)->id)); + free(popp); + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); +} diff --git a/provider/download-provider-request.c b/provider/download-provider-request.c deleted file mode 100755 index 10fea00..0000000 --- a/provider/download-provider-request.c +++ /dev/null @@ -1,941 +0,0 @@ -/* - * 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/time.h> -#include <sys/statfs.h> -#include "download-provider.h" -#include "download-provider-log.h" - -#include "download-provider-slots.h" -#include "download-provider-socket.h" -#include "download-provider-db.h" -#include "download-provider-pthread.h" - -#include "download-provider-notification.h" - -#define SMACKFS_MAGIC 0x43415d53 -#define SMACKFS_MNT "/smack" -///////// below functions are called by main thread of thread-request.c - -////////////////////////////////////////////////////////////////////////// -/// @brief create unique id as integer type -/// @return unique id combined local time and the special calculation -static int __get_download_request_id(void) -{ - static int last_uniquetime = 0; - int uniquetime = 0; - - do { - struct timeval tval; - int cipher = 1; - int c = 0; - - gettimeofday(&tval, NULL); - - int usec = tval.tv_usec; - for (c = 0; ; c++, cipher++) { - if ((usec /= 10) <= 0) - break; - } - if (tval.tv_usec == 0) - tval.tv_usec = (tval.tv_sec & 0x0fff); - int disit_unit = 10; - for (c = 0; c < cipher - 3; c++) - disit_unit = disit_unit * 10; - uniquetime = tval.tv_sec + ((tval.tv_usec << 2) * 100) + - ((tval.tv_usec >> (cipher - 1)) * disit_unit) + - ((tval.tv_usec + (tval.tv_usec % 10)) & 0x0fff); - } while (last_uniquetime == uniquetime); - last_uniquetime = uniquetime; - return uniquetime; -} - -char *dp_print_state(dp_state_type state) -{ - switch(state) - { - case DP_STATE_NONE : - return "NONE"; - case DP_STATE_READY : - return "READY"; - case DP_STATE_QUEUED : - return "QUEUED"; - case DP_STATE_CONNECTING : - return "CONNECTING"; - case DP_STATE_DOWNLOADING : - return "DOWNLOADING"; - case DP_STATE_PAUSE_REQUESTED : - return "PAUSE_REQUESTED"; - case DP_STATE_PAUSED : - return "PAUSED"; - case DP_STATE_COMPLETED : - return "COMPLETED"; - case DP_STATE_CANCELED : - return "CANCELED"; - case DP_STATE_FAILED : - return "FAILED"; - default : - break; - } - return "UNKNOWN"; -} - -char *dp_print_errorcode(dp_error_type errorcode) -{ - switch(errorcode) - { - case DP_ERROR_NONE : - return "NONE"; - case DP_ERROR_INVALID_PARAMETER : - return "INVALID_PARAMETER"; - case DP_ERROR_OUT_OF_MEMORY : - return "OUT_OF_MEMORY"; - case DP_ERROR_IO_ERROR : - return "IO_ERROR"; - case DP_ERROR_NETWORK_UNREACHABLE : - return "NETWORK_UNREACHABLE"; - case DP_ERROR_CONNECTION_TIMED_OUT : - return "CONNECTION_TIMED_OUT"; - case DP_ERROR_NO_SPACE : - return "NO_SPACE"; - case DP_ERROR_FIELD_NOT_FOUND : - return "FIELD_NOT_FOUND"; - case DP_ERROR_INVALID_STATE : - return "INVALID_STATE"; - case DP_ERROR_CONNECTION_FAILED : - return "CONNECTION_FAILED"; - case DP_ERROR_INVALID_URL : - return "INVALID_URL"; - case DP_ERROR_INVALID_DESTINATION : - return "INVALID_DESTINATION"; - case DP_ERROR_QUEUE_FULL : - return "QUEUE_FULL"; - case DP_ERROR_ALREADY_COMPLETED : - return "ALREADY_COMPLETED"; - case DP_ERROR_FILE_ALREADY_EXISTS : - return "FILE_ALREADY_EXISTS"; - case DP_ERROR_TOO_MANY_DOWNLOADS : - return "TOO_MANY_DOWNLOADS"; - case DP_ERROR_NO_DATA : - return "NO_DATA"; - case DP_ERROR_UNHANDLED_HTTP_CODE : - return "UNHANDLED_HTTP_CODE"; - case DP_ERROR_CANNOT_RESUME : - return "CANNOT_RESUME"; - case DP_ERROR_PERMISSION_DENIED : - return "PERMISSION_DENIED"; - case DP_ERROR_RESPONSE_TIMEOUT : - return "RESPONSE_TIMEOUT"; - case DP_ERROR_REQUEST_TIMEOUT : - return "REQUEST_TIMEOUT"; - case DP_ERROR_SYSTEM_DOWN : - return "SYSTEM_DOWN"; - case DP_ERROR_CLIENT_DOWN : - return "CLIENT_DOWN"; - case DP_ERROR_ID_NOT_FOUND : - return "ID_NOT_FOUND"; - default : - break; - } - return "UNKNOWN"; -} - -int dp_is_smackfs_mounted() -{ - struct statfs sfs; - int ret; - do { - ret = statfs(SMACKFS_MNT, &sfs); - } while (ret < 0 && errno == EINTR); - if (ret) { - TRACE_ERROR("[SMACK ERROR]"); - return -1; - } - if (sfs.f_type == SMACKFS_MAGIC) { - return 1; - } - TRACE_ERROR("[SMACK DISABLE]"); - return 0; -} - -char *dp_strdup(char *src) -{ - char *dest = NULL; - size_t src_len = 0; - - if (src == NULL) { - TRACE_ERROR("[CHECK PARAM]"); - return NULL; - } - - src_len = strlen(src); - if (src_len <= 0) { - TRACE_ERROR("[CHECK PARAM] len[%d]", src_len); - return NULL; - } - - dest = (char *)calloc(src_len + 1, sizeof(char)); - if (dest == NULL) { - TRACE_STRERROR("[CHECK] allocation"); - return NULL; - } - memcpy(dest, src, src_len * sizeof(char)); - dest[src_len] = '\0'; - - return dest; -} - -// check param -// create new slot -// fill info to new slot -// make new id -// save info to QUEUE(DB) -dp_error_type dp_request_create(int id, dp_client_group *group, dp_request **empty_slot) -{ - if (id != -1) { - TRACE_ERROR("[CHECK PROTOCOL] ID not -1"); - return DP_ERROR_INVALID_STATE; - } - if (group == NULL || empty_slot == NULL) { - TRACE_ERROR("[CHECK INTERNAL][%d]", id); - return DP_ERROR_INVALID_PARAMETER; - } - // New allocation Slot - dp_request *new_request = dp_request_new(); - if (new_request == NULL) { - TRACE_STRERROR("[CHECK MEMORY][%d]", id); - return DP_ERROR_OUT_OF_MEMORY; - } - - int check_id = -1; - do { - new_request->id = __get_download_request_id(); - check_id = dp_db_get_int_column(new_request->id, - DP_DB_TABLE_LOG, DP_DB_COL_ID); - } while (check_id == new_request->id); // means duplicated id - - new_request->group = group; - if (group->pkgname != NULL && strlen(group->pkgname) > 1) - new_request->packagename = dp_strdup(group->pkgname); - if (new_request->packagename == NULL) { - dp_request_free(new_request); - TRACE_ERROR("[ERROR][%d] OUT_OF_MEMORY [PACKAGENAME]", id); - return DP_ERROR_OUT_OF_MEMORY; - } - new_request->state = DP_STATE_READY; - new_request->error = DP_ERROR_NONE; - new_request->create_time = (int)time(NULL); - - if (dp_db_request_new_logging(new_request->id, new_request->state, - new_request->packagename) < 0) { - dp_request_free(new_request); - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL]"); - return DP_ERROR_NO_SPACE; - } - return DP_ERROR_OUT_OF_MEMORY; - } - *empty_slot = new_request; - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_url(int id, dp_request *request, char *url) -{ - int length = 0; - if (url == NULL || (length = strlen(url)) <= 1) - return DP_ERROR_INVALID_URL; - - if (request != NULL) { - if (request->state == DP_STATE_CONNECTING || - request->state == DP_STATE_DOWNLOADING || - request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_CONNECTING || - state == DP_STATE_DOWNLOADING || - state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - if (dp_db_replace_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_URL, - DP_DB_COL_TYPE_TEXT, url) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", id); - return DP_ERROR_NO_SPACE; - } - return DP_ERROR_OUT_OF_MEMORY; - } - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_destination(int id, dp_request *request, char *dest) -{ - int length = 0; - if (!dest || (length = strlen(dest)) <= 1) - return DP_ERROR_INVALID_DESTINATION; - - if (request != NULL) { - if (request->state == DP_STATE_CONNECTING || - request->state == DP_STATE_DOWNLOADING || - request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_CONNECTING || - state == DP_STATE_DOWNLOADING || - state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - if (dp_db_replace_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_DESTINATION, - DP_DB_COL_TYPE_TEXT, dest) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", id); - return DP_ERROR_NO_SPACE; - } - return DP_ERROR_OUT_OF_MEMORY; - } - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_filename(int id, dp_request *request, char *filename) -{ - int length = 0; - if (!filename || (length = strlen(filename)) <= 1) - return DP_ERROR_INVALID_PARAMETER; - - if (request != NULL) { - if (request->state == DP_STATE_CONNECTING || - request->state == DP_STATE_DOWNLOADING || - request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_CONNECTING || - state == DP_STATE_DOWNLOADING || - state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - if (dp_db_replace_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_FILENAME, - DP_DB_COL_TYPE_TEXT, filename) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", id); - return DP_ERROR_NO_SPACE; - } - return DP_ERROR_OUT_OF_MEMORY; - } - - TRACE_SECURE_DEBUG("ID [%d] Filename[%s]", id, filename); - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_title(int id, dp_request *request, char *title) -{ - int length = 0; - if (!title || (length = strlen(title)) <= 1) - return DP_ERROR_INVALID_PARAMETER; - - if (request != NULL) { - if (request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - if (dp_db_replace_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_TITLE, - DP_DB_COL_TYPE_TEXT, title) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", id); - return DP_ERROR_NO_SPACE; - } - return DP_ERROR_OUT_OF_MEMORY; - } - - TRACE_SECURE_DEBUG("ID [%d] title[%s]", id, title); - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_bundle(int id, dp_request *request, int type, bundle_raw *b, unsigned length) -{ - char *column = NULL; - if (b == NULL || (length < 1)) - return DP_ERROR_INVALID_PARAMETER; - - if (request != NULL) { - if (request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - switch(type) { - case DP_NOTIFICATION_BUNDLE_TYPE_ONGOING: - column = DP_DB_COL_RAW_BUNDLE_ONGOING; - break; - case DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE: - column = DP_DB_COL_RAW_BUNDLE_COMPLETE; - break; - case DP_NOTIFICATION_BUNDLE_TYPE_FAILED: - column = DP_DB_COL_RAW_BUNDLE_FAIL; - break; - default: - TRACE_ERROR("[CHECK TYPE][%d]", type); - return DP_ERROR_INVALID_PARAMETER; - } - if (dp_db_replace_blob_column - (id, DP_DB_TABLE_NOTIFICATION, column, b, length) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", id); - return DP_ERROR_NO_SPACE; - } - return DP_ERROR_OUT_OF_MEMORY; - } - - //TRACE_SECURE_DEBUG("ID [%d] title[%s]", id, title); - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_description(int id, dp_request *request, char *description) -{ - int length = 0; - if (!description || (length = strlen(description)) <= 1) - return DP_ERROR_INVALID_PARAMETER; - - if (request != NULL) { - if (request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - if (dp_db_replace_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_DESCRIPTION, - DP_DB_COL_TYPE_TEXT, description) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", id); - return DP_ERROR_NO_SPACE; - } - return DP_ERROR_OUT_OF_MEMORY; - } - - TRACE_SECURE_DEBUG("ID [%d] description[%s]", id, description); - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_noti_type(int id, dp_request *request, unsigned type) -{ - if (request != NULL) { - if (request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - if (dp_db_replace_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, - DP_DB_COL_TYPE_INT, &type) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", id); - return DP_ERROR_NO_SPACE; - } - return DP_ERROR_OUT_OF_MEMORY; - } - if (request) - { - if(!type) - request->auto_notification = 0; - else - request->auto_notification = 1; - } - TRACE_SECURE_DEBUG("ID [%d] enable[%d]", id, type); - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_notification(int id, dp_request *request, unsigned enable) -{ - if (request != NULL) { - if (request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - // update queue DB - if (dp_db_replace_column - (id, DP_DB_TABLE_REQUEST_INFO, - DP_DB_COL_NOTIFICATION_ENABLE, DP_DB_COL_TYPE_INT, - &enable) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - return DP_ERROR_OUT_OF_MEMORY; - } - // update memory - if (request) - request->auto_notification = enable; - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_auto_download(int id, dp_request *request, unsigned enable) -{ - if (request != NULL) { - if (request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - // update queue DB - if (dp_db_replace_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_AUTO_DOWNLOAD, - DP_DB_COL_TYPE_INT, &enable) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - return DP_ERROR_OUT_OF_MEMORY; - } - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_state_event(int id, dp_request *request, unsigned enable) -{ - if (request == NULL) { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - - if (state == DP_STATE_DOWNLOADING || - state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - // update queue DB - if (dp_db_replace_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_STATE_EVENT, - DP_DB_COL_TYPE_INT, &enable) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - return DP_ERROR_OUT_OF_MEMORY; - } - // update memory - if (request != NULL) - request->state_cb = enable; - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_progress_event(int id, dp_request *request, unsigned enable) -{ - if (request == NULL) { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - - if (state == DP_STATE_DOWNLOADING || - state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - // update queue DB - if (dp_db_replace_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_PROGRESS_EVENT, - DP_DB_COL_TYPE_INT, &enable) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - return DP_ERROR_OUT_OF_MEMORY; - } - // update memory - if (request) - request->progress_cb = enable; - return DP_ERROR_NONE; -} - -dp_error_type dp_request_set_network_type(int id, dp_request *request, int type) -{ - if (request != NULL) { - if (request->state == DP_STATE_CONNECTING || - request->state == DP_STATE_DOWNLOADING || - request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - return DP_ERROR_INVALID_STATE; - } - } else { - // check id in logging table. - dp_state_type state = dp_db_get_state(id); - // check again from logging table - if (state == DP_STATE_CONNECTING || - state == DP_STATE_DOWNLOADING || - state == DP_STATE_COMPLETED) { - TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state)); - return DP_ERROR_INVALID_STATE; - } - } - - // update queue DB - if (dp_db_replace_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_NETWORK_TYPE, - DP_DB_COL_TYPE_INT, &type) < 0) { - TRACE_ERROR("[CHECK SQL][%d]", id); - return DP_ERROR_OUT_OF_MEMORY; - } - // update memory - if (request) - request->network_type = type; - return DP_ERROR_NONE; -} - -char *dp_request_get_url(int id, dp_error_type *errorcode) -{ - char *url = NULL; - url = dp_db_get_text_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_URL); - if (url == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return url; -} - -char *dp_request_get_destination(int id, dp_request *request, dp_error_type *errorcode) -{ - char *dest = NULL; - dest = dp_db_get_text_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_DESTINATION); - if (dest == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return dest; -} - -char *dp_request_get_filename(int id, dp_request *request, dp_error_type *errorcode) -{ - char *filename = NULL; - filename = dp_db_get_text_column - (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_FILENAME); - if (filename == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return filename; -} - -char *dp_request_get_title(int id, dp_request *request, dp_error_type *errorcode) -{ - char *title = NULL; - title = dp_db_get_text_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_TITLE); - if (title == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return title; -} - -bundle_raw *dp_request_get_bundle(int id, dp_request *request, dp_error_type *errorcode, char* column, int *length) -{ - void *blob_data = NULL; - blob_data = dp_db_get_blob_column - (id, DP_DB_TABLE_NOTIFICATION, column, length); - if (blob_data == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return (bundle_raw*)blob_data; -} - - -char *dp_request_get_description(int id, dp_request *request, dp_error_type *errorcode) -{ - char *description = NULL; - description = dp_db_get_text_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_DESCRIPTION); - if (description == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return description; -} - -int dp_request_get_noti_type(int id, dp_request *request, dp_error_type *errorcode) -{ - int type = -1; - type = dp_db_get_int_column - (id, DP_DB_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE); - if (type == -1) - *errorcode = DP_ERROR_NO_DATA; - return type; -} - - - -char *dp_request_get_contentname(int id, dp_request *request, dp_error_type *errorcode) -{ - char *content = NULL; - content = dp_db_get_text_column - (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_NAME); - if (content == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return content; -} - -char *dp_request_get_etag(int id, dp_request *request, dp_error_type *errorcode) -{ - char *etag = NULL; - etag = dp_db_get_text_column - (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_ETAG); - if (etag == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return etag; -} - -char *dp_request_get_savedpath(int id, dp_request *request, dp_error_type *errorcode) -{ - char *savedpath = NULL; - savedpath = dp_db_get_text_column - (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_SAVED_PATH); - if (savedpath == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return savedpath; -} - -char *dp_request_get_tmpsavedpath(int id, dp_request *request, dp_error_type *errorcode) -{ - char *tmppath = NULL; - tmppath = dp_db_get_text_column - (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_TMP_SAVED_PATH); - if (tmppath == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return tmppath; -} - -char *dp_request_get_mimetype(int id, dp_request *request, dp_error_type *errorcode) -{ - char *mimetype = NULL; - mimetype = dp_db_get_text_column - (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_MIMETYPE); - if (mimetype == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return mimetype; -} - -char *dp_request_get_pkg_name(int id, dp_request *request, dp_error_type *errorcode) -{ - char *pkg_name = NULL; - pkg_name = dp_db_get_text_column - (id, DP_DB_TABLE_LOG, DP_DB_COL_PACKAGENAME); - if (pkg_name == NULL) { - *errorcode = DP_ERROR_NO_DATA; - return NULL; - } - return pkg_name; -} - -dp_request *dp_request_load_from_log(int id, dp_error_type *errorcode) -{ - dp_request *request = NULL; - - request = dp_db_load_logging_request(id); - if (request == NULL) { - *errorcode = DP_ERROR_ID_NOT_FOUND; - return NULL; - } - if (request->state == DP_STATE_COMPLETED) { - TRACE_ERROR - ("[ERROR][%d] now[%s]", id, dp_print_state(request->state)); - *errorcode = DP_ERROR_INVALID_STATE; - dp_request_free(request); - return NULL; - } - return request; -} - - -void dp_request_state_response(dp_request *request) -{ - if (request == NULL) { - return ; - } - - TRACE_INFO("[INFO][%d] state:%s error:%s", request->id, - dp_print_state(request->state), - dp_print_errorcode(request->error)); - - if (dp_db_request_update_status(request->id, request->state, - request->error) < 0) - TRACE_ERROR("[ERROR][%d][SQL]", request->id); - - if (request->group != NULL && request->group->event_socket >= 0 && - request->state_cb == 1) { - dp_ipc_send_event(request->group->event_socket, request->id, - request->state, request->error, 0); - } - - if (request->state == DP_STATE_DOWNLOADING) { - if (request->auto_notification == 1 && - request->packagename != NULL) { - if (request->noti_priv_id != -1) { - dp_update_downloadinginfo_notification - (request->noti_priv_id, - (double)request->received_size, - (double)request->file_size); - } else { - request->noti_priv_id = dp_set_downloadinginfo_notification - (request->id, request->packagename); - } - } 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 && - request->packagename != NULL) { - if (request->noti_priv_id != -1) { - dp_update_downloadinginfo_notification - (request->noti_priv_id, - (double)request->received_size, - (double)request->file_size); - } else { - request->noti_priv_id = dp_set_downloadinginfo_notification - (request->id, request->packagename); - } - } - } - request->start_time = (int)time(NULL); - request->pause_time = 0; - request->stop_time = 0; - } else if (request->state == DP_STATE_PAUSED) { - if (request->group != NULL) - request->group->queued_count--; - request->pause_time = (int)time(NULL); - } else { - if (request->group != NULL ) - request->group->queued_count--; - - if (request->auto_notification == 1 && - request->packagename != NULL) { - request->noti_priv_id = dp_set_downloadedinfo_notification - (request->noti_priv_id, request->id, - request->packagename, request->state); - - } 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_NONE && - request->packagename != NULL) - request->noti_priv_id = dp_set_downloadedinfo_notification - (request->noti_priv_id, request->id, - request->packagename, request->state); - } - - request->stop_time = (int)time(NULL); - } -} diff --git a/provider/download-provider-slots.c b/provider/download-provider-slots.c deleted file mode 100755 index ad39ee8..0000000 --- a/provider/download-provider-slots.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 <stdio.h> -#include <stdlib.h> - -#include <time.h> -#include <sys/time.h> - -#include "download-provider.h" -#include "download-provider-log.h" -#include "download-provider-pthread.h" - -#include "download-provider-slots.h" -#include "download-provider-socket.h" - -dp_group_slots *dp_client_group_slots_new(int size) -{ - dp_group_slots *slots = NULL; - if (size <= 0) - return NULL; - slots = (dp_group_slots *) calloc(size, - sizeof(dp_group_slots)); - return slots; -} - -dp_request_slots *dp_request_slots_new(int size) -{ - int i = 0; - dp_request_slots *slots = NULL; - if (size <= 0) - return NULL; - slots = (dp_request_slots *) calloc(size, - sizeof(dp_request_slots)); - for (; i < size; i++) - CLIENT_MUTEX_INIT(&slots[i].mutex, NULL); - return slots; -} - -void dp_request_init(dp_request *request) -{ - if (request == NULL) - return ; - - request->id = -1; - request->agent_id = -1; - request->create_time = 0; - request->start_time = 0; - request->pause_time = 0; - request->stop_time = 0; - request->state = DP_STATE_NONE; - request->error = DP_ERROR_NONE; - request->state_cb = 0; - request->progress_cb = 0; - request->progress_lasttime = 0; - request->received_size = 0; - request->file_size = 0; - request->network_type = DP_NETWORK_TYPE_ALL; - request->startcount = 0; - request->auto_notification = 0; - request->noti_priv_id = -1; - request->packagename = NULL; - request->group = NULL; -} - -dp_request *dp_request_new() -{ - dp_request *request = NULL; - request = (dp_request *) calloc(1, - sizeof(dp_request)); - if (!request) - return NULL; - dp_request_init(request); - return request; -} - -int dp_request_slot_free(dp_request_slots *request_slot) -{ - if (request_slot == NULL) - return -1; - CLIENT_MUTEX_LOCK(&request_slot->mutex); - dp_request_free(request_slot->request); - request_slot->request = NULL; - CLIENT_MUTEX_UNLOCK(&request_slot->mutex); - return 0; -} - -int dp_request_free(dp_request *request) -{ - if (request == NULL) - return -1; - free(request->packagename); - dp_request_init(request); - free(request); - return 0; -} - -int dp_client_group_free(dp_client_group *group) -{ - if (group != NULL) { - if (group->cmd_socket > 0) - dp_socket_free(group->cmd_socket); - group->cmd_socket = -1; - if (group->event_socket > 0) - dp_socket_free(group->event_socket); - group->event_socket = -1; - group->queued_count = 0; - free(group->pkgname); - free(group->smack_label); - free(group); - } - return 0; -} - -int dp_client_group_slots_free(dp_group_slots *slots, int size) -{ - int i = 0; - if (slots) { - for (; i < size; i++) { - if (slots->group) - dp_client_group_free(slots->group); - slots->group = NULL; - } - free(slots); - } - slots = NULL; - return 0; -} - -int dp_request_slots_free(dp_request_slots *slots, int size) -{ - int i = 0; - if (slots != NULL) { - for (; i < size; i++) { - dp_request_free(slots[i].request); - slots[i].request = NULL; - CLIENT_MUTEX_DESTROY(&slots[i].mutex); - } - free(slots); - } - slots = NULL; - return 0; -} - -////////////////////////////////////////////////////////////////////////// -/// @brief return count of requests in slot -int dp_get_request_count(dp_request_slots *slots) -{ - int i = 0; - int count = 0; - - if (!slots) - return -1; - - for (i = 0; i < DP_MAX_REQUEST; i++) { - if (slots[i].request != NULL) - count++; - } - return count; -} diff --git a/provider/download-provider-smack.c b/provider/download-provider-smack.c new file mode 100644 index 0000000..5e89c45 --- /dev/null +++ b/provider/download-provider-smack.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013 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 <stdlib.h> +#include <errno.h> +#include <sys/statfs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <sys/smack.h> + +#include <download-provider.h> +#include <download-provider-log.h> +#include <download-provider-utils.h> + +#define SMACKFS_MAGIC 0x43415d53 +#define SMACKFS_MNT "/smack" + +static int __dp_smack_is_transmute(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; +} + +int dp_smack_is_mounted() +{ + struct statfs sfs; + int ret; + do { + ret = statfs(SMACKFS_MNT, &sfs); + } while (ret < 0 && errno == EINTR); + if (ret) { + TRACE_ERROR("[SMACK ERROR]"); + return -1; + } + if (sfs.f_type == SMACKFS_MAGIC) { + return 1; + } + TRACE_ERROR("[SMACK DISABLE]"); + return 0; +} + +int dp_smack_set_label(char *label, char *source, char *target) +{ + if (label == NULL || source == NULL || target == NULL) + return DP_ERROR_PERMISSION_DENIED; + + int is_setted_dir_label = 0; + int errorcode = DP_ERROR_NONE; + + if (__dp_smack_is_transmute(source) < 0) { + TRACE_SECURE_ERROR("[SMACK] no transmute:%s", source); + } else { + char *dir_label = NULL; + if (smack_getlabel(source, &dir_label, SMACK_LABEL_ACCESS) == 0) { + if (smack_have_access(label, dir_label, "t") > 0) { + if (smack_setlabel(target, 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", label, dir_label); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + } else { + TRACE_SECURE_ERROR("[SMACK ERROR] no label:", source); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + free(dir_label); + } + if (is_setted_dir_label == 0 && + smack_setlabel(target, label, SMACK_LABEL_ACCESS) != 0) { + TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", label); + errorcode = DP_ERROR_PERMISSION_DENIED; + // remove file. + if (dp_is_file_exist(target) == 0) + unlink(target); + } + return errorcode; +} + +char *dp_smack_get_label_from_socket(int sock) +{ + char *label = NULL; + if (smack_new_label_from_socket(sock, &label) != 0) { + free(label); + return NULL; + } + return label; +} + +int dp_smack_is_valid_dir(int uid, int gid, char *smack_label, char *dir) +{ + if (smack_label == NULL || dir == NULL) { + TRACE_ERROR("check parameter %s/%s", smack_label, dir); + return -1; + } + int ret = -1; + struct stat dstate; + if (stat(dir, &dstate) == 0) { + if ((dstate.st_uid == uid && (dstate.st_mode & (S_IRUSR | S_IWUSR)) == (S_IRUSR | S_IWUSR)) || + (dstate.st_gid == gid && (dstate.st_mode & (S_IRGRP | S_IWGRP)) == (S_IRGRP | S_IWGRP)) || + ((dstate.st_mode & (S_IROTH | S_IWOTH)) == (S_IROTH | S_IWOTH))) { + char *dir_label = NULL; + if (smack_getlabel(dir, &dir_label, SMACK_LABEL_ACCESS) == 0 && + smack_have_access(smack_label, dir_label, "rw") > 0) { + ret = 0; + } + free(dir_label); + } + } + return ret; +} + +int dp_is_valid_dir(const char *dirpath) +{ + struct stat dir_state; + int stat_ret; + if (dirpath == NULL) { + TRACE_ERROR("check path"); + return -1; + } + stat_ret = stat(dirpath, &dir_state); + if (stat_ret == 0 && S_ISDIR(dir_state.st_mode)) { + return 0; + } + return -1; +} + +void dp_rebuild_dir(const char *dirpath, mode_t mode) +{ + if (dp_is_valid_dir(dirpath) < 0) { + if (mkdir(dirpath, mode) == 0) { + TRACE_INFO("check directory:%s", dirpath); + if (smack_setlabel(dirpath, "_", SMACK_LABEL_ACCESS) != 0) { + TRACE_SECURE_ERROR("failed to set smack label:%s", dirpath); + } + } else { + TRACE_STRERROR("failed to create directory:%s", dirpath); + } + } +} diff --git a/provider/download-provider-socket.c b/provider/download-provider-socket.c deleted file mode 100755 index 7feabf8..0000000 --- a/provider/download-provider-socket.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * 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 <unistd.h> - -#include <pthread.h> - -#include <time.h> -#include <sys/time.h> - -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/stat.h> -#include <systemd/sd-daemon.h> -#include <signal.h> - -#include "download-provider.h" -#include "download-provider-log.h" -#include "download-provider-socket.h" - -////////////////////////////////////////////////////////////////////////// -/// @brief write the error to socket -/// @return if success, return 0 -int dp_ipc_send_errorcode(int fd, dp_error_type errorcode) -{ - if (fd < 0) { - TRACE_ERROR("[ERROR] CHECK FD[%d]", fd); - return -1; - } - - if (fd >= 0 && write(fd, &errorcode, sizeof(dp_error_type)) <= 0) { - TRACE_STRERROR("[ERROR] write FD[%d]", fd); - return -1; - } - return 0; -} - -////////////////////////////////////////////////////////////////////////// -/// @brief write the progressinfo to socket -/// @return if success, return 0 -int dp_ipc_send_event(int fd, int id, dp_state_type state, - dp_error_type errorcode, unsigned long long received_size) -{ - if (fd < 0) { - TRACE_ERROR("[ERROR][%d] CHECK FD[%d]", id, fd); - return -1; - } - - dp_event_info eventinfo; - eventinfo.id = id; - eventinfo.state = state; - eventinfo.err = errorcode; - eventinfo.received_size = received_size; - - // write - if (fd >= 0 && write(fd, &eventinfo, sizeof(dp_event_info)) <= 0) { - TRACE_STRERROR("[ERROR][%d] write FD[%d]", id, fd); - return -1; - } - return 0; -} - -// keep the order/ unsigned , str -char *dp_ipc_read_string(int fd) -{ - unsigned length = 0; - size_t recv_size = 0; - unsigned remain_size = 0; - size_t buffer_size = 0; - char *str = NULL; - - if (fd < 0) { - TRACE_ERROR("[ERROR] CHECK FD[%d]", fd); - return NULL; - } - - // read flexible URL from client. - ssize_t recv_bytes = read(fd, &length, sizeof(unsigned)); - if (recv_bytes < 0) { - TRACE_STRERROR("[ERROR] read FD[%d] length[%d]", fd, length); - return NULL; - } - if (length < 1 || length > DP_MAX_URL_LEN) { - TRACE_ERROR("[STRING LEGNTH] [%d]", length); - return NULL; - } - str = (char *)calloc((length + 1), sizeof(char)); - if (str == NULL) { - TRACE_STRERROR("[ERROR] calloc length:%d FD[%d]", length, fd); - return NULL; - } - remain_size = length; - do { - buffer_size = 0; - if (remain_size > DP_DEFAULT_BUFFER_SIZE) - buffer_size = DP_DEFAULT_BUFFER_SIZE; - else - buffer_size = remain_size; - recv_size = (size_t)read(fd, str + (int)(length - remain_size), - buffer_size * sizeof(char)); - if (recv_size > DP_DEFAULT_BUFFER_SIZE) { - recv_size = -1; - break; - } - if (recv_size > 0) - remain_size = remain_size - (unsigned)recv_size; - } while (recv_size > 0 && remain_size > 0); - - if (recv_size == 0) { - TRACE_STRERROR("[ERROR] closed peer:%d", fd); - free(str); - return NULL; - } - str[length] = '\0'; - return str; -} - - -// 0 : Socket Error -// -1 : Invalid type -unsigned dp_ipc_read_bundle(int fd, int *type, bundle_raw **b) -{ - unsigned length = 0; - size_t recv_size = 0; - unsigned remain_size = 0; - size_t buffer_size = 0; - bundle_raw *b_raw = NULL; - - if (fd < 0) { - TRACE_ERROR("[ERROR] CHECK FD[%d]", fd); - return 0; - } - - // read flexible URL from client. - ssize_t recv_bytes = read(fd, type, sizeof(int)); - if (recv_bytes < 0) { - TRACE_STRERROR("[ERROR] read FD[%d] type[%d]", fd, type); - return 0; - } - if ((*type) != DP_NOTIFICATION_BUNDLE_TYPE_ONGOING && - (*type) != DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE && - (*type) != DP_NOTIFICATION_BUNDLE_TYPE_FAILED) { - TRACE_ERROR("[NOTI TYPE] [%d]", *type); - return -1; - } - // read flexible URL from client. - recv_bytes = read(fd, &length, sizeof(unsigned)); - if (recv_bytes < 0) { - TRACE_STRERROR("[ERROR] read FD[%d] length[%d]", fd, length); - return 0; - } - if (length < 1 || length > DP_MAX_URL_LEN) { - TRACE_ERROR("[STRING LEGNTH] [%d]", length); - return 0; - } - b_raw = (bundle_raw *)calloc(length, 1); - if (b_raw == NULL) { - TRACE_STRERROR("[ERROR] calloc length:%d FD[%d]", length, fd); - return 0; - } - remain_size = length; - do { - buffer_size = 0; - if (remain_size > DP_DEFAULT_BUFFER_SIZE) - buffer_size = DP_DEFAULT_BUFFER_SIZE; - else - buffer_size = remain_size; - recv_size = (size_t)read(fd, b_raw + (int)(length - remain_size), - buffer_size * sizeof(char)); - if (recv_size > DP_DEFAULT_BUFFER_SIZE) { - recv_size = -1; - break; - } - if (recv_size > 0) - remain_size = remain_size - (unsigned)recv_size; - } while (recv_size > 0 && remain_size > 0); - - if (recv_size <= 0) { - TRACE_STRERROR("[ERROR] closed peer:%d", fd); - bundle_free_encoded_rawdata(&b_raw); - return 0; - } - *b = b_raw; - return length; -} - -// keep the order/ unsigned , str -int dp_ipc_send_string(int fd, const char *str) -{ - unsigned length = 0; - - if (fd < 0) { - TRACE_ERROR("[ERROR] CHECK FD[%d]", fd); - return -1; - } - if (str == NULL) { - TRACE_ERROR("[ERROR] CHECK STRING FD[%d]", fd); - return -1; - } - - length = strlen(str); - if (length < 1) { - TRACE_ERROR("[ERROR] CHECK LENGTH FD[%d]", fd); - return -1; - } - if (fd >= 0 && write(fd, &length, sizeof(unsigned)) <= 0) { - TRACE_STRERROR("[ERROR] read FD[%d] length[%d]", fd, length); - return -1; - } - if (fd >= 0 && write(fd, str, length * sizeof(char)) <= 0) { - TRACE_STRERROR("[ERROR] write FD[%d]", fd); - return -1; - } - return 0; -} - -int dp_ipc_send_bundle(int fd, bundle_raw *b, unsigned length) -{ - if (fd < 0) { - TRACE_ERROR("[ERROR] CHECK FD[%d]", fd); - return -1; - } - if (b == NULL) { - TRACE_ERROR("[ERROR] CHECK STRING FD[%d]", fd); - return -1; - } - - if (length < 1) { - TRACE_ERROR("[ERROR] CHECK LENGTH FD[%d]", fd); - return -1; - } - if (fd >= 0 && write(fd, &length, sizeof(unsigned)) <= 0) { - TRACE_STRERROR("[ERROR] read FD[%d] length[%d]", fd, length); - return -1; - } - if (fd >= 0 && write(fd, b, length) <= 0) { - TRACE_STRERROR("[ERROR] write FD[%d]", fd); - return -1; - } - return 0; -} - -int dp_ipc_send_custom_type(int fd, void *value, size_t type_size) -{ - if (fd < 0) { - TRACE_ERROR("[ERROR] CHECK FD[%d]", fd); - return -1; - } - if (value == NULL) { - TRACE_ERROR("[ERROR] CHECK VALUE FD[%d]", fd); - return -1; - } - if (fd >= 0 && write(fd, value, type_size) <= 0) { - TRACE_STRERROR("[ERROR] write FD[%d]", fd); - return -1; - } - return 0; -} - -int dp_ipc_read_custom_type(int fd, void *value, size_t type_size) -{ - if (fd < 0) { - TRACE_ERROR("[ERROR] CHECK FD[%d]", fd); - return -1; - } - if (value == NULL) { - TRACE_ERROR("[ERROR] CHECK VALUE FD[%d]", fd); - return -1; - } - - ssize_t recv_bytes = read(fd, value, type_size); - if (recv_bytes < 0) { - TRACE_STRERROR("[ERROR] read FD[%d]", fd); - return -1; - } - return 0; -} - -int dp_accept_socket_new() -{ - int sockfd = -1; - struct sockaddr_un listenaddr; - - int n = sd_listen_fds(1); - if (n > 1) { - TRACE_STRERROR("too many file descriptors received"); - return -1; - } else if (n == 1) { - int r; - if ((r = sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, 1, DP_IPC, 0)) <= 0) { - TRACE_STRERROR("passed systemd file descriptor is of wrong type"); - return -1; - } - sockfd = SD_LISTEN_FDS_START + 0; - } else { - if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - TRACE_STRERROR("failed to create socket"); - return -1; - } - - bzero(&listenaddr, sizeof(listenaddr)); - listenaddr.sun_family = AF_UNIX; - strcpy(listenaddr.sun_path, DP_IPC); - - if (bind(sockfd, (struct sockaddr *)&listenaddr, sizeof listenaddr) != - 0) { - TRACE_STRERROR("[CRITICAL] bind"); - close(sockfd); - return -1; - } - - if (chmod(listenaddr.sun_path, 0777) < 0) { - TRACE_STRERROR("[CRITICAL] chmod"); - close(sockfd); - return -1; - } - - // need 3 socket per a group - if (listen(sockfd, DP_MAX_GROUP * 3) != 0) { - TRACE_STRERROR("[CRITICAL] listen"); - close(sockfd); - return -1; - } - } - return sockfd; -} - -int dp_socket_free(int sockfd) -{ - TRACE_DEBUG("[%d]", sockfd); - if (sockfd < 0) - return -1; - shutdown(sockfd, 0); - close(sockfd); - return 0; -} diff --git a/provider/download-provider-thread-queue.c b/provider/download-provider-thread-queue.c deleted file mode 100755 index b82618d..0000000 --- a/provider/download-provider-thread-queue.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * 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 <unistd.h> - -#include <time.h> -#include <sys/time.h> - -#include <sys/types.h> -#include <sys/socket.h> - -#include <signal.h> - -#include <pthread.h> - -#include "download-provider.h" -#include "download-provider-log.h" -#include "download-provider-config.h" -#include "download-provider-slots.h" -#include "download-provider-socket.h" -#include "download-provider-pthread.h" -#include "download-provider-db.h" -#include "download-provider-queue.h" -#include "download-provider-network.h" -#include "download-provider-da-interface.h" - -void dp_terminate(int signo); - -pthread_mutex_t g_dp_queue_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t g_dp_queue_cond = PTHREAD_COND_INITIALIZER; - - -////////////////////////////////////////////////////////////////////////// -/// @brief check network status is matched with the type setted by user -/// @return matched : 0 mispatch : -1 -static int __is_matched_network(dp_network_type now_state, dp_network_type setted_state) -{ - if (now_state == setted_state - || now_state == DP_NETWORK_TYPE_ETHERNET - || setted_state == DP_NETWORK_TYPE_ALL) - return 0; - #if 0 - if (setted_state == DP_NETWORK_TYPE_ALL - || setted_state == DP_NETWORK_TYPE_DATA_NETWORK - || now_state == DP_NETWORK_TYPE_WIFI - || now_state == DP_NETWORK_TYPE_ETHERNET - || (setted_state == DP_NETWORK_TYPE_WIFI - && (now_state == DP_NETWORK_TYPE_WIFI - || now_state == DP_NETWORK_TYPE_ETHERNET)) - ) - return 0; - #endif - return -1; -} - -////////////////////////////////////////////////////////////////////////// -/// @brief the count of slot downloading currently -static unsigned __get_active_count(dp_request_slots *requests) -{ - unsigned count = 0; - unsigned i = 0; - - if (requests == NULL) - return 0; - - for (i = 0; i < DP_MAX_REQUEST; i++) { - int locked = pthread_mutex_trylock(&requests[i].mutex); - // locking failure means it used by other thread. - if (locked == 0) { - if (requests[i].request != NULL) { - if (requests[i].request->state == DP_STATE_CONNECTING || - requests[i].request->state == DP_STATE_DOWNLOADING) - count++; - } - CLIENT_MUTEX_UNLOCK(&requests[i].mutex); - } - } - return count; -} - -////////////////////////////////////////////////////////////////////////// -/// @brief index of slot which last time is oldest -static int __get_oldest_request_with_network(dp_request_slots *requests, dp_state_type state, dp_network_type now_state) -{ - int i = 0; - int oldest_time = (int)time(NULL); - oldest_time++; // most last time - int oldest_index = -1; - - if (requests == NULL) - return -1; - - for (i = 0; i < DP_MAX_REQUEST; i++) { - int locked = pthread_mutex_trylock(&requests[i].mutex); - // locking failure means it used by other thread. - if (locked == 0) { - if (requests[i].request != NULL) { - if (requests[i].request->state == state && - requests[i].request->start_time > 0 && - requests[i].request->start_time < oldest_time && - __is_matched_network(now_state, - requests[i].request->network_type) == 0) { - oldest_time = requests[i].request->start_time; - oldest_index = i; - } - } - CLIENT_MUTEX_UNLOCK(&requests[i].mutex); - } - } - return oldest_index; -} - -////////////////////////////////////////////////////////////////////////// -/// @brief THREAD function for calling da_start_download_with_extension. -/// @warning da_start_download_with_extension can take long time -/// @param the pointer of memory slot allocated for this request. -/// @todo simplify da_start_download_with_extension -static void *__request_download_start_agent(void *args) -{ - dp_error_type errcode = DP_ERROR_NONE; - - dp_request_slots *request_slot = (dp_request_slots *) args; - if (request_slot == NULL) { - TRACE_ERROR("[NULL-CHECK] request_slot"); - pthread_exit(NULL); - return 0; - } - - CLIENT_MUTEX_LOCK(&request_slot->mutex); - - if (request_slot->request == NULL) { - TRACE_ERROR("[NULL-CHECK] request"); - CLIENT_MUTEX_UNLOCK(&request_slot->mutex); - pthread_exit(NULL); - return 0; - } - - dp_request *request = request_slot->request; - - if (dp_is_alive_download(request->agent_id)) { - errcode = dp_resume_agent_download(request->agent_id); - } else { - // call agent start function - errcode = dp_start_agent_download(request_slot); - } - // send to state callback. - if (errcode == DP_ERROR_NONE) { - // CONNECTING - request->state = DP_STATE_CONNECTING; - request->error = DP_ERROR_NONE; - request->startcount++; - if (dp_db_set_column - (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STARTCOUNT, - DP_DB_COL_TYPE_INT, &request->startcount) < 0) - TRACE_ERROR("[ERROR][%d][SQL]", request->id); - } else if (errcode == DP_ERROR_TOO_MANY_DOWNLOADS) { - // PENDED - request->state = DP_STATE_QUEUED; - request->error = DP_ERROR_TOO_MANY_DOWNLOADS; - } else if (errcode == DP_ERROR_CONNECTION_FAILED) { - // FAILED - request->state = DP_STATE_FAILED; - request->error = DP_ERROR_CONNECTION_FAILED; - if (request->group != NULL && - request->group->event_socket >= 0) { - dp_ipc_send_event(request->group->event_socket, - request->id, request->state, request->error, 0); - } - } else if (errcode == DP_ERROR_INVALID_STATE) { - // API FAILED - request->error = DP_ERROR_INVALID_STATE; - if (request->group != NULL && - request->group->event_socket >= 0) { - dp_ipc_send_event(request->group->event_socket, - request->id, request->state, request->error, 0); - } - } else { - request->state = DP_STATE_FAILED; - request->error = errcode; - if (request->group != NULL && - request->group->event_socket >= 0) { - dp_ipc_send_event(request->group->event_socket, - request->id, request->state, request->error, 0); - } - } - if (dp_db_request_update_status(request->id, request->state, request->error) < 0) { - TRACE_ERROR("[ERROR][%d][SQL]", request->id); - } - - CLIENT_MUTEX_UNLOCK(&request_slot->mutex); - - if (errcode == DP_ERROR_NONE) { - TRACE_DEBUG("try other requests -----------------"); - dp_thread_queue_manager_wake_up(); - } - - pthread_exit(NULL); - return 0; -} - -////////////////////////////////////////////////////////////////////////// -/// @brief create thread. -/// @warning if failed to create thread, change to PENED. -/// @param the pointer of memory slot allocated for this request. -static int __request_download_start_thread(dp_request_slots *request_slot) -{ - // declare all resources - pthread_t thread_pid; - pthread_attr_t thread_attr; - - if (request_slot == NULL || request_slot->request == NULL) { - TRACE_ERROR("[CRITICAL] Invalid Address"); - return -1; - } - dp_request *request = request_slot->request; - - // initialize - if (pthread_attr_init(&thread_attr) != 0) { - TRACE_STRERROR("[ERROR][%d] pthread_attr_init", request->id); - return -1; - } - if (pthread_attr_setdetachstate(&thread_attr, - PTHREAD_CREATE_DETACHED) != 0) { - TRACE_STRERROR - ("[ERROR][%d] pthread_attr_setdetachstate", request->id); - return -1; - } - - request->state = DP_STATE_CONNECTING; - if (pthread_create(&thread_pid, &thread_attr, - __request_download_start_agent, request_slot) != 0) { - TRACE_STRERROR("[ERROR][%d] pthread_create", request->id); - pthread_attr_destroy(&thread_attr); - request->state = DP_STATE_QUEUED; - return -1; - } - pthread_attr_destroy(&thread_attr); - return 0; -} - - -void dp_thread_queue_manager_wake_up() -{ - CLIENT_MUTEX_LOCK(&(g_dp_queue_mutex)); - pthread_cond_signal(&g_dp_queue_cond); - CLIENT_MUTEX_UNLOCK(&(g_dp_queue_mutex)); -} - - -// Main role : start download, check status of queue. -// No timeout. Wake up by Signal be sent from other thread -void *dp_thread_queue_manager(void *arg) -{ - int i; - int active_count; - dp_client_group *group = NULL; - dp_request *request = NULL; - - dp_privates *privates = (dp_privates*)arg; - if (!privates) { - TRACE_ERROR("[CRITICAL] Invalid Address"); - dp_terminate(SIGTERM); - pthread_exit(NULL); - return 0; - } - - pthread_cond_init(&g_dp_queue_cond, NULL); - while (privates != NULL && privates->listen_fd >= 0) { - - CLIENT_MUTEX_LOCK(&(g_dp_queue_mutex)); - pthread_cond_wait(&g_dp_queue_cond, &g_dp_queue_mutex); - - // request thread response instantly - CLIENT_MUTEX_UNLOCK(&(g_dp_queue_mutex)); - - if (privates == NULL || privates->requests == NULL || - privates->listen_fd < 0) { - TRACE_DEBUG("Terminate Thread"); - break; - } - - // if failed to initialize the callback for checking connection - if (!privates->connection) - privates->network_status = - dp_get_network_connection_instant_status(); - -#ifdef SUPPORT_WIFI_DIRECT - if (privates->is_connected_wifi_direct == 0) { - if (dp_network_wifi_direct_is_connected() == 0) { - // wifi-direct activated. pass. - privates->is_connected_wifi_direct = 1; - } - } -#endif - - if (privates->network_status == DP_NETWORK_TYPE_OFF && - privates->is_connected_wifi_direct == 0) { - TRACE_DEBUG("[CHECK NETWORK STATE]"); - continue; - } - - active_count = __get_active_count(privates->requests); - - TRACE_DEBUG("Status Queue: now active[%d] max[%d]", - active_count, DP_MAX_DOWNLOAD_AT_ONCE); - - // Start Conditions - // 1. state is QUEUED - // 2. 1 QUEUED per 1 Group : need not to check max limitation.!! - // if no group, it will be started later. - // 3. most old last time : below conditions need max limitation. - // 4. match network connection type - // 5. wifi-direct on - - // search group having 1 queued_count - // guarantee 1 instant download per 1 group - if (active_count >= DP_MAX_DOWNLOAD_AT_ONCE) { - for (i = 0; i < DP_MAX_REQUEST; i++) { - CLIENT_MUTEX_LOCK(&privates->requests[i].mutex); - request = privates->requests[i].request; - if (request != NULL && request->state == DP_STATE_QUEUED) { - group = privates->requests[i].request->group; - if (group && group->queued_count == 1) { - if (__is_matched_network - (privates->network_status, - request->network_type) == 0 || - (privates->is_connected_wifi_direct == 1 && - request->network_type == - DP_NETWORK_TYPE_WIFI_DIRECT)) { - if (__request_download_start_thread(&privates->requests[i]) == 0) { - TRACE_DEBUG - ("[Guarantee Intant Download] Group [%s]", group->pkgname); - active_count++; - } - } - } - } - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - } - } - - if (active_count >= DP_MAX_DOWNLOAD_AT_ONCE) { - TRACE_DEBUG("[BUSY] Active[%d] Max[%d]", - active_count, DP_MAX_DOWNLOAD_AT_ONCE); - continue; - } - - // can start download more. - // search oldest request - while(active_count < DP_MAX_DOWNLOAD_AT_ONCE) { - -#ifdef SUPPORT_WIFI_DIRECT - // WIFI-Direct first - if (privates->is_connected_wifi_direct == 1) { - i = __get_oldest_request_with_network(privates->requests, - DP_STATE_QUEUED, DP_NETWORK_TYPE_WIFI_DIRECT); - if (i >= 0) { - TRACE_DEBUG("Found WIFI-Direct request %d", i); - if (__request_download_start_thread(&privates->requests[i]) == 0) - active_count++; - continue; - } - } -#endif - - i = __get_oldest_request_with_network(privates->requests, - DP_STATE_QUEUED, privates->network_status); - if (i < 0) { - TRACE_DEBUG - ("No Request now active[%d] max[%d]", - active_count, DP_MAX_DOWNLOAD_AT_ONCE); - break; - } - TRACE_DEBUG("QUEUE Status now %d active %d/%d", i, - active_count, DP_MAX_DOWNLOAD_AT_ONCE); - __request_download_start_thread(&privates->requests[i]); - active_count++; - } - } - pthread_cond_destroy(&g_dp_queue_cond); - pthread_exit(NULL); - return 0; -} diff --git a/provider/download-provider-thread-request.c b/provider/download-provider-thread-request.c deleted file mode 100755 index 1f1e151..0000000 --- a/provider/download-provider-thread-request.c +++ /dev/null @@ -1,2158 +0,0 @@ -/* - * 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 <unistd.h> - -#include <time.h> -#include <sys/time.h> - -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <signal.h> - -#include <app_manager.h> -#include <sys/smack.h> -#include <bundle.h> - -#include "download-provider.h" -#include "download-provider-log.h" -#include "download-provider-config.h" -#include "download-provider-slots.h" -#include "download-provider-socket.h" -#include "download-provider-pthread.h" -#include "download-provider-db.h" -#include "download-provider-queue.h" -#include "download-provider-request.h" -#include "download-provider-network.h" -#include "download-provider-da-interface.h" -#include "download-provider-notification.h" - -void dp_terminate(int signo); - -static char *__print_command(dp_command_type cmd) -{ - switch(cmd) - { - case DP_CMD_CREATE : - return "CREATE"; - case DP_CMD_START : - return "START"; - case DP_CMD_PAUSE : - return "PAUSE"; - case DP_CMD_CANCEL : - return "CANCEL"; - case DP_CMD_DESTROY : - return "DESTROY"; - case DP_CMD_FREE : - return "FREE"; - case DP_CMD_ECHO : - return "ECHO"; - case DP_CMD_SET_URL : - return "SET_URL"; - case DP_CMD_SET_DESTINATION : - return "SET_DESTINATION"; - case DP_CMD_SET_FILENAME : - return "SET_FILENAME"; - case DP_CMD_SET_NOTIFICATION : - return "SET_NOTIFICATION"; - case DP_CMD_SET_STATE_CALLBACK : - return "SET_STATE_CALLBACK"; - case DP_CMD_SET_PROGRESS_CALLBACK : - return "SET_PROGRESS_CALLBACK"; - case DP_CMD_SET_AUTO_DOWNLOAD : - return "SET_AUTO_DOWNLOAD"; - case DP_CMD_SET_NETWORK_TYPE : - return "SET_NETWORK_TYPE"; - case DP_CMD_SET_HTTP_HEADER : - return "SET_HTTP_HEADER"; - case DP_CMD_DEL_HTTP_HEADER : - return "DEL_HTTP_HEADER"; - case DP_CMD_GET_HTTP_HEADER : - return "GET_HTTP_HEADER"; - case DP_CMD_GET_URL : - return "GET_URL"; - case DP_CMD_GET_DESTINATION : - return "GET_DESTINATION"; - case DP_CMD_GET_FILENAME : - return "GET_FILENAME"; - case DP_CMD_GET_NOTIFICATION : - return "GET_NOTIFICATION"; - case DP_CMD_GET_STATE_CALLBACK : - return "GET_STATE_CALLBACK"; - case DP_CMD_GET_PROGRESS_CALLBACK : - return "GET_PROGRESS_CALLBACK"; - case DP_CMD_GET_HTTP_HEADERS : - return "GET_HTTP_HEADERS"; - case DP_CMD_GET_HTTP_HEADER_LIST: - return "GET_HTTP_HEADER_LIST"; - case DP_CMD_ADD_EXTRA_PARAM : - return "ADD_EXTRA_PARAM"; - case DP_CMD_GET_EXTRA_PARAM : - return "GET_EXTRA_PARAM"; - case DP_CMD_REMOVE_EXTRA_PARAM : - return "REMOVE_EXTRA_PARAM"; - case DP_CMD_GET_AUTO_DOWNLOAD : - return "GET_AUTO_DOWNLOAD"; - case DP_CMD_GET_NETWORK_TYPE : - return "GET_NETWORK_TYPE"; - case DP_CMD_GET_SAVED_PATH : - return "GET_SAVED_PATH"; - case DP_CMD_GET_TEMP_SAVED_PATH : - return "GET_TEMP_SAVED_PATH"; - case DP_CMD_GET_MIME_TYPE : - return "GET_MIME_TYPE"; - case DP_CMD_GET_RECEIVED_SIZE : - return "GET_RECEIVED_SIZE"; - case DP_CMD_GET_TOTAL_FILE_SIZE : - return "GET_TOTAL_FILE_SIZE"; - case DP_CMD_GET_CONTENT_NAME : - return "GET_CONTENT_NAME"; - case DP_CMD_GET_HTTP_STATUS : - return "GET_HTTP_STATUS"; - case DP_CMD_GET_ETAG : - return "DP_CMD_GET_ETAG"; - case DP_CMD_GET_STATE : - return "GET_STATE"; - case DP_CMD_GET_ERROR : - return "ERROR"; - case DP_CMD_SET_COMMAND_SOCKET : - return "SET_COMMAND_SOCKET"; - case DP_CMD_SET_EVENT_SOCKET : - return "SET_EVENT_SOCKET"; - case DP_CMD_SET_NOTIFICATION_BUNDLE: - return "SET_NOTIFICATION_BUNDLE"; - case DP_CMD_SET_NOTIFICATION_TITLE: - return "SET_NOTIFICATION_TITLE"; - case DP_CMD_SET_NOTIFICATION_DESCRIPTION: - return "SET_NOTIFICATION_DESCRIPTION"; - case DP_CMD_SET_NOTIFICATION_TYPE: - return "SET_NOTIFICATION_TYPE"; - case DP_CMD_GET_NOTIFICATION_BUNDLE: - return "GET_NOTIFICATION_BUNDLE"; - case DP_CMD_GET_NOTIFICATION_TITLE: - return "GET_NOTIFICATION_TITLE"; - case DP_CMD_GET_NOTIFICATION_DESCRIPTION: - return "GET_NOTIFICATION_DESCRIPTION"; - case DP_CMD_GET_NOTIFICATION_TYPE: - return "GET_NOTIFICATION_TYPE"; - default : - break; - } - return "UNKNOWN COMMAND"; -} - -/* compare two string */ -static int __cmp_string(char *s1, char *s2) -{ - size_t s1_len = 0; - size_t s2_len = 0; - - if (s1 == NULL || s2 == NULL) { - TRACE_ERROR("[CHECK PARAM]"); - return -1; - } - - s1_len = strlen(s1); - if (s1_len <= 0) { - TRACE_ERROR("[CHECK PARAM] len[%d]", s1_len); - return -1; - } - - s2_len = strlen(s2); - if (s2_len <= 0) { - TRACE_ERROR("[CHECK PARAM] len[%d]", s2_len); - return -1; - } - - if (s1_len != s2_len) { - TRACE_ERROR("[DIFF] len[%d:%d]", s1_len, s2_len); - return -1; - } - - if (strncmp(s1, s2, s1_len) != 0) { - TRACE_ERROR("[DIFF] cmp"); - return -1; - } - - return 0; -} - -////////////////////////////////////////////////////////////////////////// -/// @brief return index of empty slot -static int __get_empty_request_index(dp_request_slots *slots) -{ - int i = 0; - - if (slots == NULL) - return -1; - - for (i = 0; i < DP_MAX_REQUEST; i++) { - if (slots[i].request == NULL) - return i; - } - return -1; -} - -////////////////////////////////////////////////////////////////////////// -/// @brief return index of slot having same ID -/// @param ID want to search -static int __get_same_request_index(dp_request_slots *slots, int id) -{ - int i = 0; - - if (!slots || id < 0) - return -1; - - for (i = 0; i < DP_MAX_REQUEST; i++) { - if (slots[i].request != NULL) { - if (slots[i].request->id == id) - return i; - } - } - return -1; -} - -////////////////////////////////////////////////////////////////////////// -/// @brief return custom value via IPC -static void __send_return_custom_type(int fd, dp_error_type errcode, void *value, size_t type_size) -{ - dp_ipc_send_errorcode(fd, errcode); - dp_ipc_send_custom_type(fd, value, type_size); -} - -static int __is_downloading(dp_state_type state) -{ - if (state == DP_STATE_CONNECTING || state == DP_STATE_DOWNLOADING) - return 0; - return -1; -} - -static int __is_started(dp_state_type state) -{ - if (state == DP_STATE_QUEUED || __is_downloading(state) == 0) - return 0; - return -1; -} - -static int __is_stopped(dp_state_type state) -{ - if (state == DP_STATE_COMPLETED || state == DP_STATE_FAILED || - state == DP_STATE_CANCELED) - return 0; - return -1; -} - -// cancel the downloading if no auto-download, then clear group -static void __clear_group(dp_privates *privates, dp_client_group *group) -{ - dp_request *request = NULL; - int i = 0; - - for (i = 0; i < DP_MAX_REQUEST; i++) { - - CLIENT_MUTEX_LOCK(&privates->requests[i].mutex); - - if (privates->requests[i].request == NULL) { - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - continue; - } - - request = privates->requests[i].request; - - if (request->group == NULL || request->id <= 0 || - request->group != group) { - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - continue; - } - - // if stopped, paused or not started yet, clear request - if (__is_started(request->state) < 0) { - TRACE_DEBUG("[FREE][%d] state[%s]", request->id, - dp_print_state(request->state)); - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - dp_request_slot_free(&privates->requests[i]); - continue; - } - - // disconnect the request from group. - TRACE_SECURE_DEBUG("[DISCONNECT][%d] state:%s pkg:%s sock:%d", - request->id, dp_print_state(request->state), - request->group->pkgname, request->group->cmd_socket); - request->group = NULL; - request->state_cb = 0; - request->progress_cb = 0; - - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - - } - // clear this group - dp_client_group_free(group); -} - -static void __dp_remove_tmpfile(int id, dp_request *request) -{ - dp_error_type errorcode = DP_ERROR_NONE; - char *path = - dp_request_get_tmpsavedpath(id, request, &errorcode); - if (errorcode == DP_ERROR_NONE && - (path != NULL && strlen(path) > 0) && - dp_is_file_exist(path) == 0) { - TRACE_SECURE_DEBUG("[REMOVE][%d] TEMP FILE [%s]", id, path); - if (unlink(path) != 0) - TRACE_STRERROR("[ERROR][%d] remove file", id); - } - free(path); -} - -static int __dp_check_valid_directory(dp_request *request, char *dir) -{ - int ret = -1; - int ret_val = 0; - char *dir_label = NULL; - struct stat dir_state; - - ret_val = stat(dir, &dir_state); - if (ret_val == 0) { - 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; - } - if (dir_state.st_uid == cred.uid - && (dir_state.st_mode & (S_IRUSR | S_IWUSR)) - == (S_IRUSR | S_IWUSR)) { - ret = 0; - } else if (dir_state.st_gid == cred.gid - && (dir_state.st_mode & (S_IRGRP | S_IWGRP)) - == (S_IRGRP | S_IWGRP)) { - ret = 0; - } else if ((dir_state.st_mode & (S_IROTH | S_IWOTH)) - == (S_IROTH | S_IWOTH)) { - ret = 0; - } - } - - if (ret != 0) - return ret; - - ret_val = smack_getlabel(dir, &dir_label, SMACK_LABEL_ACCESS); - if (ret_val != 0) { - TRACE_SECURE_ERROR("[ERROR][%d][SMACK ERROR]", request->id); - free(dir_label); - return -1; - } - - char *smack_label = NULL; - 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); - if (smack_label != NULL) { - ret_val = smack_have_access(smack_label, dir_label, "rw"); - free(smack_label); - } - } else { - if (request->group->smack_label != NULL) { - ret_val = smack_have_access(request->group->smack_label, dir_label, "rw"); - } - } - if (ret_val == 0) { - TRACE_SECURE_ERROR("[ERROR][%d][SMACK NO RULE]", request->id); - ret = -1; - } else if (ret_val < 0){ - TRACE_SECURE_ERROR("[ERROR][%d][SMACK ERROR]", request->id); - ret = -1; - } - free(dir_label); - return ret; -} - -static int __dp_call_cancel_agent(dp_request *request) -{ - int ret = -1; - if (request != NULL) { - if (request->agent_id >= 0) { - TRACE_INFO("[%d]cancel_agent(%d) state:%s", request->id, - request->agent_id, dp_print_state(request->state)); - if (dp_cancel_agent_download(request->agent_id) == 0) - ret = 0; - } else { - TRACE_DEBUG("[CHECK] agent-id"); - } - } - return ret; -} - -static int __dp_add_extra_param(int fd, int id) -{ - dp_error_type ret = DP_ERROR_NONE; - int length = 0; - int i = 0; - unsigned values_length = 0; - char *key = NULL; - char **values = NULL; - - if (fd < 0) { - TRACE_ERROR("[CHECK] socket"); - return DP_ERROR_IO_ERROR; - } - if (id < 0) { - TRACE_ERROR("[CHECK] ID"); - return DP_ERROR_INVALID_PARAMETER; - } - - if (dp_ipc_read_custom_type(fd, &length, sizeof(int)) < 0) { - TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]", id); - ret = DP_ERROR_IO_ERROR; - } else { - TRACE_DEBUG("[RECV] length %d", length); - if (length <= 0) { - ret = DP_ERROR_INVALID_PARAMETER; - } else { - key = dp_ipc_read_string(fd); - if (key == NULL) { - TRACE_ERROR("[ERROR][%d][IO_ERROR] key", id); - ret = DP_ERROR_IO_ERROR; - } else { - if (length > 1) { - TRACE_SECURE_DEBUG("[RECV] key : %s", key); - // get values - values = (char **)calloc((length - 1), sizeof(char *)); - if (values == NULL) { - ret = DP_ERROR_OUT_OF_MEMORY; - } else { - for (i = 0; i < length - 1; i++) { - values[i] = dp_ipc_read_string(fd); - if (values[i] == NULL) { - ret = DP_ERROR_IO_ERROR; - break; - } - values_length++; - } - } - } else { - TRACE_ERROR("[ERROR][%d] length [%d]", id, length); - ret = DP_ERROR_INVALID_PARAMETER; - } - } - } - } - if (ret == DP_ERROR_NONE) { - // store to DB - for (i = 0; i < length - 1; i++) { - int conds_count = 3; - db_conds_list_fmt conds_p[conds_count]; // id + key + value - memset(&conds_p, 0x00, conds_count * sizeof(db_conds_list_fmt)); - conds_p[0].column = DP_DB_COL_ID; - conds_p[0].type = DP_DB_COL_TYPE_INT; - conds_p[0].value = &id; - conds_p[1].column = DP_DB_COL_EXTRA_KEY; - conds_p[1].type = DP_DB_COL_TYPE_TEXT; - conds_p[1].value = key; - conds_p[2].column = DP_DB_COL_EXTRA_VALUE; - conds_p[2].type = DP_DB_COL_TYPE_TEXT; - conds_p[2].value = values[i]; - int check_key = - dp_db_get_conds_rows_count(DP_DB_TABLE_NOTIFICATION, - DP_DB_COL_ID, "AND", conds_count, conds_p); - if (check_key <= 0) { // create newly - // insert - if (dp_db_insert_columns(DP_DB_TABLE_NOTIFICATION, - conds_count, conds_p) < 0) { - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", id); - ret = DP_ERROR_NO_SPACE; - } else { - ret = DP_ERROR_OUT_OF_MEMORY; - } - break; - } - } // else skip. already exist - } - } - free(key); - for (i = 0; i < values_length; i++) { - free(values[i]); - } - free(values); - return ret; -} - -static int __dp_get_extra_param_values(int fd, int id, char ***values, - unsigned *count) -{ - dp_error_type ret = DP_ERROR_NONE; - int length = 0; - char *key = NULL; - char **rows_array = NULL; - - if (fd < 0) { - TRACE_ERROR("[CHECK] socket"); - return DP_ERROR_IO_ERROR; - } - if (id < 0) { - TRACE_ERROR("[CHECK] ID"); - return DP_ERROR_INVALID_PARAMETER; - } - - if (dp_ipc_read_custom_type(fd, &length, sizeof(int)) < 0) { - TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]", id); - ret = DP_ERROR_IO_ERROR; - } else { - TRACE_DEBUG("[RECV] length %d", length); - if (length != 1) { // only a key - ret = DP_ERROR_INVALID_PARAMETER; - } else { - if ((key = dp_ipc_read_string(fd)) == NULL) { - TRACE_ERROR("[ERROR][%d][IO_ERROR] key", id); - ret = DP_ERROR_IO_ERROR; - } - } - } - if (ret == DP_ERROR_NONE) { - int conds_count = 2; - db_conds_list_fmt conds_p[conds_count]; // id + key + value - memset(&conds_p, 0x00, conds_count * sizeof(db_conds_list_fmt)); - conds_p[0].column = DP_DB_COL_ID; - conds_p[0].type = DP_DB_COL_TYPE_INT; - conds_p[0].value = &id; - conds_p[1].column = DP_DB_COL_EXTRA_KEY; - conds_p[1].type = DP_DB_COL_TYPE_TEXT; - conds_p[1].value = key; - int check_rows = dp_db_get_conds_rows_count - (DP_DB_TABLE_NOTIFICATION, DP_DB_COL_EXTRA_VALUE, "AND", - conds_count, conds_p); - if (check_rows <= 0) { - // NO_DATA - ret = DP_ERROR_NO_DATA; - } else { - rows_array = (char **)calloc(check_rows, sizeof(char *)); - if (rows_array == NULL) { - ret = DP_ERROR_OUT_OF_MEMORY; - } else { - // getting the array from DB with key condition - int rows_count = - dp_db_get_conds_list(DP_DB_TABLE_NOTIFICATION, - DP_DB_COL_EXTRA_VALUE, DP_DB_COL_TYPE_TEXT, - (void **)rows_array, check_rows, -1, NULL, NULL, - "AND", conds_count, conds_p); - if (rows_count <= 0) { - // NO_DATA - ret = DP_ERROR_NO_DATA; - free(rows_array); - } else { - *count = rows_count; - *values = rows_array; - } - } - free(key); - } - } - return ret; -} - -static int __dp_remove_extra_param(int fd, int id) -{ - dp_error_type ret = DP_ERROR_NONE; - char *key = NULL; - - if (fd < 0) { - TRACE_ERROR("[CHECK] socket"); - return DP_ERROR_IO_ERROR; - } - if (id < 0) { - TRACE_ERROR("[CHECK] ID"); - return DP_ERROR_INVALID_PARAMETER; - } - - if ((key = dp_ipc_read_string(fd)) == NULL) { - TRACE_ERROR("[ERROR][%d] INVALID_PARAMETER", id); - ret = DP_ERROR_IO_ERROR; - } - if (ret == DP_ERROR_NONE) { - if (dp_db_cond_remove(id, DP_DB_TABLE_NOTIFICATION, - DP_DB_COL_EXTRA_KEY, DP_DB_COL_TYPE_TEXT, key) < 0) { - TRACE_ERROR("[fail][%d][sql]", id); - TRACE_SECURE_ERROR("[fail]key:%s", key); - ret = DP_ERROR_OUT_OF_MEMORY; - } - } - TRACE_DEBUG("[ERROR][%d][%s]", id, dp_print_errorcode(ret)); - TRACE_SECURE_DEBUG("key:%s", key); - free(key); - return ret; -} - -static int __dp_get_http_header_fields(int fd, int id, char ***values, - unsigned *count) -{ - dp_error_type ret = DP_ERROR_NONE; - char **rows_array = NULL; - - if (fd < 0) { - TRACE_ERROR("[CHECK] socket"); - return DP_ERROR_IO_ERROR; - } - if (id < 0) { - TRACE_ERROR("[CHECK] ID"); - return DP_ERROR_INVALID_PARAMETER; - } - - db_conds_list_fmt conds_p; - conds_p.column = DP_DB_COL_ID; - conds_p.type = DP_DB_COL_TYPE_INT; - conds_p.value = &id; - conds_p.is_like = 0; - int check_rows = dp_db_get_conds_rows_count - (DP_DB_TABLE_HTTP_HEADERS, DP_DB_COL_HEADER_FIELD, "AND", - 1, &conds_p); - if (check_rows <= 0) { - // NO_DATA - ret = DP_ERROR_NO_DATA; - } else { - rows_array = (char **)calloc(check_rows, sizeof(char *)); - if (rows_array == NULL) { - ret = DP_ERROR_OUT_OF_MEMORY; - } else { - int rows_count = - dp_db_get_conds_list(DP_DB_TABLE_HTTP_HEADERS, - DP_DB_COL_HEADER_FIELD, DP_DB_COL_TYPE_TEXT, - (void **)rows_array, check_rows, -1, NULL, NULL, - "AND", 1, &conds_p); - if (rows_count <= 0) { - // NO_DATA - ret = DP_ERROR_NO_DATA; - free(rows_array); - } else { - *count = rows_count; - *values = rows_array; - } - } - } - return ret; -} - -static int __dp_set_group_new(int clientfd, dp_group_slots *groups, - dp_credential credential, fd_set *listen_fdset) -{ - // search in groups. - // if same group. update it. - // search same pkg or pid in groups - int pkg_len = 0; - int i = 0; - struct timeval tv_timeo; // 2.5 sec - char *pkgname = NULL; - char *smack_label = NULL; - int ret = 0; - - tv_timeo.tv_sec = 2; - tv_timeo.tv_usec = 500000; - if (setsockopt(clientfd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, - sizeof(tv_timeo)) < 0) { - TRACE_STRERROR("[CRITICAL] setsockopt SO_RCVTIMEO"); - return -1; - } - - // getting the package name via pid - if (app_manager_get_package(credential.pid, &pkgname) == - APP_MANAGER_ERROR_NONE) { - TRACE_SECURE_DEBUG("package : %s", pkgname); - } else - TRACE_ERROR("[CRITICAL] app_manager_get_package"); - - //// TEST CODE ... to allow sample client ( no package name ). - if (pkgname == NULL) { - pkgname = dp_strdup("unknown_app"); - TRACE_DEBUG("default package naming : %s", pkgname); - } - - if (pkgname == NULL) { - TRACE_ERROR("[CRITICAL] app_manager_get_package"); - return -1; - } - if ((pkg_len = strlen(pkgname)) <= 0) { - TRACE_ERROR("[CRITICAL] pkgname:%s", pkgname); - free(pkgname); - return -1; - } - - for (i = 0; i < DP_MAX_GROUP; i++) { - if (groups[i].group != NULL) { - // clean garbage slot - if (groups[i].group->cmd_socket <= 0 || - groups[i].group->pkgname == NULL) { - dp_client_group_free(groups[i].group); - groups[i].group = NULL; - continue; - } - if (strlen(groups[i].group->pkgname) == pkg_len && - strncmp(groups[i].group->pkgname, pkgname, - pkg_len) == 0 ) { - // Found Same Group - TRACE_SECURE_INFO("UPDATE Group: slot:%d pid:%d sock:%d [%s]", - i, credential.pid, clientfd, pkgname); - if (groups[i].group->cmd_socket > 0 && - groups[i].group->cmd_socket != clientfd) { - FD_CLR(groups[i].group->cmd_socket, listen_fdset); - dp_socket_free(groups[i].group->cmd_socket); - } - groups[i].group->cmd_socket = clientfd; - free(pkgname); - return 0; - } - } - } - - // new client - // search emtpy slot in groups - for (i = 0; i < DP_MAX_GROUP; i++) - if (groups[i].group == NULL) - break; - if (i >= DP_MAX_GROUP) { - TRACE_ERROR("[CRITICAL] No space in groups"); - free(pkgname); - return -1; - } - // allocation - groups[i].group = - (dp_client_group *)calloc(1, sizeof(dp_client_group)); - if (groups[i].group == NULL) { - TRACE_ERROR("[CRITICAL] calloc, ignore this client"); - free(pkgname); - return -1; - } - - // fill info - groups[i].group->cmd_socket = clientfd; - groups[i].group->event_socket = -1; - groups[i].group->queued_count = 0; - groups[i].group->pkgname = dp_strdup(pkgname); - groups[i].group->credential.pid = credential.pid; - groups[i].group->credential.uid = credential.uid; - groups[i].group->credential.gid = credential.gid; - - int conds_count = 4; - db_conds_list_fmt conds_p[conds_count]; - memset(&conds_p, 0x00, conds_count * sizeof(db_conds_list_fmt)); - conds_p[0].column = DP_DB_GROUPS_COL_UID; - conds_p[0].type = DP_DB_COL_TYPE_INT; - conds_p[0].value = &credential.uid; - conds_p[1].column = DP_DB_GROUPS_COL_GID; - conds_p[1].type = DP_DB_COL_TYPE_INT; - conds_p[1].value = &credential.gid; - conds_p[2].column = DP_DB_GROUPS_COL_PKG; - conds_p[2].type = DP_DB_COL_TYPE_TEXT; - conds_p[2].value = pkgname; - - if (dp_is_smackfs_mounted() == 1) { - ret = smack_new_label_from_socket(clientfd, &smack_label); - if (ret != 0) { - TRACE_ERROR("[CRITICAL] cannot get smack label"); - free(pkgname); - free(smack_label); - return -1; - } - TRACE_SECURE_INFO("credential label:[%s]", smack_label); - groups[i].group->smack_label = smack_label; - - conds_p[3].column = DP_DB_GROUPS_COL_SMACK_LABEL; - conds_p[3].type = DP_DB_COL_TYPE_TEXT; - conds_p[3].value = smack_label; - } else { - conds_count = 3; // ignore smack label - groups[i].group->smack_label = NULL; - } - - if (dp_db_insert_columns(DP_DB_TABLE_GROUPS, conds_count, conds_p) < 0) { - free(pkgname); - free(smack_label); - if (dp_db_is_full_error() == 0) - TRACE_ERROR("[SQLITE_FULL]"); - return -1; - } - - TRACE_SECURE_INFO("New Group: slot:%d pid:%d sock:%d [%s]", i, - credential.pid, clientfd, pkgname); - free(pkgname); - return 0; -} - - -static int __dp_set_group_event_sock(int clientfd, - dp_group_slots *groups, dp_credential credential) -{ - int i = 0; - - TRACE_DEBUG("Check event pid:%d sock:%d", credential.pid, clientfd); - // search same pid in groups - for (i = 0; i < DP_MAX_GROUP; i++) { - if (groups[i].group != NULL && - groups[i].group->credential.pid == credential.pid) { - if (groups[i].group->event_socket > 0 && - groups[i].group->event_socket != clientfd) - dp_socket_free(groups[i].group->event_socket); - groups[i].group->event_socket = clientfd; - TRACE_SECURE_INFO - ("Found Group : slot:%d pid:%d csock:%d esock:%d [%s]", - i, credential.pid, groups[i].group->cmd_socket, - clientfd, groups[i].group->pkgname); - break; - } - } - if (i >= DP_MAX_GROUP) { - TRACE_ERROR - ("[CRITICAL] Not found group for PID [%d]", credential.pid); - return -1; - } - return 0; -} - -static dp_error_type __dp_do_get_command(int sock, dp_command* cmd, dp_request *request) -{ - unsigned is_checked = 1; - dp_error_type errorcode = DP_ERROR_NONE; - - char *read_str = NULL; - // No read(), write a string - switch(cmd->cmd) { - case DP_CMD_GET_URL: - read_str = dp_request_get_url(cmd->id, &errorcode); - break; - case DP_CMD_GET_DESTINATION: - read_str = dp_request_get_destination(cmd->id, request, &errorcode); - break; - case DP_CMD_GET_FILENAME: - read_str = dp_request_get_filename(cmd->id, request, &errorcode); - break; - case DP_CMD_GET_SAVED_PATH: - read_str = dp_request_get_savedpath(cmd->id, request, &errorcode); - break; - case DP_CMD_GET_TEMP_SAVED_PATH: - read_str = dp_request_get_tmpsavedpath(cmd->id, request, &errorcode); - break; - case DP_CMD_GET_MIME_TYPE: - read_str = dp_request_get_mimetype(cmd->id, request, &errorcode); - break; - case DP_CMD_GET_CONTENT_NAME: - read_str = dp_request_get_contentname(cmd->id, request, &errorcode); - break; - case DP_CMD_GET_ETAG: - read_str = dp_request_get_etag(cmd->id, request, &errorcode); - break; - case DP_CMD_GET_NOTIFICATION_TITLE: - read_str = dp_request_get_title(cmd->id, request, &errorcode); - break; - case DP_CMD_GET_NOTIFICATION_DESCRIPTION: - read_str = dp_request_get_description(cmd->id, request, &errorcode); - break; - default: - is_checked = 0; - break; - } - if (is_checked == 1) { - if (read_str == NULL || strlen(read_str) < 1) - errorcode = DP_ERROR_NO_DATA; - dp_ipc_send_errorcode(sock, errorcode); - if (errorcode == DP_ERROR_NONE) { - dp_ipc_send_string(sock, read_str); - } else { - TRACE_ERROR("[ERROR][%d][%s][%s]", cmd->id, - __print_command(cmd->cmd), dp_print_errorcode(errorcode)); - } - free(read_str); - return errorcode; - } - - // No read(), write a integer variable - int read_int = 0; - errorcode = DP_ERROR_NONE; - is_checked = 1; - switch(cmd->cmd) { - case DP_CMD_GET_NOTIFICATION: - read_int = dp_db_get_int_column(cmd->id, DP_DB_TABLE_REQUEST_INFO, - DP_DB_COL_NOTIFICATION_ENABLE); - break; - case DP_CMD_GET_AUTO_DOWNLOAD: - read_int = dp_db_get_int_column(cmd->id, DP_DB_TABLE_REQUEST_INFO, - DP_DB_COL_AUTO_DOWNLOAD); - break; - case DP_CMD_GET_NETWORK_TYPE: - read_int = dp_db_get_int_column(cmd->id, DP_DB_TABLE_REQUEST_INFO, - DP_DB_COL_NETWORK_TYPE); - break; - case DP_CMD_GET_HTTP_STATUS: - read_int = dp_db_get_int_column(cmd->id, DP_DB_TABLE_DOWNLOAD_INFO, - DP_DB_COL_HTTP_STATUS); - break; - case DP_CMD_GET_STATE: - if (request == NULL) { - read_int = dp_db_get_state(cmd->id); - } else { - read_int = request->state; - } - break; - case DP_CMD_GET_NOTIFICATION_TYPE: - TRACE_DEBUG("DP_CMD_GET_NOTIFICATION_TYPE"); - read_int = dp_request_get_noti_type(cmd->id, request, &errorcode); - break; - case DP_CMD_GET_ERROR: - if (request == NULL) { - read_int = dp_db_get_int_column(cmd->id, - DP_DB_TABLE_LOG, DP_DB_COL_ERRORCODE); - } else { - read_int = request->error; - } - break; - default: - is_checked = 0; - break; - } - if (is_checked == 1) { - if (read_int < 0) - errorcode = DP_ERROR_NO_DATA; - dp_ipc_send_errorcode(sock, errorcode); - if (errorcode == DP_ERROR_NONE) { - dp_ipc_send_custom_type(sock, &read_int, sizeof(int)); - } else { - TRACE_ERROR("[ERROR][%d][%s][%s]", cmd->id, - __print_command(cmd->cmd), dp_print_errorcode(errorcode)); - } - return errorcode; - } - - // No read(), write a long long variable - unsigned long long recv_long = 0; - errorcode = DP_ERROR_NONE; - is_checked = 1; - switch(cmd->cmd) { - case DP_CMD_GET_RECEIVED_SIZE: - if (request == NULL) - errorcode = DP_ERROR_NO_DATA; - else - recv_long = request->received_size; - break; - case DP_CMD_GET_TOTAL_FILE_SIZE: - if (request != NULL) { - recv_long = request->file_size; - } else { - long long file_size = - dp_db_get_int64_column(cmd->id, - DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_SIZE); - if (file_size < 0) - errorcode = DP_ERROR_NO_DATA; - else // casting - recv_long = file_size; - } - break; - default: - is_checked = 0; - break; - } - if (is_checked == 1) { - dp_ipc_send_errorcode(sock, errorcode); - if (errorcode == DP_ERROR_NONE) { - dp_ipc_send_custom_type(sock, &recv_long, - sizeof(unsigned long long)); - } else { - TRACE_ERROR("[ERROR][%d][%s][%s]", cmd->id, - __print_command(cmd->cmd), dp_print_errorcode(errorcode)); - } - return errorcode; - } - - // No read(), write a bundle variable - bundle_raw *b_raw = NULL; - int length = -1; - char *column = NULL; - errorcode = DP_ERROR_NONE; - is_checked = 1; - switch(cmd->cmd) { - case DP_CMD_GET_NOTIFICATION_BUNDLE: - TRACE_DEBUG("DP_CMD_GET_NOTIFICATION_BUNDLE"); - dp_ipc_send_errorcode(sock, DP_ERROR_NONE); - if ((dp_ipc_read_custom_type(sock, &read_int, sizeof(int)) < 0)) { - TRACE_ERROR("DP_CMD_GET_NOTIFICATION_BUNDLE read fail"); - errorcode = DP_ERROR_IO_ERROR; - break; - } - switch(read_int) { - case DP_NOTIFICATION_BUNDLE_TYPE_ONGOING: - column = DP_DB_COL_RAW_BUNDLE_ONGOING; - break; - case DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE: - column = DP_DB_COL_RAW_BUNDLE_COMPLETE; - break; - case DP_NOTIFICATION_BUNDLE_TYPE_FAILED: - column = DP_DB_COL_RAW_BUNDLE_FAIL; - break; - default: - TRACE_ERROR("[CHECK TYPE][%d]", read_int); - errorcode = DP_ERROR_INVALID_PARAMETER; - break; - } - b_raw = dp_request_get_bundle(cmd->id, request, - &errorcode, column, &length); - break; - default: - is_checked = 0; - break; - } - if (is_checked == 1) { - dp_ipc_send_errorcode(sock, errorcode); - if (errorcode == DP_ERROR_NONE) { - dp_ipc_send_bundle(sock, b_raw, length); - } else { - TRACE_ERROR("[ERROR][%d][%s][%s]", cmd->id, - __print_command(cmd->cmd), dp_print_errorcode(errorcode)); - } - bundle_free_encoded_rawdata(&b_raw); - return errorcode; - } - - dp_ipc_send_errorcode(sock, DP_ERROR_NONE); - // complex read() and write(). - char *read_str2 = NULL; - errorcode = DP_ERROR_NONE; - read_str = NULL; - is_checked = 1; - switch(cmd->cmd) { - case DP_CMD_GET_HTTP_HEADER: - if ((read_str = dp_ipc_read_string(sock)) == NULL) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - read_str2 = dp_db_cond_get_text_column(cmd->id, - DP_DB_TABLE_HTTP_HEADERS, DP_DB_COL_HEADER_DATA, - DP_DB_COL_HEADER_FIELD, DP_DB_COL_TYPE_TEXT, read_str); - if (read_str2 == NULL) - errorcode = DP_ERROR_NO_DATA; - dp_ipc_send_errorcode(sock, errorcode); - if (errorcode == DP_ERROR_NONE) - dp_ipc_send_string(sock, read_str2); - break; - case DP_CMD_GET_HTTP_HEADER_LIST: - { - char **values = NULL; - unsigned rows_count = 0; - errorcode = __dp_get_http_header_fields(sock, - cmd->id, &values, &rows_count); - if (errorcode == DP_ERROR_NONE) { - __send_return_custom_type(sock, DP_ERROR_NONE, - &rows_count, sizeof(int)); - // sending strings - int i = 0; - for (i = 0; i < rows_count; i++) { - if (dp_ipc_send_string(sock, values[i]) < 0) - break; - } - for (i = 0; i < rows_count; i++) - free(values[i]); - } else { - if (errorcode != DP_ERROR_IO_ERROR) - dp_ipc_send_errorcode(sock, errorcode); - } - free(values); - break; - } - case DP_CMD_GET_EXTRA_PARAM: - { - char **values = NULL; - unsigned rows_count = 0; - errorcode = __dp_get_extra_param_values(sock, - cmd->id, &values, &rows_count); - if (errorcode == DP_ERROR_NONE) { - __send_return_custom_type(sock, DP_ERROR_NONE, - &rows_count, sizeof(int)); - // sending strings - int i = 0; - for (i = 0; i < rows_count; i++) { - if (dp_ipc_send_string(sock, values[i]) < 0) - break; - } - for (i = 0; i < rows_count; i++) - free(values[i]); - } else { - if (errorcode != DP_ERROR_IO_ERROR) - dp_ipc_send_errorcode(sock, errorcode); - } - free(values); - break; - } - default: - is_checked = 0; - break; - } - if (is_checked == 1) { - if (errorcode != DP_ERROR_NONE) { - TRACE_ERROR("[ERROR][%d][%s][%s]", cmd->id, - __print_command(cmd->cmd), dp_print_errorcode(errorcode)); - } - free(read_str); - free(read_str2); - return errorcode; - } - return DP_ERROR_UNKNOWN; -} - -static dp_error_type __dp_do_set_command(int sock, dp_command *cmd, dp_request *request) -{ - unsigned is_checked = 1; - int read_int = 0; - dp_error_type errorcode = DP_ERROR_NONE; - char *read_str = NULL; - bundle_raw *b_raw = NULL; - unsigned bundle_length = 0; - int noti_bundle_type = 0; - - dp_ipc_send_errorcode(sock, DP_ERROR_NONE); - // read a interger or a string, return errorcode. - errorcode = DP_ERROR_NONE; - switch(cmd->cmd) { - case DP_CMD_SET_STATE_CALLBACK: - if (dp_ipc_read_custom_type(sock, &read_int, sizeof(int)) < 0) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - errorcode = dp_request_set_state_event(cmd->id, request, read_int); - break; - case DP_CMD_SET_PROGRESS_CALLBACK: - if (dp_ipc_read_custom_type(sock, &read_int, sizeof(int)) < 0) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - errorcode = dp_request_set_progress_event(cmd->id, request, read_int); - break; - case DP_CMD_SET_NETWORK_TYPE: - if (dp_ipc_read_custom_type(sock, &read_int, sizeof(int)) < 0) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - if (read_int == DP_NETWORK_TYPE_ALL || - read_int == DP_NETWORK_TYPE_WIFI || - read_int == DP_NETWORK_TYPE_DATA_NETWORK || - read_int == DP_NETWORK_TYPE_ETHERNET || - read_int == DP_NETWORK_TYPE_WIFI_DIRECT) - errorcode = dp_request_set_network_type(cmd->id, request, read_int); - else - errorcode = DP_ERROR_INVALID_PARAMETER; - break; - case DP_CMD_SET_AUTO_DOWNLOAD: - if (dp_ipc_read_custom_type(sock, &read_int, sizeof(int)) < 0) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - errorcode = dp_request_set_auto_download(cmd->id, request, read_int); - break; - case DP_CMD_SET_NOTIFICATION: - if (dp_ipc_read_custom_type(sock, &read_int, sizeof(int)) < 0) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - errorcode = dp_request_set_notification(cmd->id, request, read_int); - break; - case DP_CMD_SET_URL: - if ((read_str = dp_ipc_read_string(sock)) == NULL) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - errorcode = dp_request_set_url(cmd->id, request, read_str); - break; - case DP_CMD_SET_DESTINATION: - if ((read_str = dp_ipc_read_string(sock)) == NULL) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - if (dp_is_smackfs_mounted() == 1 && - __dp_check_valid_directory(request, read_str) != 0){ - errorcode = DP_ERROR_PERMISSION_DENIED; - break; - } - errorcode = dp_request_set_destination(cmd->id, request, read_str); - break; - case DP_CMD_SET_FILENAME: - if ((read_str = dp_ipc_read_string(sock)) == NULL) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - errorcode = dp_request_set_filename(cmd->id, request, read_str); - break; - case DP_CMD_SET_NOTIFICATION_BUNDLE: - bundle_length = dp_ipc_read_bundle(sock, ¬i_bundle_type, &b_raw); - if (bundle_length == 0) { - errorcode = DP_ERROR_IO_ERROR; - break; - } else if (bundle_length == -1) { - errorcode = DP_ERROR_INVALID_PARAMETER; - break; - } - errorcode = dp_request_set_bundle(cmd->id, request, - noti_bundle_type, b_raw, bundle_length); - break; - case DP_CMD_SET_NOTIFICATION_TITLE: - if ((read_str = dp_ipc_read_string(sock)) == NULL) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - errorcode = dp_request_set_title(cmd->id, request, read_str); - break; - case DP_CMD_SET_NOTIFICATION_DESCRIPTION: - if ((read_str = dp_ipc_read_string(sock)) == NULL) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - errorcode = dp_request_set_description(cmd->id, request, read_str); - break; - case DP_CMD_SET_NOTIFICATION_TYPE: - if ((dp_ipc_read_custom_type(sock, &read_int, sizeof(int)) < 0)) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - if (read_int == DP_NOTIFICATION_TYPE_NONE || - read_int == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || - read_int == DP_NOTIFICATION_TYPE_ALL) - errorcode = dp_request_set_noti_type(cmd->id, request, read_int); - else - errorcode = DP_ERROR_INVALID_PARAMETER; - break; - default: - is_checked = 0; - break; - } - if (is_checked == 1) { - free(read_str); - bundle_free_encoded_rawdata(&b_raw); - if (errorcode != DP_ERROR_NONE) { - TRACE_ERROR("[ERROR][%d][%s][%s]", cmd->id, - __print_command(cmd->cmd), dp_print_errorcode(errorcode)); - } - if (errorcode == DP_ERROR_IO_ERROR) - return errorcode; - dp_ipc_send_errorcode(sock, errorcode); - return errorcode; - } - - // complex read() and write(). - char *read_str2 = NULL; - errorcode = DP_ERROR_NONE; - read_str = NULL; - is_checked = 1; - switch(cmd->cmd) { - case DP_CMD_SET_HTTP_HEADER: - { - if ((read_str = dp_ipc_read_string(sock)) == NULL) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - if ((read_str2 = dp_ipc_read_string(sock)) == NULL) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - int conds_count = 3; // id + field + data - db_conds_list_fmt conds_p[conds_count]; - memset(&conds_p, 0x00, - conds_count * sizeof(db_conds_list_fmt)); - conds_p[0].column = DP_DB_COL_ID; - conds_p[0].type = DP_DB_COL_TYPE_INT; - conds_p[0].value = &cmd->id; - conds_p[1].column = DP_DB_COL_HEADER_FIELD; - conds_p[1].type = DP_DB_COL_TYPE_TEXT; - conds_p[1].value = read_str; - conds_p[2].column = DP_DB_COL_HEADER_DATA; - conds_p[2].type = DP_DB_COL_TYPE_TEXT; - conds_p[2].value = read_str2; - if (dp_db_get_conds_rows_count(DP_DB_TABLE_HTTP_HEADERS, - DP_DB_COL_ID, "AND", 2, conds_p) <= 0) { // insert - if (dp_db_insert_columns(DP_DB_TABLE_HTTP_HEADERS, - conds_count, conds_p) < 0) { - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", cmd->id); - errorcode = DP_ERROR_NO_SPACE; - } else { - errorcode = DP_ERROR_OUT_OF_MEMORY; - } - } - } else { // update data by field - if (dp_db_cond_set_column(cmd->id, DP_DB_TABLE_HTTP_HEADERS, - DP_DB_COL_HEADER_DATA, DP_DB_COL_TYPE_TEXT, read_str2, - DP_DB_COL_HEADER_FIELD, DP_DB_COL_TYPE_TEXT, read_str) < 0) { - if (dp_db_is_full_error() == 0) { - TRACE_ERROR("[SQLITE_FULL][%d]", cmd->id); - errorcode = DP_ERROR_NO_SPACE; - } else { - errorcode = DP_ERROR_OUT_OF_MEMORY; - } - } - } - dp_ipc_send_errorcode(sock, errorcode); - break; - } - case DP_CMD_DEL_HTTP_HEADER: - if ((read_str = dp_ipc_read_string(sock)) == NULL) { - errorcode = DP_ERROR_IO_ERROR; - break; - } - if (dp_db_get_cond_rows_count(cmd->id, DP_DB_TABLE_HTTP_HEADERS, - DP_DB_COL_HEADER_FIELD, DP_DB_COL_TYPE_TEXT, - read_str) <= 0) { - errorcode = DP_ERROR_NO_DATA; - } else { - if (dp_db_cond_remove(cmd->id, DP_DB_TABLE_HTTP_HEADERS, - DP_DB_COL_HEADER_FIELD, DP_DB_COL_TYPE_TEXT, read_str) < 0) - errorcode = DP_ERROR_OUT_OF_MEMORY; - } - dp_ipc_send_errorcode(sock, errorcode); - break; - case DP_CMD_ADD_EXTRA_PARAM: - errorcode = __dp_add_extra_param(sock, cmd->id); - if (errorcode != DP_ERROR_IO_ERROR) - dp_ipc_send_errorcode(sock, errorcode); - break; - case DP_CMD_REMOVE_EXTRA_PARAM: - errorcode = __dp_remove_extra_param(sock, cmd->id); - if (errorcode != DP_ERROR_IO_ERROR) - dp_ipc_send_errorcode(sock, errorcode); - break; - default: - is_checked = 0; - break; - } - if (is_checked == 1) { - if (errorcode != DP_ERROR_NONE) { - TRACE_ERROR("[ERROR][%d][%s][%s]", cmd->id, - __print_command(cmd->cmd), dp_print_errorcode(errorcode)); - } - free(read_str); - free(read_str2); - return errorcode; - } - return DP_ERROR_UNKNOWN; -} - -static dp_error_type __dp_do_action_command(int sock, dp_command* cmd, dp_request *request) -{ - unsigned is_checked = 1; - int read_int = 0; - dp_error_type errorcode = DP_ERROR_NONE; - - read_int = 0; - errorcode = DP_ERROR_NONE; - is_checked = 1; - switch(cmd->cmd) { - case DP_CMD_DESTROY: - if (request != NULL) {// just update the state - if (__is_started(request->state) == 0) { - read_int = DP_STATE_CANCELED; - if (dp_db_set_column(cmd->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE, - DP_DB_COL_TYPE_INT, &read_int) < 0) { - errorcode = DP_ERROR_OUT_OF_MEMORY; - } else { - if (__dp_call_cancel_agent(request) < 0) - TRACE_ERROR("[fail][%d]cancel_agent", cmd->id); - request->state = DP_STATE_CANCELED; - if (request->auto_notification == 1 && - request->packagename != NULL) { - request->noti_priv_id = dp_set_downloadedinfo_notification - (request->noti_priv_id, request->id, - request->packagename, request->state); - } 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_NONE && - request->packagename != NULL) - request->noti_priv_id = dp_set_downloadedinfo_notification - (request->noti_priv_id, request->id, - request->packagename, request->state); - } - } - } - } - break; - case DP_CMD_PAUSE: - { - // to check fastly, divide the case by request value - if (request == NULL) { - dp_state_type state = dp_db_get_state(cmd->id); - // already paused or stopped - if (state > DP_STATE_DOWNLOADING) { - errorcode = DP_ERROR_INVALID_STATE; - } else { - // change state to paused. - state = DP_STATE_PAUSED; - if (dp_db_set_column(cmd->id, DP_DB_TABLE_LOG, - DP_DB_COL_STATE, DP_DB_COL_TYPE_INT, &state) < 0) - errorcode = DP_ERROR_OUT_OF_MEMORY; - } - break; - } - - if (request->state > DP_STATE_DOWNLOADING) { - errorcode = DP_ERROR_INVALID_STATE; - break; - } - - // before downloading including QUEUED - if (__is_downloading(request->state) < 0) { - dp_state_type state = DP_STATE_PAUSED; - if (dp_db_set_column(cmd->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE, - DP_DB_COL_TYPE_INT, &state) < 0) { - errorcode = DP_ERROR_OUT_OF_MEMORY; - } else { - request->state = state; - } - break; - } - // only downloading. - dp_state_type state = DP_STATE_PAUSE_REQUESTED; - if (dp_db_set_column(cmd->id, DP_DB_TABLE_LOG, - DP_DB_COL_STATE, DP_DB_COL_TYPE_INT, &state) < 0) { - errorcode = DP_ERROR_OUT_OF_MEMORY; - } else { - TRACE_INFO("[%s][%d]pause_agent(%d) state:%s", - __print_command(cmd->cmd), cmd->id, - request->agent_id, - dp_print_state(request->state)); - if (dp_pause_agent_download - (request->agent_id) < 0) { - TRACE_ERROR("[fail][%d]pause_agent(%d)", - cmd->id, request->agent_id); - } - request->state = state; - request->error = DP_ERROR_NONE; - request->pause_time = (int)time(NULL); - dp_db_update_date(cmd->id, DP_DB_TABLE_LOG, - DP_DB_COL_ACCESS_TIME); - } - break; - } - case DP_CMD_CANCEL: - { - // to check fastly, divide the case by request value - if (request == NULL) { - dp_state_type state = dp_db_get_state(cmd->id); - // already paused or stopped - if (__is_stopped(state) == 0) { - errorcode = DP_ERROR_INVALID_STATE; - } else { - // change state to canceled. - state = DP_STATE_CANCELED; - if (dp_db_set_column(cmd->id, DP_DB_TABLE_LOG, - DP_DB_COL_STATE, DP_DB_COL_TYPE_INT, &state) < 0) - errorcode = DP_ERROR_OUT_OF_MEMORY; - } - break; - } - - if (__is_stopped(request->state) == 0) { - TRACE_ERROR("[%s][%d]__is_stopped agentid:%d state:%s", - __print_command(cmd->cmd), cmd->id, - request->agent_id, dp_print_state(request->state)); - errorcode = DP_ERROR_INVALID_STATE; - } else { - // change state to canceled. - dp_state_type state = DP_STATE_CANCELED; - if (dp_db_set_column(cmd->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE, - DP_DB_COL_TYPE_INT, &state) < 0) - errorcode = DP_ERROR_OUT_OF_MEMORY; - } - if (errorcode == DP_ERROR_NONE) { - if (__dp_call_cancel_agent(request) < 0) - TRACE_ERROR("[fail][%d]cancel_agent", cmd->id); - request->state = DP_STATE_CANCELED; - } - dp_db_update_date(cmd->id, DP_DB_TABLE_LOG, DP_DB_COL_ACCESS_TIME); - break; - } - default: - is_checked = 0; - break; - } - if (is_checked == 1) { - if (errorcode != DP_ERROR_NONE) { - TRACE_ERROR("[ERROR][%d][%s][%s]", cmd->id, - __print_command(cmd->cmd), dp_print_errorcode(errorcode)); - } - dp_ipc_send_errorcode(sock, errorcode); - return errorcode; - } - return DP_ERROR_UNKNOWN; -} - -static dp_error_type __do_dp_start_command(int sock, int id, dp_privates *privates, - dp_client_group *group, dp_request *request) -{ - dp_error_type errorcode = DP_ERROR_NONE; - - // need URL at least - char *url = dp_request_get_url(id, &errorcode); - free(url); - if (errorcode == DP_ERROR_NO_DATA) { - errorcode = DP_ERROR_INVALID_URL; - dp_ipc_send_errorcode(sock, errorcode); - return errorcode; - } - - if (request == NULL) { // Support Re-download - // Support Re-download - int index = __get_empty_request_index(privates->requests); - if (index < 0) { // Busy, No Space in slot - errorcode = DP_ERROR_QUEUE_FULL; - TRACE_SECURE_ERROR("[ERROR][%d][RESTORE][%s]", id, - dp_print_errorcode(errorcode)); - } else { - CLIENT_MUTEX_LOCK(&privates->requests[index].mutex); - dp_request *tmp_request = - dp_request_load_from_log (id, &errorcode); - if (tmp_request != NULL) { - // restore callback info - tmp_request->state_cb = dp_db_get_int_column(id, - DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_STATE_EVENT); - tmp_request->progress_cb = dp_db_get_int_column(id, - DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_PROGRESS_EVENT); - tmp_request->auto_notification = - dp_db_get_int_column(id, DP_DB_TABLE_REQUEST_INFO, - DP_DB_COL_NOTIFICATION_ENABLE); - if (group != NULL) // for send event to client - tmp_request->group = group; - privates->requests[index].request = tmp_request; - request = privates->requests[index].request; - } else { - TRACE_SECURE_ERROR("[ERROR][%d][RESTORE][%s]", id, - dp_print_errorcode(errorcode)); - dp_ipc_send_errorcode(sock, errorcode); - CLIENT_MUTEX_UNLOCK(&privates->requests[index].mutex); - return errorcode; - } - CLIENT_MUTEX_UNLOCK(&privates->requests[index].mutex); - } - } - - // check status - if (errorcode == DP_ERROR_NONE && - (__is_started(request->state) == 0 || - request->state == DP_STATE_COMPLETED)) - errorcode = DP_ERROR_INVALID_STATE; - - if (errorcode == DP_ERROR_NONE) { - - dp_state_type state = DP_STATE_QUEUED; - if (dp_db_set_column(id, DP_DB_TABLE_LOG, - DP_DB_COL_STATE, DP_DB_COL_TYPE_INT, &state) < 0) { - errorcode = DP_ERROR_OUT_OF_MEMORY; - } else { - if (group != NULL) - group->queued_count++; - request->start_time = (int)time(NULL); - request->pause_time = 0; - request->stop_time = 0; - request->state = state; - request->error = DP_ERROR_NONE; - dp_db_update_date(id, DP_DB_TABLE_LOG, DP_DB_COL_ACCESS_TIME); - } - - } - - dp_ipc_send_errorcode(sock, errorcode); - if (errorcode != DP_ERROR_NONE) { - TRACE_SECURE_ERROR("[ERROR][%d][START][%s]", id, - dp_print_errorcode(errorcode)); - } - return errorcode; -} - -// in url-download, make 3 connection before send CREATE command. -// after accepting, fill info to pacakgelist. -// 3 socket per 1 package ( info/request/progress ) -void *dp_thread_requests_manager(void *arg) -{ - fd_set rset, eset, listen_fdset, except_fdset; - struct timeval timeout; // for timeout of select - long flexible_timeout = DP_CARE_CLIENT_MAX_INTERVAL; - int listenfd, clientfd, maxfd; - socklen_t clientlen; - struct sockaddr_un clientaddr; - dp_credential credential; - unsigned i, is_timeout; - int prev_timeout = 0; - dp_error_type errorcode = DP_ERROR_NONE; - - dp_privates *privates = (dp_privates*)arg; - if (privates == NULL || privates->groups == NULL) { - TRACE_ERROR("[CRITICAL] Invalid Address"); - dp_terminate(SIGTERM); - pthread_exit(NULL); - return 0; - } - - listenfd = privates->listen_fd; - maxfd = listenfd; - - TRACE_DEBUG("Ready to listen [%d][%s]", listenfd, DP_IPC); - - FD_ZERO(&listen_fdset); - FD_ZERO(&except_fdset); - FD_SET(listenfd, &listen_fdset); - FD_SET(listenfd, &except_fdset); - - while (privates != NULL && privates->listen_fd >= 0) { - - // select with timeout - // initialize timeout structure for calling timeout exactly - memset(&timeout, 0x00, sizeof(struct timeval)); - timeout.tv_sec = flexible_timeout; - clientfd = -1; - credential.pid = -1; - credential.uid = -1; - credential.gid = -1; - is_timeout = 1; - - rset = listen_fdset; - eset = except_fdset; - - if (select((maxfd + 1), &rset, 0, &eset, &timeout) < 0) { - TRACE_STRERROR("[CRITICAL] select"); - break; - } - - if (privates == NULL || privates->listen_fd < 0) { - TRACE_DEBUG("Terminate Thread"); - break; - } - - if (FD_ISSET(listenfd, &eset) > 0) { - TRACE_ERROR("[CRITICAL] listenfd Exception of socket"); - break; - } else if (FD_ISSET(listenfd, &rset) > 0) { - // new client(package) called url_download_create API. - // update g_dp_request_max_fd & g_dp_info_max_fd - // add to socket to g_dp_request_rset & g_dp_info_rset - - is_timeout = 0; - - // Anyway accept client. - clientlen = sizeof(clientaddr); - clientfd = accept(listenfd, - (struct sockaddr*)&clientaddr, - &clientlen); - if (clientfd < 0) { - TRACE_ERROR("[CRITICAL] accept provider was crashed ?"); - // provider need the time of refresh. - break; - } - - dp_command_type connect_cmd = DP_CMD_NONE; - if (dp_ipc_read_custom_type(clientfd, - &connect_cmd, sizeof(dp_command_type)) < 0) { - TRACE_ERROR("[CRITICAL] CAPI not support CONNECT CMD"); - close(clientfd); - continue; - } - if (connect_cmd <= 0) { - TRACE_ERROR("[CRITICAL] peer terminate ?"); - close(clientfd); - continue; - } - -#ifdef SO_PEERCRED - // getting the info of client - socklen_t cr_len = sizeof(credential); - if (getsockopt(clientfd, SOL_SOCKET, SO_PEERCRED, - &credential, &cr_len) == 0) { - TRACE_DEBUG - ("credential : pid=%d, uid=%d, gid=%d", - credential.pid, credential.uid, credential.gid); - } -#else // In case of not supported SO_PEERCRED - int client_pid = 0; - if (dp_ipc_read_custom_type(clientfd, - &client_pid, sizeof(int)) < 0) { - TRACE_ERROR("[CRITICAL] not support SO_PEERCRED"); - close(clientfd); - continue; - } - if (client_pid <= 0) { - TRACE_ERROR("[CRITICAL] not support SO_PEERCRED"); - close(clientfd); - continue; - } - credential.pid = client_pid; - if (dp_ipc_read_custom_type(clientfd, - &credential.uid, sizeof(int)) < 0) { - TRACE_ERROR("[CRITICAL] not support SO_PEERCRED"); - close(clientfd); - continue; - } - if (dp_ipc_read_custom_type(clientfd, - &credential.gid, sizeof(int)) < 0) { - TRACE_ERROR("[CRITICAL] not support SO_PEERCRED"); - close(clientfd); - continue; - } -#endif - - switch(connect_cmd) { - case DP_CMD_SET_COMMAND_SOCKET: - if (__dp_set_group_new(clientfd, privates->groups, - credential, &listen_fdset) == 0) { - FD_SET(clientfd, &listen_fdset); - if (clientfd > maxfd) - maxfd = clientfd; - } else { - close(clientfd); - } - break; - case DP_CMD_SET_EVENT_SOCKET: - if (__dp_set_group_event_sock(clientfd, - privates->groups, credential) < 0) - close(clientfd); - break; - default: - TRACE_ERROR("[CRITICAL] Bad access,ignore this client"); - close(clientfd); - break; - } - } // New Connection - - // listen cmd_socket of all group - for (i = 0; i < DP_MAX_GROUP; i++) { - dp_client_group *group = privates->groups[i].group; - if (group == NULL || group->cmd_socket < 0) - continue; - const int sock = group->cmd_socket; - int time_of_job = (int)time(NULL); - if (FD_ISSET(sock, &rset) > 0) { - int index = -1; - dp_command command; - - is_timeout = 0; - command.cmd = DP_CMD_NONE; - command.id = -1; - - if (dp_ipc_read_custom_type(sock, &command, - sizeof(dp_command)) < 0) { - TRACE_STRERROR("failed to read cmd"); - //Resource temporarily unavailable - continue; - } - - if (command.cmd == 0 || command.cmd >= DP_CMD_LAST_SECT) { // Client meet some Error. - TRACE_SECURE_INFO("[Closed Peer] pkg:%s sock:%d slot:%d", - group->pkgname, sock, i); - // check all request included to this group - FD_CLR(sock, &listen_fdset); - __clear_group(privates, group); - privates->groups[i].group = NULL; - continue; - } - - // Echo .client can check whether provider is busy - if (command.cmd == DP_CMD_ECHO) { - // provider can clear read buffer here - TRACE_DEBUG("[ECHO] sock:%d", sock); - if (dp_ipc_send_errorcode(sock, - DP_ERROR_NONE) < 0) { - // disconnect this group, bad client - TRACE_ERROR("[ECHO] IO ERROR CLEAN sock:%d", sock); - FD_CLR(sock, &listen_fdset); - __clear_group(privates, group); - privates->groups[i].group = NULL; - } - continue; - } - - if (command.cmd == DP_CMD_CREATE) { - TRACE_SECURE_INFO("[CREATE] id:%d sock:%d pid:%d gindex:%d pkg:%s", - command.id, sock, - group->credential.pid, i, group->pkgname); - // search empty slot in privates->requests - index = - __get_empty_request_index(privates->requests); - if (index < 0) { - TRACE_ERROR("[CHECK] [DP_ERROR_QUEUE_FULL]"); - // Busy, No Space in slot - dp_ipc_send_errorcode(sock, DP_ERROR_QUEUE_FULL); - } else { - errorcode = DP_ERROR_NONE; - CLIENT_MUTEX_LOCK(&privates->requests[index].mutex); - errorcode = dp_request_create(command.id, group, - &privates->requests[index].request); - dp_ipc_send_errorcode(sock, errorcode); - if (errorcode == DP_ERROR_NONE) { - dp_ipc_send_custom_type(sock, - &privates->requests[index].request->id, - sizeof(int)); - TRACE_DEBUG("[CREATE] GOOD id:%d slot:%d time:%d", - privates->requests[index].request->id, - index, ((int)time(NULL) - time_of_job)); - } else { - TRACE_ERROR("[ERROR][%s]", - dp_print_errorcode(errorcode)); - } - CLIENT_MUTEX_UNLOCK(&privates->requests[index].mutex); - } - continue; - } - - // below commands must need ID - // check exception before searching slots. - if (command.id < 0) { - TRACE_ERROR("[CHECK PROTOCOL] ID should not be -1"); - dp_ipc_send_errorcode(sock, - DP_ERROR_INVALID_PARAMETER); - // disconnect this group, bad client - FD_CLR(sock, &listen_fdset); - __clear_group(privates, group); - privates->groups[i].group = NULL; - continue; - } - - // search id in requests slot - index = __get_same_request_index(privates->requests, - command.id); - - dp_request_slots *request_slot = NULL; - unsigned is_loaded = 0; - errorcode = DP_ERROR_NONE; - - if (index >= 0) { - CLIENT_MUTEX_LOCK(&privates->requests[index].mutex); - if (privates->requests[index].request != NULL) - is_loaded = 1; - else - CLIENT_MUTEX_UNLOCK(&privates->requests[index].mutex); - } - - errorcode = DP_ERROR_UNKNOWN; // check matched command - - // divide on memory or from DB - if (is_loaded == 1 && index >= 0) { // already locked - - TRACE_SECURE_INFO("[%s] id:%d sock:%d pid:%d gindex:%d slot:%d pkg:%s", - __print_command(command.cmd), command.id, sock, - group->credential.pid, i, index, group->pkgname); - - request_slot = &privates->requests[index]; - - // auth by pkgname - if (__cmp_string(group->pkgname, request_slot->request->packagename) < 0) { - TRACE_SECURE_ERROR("[ERROR][%d] Auth [%s]/[%s]", - command.id, group->pkgname, request_slot->request->packagename); - TRACE_ERROR("[ERROR][%d][INVALID_PARAMETER]", command.id); - dp_ipc_send_errorcode(sock, DP_ERROR_INVALID_PARAMETER); - CLIENT_MUTEX_UNLOCK(&request_slot->mutex); - continue; - } - - // if no group, update group. - if (request_slot->request->group == NULL) - request_slot->request->group = group; - - if (command.cmd == DP_CMD_START) - errorcode = __do_dp_start_command(sock, command.id, privates, group, request_slot->request); - else if (command.cmd > DP_CMD_SET_SECT && command.cmd < DP_CMD_LAST_SECT) - errorcode = __dp_do_set_command(sock, &command, request_slot->request); - else if (command.cmd > DP_CMD_GET_SECT && command.cmd < DP_CMD_SET_SECT) - errorcode = __dp_do_get_command(sock, &command, request_slot->request); - else if (command.cmd > DP_CMD_ACTION_SECT && command.cmd < DP_CMD_GET_SECT) - errorcode = __dp_do_action_command(sock, &command, request_slot->request); - - CLIENT_MUTEX_UNLOCK(&request_slot->mutex); - - if (command.cmd == DP_CMD_START && errorcode == DP_ERROR_NONE) { - //send signal to queue thread - dp_thread_queue_manager_wake_up(); - } - if (command.cmd == DP_CMD_FREE) {// enter after unlock - dp_request_slot_free(request_slot); - errorcode = DP_ERROR_NONE; - } - - } else { // not found on the slots - - TRACE_SECURE_INFO("[%s] id:%d sock:%d pid:%d gindex:%d slot:no pkg:%s", - __print_command(command.cmd), command.id, sock, - group->credential.pid, i, group->pkgname); - - int check_id = dp_db_get_int_column(command.id, - DP_DB_TABLE_LOG, DP_DB_COL_ID); - if (check_id < 0 || check_id != command.id) { - errorcode = DP_ERROR_ID_NOT_FOUND; - TRACE_ERROR("[ERROR][%d][ID_NOT_FOUND]", command.id); - dp_ipc_send_errorcode(sock, DP_ERROR_ID_NOT_FOUND); - continue; - } - // auth by pkgname - char *auth_pkgname = dp_db_get_text_column(command.id, - DP_DB_TABLE_LOG, DP_DB_COL_PACKAGENAME); - if (auth_pkgname == NULL) { - TRACE_ERROR("[ERROR][%d][ID_NOT_FOUND]", command.id); - dp_ipc_send_errorcode(sock, DP_ERROR_ID_NOT_FOUND); - continue; - } - // auth by pkgname - if (__cmp_string(group->pkgname, auth_pkgname) < 0) { - TRACE_SECURE_ERROR("[ERROR][%d] Auth [%s]/[%s]", - command.id, group->pkgname, auth_pkgname); - TRACE_ERROR("[ERROR][%d][INVALID_PARAMETER]", command.id); - dp_ipc_send_errorcode(sock, DP_ERROR_INVALID_PARAMETER); - free(auth_pkgname); - continue; - } - free(auth_pkgname); - - if (command.cmd == DP_CMD_START) - errorcode = __do_dp_start_command(sock, command.id, privates, group, NULL); - else if (command.cmd == DP_CMD_FREE) - errorcode = DP_ERROR_NONE; - else if (command.cmd > DP_CMD_SET_SECT && command.cmd < DP_CMD_LAST_SECT) - errorcode = __dp_do_set_command(sock, &command, NULL); - else if (command.cmd > DP_CMD_GET_SECT && command.cmd < DP_CMD_SET_SECT) - errorcode = __dp_do_get_command(sock, &command, NULL); - else if (command.cmd > DP_CMD_ACTION_SECT && command.cmd < DP_CMD_GET_SECT) - errorcode = __dp_do_action_command(sock, &command, NULL); - - if (command.cmd == DP_CMD_START && errorcode == DP_ERROR_NONE) { - //send signal to queue thread - dp_thread_queue_manager_wake_up(); - } - } - - if (errorcode == DP_ERROR_IO_ERROR) { - TRACE_ERROR("[IO_ERROR][%d] slot:%d pid:%d", - command.id, i, - privates->groups[i].group->credential.pid); - FD_CLR(sock, &listen_fdset); - __clear_group(privates, group); - privates->groups[i].group = NULL; - continue; - } - if (errorcode == DP_ERROR_UNKNOWN) { // UnKnown Command - TRACE_INFO("[UNKNOWN][%d] slot:%d pid:%d", - command.id, i, - privates->groups[i].group->credential.pid); - dp_ipc_send_errorcode(sock, DP_ERROR_IO_ERROR); - // disconnect this group, bad client - FD_CLR(sock, &listen_fdset); - __clear_group(privates, group); - privates->groups[i].group = NULL; - } - - } // FD_ISSET - } // DP_MAX_GROUP - - // timeout - if (is_timeout == 1) { - int now_timeout = (int)time(NULL); - TRACE_DEBUG("[TIMEOUT] prev %ld, now %ld, setted %ld sec", - prev_timeout, now_timeout, flexible_timeout); - if (prev_timeout == 0) { - prev_timeout = now_timeout; - } else if (now_timeout < prev_timeout || - (now_timeout - prev_timeout) > flexible_timeout) { - TRACE_ERROR("[WARN] check system date prev[%ld]now[%ld]", - prev_timeout, now_timeout); - } else { - if ((now_timeout - prev_timeout) < - DP_CARE_CLIENT_MIN_INTERVAL) { - // this is error. - // terminate Process - TRACE_STRERROR - ("[CRITICAL] Sock exception prev[%ld]now[%ld][%ld]", - prev_timeout, now_timeout, flexible_timeout); - break; - } - } - - // get 48hour old request from log DB - // clear old request - dp_db_limit_rows(DP_LOG_DB_LIMIT_ROWS); - int old_request_count = dp_db_get_count_by_limit_time(); - if (old_request_count > 0) { - if (old_request_count > DP_LOG_DB_CLEAR_LIMIT_ONE_TIME) - old_request_count = DP_LOG_DB_CLEAR_LIMIT_ONE_TIME; - - TRACE_DEBUG - ("[CLEAR] [%d] old reqeusts", old_request_count); - - dp_request_slots *old_requests = - dp_request_slots_new(old_request_count); - if (old_requests != NULL) { - int list_count = dp_db_get_list_by_limit_time - (old_requests, old_request_count); - for (i = 0; i < list_count; i++) { - // search on slots by ID. - int index = __get_same_request_index - (privates->requests, - old_requests[i].request->id); - if (index >= 0) { - CLIENT_MUTEX_LOCK(&privates->requests[index].mutex); - dp_request *request = - privates->requests[index].request; - // if downloading..remain it. - if (request == NULL || __is_downloading(request->state) == 0) { - CLIENT_MUTEX_UNLOCK(&privates->requests[index].mutex); - continue; - } - CLIENT_MUTEX_UNLOCK(&privates->requests[index].mutex); - TRACE_DEBUG("[CLEAR][%d] 48 hour state:%s", - request->id, - dp_print_state(request->state)); - // unload from slots ( memory ) - dp_request_slot_free(&privates->requests[index]); - } - // remove tmp file regardless - __dp_remove_tmpfile - (old_requests[i].request->id, - old_requests[i].request); - // remove from DB - dp_db_remove_all(old_requests[i].request->id); - } - dp_request_slots_free(old_requests, old_request_count); - } - } - - // clean slots - int ready_requests = 0; - for (i = 0; i < DP_MAX_REQUEST; i++) { - CLIENT_MUTEX_LOCK(&privates->requests[i].mutex); - if (privates->requests[i].request == NULL) { - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - continue; - } - dp_request *request = privates->requests[i].request; - - // If downloading is too slow ? how to deal this request? - // can limit too slot download using starttime.(48 hours) - if (__is_downloading(request->state) == 0) { - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - continue; - } - - // paused & agent_id not exist.... unload from memory. - if (request->state == DP_STATE_PAUSED && - dp_is_alive_download(request->agent_id) == 0) { - TRACE_DEBUG("[FREE][%d] dead agent-id(%d) state:%s", - request->id, request->agent_id, - dp_print_state(request->state)); - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - dp_request_slot_free(&privates->requests[i]); - continue; - } - - // client should call START command in 60 sec - // unload from memory - if (request->start_time <= 0 && - (now_timeout - request->create_time) > - DP_CARE_CLIENT_MAX_INTERVAL) { - int download_id = request->id; - dp_state_type state = DP_STATE_FAILED; - errorcode = DP_ERROR_RESPONSE_TIMEOUT; - TRACE_DEBUG - ("[FREE][%d] start in %d sec state:%s last:%ld", - download_id, DP_CARE_CLIENT_MAX_INTERVAL, - dp_print_state(request->state), - request->start_time); - if (request->group != NULL && - request->state_cb == 1 && - request->group->event_socket >= 0) - dp_ipc_send_event(request->group->event_socket, - download_id, state, errorcode, 0); - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - dp_request_slot_free(&privates->requests[i]); - // no problem although updating is failed. - if (dp_db_request_update_status(download_id, state, errorcode) < 0) { - TRACE_ERROR("[fail][%d][sql] set state:%s error:%s", - download_id, dp_print_state(state), dp_print_errorcode(errorcode)); - } - continue; - } - - // stopped by ipchanged. decide auto resume - if (request->stop_time <= 0 && - request->state == DP_STATE_FAILED && - request->error == DP_ERROR_CONNECTION_FAILED) { - if (dp_get_network_connection_instant_status() != - DP_NETWORK_TYPE_OFF && - request->ip_changed == 1) { - TRACE_DEBUG("[RESUME][%d] will be queued", - request->id); - request->state = DP_STATE_QUEUED; - request->error = DP_ERROR_NONE; - ready_requests++; - } else { - dp_request_state_response(request); - } - } - - // client should call DESTROY command in MAX_INTERVAL sec after finished - if (request->stop_time > 0 && - (now_timeout - request->stop_time) > - DP_CARE_CLIENT_MAX_INTERVAL) { - // check state again. stop_time means it's stopped - if (__is_stopped(request->state) == 0) { - TRACE_DEBUG - ("[FREE][%d] by timeout state:%s stop:%ld", - request->id, - dp_print_state(request->state), - request->stop_time); - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - dp_request_slot_free(&privates->requests[i]); - continue; - } - } - - // check after clear - if (request->state == DP_STATE_QUEUED) - ready_requests++; - - CLIENT_MUTEX_UNLOCK(&privates->requests[i].mutex); - } - - if (ready_requests > 0) { - //send signal to queue thread will check queue. - dp_thread_queue_manager_wake_up(); - } else { - // if no request & timeout is bigger than 60 sec - // terminate by self. - if ((now_timeout - prev_timeout) >= flexible_timeout && - dp_get_request_count(privates->requests) <= 0) { - TRACE_DEBUG("No Request. Terminate Daemon"); - break; - } - } - prev_timeout = now_timeout; - } else { - prev_timeout = 0; - } - } - TRACE_DEBUG("terminate main thread ..."); - dp_terminate(SIGTERM); - pthread_exit(NULL); - return 0; -} diff --git a/provider/download-provider-utils.c b/provider/download-provider-utils.c new file mode 100644 index 0000000..a1fb736 --- /dev/null +++ b/provider/download-provider-utils.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013 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 <string.h> + +#include <sys/stat.h> +#include <sys/types.h> + +#include <sys/time.h> +#include <sys/statfs.h> +#include <unistd.h> + +#include "download-provider-log.h" + +char *dp_strdup(char *src) +{ + char *dest = NULL; + size_t src_len = 0; + + if (src == NULL) { + TRACE_ERROR("[CHECK PARAM]"); + return NULL; + } + + src_len = strlen(src); + if (src_len <= 0) { + TRACE_ERROR("[CHECK PARAM] len[%d]", src_len); + return NULL; + } + + dest = (char *)calloc(src_len + 1, sizeof(char)); + if (dest == NULL) { + TRACE_STRERROR("[CHECK] allocation"); + return NULL; + } + memcpy(dest, src, src_len * sizeof(char)); + dest[src_len] = '\0'; + + return dest; +} + +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; +} + +long dp_get_file_modified_time(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) + return file_state.st_mtime; + return -1; +} + +int dp_remove_file(const char *file_path) +{ + if ((file_path != NULL && strlen(file_path) > 0) && + dp_is_file_exist(file_path) == 0) { + if (unlink(file_path) != 0) { + TRACE_STRERROR("failed to remove file"); + return -1; + } + return 0; + } + return -1; +} diff --git a/provider/include/download-provider-client-manager.h b/provider/include/download-provider-client-manager.h new file mode 100644 index 0000000..0bb02ec --- /dev/null +++ b/provider/include/download-provider-client-manager.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 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. + */ + +#ifndef DOWNLOAD_PROVIDER_CLIENT_MANAGER_H +#define DOWNLOAD_PROVIDER_CLIENT_MANAGER_H + +#include <download-provider.h> +#include <download-provider-client.h> + +typedef struct { + dp_credential credential; + pthread_mutex_t mutex; // lock whenever access client variable + pthread_t thread; + char *pkgname; + dp_client_fmt client; +} dp_client_slots_fmt; + +int dp_client_slot_free(dp_client_slots_fmt *slot); +void dp_broadcast_signal(); +char *dp_db_get_client_smack_label(const char *pkgname); + +#endif diff --git a/provider/include/download-provider-client.h b/provider/include/download-provider-client.h new file mode 100644 index 0000000..6ce8d14 --- /dev/null +++ b/provider/include/download-provider-client.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013 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. + */ + +#ifndef DOWNLOAD_PROVIDER_CLIENT_H +#define DOWNLOAD_PROVIDER_CLIENT_H + +#include <pthread.h> +#include <download-provider.h> + +typedef struct { + int state; // downloading state, to prevent the crash, placed at the head of structure. + int id; // ID created in create request in requests thread. + int agent_id; + int error; + int network_type; + int access_time; + unsigned state_cb; // set : 1 unset : 0 + unsigned progress_cb; // set : 1 unset : 0 + unsigned startcount; + size_t progress_lasttime; + unsigned long long received_size; // progress + unsigned long long file_size; + dp_content_type content_type; + int noti_type; + int noti_priv_id; + void *next; +} dp_request_fmt; + +typedef struct { + int channel; // ipc , if negative means dummy client + int notify; // event + int access_time; + void *dbhandle; + dp_request_fmt *requests; +} dp_client_fmt; + +void *dp_client_request_thread(void *arg); +char *dp_print_state(int state); +char *dp_print_errorcode(int errorcode); +char *dp_print_section(short section); +char *dp_print_property(unsigned property); +void dp_request_create(dp_client_fmt *client, dp_request_fmt *request); +void dp_request_free(dp_request_fmt *request); +int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp); +void dp_client_clear_requests(void *slotp); + +#endif diff --git a/provider/include/download-provider-config.h b/provider/include/download-provider-config.h index 96862ec..5ab6bce 100755 --- a/provider/include/download-provider-config.h +++ b/provider/include/download-provider-config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2013 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. @@ -14,33 +14,26 @@ * limitations under the License. */ -#ifndef DOWNLOAD_PROVIDER2_CONFIG_H -#define DOWNLOAD_PROVIDER2_CONFIG_H +#ifndef DOWNLOAD_PROVIDER_CONFIG_H +#define DOWNLOAD_PROVIDER_CONFIG_H #include <download-provider.h> -#include <download-provider-slots.h> -#include <net_connection.h> +// client-manager +#define DP_MAX_CLIENTS 32 // the maximun number of slots +#define DP_CARE_CLIENT_MANAGER_INTERVAL 120 +#define DP_CARE_CLIENT_REQUEST_INTERVAL 120 +#define DP_CARE_CLIENT_CLEAR_INTERVAL 200 -#define DP_LOCK_PID "/tmp/download-provider.lock" - -#define DP_CARE_CLIENT_MIN_INTERVAL 5 -#define DP_CARE_CLIENT_MAX_INTERVAL 120 - -// check this value should be lower than DP_MAX_REQUEST -#define DP_MAX_DOWNLOAD_AT_ONCE 50 +// database +#define DP_CARE_CLIENT_INFO_PERIOD 48 // hour +// each client thread +#define DP_MAX_REQUEST MAX_DOWNLOAD_HANDLE #define DP_LOG_DB_LIMIT_ROWS 1000 #define DP_LOG_DB_CLEAR_LIMIT_ONE_TIME 100 -// Share the structure for all threads -typedef struct { - int listen_fd; - int is_connected_wifi_direct; - connection_h connection; - dp_network_type network_status; - dp_group_slots *groups; - dp_request_slots *requests; -} dp_privates; +// queue-manager +#define DP_MAX_DOWNLOAD_AT_ONCE 50 #endif diff --git a/provider/include/download-provider-db-defs.h b/provider/include/download-provider-db-defs.h new file mode 100644 index 0000000..6fd1a46 --- /dev/null +++ b/provider/include/download-provider-db-defs.h @@ -0,0 +1,157 @@ +/* + * 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. + */ + +#ifndef DOWNLOAD_PROVIDER_DB_DEFS_H +#define DOWNLOAD_PROVIDER_DB_DEFS_H + +#define DP_DBFILE_CLIENTS ".download-provider-clients" + +// provider have a groups database file. +#define DP_TABLE_CLIENTS "clients" +// each client has a database file with below tables. file is named as pkgname. +#define DP_TABLE_LOGGING "logging" +#define DP_TABLE_REQUEST "request" +#define DP_TABLE_DOWNLOAD "download" +#define DP_TABLE_HEADERS "header" +#define DP_TABLE_NOTIFICATION "notification" + +// common +#define DP_DB_COL_ROW_ID "ROWID" +#define DP_DB_COL_ID "id" +#define DP_DB_COL_CREATE_TIME "createtime" +#define DP_DB_COL_ACCESS_TIME "accesstime" + +// clients table +#define DP_DB_COL_SMACK_LABEL "smack_label" +#define DP_DB_COL_PACKAGE "package" +#define DP_DB_COL_UID "uid" +#define DP_DB_COL_GID "gid" +#define DP_DB_COL_REQUEST_COUNT "requests" + +// logging table +#define DP_DB_COL_STATE "state" +#define DP_DB_COL_ERRORCODE "errorcode" +#define DP_DB_COL_AUTO_DOWNLOAD "auto_download" +#define DP_DB_COL_STARTCOUNT "startcount" + +// request table +#define DP_DB_COL_URL "url" +#define DP_DB_COL_DESTINATION "destination" +#define DP_DB_COL_FILENAME "filename" +#define DP_DB_COL_STATE_EVENT "state_event" +#define DP_DB_COL_PROGRESS_EVENT "progress_event" +#define DP_DB_COL_NETWORK_TYPE "network_type" +#define DP_DB_COL_NETWORK_BONDING "network_bonding" +#define DP_DB_COL_TEMP_FILE_PATH "temp_file_path" + +// download table +#define DP_DB_COL_SAVED_PATH "saved_path" +#define DP_DB_COL_TMP_SAVED_PATH "tmp_saved_path" +#define DP_DB_COL_MIMETYPE "mimetype" +#define DP_DB_COL_CONTENT_NAME "content_name" +#define DP_DB_COL_ETAG "etag" +#define DP_DB_COL_CONTENT_SIZE "content_size" +#define DP_DB_COL_HTTP_STATUS "http_status" + +// notification table +#define DP_DB_COL_NOTI_TYPE "type" +#define DP_DB_COL_NOTI_SUBJECT "subject" +#define DP_DB_COL_NOTI_DESCRIPTION "description" +#define DP_DB_COL_NOTI_PRIV_ID "priv_id" +#define DP_DB_COL_NOTI_RAW_ONGOING "raw_ongoing" +#define DP_DB_COL_NOTI_RAW_COMPLETE "raw_completed" +#define DP_DB_COL_NOTI_RAW_FAIL "raw_failed" + +// http headers table +#define DP_DB_COL_HEADER_FIELD "header_field" +#define DP_DB_COL_HEADER_DATA "header_data" + + + +// when a client is accepted, add +// when disconnected with no request, clear +// if exist, it's possible to be remain some requests +#define DP_SCHEMA_CLIENTS "CREATE TABLE IF NOT EXISTS clients(\ +id INTEGER UNIQUE PRIMARY KEY,\ +package TEXT UNIQUE NOT NULL,\ +smack_label TEXT DEFAULT NULL,\ +uid INTEGER DEFAULT 0,\ +gid INTEGER DEFAULT 0,\ +requests INTEGER DEFAULT 0,\ +createtime DATE,\ +accesstime DATE\ +)" + +// limitation : 1000 rows, 48 hours standard by createtime +#define DP_SCHEMA_LOGGING "CREATE TABLE IF NOT EXISTS logging(\ +id INTEGER UNIQUE PRIMARY KEY DESC NOT NULL,\ +state INTEGER DEFAULT 0,\ +errorcode INTEGER DEFAULT 0,\ +auto_download BOOLEAN DEFAULT 0,\ +startcount INTEGER DEFAULT 0,\ +createtime DATE,\ +accesstime DATE\ +)" + +#define DP_SCHEMA_REQUEST "CREATE TABLE IF NOT EXISTS request(\ +id INTEGER UNIQUE PRIMARY KEY,\ +state_event BOOLEAN DEFAULT 0,\ +progress_event BOOLEAN DEFAULT 0,\ +network_type TINYINT DEFAULT 3,\ +filename TEXT DEFAULT NULL,\ +destination TEXT DEFAULT NULL,\ +url TEXT DEFAULT NULL,\ +temp_file_path TEXT DEFAULT NULL,\ +network_bonding BOOLEAN DEFAULT 0,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_DOWNLOAD "CREATE TABLE IF NOT EXISTS download(\ +id INTEGER UNIQUE PRIMARY KEY,\ +http_status INTEGER DEFAULT 0,\ +content_size UNSIGNED BIG INT DEFAULT 0,\ +mimetype VARCHAR(64) DEFAULT NULL,\ +content_name TEXT DEFAULT NULL,\ +saved_path TEXT DEFAULT NULL,\ +tmp_saved_path TEXT DEFAULT NULL,\ +etag TEXT DEFAULT NULL,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_NOTIFICATION "CREATE TABLE IF NOT EXISTS notification(\ +id INTEGER UNIQUE PRIMARY KEY,\ +subject TEXT DEFAULT NULL,\ +description TEXT DEFAULT NULL,\ +type INTEGER DEFAULT 0,\ +priv_id INTEGER DEFAULT -1,\ +raw_completed BLOB DEFAULT NULL,\ +raw_failed BLOB DEFAULT NULL,\ +raw_ongoing BLOB DEFAULT NULL,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_HEADER "CREATE TABLE IF NOT EXISTS header(\ +id INTEGER NOT NULL,\ +header_field TEXT DEFAULT NULL,\ +header_data TEXT DEFAULT NULL,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_LOGGING_INDEX "CREATE UNIQUE INDEX IF NOT EXISTS requests_index ON logging (id, state, errorcode, createtime, accesstime)" + + + +#endif diff --git a/provider/include/download-provider-db.h b/provider/include/download-provider-db.h index 24a7d27..6f3a938 100755 --- a/provider/include/download-provider-db.h +++ b/provider/include/download-provider-db.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2013 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. @@ -14,230 +14,42 @@ * limitations under the License. */ -#ifndef DOWNLOAD_PROVIDER2_DB_H -#define DOWNLOAD_PROVIDER2_DB_H +#ifndef DOWNLOAD_PROVIDER_DB_H +#define DOWNLOAD_PROVIDER_DB_H + +int dp_db_check_connection(void *handle); +int dp_db_open_client_manager(void **handle); +int dp_db_open_client(void **handle, char *pkgname); +int dp_db_open_client_v2(void **handle, char *pkgname); +int dp_db_remove_database(char *pkgname, long now_time, long diff_time); +int dp_db_get_ids(void *handle, const char *table, char *idcolumn, int *ids, const char *where, const int limit, char *ordercolumn, char *ordering, int *error); +int dp_db_get_crashed_ids(void *handle, const char *table, int *ids, const int limit, int *error); +void dp_db_close(void *handle); +void dp_db_reset(void *stmt); +void dp_db_finalize(void *stmt); +int dp_db_get_errorcode(void *handle); + +int dp_db_check_duplicated_int(void *handle, const char *table, const char *column, const int value, int *error); +int dp_db_check_duplicated_string(void *handle, const int id, const char *table, const char *column, const int is_like, const char *value, int *error); +int dp_db_update_client_info(void *handle, const char *pkgname, const char *smack, const int uid, const int gid, int *error); +int dp_db_get_client_property_string(void *handle, const char *pkgname, const char *column, unsigned char **value, unsigned *length, int *error); +int dp_db_new_logging(void *handle, const int id, const int state, const int errorvalue, int *error); +int dp_db_update_logging(void *handle, const int id, const int state, const int errorvalue, int *error); +int dp_db_replace_property(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned length, const unsigned valuetype, int *error); +int dp_db_get_property_string(void *handle, const int id, const char *table, const char *column, unsigned char **value, unsigned *length, int *error); +int dp_db_get_property_int(void *handle, const int id, const char *table, const char *column, void *value, int *error); +int dp_db_unset_property_string(void *handle, const int id, const char *table, const char *column, int *error); +int dp_db_delete(void *handle, const int id, const char *table, int *error); + + +int dp_db_new_header(void *handle, const int id, const char *field, const char *value, int *error); +int dp_db_update_header(void *handle, const int id, const char *field, const char *value, int *error); +int dp_db_get_header_value(void *handle, const int id, const char *field, unsigned char **value, unsigned *length, int *error); +int dp_db_cond_delete(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned valuetype, int *error); +int dp_db_get_cond_ids(void *handle, const char *table, const char *getcolumn, const char *column, const int value, int *ids, const int limit, int *error); +int dp_db_get_cond_string(void *handle, const char *table, char *wherecolumn, const int wherevalue, const char *getcolumn, unsigned char **value, unsigned *length, int *error); +int dp_db_limit_rows(void *handle, const char *table, int limit, int *error); +int dp_db_limit_time(void *handle, const char *table, int hours, int *error); +int dp_db_get_http_headers_list(void *handle, int id, char **headers, int *error); -#include "download-provider-config.h" -#include "download-provider-slots.h" - -/* - * Memory ( sync with logging ) : id, state, errorcode, startcount, packagename - * DB TABLES - * logging : id, state, errorcode, startcount, createtime, accesstime, packagename - * requestinfo : id, auto_download, network_type, filename, destination, url - * downloadinfo : id, http_status, content_size, mimetype, contentname, saved_path, tmp_saved_path, etag - * httpheaders : id, header_field, header_data - * notification : id, noti_enable, extra_key, extra_data - */ -/* -CREATE TABLE IF NOT EXISTS groups -( - id INTEGER UNIQUE PRIMARY KEY, - uid INTEGER DEFAULT 0, - gid INTEGER DEFAULT 0, - extra_int INTEGER DEFAULT 0, - packagename TEXT DEFAULT NULL, - smack_label TEXT DEFAULT NULL, - extra TEXT DEFAULT NULL, - date_first_connected DATE, - date_last_connected DATE -); - -CREATE TABLE logging -( - id INTEGER UNIQUE PRIMARY KEY, - state INTEGER DEFAULT 0, - errorcode INTEGER DEFAULT 0, - startcount INTEGER DEFAULT 0, - packagename TEXT DEFAULT NULL, - createtime DATE, - accesstime DATE -); - -CREATE TABLE requestinfo -( - id INTEGER UNIQUE PRIMARY KEY, - auto_download BOOLEAN DEFAULT 0, - state_event BOOLEAN DEFAULT 0, - progress_event BOOLEAN DEFAULT 0, - network_type TINYINT DEFAULT 0, - filename TEXT DEFAULT NULL, - destination TEXT DEFAULT NULL, - url TEXT DEFAULT NULL, - FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE -); - -CREATE TABLE downloadinfo -( - id INTEGER UNIQUE PRIMARY KEY, - http_status INTEGER DEFAULT 0, - content_size UNSIGNED BIG INT DEFAULT 0, - mimetype VARCHAR(64) DEFAULT NULL, - content_name TEXT DEFAULT NULL, - saved_path TEXT DEFAULT NULL, - tmp_saved_path TEXT DEFAULT NULL, - etag TEXT DEFAULT NULL, - FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE -); - -CREATE TABLE httpheaders -( - id INTEGER NOT NULL, - header_field TEXT DEFAULT NULL, - header_data TEXT DEFAULT NULL, - FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE -); - -CREATE TABLE notification -( - id INTEGER UNIQUE PRIMARY KEY, - noti_enable BOOLEAN DEFAULT 0, - extra_key TEXT DEFAULT NULL, - extra_data TEXT DEFAULT NULL, - FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE -); - -CREATE UNIQUE INDEX requests_index ON logging (id, state, errorcode, packagename, createtime, accesstime); -*/ - -#define DP_DB_TABLE_GROUPS "groups" -#define DP_DB_TABLE_LOG "logging" -#define DP_DB_TABLE_REQUEST_INFO "requestinfo" -#define DP_DB_TABLE_DOWNLOAD_INFO "downloadinfo" -#define DP_DB_TABLE_HTTP_HEADERS "httpheaders" -#define DP_DB_TABLE_NOTIFICATION "notification" - -#define DP_DB_COL_ID "id" -#define DP_DB_COL_STATE "state" -#define DP_DB_COL_ERRORCODE "errorcode" -#define DP_DB_COL_NETWORK_TYPE "network_type" -#define DP_DB_COL_HTTP_STATUS "http_status" -#define DP_DB_COL_AUTO_DOWNLOAD "auto_download" -#define DP_DB_COL_STATE_EVENT "state_event" -#define DP_DB_COL_PROGRESS_EVENT "progress_event" -#define DP_DB_COL_CONTENT_SIZE "content_size" -#define DP_DB_COL_CREATE_TIME "createtime" -#define DP_DB_COL_ACCESS_TIME "accesstime" -#define DP_DB_COL_STARTCOUNT "startcount" -#define DP_DB_COL_PACKAGENAME "packagename" -#define DP_DB_COL_DESTINATION "destination" -#define DP_DB_COL_FILENAME "filename" -#define DP_DB_COL_CONTENT_NAME "content_name" -#define DP_DB_COL_MIMETYPE "mimetype" -#define DP_DB_COL_ETAG "etag" -#define DP_DB_COL_SAVED_PATH "saved_path" -#define DP_DB_COL_TMP_SAVED_PATH "tmp_saved_path" -#define DP_DB_COL_URL "url" -#define DP_DB_COL_HEADER_FIELD "header_field" -#define DP_DB_COL_HEADER_DATA "header_data" -#define DP_DB_COL_NOTIFICATION_ENABLE "noti_enable" -#define DP_DB_COL_EXTRA_KEY "extra_key" -#define DP_DB_COL_DISTINCT_EXTRA_KEY "DISTINCT extra_key" -#define DP_DB_COL_EXTRA_VALUE "extra_data" -#define DP_DB_COL_RAW_BUNDLE_ONGOING "raw_bundle_data_ongoing_state" -#define DP_DB_COL_RAW_BUNDLE_COMPLETE "raw_bundle_data_complete_state" -#define DP_DB_COL_RAW_BUNDLE_FAIL "raw_bundle_data_fail_state" -#define DP_DB_COL_TITLE "title" -#define DP_DB_COL_DESCRIPTION "description" -#define DP_DB_COL_NOTI_TYPE "noti_type" - -#define DP_DB_GROUPS_COL_UID "uid" -#define DP_DB_GROUPS_COL_GID "gid" -#define DP_DB_GROUPS_COL_PKG "packagename" -#define DP_DB_GROUPS_COL_SMACK_LABEL "smack_label" - - -typedef enum { - DP_DB_COL_TYPE_NONE = 0, - DP_DB_COL_TYPE_INT = 10, - DP_DB_COL_TYPE_INT64 = 20, - DP_DB_COL_TYPE_TEXT = 30 -} db_column_data_type; - -typedef struct { - char *column; - db_column_data_type type; - int is_like; - void *value; -} db_conds_list_fmt; - -int dp_db_open(); -void dp_db_close(); - -int dp_db_is_full_error(); - -int dp_db_remove_all(int id); -int dp_db_remove(int id, char *table); -int dp_db_insert_column(int id, char *table, char *column, - db_column_data_type datatype, void *value); -int dp_db_insert_blob_column(int id, char *table, char *column, - void *value, unsigned length); -int dp_db_set_column(int id, char *table, char *column, - db_column_data_type datatype, void *value); -int dp_db_set_blob_column(int id, char *table, char *column, - void *value, unsigned length); -int dp_db_replace_column(int id, char *table, char *column, - db_column_data_type datatype, void *value); -int dp_db_replace_blob_column(int id, char *table, char *column, - void *value, unsigned length); -char *dp_db_get_text_column(int id, char *table, char *column); -void *dp_db_get_blob_column(int id, char *table, char *column, int *length); -int dp_db_get_int_column(int id, char *table, char *column); -long long dp_db_get_int64_column(int id, char *table, char *column); -int dp_db_update_date(int id, char *table, char *column); - -// cond : id & cond -int dp_db_cond_set_column(int id, char *table, char *column, - db_column_data_type datatype, void *value, - char *condcolumn, db_column_data_type condtype, - void *condvalue); -char *dp_db_cond_get_text_column(int id, char *table, char *column, - char *condcolumn, db_column_data_type condtype, - void *condvalue); -int dp_db_cond_remove(int id, char *table, - char *condcolumn, db_column_data_type condtype, - void *condvalue); -int dp_db_get_cond_rows_count(int id, char *table, - char *condcolumn, db_column_data_type condtype, - void *condvalue); - -char *dp_db_cond_get_text(char *table, char *column, char *condcolumn, - db_column_data_type condtype, void *condvalue); -int dp_db_cond_get_int(char *table, char *column, char *condcolumn, - db_column_data_type condtype, void *condvalue); - -// Special API for http headers -int dp_db_get_http_headers_list(int id, char **headers); - -// For auto-download in booting time -int dp_db_crashed_list(dp_request_slots *requests, int limit); - -// For loading to memory when no in memory -dp_request *dp_db_load_logging_request(int id); - -// For limitation by 48 hours & 1000 rows -int dp_db_limit_rows(int limit); -int dp_db_get_count_by_limit_time(); -int dp_db_get_list_by_limit_time(dp_request_slots *requests, int limit); - -int dp_db_insert_columns(char *table, int column_count, - db_conds_list_fmt *columns); -int dp_db_update_columns(int id, char *table, int column_count, - db_conds_list_fmt *columns); - -int dp_db_get_conds_rows_count(char *table, char *getcolumn, char *op, - int conds_count, db_conds_list_fmt *conds); - -int dp_db_get_conds_list(char *table, char *getcolumn, - db_column_data_type gettype, void **list, - int rowslimit, int rowsoffset, - char *ordercolumn, char *ordering, - char *op, int conds_count, - db_conds_list_fmt *conds); - -int dp_db_request_new_logging(const int id, const int state, const char *pkgname); -int dp_db_request_update_status(const int id, const int state, const int download_error); -int dp_db_get_state(int id); -int dp_db_request_new_logging(const int id, - const int state, const char *pkgname); #endif diff --git a/provider/include/download-provider-defs.h b/provider/include/download-provider-defs.h deleted file mode 100755 index af166fd..0000000 --- a/provider/include/download-provider-defs.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2013 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. - */ - -#ifndef DOWNLOAD_PROVIDER_DEFS_H -#define DOWNLOAD_PROVIDER_DEFS_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - DP_STATE_NONE = 0, - DP_STATE_READY = DP_STATE_NONE + 5, // created id, set some info. - DP_STATE_QUEUED = DP_STATE_NONE + 10, // request to start - DP_STATE_CONNECTING = DP_STATE_NONE + 15, // try to connect to url - DP_STATE_DOWNLOADING = DP_STATE_NONE + 20, // started - DP_STATE_PAUSE_REQUESTED = DP_STATE_NONE + 25, - DP_STATE_PAUSED = DP_STATE_NONE + 30, // paused actually - DP_STATE_COMPLETED = DP_STATE_NONE + 40, - DP_STATE_CANCELED = DP_STATE_NONE + 45, // stopped with error - DP_STATE_FAILED = DP_STATE_NONE + 50 // failed with error -} dp_state_type; - -typedef enum { - DP_ERROR_NONE = 10, - DP_ERROR_INVALID_PARAMETER = DP_ERROR_NONE + 1, - DP_ERROR_OUT_OF_MEMORY = DP_ERROR_NONE + 2, - DP_ERROR_IO_ERROR = DP_ERROR_NONE + 3, - DP_ERROR_NETWORK_UNREACHABLE = DP_ERROR_NONE + 4, - DP_ERROR_CONNECTION_TIMED_OUT = DP_ERROR_NONE + 5, - DP_ERROR_NO_SPACE = DP_ERROR_NONE + 6, - DP_ERROR_FIELD_NOT_FOUND = DP_ERROR_NONE + 7, - DP_ERROR_INVALID_STATE = DP_ERROR_NONE + 8, - DP_ERROR_CONNECTION_FAILED = DP_ERROR_NONE + 9, - DP_ERROR_INVALID_URL = DP_ERROR_NONE + 10, - DP_ERROR_INVALID_DESTINATION = DP_ERROR_NONE + 11, - DP_ERROR_QUEUE_FULL = DP_ERROR_NONE + 12, - DP_ERROR_ALREADY_COMPLETED = DP_ERROR_NONE + 13, - DP_ERROR_FILE_ALREADY_EXISTS = DP_ERROR_NONE + 14, - DP_ERROR_TOO_MANY_DOWNLOADS = DP_ERROR_NONE + 15, - DP_ERROR_NO_DATA = DP_ERROR_NONE + 17, - DP_ERROR_UNHANDLED_HTTP_CODE = DP_ERROR_NONE + 18, - DP_ERROR_CANNOT_RESUME = DP_ERROR_NONE + 19, - DP_ERROR_PERMISSION_DENIED = DP_ERROR_NONE + 20, - DP_ERROR_RESPONSE_TIMEOUT = DP_ERROR_NONE + 50, - DP_ERROR_REQUEST_TIMEOUT = DP_ERROR_NONE + 55, - DP_ERROR_SYSTEM_DOWN = DP_ERROR_NONE + 60, - DP_ERROR_CLIENT_DOWN = DP_ERROR_NONE + 65, - DP_ERROR_ID_NOT_FOUND = DP_ERROR_NONE + 90, - DP_ERROR_IO_EAGAIN = DP_ERROR_NONE + 97, - DP_ERROR_IO_EINTR = DP_ERROR_NONE + 98, - DP_ERROR_IO_TIMEOUT = DP_ERROR_NONE + 99, - DP_ERROR_UNKNOWN = DP_ERROR_NONE + 100 -} dp_error_type; - -typedef enum { - DP_NETWORK_TYPE_OFF = -1, - DP_NETWORK_TYPE_ALL = 0, - DP_NETWORK_TYPE_WIFI = 1, - DP_NETWORK_TYPE_DATA_NETWORK = 2, - DP_NETWORK_TYPE_ETHERNET = 3, - DP_NETWORK_TYPE_WIFI_DIRECT = 4 -} dp_network_type; - -typedef enum { - DP_NOTIFICATION_BUNDLE_TYPE_ONGOING = 0, // Ongoing, Failed - DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE, // Completed - DP_NOTIFICATION_BUNDLE_TYPE_FAILED // Failed -} dp_notification_bundle_type; - -typedef enum { - DP_NOTIFICATION_TYPE_NONE = 0, // Not register Noti. - DP_NOTIFICATION_TYPE_COMPLETE_ONLY, // Success, Failed - DP_NOTIFICATION_TYPE_ALL // Ongoing, Success, Failed -} dp_notification_type; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/provider/download-provider-pid.c b/provider/include/download-provider-ipc.h index bd1a223..afddbe6 100755..100644 --- a/provider/download-provider-pid.c +++ b/provider/include/download-provider-ipc.h @@ -1,3 +1,4 @@ + /* * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved * @@ -14,21 +15,22 @@ * limitations under the License. */ -#include <unistd.h> -#include <fcntl.h> - -////////////////////////////////////////////////////////////////////////// -/// @brief check whether daemon is alive -/// @warning lockfd should be managed without close() -/// @param the patch for locking the file -int dp_lock_pid(char *path) -{ - int lockfd = -1; - if ((lockfd = open(path, O_WRONLY | O_CREAT, (0666 & (~000)))) < 0) { - return -1; - } else if (lockf(lockfd, F_TLOCK, 0) < 0) { - close(lockfd); - return -1; - } - return lockfd; -} +#ifndef DOWNLOAD_PROVIDER_IPC_H +#define DOWNLOAD_PROVIDER_IPC_H + +#include "download-provider.h" + +int dp_ipc_check_stderr(int basecode); +int dp_ipc_write(int sock, void *value, size_t type_size); +ssize_t dp_ipc_read(int sock, void *value, size_t type_size, + const char *func); + + +dp_ipc_fmt *dp_ipc_get_fmt(int sock); +int dp_ipc_query(int sock, int download_id, short section, + unsigned property, int error, size_t size); + +int dp_ipc_socket_free(int sockfd); + +#endif + diff --git a/provider/include/download-provider-log.h b/provider/include/download-provider-log.h index e828905..5b1b0cd 100755 --- a/provider/include/download-provider-log.h +++ b/provider/include/download-provider-log.h @@ -23,23 +23,28 @@ #ifdef LOG_TAG #undef LOG_TAG #endif -#define LOG_TAG "DOWNLOAD_PROVIDER" +#define LOG_TAG DOWNLOAD_PROVIDER_LOG_TAG +#if defined(LOGD) && defined(TIZEN_DEBUG_ENABLE) #define TRACE_DEBUG(format, ARG...) LOGD(format, ##ARG) +#else +#define TRACE_DEBUG(...) do { } while(0) +#endif #define TRACE_ERROR(format, ARG...) LOGE(format, ##ARG) #define TRACE_STRERROR(format, ARG...) LOGE(format" [%s]", ##ARG, strerror(errno)) #define TRACE_INFO(format, ARG...) LOGI(format, ##ARG) +#define TRACE_WARN(format, ARG...) LOGW(format, ##ARG) -#ifdef SECURE_LOGD +#if defined(SECURE_LOGD) && defined(TIZEN_DEBUG_ENABLE) #define TRACE_SECURE_DEBUG(format, ARG...) SECURE_LOGD(format, ##ARG) #else #define TRACE_SECURE_DEBUG(...) do { } while(0) #endif -#ifdef SECURE_LOGI +#if defined(SECURE_LOGI) && defined(TIZEN_DEBUG_ENABLE) #define TRACE_SECURE_INFO(format, ARG...) SECURE_LOGI(format, ##ARG) #else #define TRACE_SECURE_INFO(...) do { } while(0) #endif -#ifdef SECURE_LOGE +#if defined(SECURE_LOGE) && defined(TIZEN_DEBUG_ENABLE) #define TRACE_SECURE_ERROR(format, ARG...) SECURE_LOGE(format, ##ARG) #else #define TRACE_SECURE_ERROR(...) do { } while(0) @@ -50,6 +55,7 @@ #define TRACE_ERROR(...) do { } while(0) #define TRACE_STRERROR(...) do { } while(0) #define TRACE_INFO(...) do { } while(0) +#define TRACE_WARN(...) do { } while(0) #define TRACE_SECURE_DEBUG(...) do { } while(0) #define TRACE_SECURE_INFO(...) do { } while(0) #define TRACE_SECURE_ERROR(...) do { } while(0) diff --git a/provider/include/download-provider-network.h b/provider/include/download-provider-network.h index 98a9b43..73fc12d 100755 --- a/provider/include/download-provider-network.h +++ b/provider/include/download-provider-network.h @@ -14,21 +14,21 @@ * limitations under the License. */ -#ifndef DOWNLOAD_PROVIDER2_NETWORK_H -#define DOWNLOAD_PROVIDER2_NETWORK_H +#ifndef DOWNLOAD_PROVIDER_NETWORK_H +#define DOWNLOAD_PROVIDER_NETWORK_H -#include <net_connection.h> +#define DP_NETWORK_OFF -1 -#include "download-provider.h" +typedef enum { + DP_NETWORK_DATA_NETWORK = 0, + DP_NETWORK_WIFI = 1, + DP_NETWORK_WIFI_DIRECT = 2, + DP_NETWORK_ALL = 3 +} dp_network_defs; -dp_network_type dp_get_network_connection_status(connection_h connection, connection_type_e type); -void dp_network_connection_type_changed_cb(connection_type_e type, void *data); -int dp_network_connection_init(dp_privates *privates); -void dp_network_connection_destroy(connection_h connection); -dp_network_type dp_get_network_connection_instant_status(); - -#ifdef SUPPORT_WIFI_DIRECT -int dp_network_wifi_direct_is_connected(); -#endif +int dp_network_connection_init(); +void dp_network_connection_destroy(); +int dp_network_get_status(); +int dp_network_is_wifi_direct(); #endif diff --git a/provider/include/download-provider-notification-manager.h b/provider/include/download-provider-notification-manager.h new file mode 100644 index 0000000..0ffa740 --- /dev/null +++ b/provider/include/download-provider-notification-manager.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 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. + */ + +#ifndef DOWNLOAD_PROVIDER_NOTIFICATION_MANAGER_H +#define DOWNLOAD_PROVIDER_NOTIFICATION_MANAGER_H + +typedef enum { + DP_NOTIFICATION = 0, + DP_NOTIFICATION_ONGOING, + DP_NOTIFICATION_ONGOING_PROGRESS, + DP_NOTIFICATION_ONGOING_UPDATE, +} dp_noti_type; + +void dp_notification_manager_kill(); +void dp_notification_manager_wake_up(); +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type); +//int dp_notification_manager_push_notification_ongoing(void *slot, void *request, const dp_noti_type type); +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type); + +#endif diff --git a/provider/include/download-provider-notification.h b/provider/include/download-provider-notification.h index 5a9f5b9..eb3f56e 100755 --- a/provider/include/download-provider-notification.h +++ b/provider/include/download-provider-notification.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2013 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. @@ -14,14 +14,20 @@ * limitations under the License. */ -#ifndef DOWNLOAD_PROVIDER2_NOTIFICATION_H -#define DOWNLOAD_PROVIDER2_NOTIFICATION_H +#ifndef DOWNLOAD_PROVIDER_NOTIFICATION_H +#define DOWNLOAD_PROVIDER_NOTIFICATION_H -#include "download-provider-config.h" - -int dp_set_downloadinginfo_notification(int id, char *packagename); -int dp_set_downloadedinfo_notification(int priv_id, int id, char *packagename, dp_state_type state); -void dp_update_downloadinginfo_notification(int priv_id, double received_size, double file_size); -void dp_clear_downloadinginfo_notification(void); +#ifdef SUPPORT_NOTIFICATION +void dp_notification_set_locale(void); +void dp_notification_clear_locale(void); +void dp_notification_clear_ongoings(void); +int dp_notification_delete_ongoing(const int noti_priv_id); +int dp_notification_delete(const int noti_priv_id); +int dp_notification_ongoing_new(const char *pkgname, const char *subject, unsigned char *raws_buffer, const int raws_length); +int dp_notification_ongoing_update(const int noti_priv_id, const double received_size, const double file_size, const char *subject); +int dp_notification_new(void *dbhandle, const int download_id, const int state, int content_type, const char *pkgname); +#else +void dp_notification_clear_ongoings(void); +#endif #endif diff --git a/provider/include/download-provider-notify.h b/provider/include/download-provider-notify.h new file mode 100644 index 0000000..80c21d9 --- /dev/null +++ b/provider/include/download-provider-notify.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 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. + */ + +#ifndef DOWNLOAD_PROVIDER_NOTIFY_H +#define DOWNLOAD_PROVIDER_NOTIFY_H + +int dp_notify_init(pid_t pid); +void dp_notify_deinit(pid_t pid); +int dp_notify_feedback(int sock, void *slot, int id, int state, int errorcode, unsigned long long received_size); + +#endif diff --git a/provider/include/download-provider-da-interface.h b/provider/include/download-provider-plugin-download-agent.h index ab6e716..e3fb9c7 100755..100644 --- a/provider/include/download-provider-da-interface.h +++ b/provider/include/download-provider-plugin-download-agent.h @@ -14,16 +14,18 @@ * limitations under the License. */ -#ifndef DOWNLOAD_PROVIDER2_DA_INTERFACE_H -#define DOWNLOAD_PROVIDER2_DA_INTERFACE_H +#ifndef DOWNLOAD_PROVIDER_PLUGIN_DOWNLOAD_AGENT_H +#define DOWNLOAD_PROVIDER_PLUGIN_DOWNLOAD_AGENT_H int dp_is_file_exist(const char *file_path); int dp_init_agent(); void dp_deinit_agent(); -dp_error_type dp_start_agent_download(dp_request_slots *request); -dp_error_type dp_resume_agent_download(int req_id); -dp_error_type dp_pause_agent_download(int req_id); -dp_error_type dp_cancel_agent_download(int req_id); +int dp_start_agent_download(void *slot, void *request); +int dp_resume_agent_download(int req_id); +int dp_pause_agent_download(int req_id); +int dp_cancel_agent_download(int req_id); int dp_is_alive_download(int req_id); +int dp_cancel_agent_download_without_update(int req_id); +int dp_pause_agent_download_without_update(int req_id); #endif diff --git a/provider/include/download-provider-pthread.h b/provider/include/download-provider-pthread.h index 8c02c59..74e6036 100755 --- a/provider/include/download-provider-pthread.h +++ b/provider/include/download-provider-pthread.h @@ -14,81 +14,29 @@ * limitations under the License. */ -#ifndef DOWNLOAD_PROVIDER2_PTHREAD_H -#define DOWNLOAD_PROVIDER2_PTHREAD_H +#ifndef DOWNLOAD_PROVIDER_PTHREAD_H +#define DOWNLOAD_PROVIDER_PTHREAD_H #ifdef __cplusplus extern "C" { #endif -#include <unistd.h> #include <pthread.h> -#include <errno.h> // download-provider use default style mutex. - -#define CLIENT_MUTEX_LOCK(mutex_add) {\ - int ret = 0;\ - ret = pthread_mutex_lock(mutex_add);\ - if (EINVAL == ret) {\ - TRACE_STRERROR("ERR:pthread_mutex_lock FAIL with EINVAL.");\ - } else if (EDEADLK == ret) {\ - TRACE_STRERROR("ERR:pthread_mutex_lock FAIL with EDEADLK.");\ - } else if (ret != 0) {\ - TRACE_STRERROR("ERR:pthread_mutex_lock FAIL with %d.", ret);\ - } \ -} - -#define CLIENT_MUTEX_UNLOCK(mutex_add) {\ - int ret = 0;\ - ret = pthread_mutex_unlock(mutex_add);\ - if (EINVAL == ret) {\ - TRACE_STRERROR("ERR:pthread_mutex_unlock FAIL with EINVAL.");\ - } else if (EDEADLK == ret) {\ - TRACE_STRERROR("ERR:pthread_mutex_unlock FAIL with EDEADLK.");\ - } else if (ret != 0) {\ - TRACE_STRERROR("ERR:pthread_mutex_unlock FAIL with %d.", ret);\ - } \ -} - -#define CLIENT_MUTEX_DESTROY(mutex_add) { \ - int ret = 0; \ - ret = pthread_mutex_destroy(mutex_add); \ - if(EINVAL == ret) {\ - TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with EINVAL."); \ - } else if(ENOMEM == ret) {\ - TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with ENOMEM."); \ - } else if(EBUSY == ret) {\ - TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with EBUSY."); \ - if (pthread_mutex_unlock(mutex_add) == 0) \ - pthread_mutex_destroy(mutex_add); \ - } else if (ret != 0) {\ - TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with %d.", ret); \ - } \ -} - -#define CLIENT_MUTEX_INIT(mutex_add, attr) { \ - int ret = 0; \ - unsigned retry = 3; \ - while (retry > 0) { \ - ret = pthread_mutex_init(mutex_add, attr); \ - if (0 == ret) { \ - break; \ - } else if(EINVAL == ret) { \ - TRACE_STRERROR("ERR:pthread_mutex_init FAIL with EINVAL."); \ - } else if(ENOMEM == ret) { \ - TRACE_STRERROR("ERR:pthread_mutex_init FAIL with ENOMEM."); \ - usleep(1000); \ - } else if(EBUSY == ret) {\ - TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with EBUSY."); \ - if (pthread_mutex_unlock(mutex_add) == 0) \ - pthread_mutex_destroy(mutex_add); \ - } else if (ret != 0) { \ - TRACE_STRERROR("ERR:pthread_mutex_init FAIL with %d.", ret); \ - } \ - retry--; \ - } \ -} +int dp_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); +void dp_mutex_lock(pthread_mutex_t *mutex, const char *func, int line); +int dp_mutex_check_lock(pthread_mutex_t *mutex, const char *func, int line); +int dp_mutex_trylock(pthread_mutex_t *mutex, const char *func, int line); +int dp_mutex_timedlock(pthread_mutex_t *mutex, int sec, const char *func, int line); +void dp_mutex_unlock(pthread_mutex_t *mutex, const char *func, int line); +void dp_mutex_destroy(pthread_mutex_t *mutex); + +#define CLIENT_MUTEX_LOCK(mutex) dp_mutex_lock(mutex, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_CHECKLOCK(mutex) dp_mutex_check_lock(mutex, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_TRYLOCK(mutex) dp_mutex_trylock(mutex, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_TIMEDLOCK(mutex, sec) dp_mutex_timedlock(mutex, sec, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_UNLOCK(mutex) dp_mutex_unlock(mutex, __FUNCTION__, __LINE__) #ifdef __cplusplus } diff --git a/provider/include/download-provider-queue-manager.h b/provider/include/download-provider-queue-manager.h new file mode 100644 index 0000000..ba7e641 --- /dev/null +++ b/provider/include/download-provider-queue-manager.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 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. + */ + +#ifndef DOWNLOAD_PROVIDER_QUEUE_MANAGER_H +#define DOWNLOAD_PROVIDER_QUEUE_MANAGER_H + +void dp_queue_manager_kill(); +void dp_queue_manager_wake_up(); +int dp_queue_manager_push_queue(void *slot, void *request); +void dp_queue_manager_clear_queue(void *request); + +#endif diff --git a/provider/include/download-provider-queue.h b/provider/include/download-provider-queue.h index 71bb62b..a8efcfa 100755 --- a/provider/include/download-provider-queue.h +++ b/provider/include/download-provider-queue.h @@ -1,5 +1,5 @@ /*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2013 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.
@@ -14,10 +14,18 @@ * limitations under the License.
*/
-#ifndef DOWNLOAD_PROVIDER2_QUEUE_H
-#define DOWNLOAD_PROVIDER2_QUEUE_H
+#ifndef DOWNLOAD_PROVIDER_QUEUE_H
+#define DOWNLOAD_PROVIDER_QUEUE_H
-void dp_thread_queue_manager_wake_up();
-void *dp_thread_queue_manager(void *arg);
+typedef struct { // manage clients without mutex
+ void *slot; // client can not be NULL. it will exist in dummy
+ void *request;
+ void *next;
+} dp_queue_fmt;
+
+int dp_queue_push(dp_queue_fmt **queue, void *slot, void *request);
+int dp_queue_pop(dp_queue_fmt **queue, void **slot, void **request);
+void dp_queue_clear(dp_queue_fmt **queue, void *request);
+void dp_queue_clear_all(dp_queue_fmt **queue);
#endif
diff --git a/provider/include/download-provider-request.h b/provider/include/download-provider-request.h deleted file mode 100755 index bc26953..0000000 --- a/provider/include/download-provider-request.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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. - */ - -#ifndef DOWNLOAD_PROVIDER2_REQUEST_H -#define DOWNLOAD_PROVIDER2_REQUEST_H - -#include "download-provider.h" -#include <bundle.h> - -// for Debugging -char *dp_print_state(dp_state_type state); -char *dp_print_errorcode(dp_error_type errorcode); - -int dp_is_smackfs_mounted(void); -char *dp_strdup(char *src); - -dp_error_type dp_request_create(int id, dp_client_group *group, dp_request** empty_slot); -dp_error_type dp_request_set_url(int id, dp_request *request, char *url); -dp_error_type dp_request_set_destination(int id, dp_request *request, char *dest); -dp_error_type dp_request_set_filename(int id, dp_request *request, char *filename); -dp_error_type dp_request_set_title(int id, dp_request *request, char *filename); -dp_error_type dp_request_set_bundle(int id, dp_request *request, int type, bundle_raw *b, unsigned length); -dp_error_type dp_request_set_description(int id, dp_request *request, char *description); -dp_error_type dp_request_set_noti_type(int id, dp_request *request, unsigned type); -dp_error_type dp_request_set_notification(int id, dp_request *request, unsigned enable); -dp_error_type dp_request_set_auto_download(int id, dp_request *request, unsigned enable); -dp_error_type dp_request_set_state_event(int id, dp_request *request, unsigned enable); -dp_error_type dp_request_set_progress_event(int id, dp_request *request, unsigned enable); -dp_error_type dp_request_set_network_type(int id, dp_request *request, int type); -char *dp_request_get_url(int id, dp_error_type *errorcode); -char *dp_request_get_destination(int id, dp_request *request, dp_error_type *errorcode); -char *dp_request_get_filename(int id, dp_request *request, dp_error_type *errorcode); -char *dp_request_get_title(int id, dp_request *request, dp_error_type *errorcode); -bundle_raw *dp_request_get_bundle(int id, dp_request *request, dp_error_type *errorcode, char* column, int* length); -char *dp_request_get_description(int id, dp_request *request, dp_error_type *errorcode); -int dp_request_get_noti_type(int id, dp_request *request, dp_error_type *errorcode); -char *dp_request_get_contentname(int id, dp_request *request, dp_error_type *errorcode); -char *dp_request_get_etag(int id, dp_request *request, dp_error_type *errorcode); -char *dp_request_get_savedpath(int id, dp_request *request, dp_error_type *errorcode); -char *dp_request_get_tmpsavedpath(int id, dp_request *request, dp_error_type *errorcode); -char *dp_request_get_mimetype(int id, dp_request *request, dp_error_type *errorcode); -char *dp_request_get_pkg_name(int id, dp_request *request, dp_error_type *errorcode); -dp_request *dp_request_load_from_log(int id, dp_error_type *errorcode); -void dp_request_state_response(dp_request *request); -#endif diff --git a/provider/include/download-provider-slots.h b/provider/include/download-provider-slots.h deleted file mode 100755 index 53859f8..0000000 --- a/provider/include/download-provider-slots.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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. - */ - -#ifndef DOWNLOAD_PROVIDER2_SLOTS_H -#define DOWNLOAD_PROVIDER2_SLOTS_H - -#include "download-provider.h" -#include "download-provider-pthread.h" - -// Backgound Daemon should has the limitation of resource. -#define DP_MAX_GROUP 15 -#define DP_MAX_REQUEST 64 - -typedef struct { - pid_t pid; - uid_t uid; - gid_t gid; -} dp_credential; - -typedef struct { - // send command * get return value. - int cmd_socket; - // send event to client - int event_socket; - unsigned queued_count; // start ++, finish or failed -- ( queue & active ) - // fill by app-manager - char *pkgname; - dp_credential credential; - char *smack_label; -} dp_client_group; - -typedef struct { - int id; // ID created in create request in requests thread. - int agent_id; - int create_time; - int start_time; // setted by START command - int pause_time; // setted by PAUSE command - int stop_time; // time setted by finished_cb - int noti_priv_id; - unsigned state_cb; // set : 1 unset : 0 - unsigned progress_cb; // set : 1 unset : 0 - unsigned startcount; - unsigned auto_notification; - unsigned ip_changed; - dp_state_type state; // downloading state - dp_error_type error; - dp_network_type network_type; - size_t progress_lasttime; - unsigned long long received_size; // progress - unsigned long long file_size; - char *packagename; - dp_client_group *group; // indicate dp_client_group included this request -} dp_request; - -typedef struct { - dp_client_group *group; -} dp_group_slots; - -typedef struct { - pthread_mutex_t mutex; - dp_request *request; -} dp_request_slots; - - -// functions -dp_group_slots *dp_client_group_slots_new(int size); -dp_request_slots *dp_request_slots_new(int size); -int dp_client_group_free(dp_client_group *group); -int dp_client_group_slots_free(dp_group_slots *slots, int size); -dp_request *dp_request_new(); -void dp_request_init(dp_request *request); -int dp_request_free(dp_request *request); -int dp_request_slot_free(dp_request_slots *request_slot); -int dp_request_slots_free(dp_request_slots *slots, int size); -int dp_get_request_count(dp_request_slots *slots); - -#endif diff --git a/provider/include/download-provider-smack.h b/provider/include/download-provider-smack.h new file mode 100644 index 0000000..aa78d01 --- /dev/null +++ b/provider/include/download-provider-smack.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 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. + */ + +#ifndef DOWNLOAD_PROVIDER_SMACK_H +#define DOWNLOAD_PROVIDER_SMACK_H + +#ifdef SUPPORT_SECURITY_PRIVILEGE +#include <security-server.h> +#define SECURITY_PRIVILEGE_INTERNET "system::use_internet" +#endif + +int dp_smack_is_mounted(); +int dp_smack_set_label(char *label, char *source, char *target); +char *dp_smack_get_label_from_socket(int sock); +int dp_smack_is_valid_dir(int uid, int gid, char *smack_label, char *dir); +void dp_rebuild_dir(const char *dirpath, mode_t mode); +int dp_is_valid_dir(const char *dirpath); + + +#endif diff --git a/provider/include/download-provider-socket.h b/provider/include/download-provider-socket.h deleted file mode 100755 index b5a37cb..0000000 --- a/provider/include/download-provider-socket.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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. - */ - -#ifndef DOWNLOAD_PROVIDER2_SOCKET_H -#define DOWNLOAD_PROVIDER2_SOCKET_H - -#include <bundle.h> -#include "download-provider.h" -#include "download-provider-slots.h" - -int dp_ipc_send_errorcode(int fd, dp_error_type errorcode); -int dp_ipc_send_event(int fd, int id, dp_state_type state, - dp_error_type errorcode, unsigned long long received_size); -#if 0 -int dp_ipc_send_progressinfo(int fd, int id, - unsigned long long received_size, unsigned long long file_size, - unsigned int chunk_size); -int dp_ipc_send_stateinfo(int fd, int id, dp_state_type state, - dp_error_type errorcode); -#endif -char *dp_ipc_read_string(int fd); -unsigned dp_ipc_read_bundle(int fd, int *type, bundle_raw **b); -int dp_ipc_send_string(int fd, const char *str); -int dp_ipc_send_bundle(int fd, bundle_raw *b, unsigned length); -int dp_ipc_send_custom_type(int fd, void *value, size_t type_size); -int dp_ipc_read_custom_type(int fd, void *value, size_t type_size); -int dp_accept_socket_new(); -int dp_socket_free(int sockfd); - -#endif diff --git a/agent/include/download-agent-utils-dl-id-history.h b/provider/include/download-provider-utils.h index 3e32048..d965db4 100755..100644 --- a/agent/include/download-agent-utils-dl-id-history.h +++ b/provider/include/download-provider-utils.h @@ -14,22 +14,12 @@ * limitations under the License. */ -#ifndef _Download_Agent_Utils_Hash_Table_H -#define _Download_Agent_Utils_Hash_Table_H +#ifndef DOWNLOAD_PROVIDER_UTILS_H +#define DOWNLOAD_PROVIDER_UTILS_H -#include "download-agent-pthread.h" +char *dp_strdup(char *src); +int dp_is_file_exist(const char *file_path); +long dp_get_file_modified_time(const char *file_path); +int dp_remove_file(const char *file_path); -typedef struct _dl_id_history_t dl_id_history_t; -struct _dl_id_history_t { - int starting_num; - int cur_dl_id; - pthread_mutex_t mutex; -}; - -da_result_t init_dl_id_history(dl_id_history_t *dl_id_history); -da_result_t deinit_dl_id_history(dl_id_history_t *dl_id_history); - -int get_available_dl_id(dl_id_history_t *dl_id_history); - - -#endif /* _Download_Agent_Utils_Hash_Table_H */ +#endif diff --git a/provider/include/download-provider.h b/provider/include/download-provider.h index a1f22f3..92e1fde 100755 --- a/provider/include/download-provider.h +++ b/provider/include/download-provider.h @@ -14,105 +14,176 @@ * limitations under the License. */ -#ifndef DOWNLOAD_PROVIDER2_H -#define DOWNLOAD_PROVIDER2_H - -#include "download-provider-defs.h" +#ifndef DOWNLOAD_PROVIDER_H +#define DOWNLOAD_PROVIDER_H #ifdef __cplusplus extern "C" { #endif -#define DP_IPC "/tmp/download-provider" +typedef enum { + DP_STATE_NONE = 0, + DP_STATE_READY = DP_STATE_NONE + 5, // created id, set some info. + DP_STATE_QUEUED = DP_STATE_NONE + 10, // request to start + DP_STATE_CONNECTING = DP_STATE_NONE + 15, // try to connect to url + DP_STATE_DOWNLOADING = DP_STATE_NONE + 20, // started + DP_STATE_PAUSED = DP_STATE_NONE + 30, // paused actually + DP_STATE_COMPLETED = DP_STATE_NONE + 40, + DP_STATE_CANCELED = DP_STATE_NONE + 45, // stopped with error + DP_STATE_FAILED = DP_STATE_NONE + 50 // failed with error +} dp_state_type; + +typedef enum { + DP_ERROR_NONE = 10, + DP_ERROR_INVALID_PARAMETER = DP_ERROR_NONE + 1, + DP_ERROR_OUT_OF_MEMORY = DP_ERROR_NONE + 2, + DP_ERROR_IO_ERROR = DP_ERROR_NONE + 3, + DP_ERROR_NETWORK_UNREACHABLE = DP_ERROR_NONE + 4, + DP_ERROR_CONNECTION_TIMED_OUT = DP_ERROR_NONE + 5, + DP_ERROR_NO_SPACE = DP_ERROR_NONE + 6, + DP_ERROR_FIELD_NOT_FOUND = DP_ERROR_NONE + 7, + DP_ERROR_INVALID_STATE = DP_ERROR_NONE + 8, + DP_ERROR_CONNECTION_FAILED = DP_ERROR_NONE + 9, + DP_ERROR_INVALID_URL = DP_ERROR_NONE + 10, + DP_ERROR_INVALID_DESTINATION = DP_ERROR_NONE + 11, + DP_ERROR_QUEUE_FULL = DP_ERROR_NONE + 12, + DP_ERROR_ALREADY_COMPLETED = DP_ERROR_NONE + 13, + DP_ERROR_FILE_ALREADY_EXISTS = DP_ERROR_NONE + 14, + DP_ERROR_TOO_MANY_DOWNLOADS = DP_ERROR_NONE + 15, + DP_ERROR_NETWORK_ERROR = DP_ERROR_NONE + 16, + DP_ERROR_NO_DATA = DP_ERROR_NONE + 17, + DP_ERROR_UNHANDLED_HTTP_CODE = DP_ERROR_NONE + 18, + DP_ERROR_CANNOT_RESUME = DP_ERROR_NONE + 19, + DP_ERROR_PERMISSION_DENIED = DP_ERROR_NONE + 20, + DP_ERROR_INVALID_NETWORK_TYPE = DP_ERROR_NONE + 21, + DP_ERROR_RESPONSE_TIMEOUT = DP_ERROR_NONE + 50, + DP_ERROR_REQUEST_TIMEOUT = DP_ERROR_NONE + 55, + DP_ERROR_SYSTEM_DOWN = DP_ERROR_NONE + 60, + DP_ERROR_CLIENT_DOWN = DP_ERROR_NONE + 65, + DP_ERROR_DISK_BUSY = DP_ERROR_NONE + 70, + DP_ERROR_ID_NOT_FOUND = DP_ERROR_NONE + 90, + DP_ERROR_IO_EAGAIN = DP_ERROR_NONE + 97, + DP_ERROR_IO_EINTR = DP_ERROR_NONE + 98, + DP_ERROR_IO_TIMEOUT = DP_ERROR_NONE + 99, + DP_ERROR_UNKNOWN = DP_ERROR_NONE + 100 +} dp_error_type; + +typedef enum { + DP_NOTIFICATION_BUNDLE_TYPE_ONGOING = 0, // Ongoing, Failed + DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE, // Completed + DP_NOTIFICATION_BUNDLE_TYPE_FAILED // Failed +} dp_notification_bundle_type; + +typedef enum { + DP_NOTIFICATION_SERVICE_TYPE_ONGOING = 0, // Ongoing, Failed + DP_NOTIFICATION_SERVICE_TYPE_COMPLETE, // Completed + DP_NOTIFICATION_SERVICE_TYPE_FAILED // Failed +} dp_notification_service_type; -#define DP_MAX_STR_LEN_64 64 -#define DP_MAX_STR_LEN 256 -#define DP_MAX_PATH_LEN DP_MAX_STR_LEN -#define DP_MAX_URL_LEN 2048 -#define DP_DEFAULT_BUFFER_SIZE 1024 typedef enum { - DP_CMD_NONE = 0, - DP_CMD_ECHO, - DP_CMD_CREATE, - DP_CMD_START, - DP_CMD_SET_COMMAND_SOCKET, - DP_CMD_SET_EVENT_SOCKET, - DP_CMD_FREE, - - DP_CMD_ACTION_SECT = 100, - DP_CMD_PAUSE, - DP_CMD_CANCEL, - DP_CMD_DESTROY, - - DP_CMD_GET_SECT = 200, - DP_CMD_GET_URL, - DP_CMD_GET_DESTINATION, - DP_CMD_GET_FILENAME, - DP_CMD_GET_NOTIFICATION, - DP_CMD_GET_STATE_CALLBACK, - DP_CMD_GET_PROGRESS_CALLBACK, - DP_CMD_GET_HTTP_HEADERS, - DP_CMD_GET_AUTO_DOWNLOAD, - DP_CMD_GET_NETWORK_TYPE, - DP_CMD_GET_SAVED_PATH, - DP_CMD_GET_TEMP_SAVED_PATH, - DP_CMD_GET_MIME_TYPE, - DP_CMD_GET_HTTP_HEADER, - DP_CMD_GET_HTTP_HEADER_LIST, - DP_CMD_GET_EXTRA_PARAM, - DP_CMD_GET_RECEIVED_SIZE, - DP_CMD_GET_TOTAL_FILE_SIZE, - DP_CMD_GET_CONTENT_NAME, - DP_CMD_GET_HTTP_STATUS, - DP_CMD_GET_ETAG, - DP_CMD_GET_STATE, - DP_CMD_GET_ERROR, - DP_CMD_GET_NOTIFICATION_BUNDLE, - DP_CMD_GET_NOTIFICATION_TITLE, - DP_CMD_GET_NOTIFICATION_DESCRIPTION, - DP_CMD_GET_NOTIFICATION_TYPE, - - DP_CMD_SET_SECT = 300, - DP_CMD_SET_URL, - DP_CMD_SET_DESTINATION, - DP_CMD_SET_FILENAME, - DP_CMD_SET_NOTIFICATION, - DP_CMD_SET_STATE_CALLBACK, - DP_CMD_SET_PROGRESS_CALLBACK, - DP_CMD_SET_AUTO_DOWNLOAD, - DP_CMD_SET_NETWORK_TYPE, - DP_CMD_SET_HTTP_HEADER, - DP_CMD_SET_EXTRA_PARAM, // prevent build error - DP_CMD_DEL_HTTP_HEADER, - DP_CMD_ADD_EXTRA_PARAM, - DP_CMD_REMOVE_EXTRA_PARAM, - DP_CMD_SET_NOTIFICATION_BUNDLE, - DP_CMD_SET_NOTIFICATION_TITLE, - DP_CMD_SET_NOTIFICATION_DESCRIPTION, - DP_CMD_SET_NOTIFICATION_TYPE, - - DP_CMD_LAST_SECT = 400 -} dp_command_type; + DP_NOTIFICATION_TYPE_NONE = 0, // Not register Noti. + DP_NOTIFICATION_TYPE_COMPLETE_ONLY, // Success, Failed + DP_NOTIFICATION_TYPE_ALL // Ongoing, Success, Failed +} dp_notification_type; + + +#ifndef IPC_SOCKET +#define IPC_SOCKET "/opt/data/download-provider/download-provider.sock" +#endif + +#define MAX_DOWNLOAD_HANDLE 32 +#define DP_MAX_STR_LEN 2048 +#define DP_DEFAULT_BUFFER_SIZE 1024 + +// string to check invalid characters in path before using open() and fopen() API's +#define DP_INVALID_PATH_STRING ";\\\":*?<>|()" + + +#include <unistd.h> typedef struct { - unsigned int length; - char *str; -} dp_string; + pid_t pid; + uid_t uid; + gid_t gid; +} dp_credential; + +typedef enum { + DP_SEC_NONE = 0, + DP_SEC_INIT, + DP_SEC_DEINIT, + DP_SEC_CONTROL, + DP_SEC_GET, + DP_SEC_SET, + DP_SEC_UNSET +} dp_ipc_section_defs; + +typedef enum { + DP_PROP_NONE = 0, + DP_PROP_CREATE, + DP_PROP_START, + DP_PROP_PAUSE, + DP_PROP_CANCEL, + DP_PROP_DESTROY, + DP_PROP_URL, + DP_PROP_DESTINATION, + DP_PROP_FILENAME, + DP_PROP_STATE_CALLBACK, + DP_PROP_PROGRESS_CALLBACK, + DP_PROP_AUTO_DOWNLOAD, + DP_PROP_NETWORK_TYPE, + DP_PROP_NETWORK_BONDING, + DP_PROP_SAVED_PATH, + DP_PROP_TEMP_SAVED_PATH, + DP_PROP_MIME_TYPE, + DP_PROP_RECEIVED_SIZE, + DP_PROP_TOTAL_FILE_SIZE, + DP_PROP_CONTENT_NAME, + DP_PROP_HTTP_STATUS, + DP_PROP_ETAG, + DP_PROP_STATE, + DP_PROP_ERROR, + DP_PROP_HTTP_HEADERS, + DP_PROP_HTTP_HEADER, + DP_PROP_NOTIFICATION_RAW, + DP_PROP_NOTIFICATION_SUBJECT, + DP_PROP_NOTIFICATION_DESCRIPTION, + DP_PROP_NOTIFICATION_TYPE +} dp_ipc_property_defs; + +typedef enum { + DP_CONTENT_UNKNOWN = 0, + DP_CONTENT_IMAGE, + DP_CONTENT_VIDEO, + DP_CONTENT_MUSIC, + DP_CONTENT_PDF, + DP_CONTENT_WORD, + DP_CONTENT_PPT, // 5 + DP_CONTENT_EXCEL, + DP_CONTENT_HTML, + DP_CONTENT_TEXT, + DP_CONTENT_DRM, + DP_CONTENT_SD_DRM, //10 + DP_CONTENT_FLASH, + DP_CONTENT_TPK, + DP_CONTENT_VCAL, //13 +} dp_content_type; + typedef struct { + short section; + unsigned property; int id; - dp_state_type state; - dp_error_type err; - unsigned long long received_size; -} dp_event_info; + int errorcode; + size_t size; // followed extra packet size +} dp_ipc_fmt; typedef struct { - dp_command_type cmd; int id; -} dp_command; - - // Usage IPC : send(dp_command);send(dp_string); + int state; + int errorcode; + unsigned long long received_size; +} dp_ipc_event_fmt; #ifdef __cplusplus } diff --git a/res/images/Notification_download_animation.gif b/res/images/Notification_download_animation.gif Binary files differdeleted file mode 100644 index 17dd2bb..0000000 --- a/res/images/Notification_download_animation.gif +++ /dev/null diff --git a/res/images/Q02_Notification_download_complete.png b/res/images/Q02_Notification_download_complete.png Binary files differdeleted file mode 100644 index 7a11f3e..0000000 --- a/res/images/Q02_Notification_download_complete.png +++ /dev/null diff --git a/res/images/Q02_Notification_download_failed.png b/res/images/Q02_Notification_download_failed.png Binary files differdeleted file mode 100644 index d59dd6f..0000000 --- a/res/images/Q02_Notification_download_failed.png +++ /dev/null diff --git a/res/images/redwood/B03_processing_download_complete.png b/res/images/redwood/B03_processing_download_complete.png Binary files differnew file mode 100644 index 0000000..109512e --- /dev/null +++ b/res/images/redwood/B03_processing_download_complete.png diff --git a/res/images/redwood/B03_processing_download_fail.png b/res/images/redwood/B03_processing_download_fail.png Binary files differnew file mode 100644 index 0000000..be67ffe --- /dev/null +++ b/res/images/redwood/B03_processing_download_fail.png diff --git a/res/images/redwood/U01_icon_broken.png b/res/images/redwood/U01_icon_broken.png Binary files differnew file mode 100644 index 0000000..9020234 --- /dev/null +++ b/res/images/redwood/U01_icon_broken.png diff --git a/res/images/redwood/U01_icon_drm.png b/res/images/redwood/U01_icon_drm.png Binary files differnew file mode 100644 index 0000000..06e682b --- /dev/null +++ b/res/images/redwood/U01_icon_drm.png diff --git a/res/images/redwood/U01_icon_excel.png b/res/images/redwood/U01_icon_excel.png Binary files differnew file mode 100644 index 0000000..6efd14a --- /dev/null +++ b/res/images/redwood/U01_icon_excel.png diff --git a/res/images/redwood/U01_icon_html.png b/res/images/redwood/U01_icon_html.png Binary files differnew file mode 100644 index 0000000..01260ba --- /dev/null +++ b/res/images/redwood/U01_icon_html.png diff --git a/res/images/redwood/U01_icon_pdf.png b/res/images/redwood/U01_icon_pdf.png Binary files differnew file mode 100644 index 0000000..3f8cda6 --- /dev/null +++ b/res/images/redwood/U01_icon_pdf.png diff --git a/res/images/redwood/U01_icon_ppt.png b/res/images/redwood/U01_icon_ppt.png Binary files differnew file mode 100644 index 0000000..79302eb --- /dev/null +++ b/res/images/redwood/U01_icon_ppt.png diff --git a/res/images/redwood/U01_icon_swf.png b/res/images/redwood/U01_icon_swf.png Binary files differnew file mode 100644 index 0000000..39a49da --- /dev/null +++ b/res/images/redwood/U01_icon_swf.png diff --git a/res/images/redwood/U01_icon_text.png b/res/images/redwood/U01_icon_text.png Binary files differnew file mode 100644 index 0000000..5f8b3bd --- /dev/null +++ b/res/images/redwood/U01_icon_text.png diff --git a/res/images/redwood/U01_icon_tpk.png b/res/images/redwood/U01_icon_tpk.png Binary files differnew file mode 100644 index 0000000..796c788 --- /dev/null +++ b/res/images/redwood/U01_icon_tpk.png diff --git a/res/images/redwood/U01_icon_unkown.png b/res/images/redwood/U01_icon_unkown.png Binary files differnew file mode 100644 index 0000000..25a2801 --- /dev/null +++ b/res/images/redwood/U01_icon_unkown.png diff --git a/res/images/redwood/U01_icon_vcs.png b/res/images/redwood/U01_icon_vcs.png Binary files differnew file mode 100644 index 0000000..72dbf76 --- /dev/null +++ b/res/images/redwood/U01_icon_vcs.png diff --git a/res/images/redwood/U01_icon_word.png b/res/images/redwood/U01_icon_word.png Binary files differnew file mode 100644 index 0000000..a45acd7 --- /dev/null +++ b/res/images/redwood/U01_icon_word.png diff --git a/res/images/redwood/U01_list_icon_image.png b/res/images/redwood/U01_list_icon_image.png Binary files differnew file mode 100644 index 0000000..ebb2a3c --- /dev/null +++ b/res/images/redwood/U01_list_icon_image.png diff --git a/res/images/redwood/U01_list_icon_mp3.png b/res/images/redwood/U01_list_icon_mp3.png Binary files differnew file mode 100644 index 0000000..c5176be --- /dev/null +++ b/res/images/redwood/U01_list_icon_mp3.png diff --git a/res/images/redwood/U01_list_icon_mp4.png b/res/images/redwood/U01_list_icon_mp4.png Binary files differnew file mode 100644 index 0000000..2e3c87b --- /dev/null +++ b/res/images/redwood/U01_list_icon_mp4.png diff --git a/res/images/redwood/noti_download_complete.png b/res/images/redwood/noti_download_complete.png Binary files differnew file mode 100644 index 0000000..6171bd8 --- /dev/null +++ b/res/images/redwood/noti_download_complete.png diff --git a/res/images/redwood/noti_download_failed.png b/res/images/redwood/noti_download_failed.png Binary files differnew file mode 100644 index 0000000..5eb122b --- /dev/null +++ b/res/images/redwood/noti_download_failed.png diff --git a/res/images/tizen2.3/B03_Processing_download_complete.png b/res/images/tizen2.3/B03_Processing_download_complete.png Binary files differnew file mode 100644 index 0000000..8dfb542 --- /dev/null +++ b/res/images/tizen2.3/B03_Processing_download_complete.png diff --git a/res/images/tizen2.3/B03_Processing_download_failed.png b/res/images/tizen2.3/B03_Processing_download_failed.png Binary files differnew file mode 100644 index 0000000..11d34ab --- /dev/null +++ b/res/images/tizen2.3/B03_Processing_download_failed.png diff --git a/res/images/tizen2.3/download_manager_icon_date.png b/res/images/tizen2.3/download_manager_icon_date.png Binary files differnew file mode 100644 index 0000000..f1ff0f8 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_date.png diff --git a/res/images/tizen2.3/download_manager_icon_drm.png b/res/images/tizen2.3/download_manager_icon_drm.png Binary files differnew file mode 100644 index 0000000..7965232 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_drm.png diff --git a/res/images/tizen2.3/download_manager_icon_html.png b/res/images/tizen2.3/download_manager_icon_html.png Binary files differnew file mode 100644 index 0000000..f4a2bfc --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_html.png diff --git a/res/images/tizen2.3/download_manager_icon_img.png b/res/images/tizen2.3/download_manager_icon_img.png Binary files differnew file mode 100644 index 0000000..1c2f137 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_img.png diff --git a/res/images/tizen2.3/download_manager_icon_movie.png b/res/images/tizen2.3/download_manager_icon_movie.png Binary files differnew file mode 100644 index 0000000..5902a67 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_movie.png diff --git a/res/images/tizen2.3/download_manager_icon_music.png b/res/images/tizen2.3/download_manager_icon_music.png Binary files differnew file mode 100644 index 0000000..39f4c06 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_music.png diff --git a/res/images/tizen2.3/download_manager_icon_pdf.png b/res/images/tizen2.3/download_manager_icon_pdf.png Binary files differnew file mode 100644 index 0000000..96b1a9a --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_pdf.png diff --git a/res/images/tizen2.3/download_manager_icon_ppt.png b/res/images/tizen2.3/download_manager_icon_ppt.png Binary files differnew file mode 100644 index 0000000..29159cf --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_ppt.png diff --git a/res/images/tizen2.3/download_manager_icon_swf.png b/res/images/tizen2.3/download_manager_icon_swf.png Binary files differnew file mode 100644 index 0000000..b6335d7 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_swf.png diff --git a/res/images/tizen2.3/download_manager_icon_text.png b/res/images/tizen2.3/download_manager_icon_text.png Binary files differnew file mode 100644 index 0000000..4961fb5 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_text.png diff --git a/res/images/tizen2.3/download_manager_icon_tpk.png b/res/images/tizen2.3/download_manager_icon_tpk.png Binary files differnew file mode 100644 index 0000000..58953be --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_tpk.png diff --git a/res/images/tizen2.3/download_manager_icon_unknown.png b/res/images/tizen2.3/download_manager_icon_unknown.png Binary files differnew file mode 100644 index 0000000..9a367ec --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_unknown.png diff --git a/res/images/tizen2.3/download_manager_icon_word.png b/res/images/tizen2.3/download_manager_icon_word.png Binary files differnew file mode 100644 index 0000000..3218b53 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_word.png diff --git a/res/images/tizen2.3/download_manager_icon_xls.png b/res/images/tizen2.3/download_manager_icon_xls.png Binary files differnew file mode 100644 index 0000000..aeddf20 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_xls.png diff --git a/systemd/download-provider.service b/systemd/download-provider.service index 30b14d7..4286283 100644 --- a/systemd/download-provider.service +++ b/systemd/download-provider.service @@ -5,6 +5,7 @@ After=check-mount.service [Service] Type=simple ExecStart=/usr/bin/download-provider +MemoryLimit=100M [Install] WantedBy=graphical.target diff --git a/systemd/download-provider.socket b/systemd/download-provider.socket index 944b28d..3130e34 100644 --- a/systemd/download-provider.socket +++ b/systemd/download-provider.socket @@ -1,6 +1,10 @@ [Socket] -ListenStream=/tmp/download-provider +ListenStream=/opt/data/download-provider/download-provider.sock SocketMode=0777 +PassCredentials=yes +Accept=false +SmackLabelIPIn=download-provider +SmackLabelIPOut=download-provider [Install] WantedBy=sockets.target |