/* * media-thumbnail-server * * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: Hyunjun Ko * * 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 "thumb-server-internal.h" #include "media-thumb-util.h" #include "media-thumb-debug.h" #include #include #include #include #include #include #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "MEDIA_THUMBNAIL_SERVER" #define THUMB_DEFAULT_WIDTH 320 #define THUMB_DEFAULT_HEIGHT 240 #define THUMB_COMM_SOCK_PATH tzplatform_mkpath(TZ_SYS_RUN, "media-server/media_ipc_thumbcomm.socket") #define THUMB_EMPTY_STR "" GMainLoop *g_thumb_server_mainloop; // defined in thumb-server.c as extern static gboolean __thumb_server_send_msg_to_agent(int msg_type); static gboolean _thumb_server_send_deny_message(int sockfd); gboolean _thumb_daemon_start_jobs(gpointer data) { thumb_dbg(""); __thumb_server_send_msg_to_agent(MS_MSG_THUMB_SERVER_READY); return FALSE; } int _thumb_daemon_process_job(thumbMsg *req_msg, thumbMsg *res_msg) { int err = MS_MEDIA_ERR_NONE; if (req_msg->msg_type == THUMB_REQUEST_RAW_DATA) { err = _media_thumb_process_raw(req_msg, res_msg); if (err != MS_MEDIA_ERR_NONE) thumb_warn("_media_thumb_process_raw is failed: %d", err); } else if (req_msg->msg_type == THUMB_REQUEST_DB_INSERT) { err = _media_thumb_process(req_msg, res_msg); if (err != MS_MEDIA_ERR_NONE) thumb_warn("_media_thumb_process is failed: %d", err); } return err; } gboolean _thumb_server_read_socket(GIOChannel *src, GIOCondition condition, gpointer data) { struct sockaddr_un client_addr; unsigned int client_addr_len; thumbMsg recv_msg; thumbMsg res_msg; ms_peer_credentials credentials; int sock = -1; int client_sock = -1; memset((void *)&recv_msg, 0, sizeof(recv_msg)); memset((void *)&res_msg, 0, sizeof(res_msg)); memset((void *)&credentials, 0, sizeof(credentials)); sock = g_io_channel_unix_get_fd(src); if (sock < 0) { thumb_err("sock fd is invalid!"); return TRUE; } client_addr_len = sizeof(client_addr); if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) { thumb_stderror("accept failed"); return TRUE; } if (ms_cynara_receive_untrusted_message_thumb(client_sock, &recv_msg, &credentials) != MS_MEDIA_ERR_NONE) { thumb_err("ms_cynara_receive_untrusted_message_thumb failed"); close(client_sock); return FALSE; } if (recv_msg.msg_type != THUMB_REQUEST_KILL_SERVER) { if (ms_cynara_check(&credentials, MEDIA_STORAGE_PRIVILEGE) != MS_MEDIA_ERR_NONE) { thumb_err("Cynara denied access to process request"); _thumb_server_send_deny_message(client_sock); close(client_sock); return TRUE; } } else { thumb_warn("Shutting down..."); g_main_loop_quit(g_thumb_server_mainloop); close(client_sock); return TRUE; } SAFE_FREE(credentials.smack); SAFE_FREE(credentials.uid); thumb_warn_slog("Received [%d] %.*s(%zu) from PID(%d)", recv_msg.msg_type, MAX_FILEPATH_LEN, recv_msg.org_path, strlen(recv_msg.org_path), recv_msg.pid); _thumb_daemon_process_job(&recv_msg, &res_msg); if (res_msg.msg_type == 0) res_msg.msg_type = recv_msg.msg_type; res_msg.request_id = recv_msg.request_id; SAFE_STRLCPY(res_msg.org_path, recv_msg.org_path, sizeof(res_msg.org_path)); if (res_msg.msg_type != THUMB_RESPONSE_RAW_DATA) res_msg.thumb_size = 0; else res_msg.dst_path[0] = '\0'; int buf_size = 0; int send_len = 0; int send_pos = 0; unsigned char *buf = NULL; _media_thumb_set_buffer(&res_msg, &buf, &buf_size); while (buf_size > 0) { if ((send_len = send(client_sock, buf + send_pos, buf_size, 0)) < 0) { thumb_stderror("send failed"); break; } send_pos += send_len; buf_size -= send_len; } SAFE_FREE(buf); SAFE_FREE(res_msg.thumb_data); close(client_sock); return TRUE; } static gboolean __thumb_server_send_msg_to_agent(int msg_type) { int sock; struct sockaddr_un serv_addr; ms_thumb_server_msg send_msg; if (ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sock) < 0) { thumb_err("ms_ipc_create_server_socket failed"); return FALSE; } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sun_family = AF_UNIX; SAFE_STRLCPY(serv_addr.sun_path, THUMB_COMM_SOCK_PATH, sizeof(serv_addr.sun_path)); /* Connecting to the thumbnail server */ if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { thumb_stderror("connect"); close(sock); return MS_MEDIA_ERR_SOCKET_CONN; } send_msg.msg_type = msg_type; if (send(sock, &send_msg, sizeof(ms_thumb_server_msg), 0) < 0) { thumb_stderror("send failed"); close(sock); return FALSE; } thumb_dbg("Sending msg to thumbnail agent[%d] is successful", send_msg.msg_type); close(sock); return TRUE; } static gboolean _thumb_server_send_deny_message(int sockfd) { thumbMsg msg = {0}; int bytes_to_send = sizeof(msg); msg.msg_type = THUMB_RESPONSE; msg.status = MS_MEDIA_ERR_PERMISSION_DENIED; if (send(sockfd, &msg, bytes_to_send, 0) < 0) { thumb_stderror("send failed"); return FALSE; } return TRUE; } gboolean _thumb_server_prepare_socket(int *sock_fd) { int sock; if (ms_ipc_create_server_socket(MS_THUMB_DAEMON_PORT, &sock) < 0) { thumb_err("ms_ipc_create_server_socket failed"); return FALSE; } if (ms_cynara_enable_credentials_passing(sock) != MS_MEDIA_ERR_NONE) { thumb_err("ms_cynara_enable_credentials_passing failed"); close(sock); return FALSE; } *sock_fd = sock; return TRUE; } int _thumbnail_get_data(const char *origin_path, char *thumb_path) { int err = MS_MEDIA_ERR_NONE; int file_type = THUMB_NONE_TYPE; if (origin_path == NULL) { thumb_err("Original path is null"); return MS_MEDIA_ERR_INVALID_PARAMETER; } if (!g_file_test(origin_path, G_FILE_TEST_IS_REGULAR)) { thumb_err("Original path (%s) does not exist", origin_path); return MS_MEDIA_ERR_INVALID_PARAMETER; } thumb_dbg("Origin path : %s", origin_path); file_type = _media_thumb_get_file_type(origin_path); if (file_type == THUMB_IMAGE_TYPE) { err = _media_thumb_image(origin_path, thumb_path, THUMB_DEFAULT_WIDTH, THUMB_DEFAULT_HEIGHT, NULL); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_image failed"); } else if (file_type == THUMB_VIDEO_TYPE) { err = _media_thumb_video(origin_path, thumb_path, THUMB_DEFAULT_WIDTH, THUMB_DEFAULT_HEIGHT, NULL); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_video failed"); } else { thumb_err("invalid file type"); return MS_MEDIA_ERR_THUMB_UNSUPPORTED; } thumb_dbg("Thumb data is generated successfully"); return MS_MEDIA_ERR_NONE; } int _thumbnail_get_raw_data(const char *origin_path, int *width, int *height, unsigned char **data, int *size) { int err = MS_MEDIA_ERR_NONE; int thumb_width = -1; int thumb_height = -1; if (origin_path == NULL || *width <= 0 || *height <= 0) { thumb_err("Invalid parameter"); return MS_MEDIA_ERR_INVALID_PARAMETER; } if (!g_file_test(origin_path, G_FILE_TEST_IS_REGULAR)) { thumb_err("Original path (%s) does not exist", origin_path); return MS_MEDIA_ERR_INVALID_PARAMETER; } int file_type = THUMB_NONE_TYPE; media_thumb_info thumb_info = {0,}; file_type = _media_thumb_get_file_type(origin_path); thumb_width = *width; thumb_height = *height; if (file_type == THUMB_IMAGE_TYPE) { err = _media_thumb_image(origin_path, NULL, thumb_width, thumb_height, &thumb_info); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_image failed"); } else if (file_type == THUMB_VIDEO_TYPE) { err = _media_thumb_video(origin_path, NULL, thumb_width, thumb_height, &thumb_info); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_video failed"); } else { thumb_err("invalid file type"); return MS_MEDIA_ERR_THUMB_UNSUPPORTED; } if (size) *size = thumb_info.size; *data = thumb_info.data; *width = thumb_info.width; *height = thumb_info.height; return MS_MEDIA_ERR_NONE; } int _media_thumb_process(thumbMsg *req_msg, thumbMsg *res_msg) { int err = MS_MEDIA_ERR_NONE; char *thumb_path = NULL; thumb_retvm_if(req_msg == NULL || res_msg == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid msg"); const char *origin_path = req_msg->org_path; memset(res_msg->dst_path, 0, MAX_FILEPATH_LEN); thumb_path = res_msg->dst_path; res_msg->status = MS_MEDIA_ERR_NONE; if (!g_file_test(origin_path, G_FILE_TEST_IS_REGULAR)) { thumb_err("origin_path does not exist in file system."); res_msg->status = MS_MEDIA_ERR_FILE_NOT_EXIST; return MS_MEDIA_ERR_FILE_NOT_EXIST; } err = _media_thumb_get_thumb_from_db(origin_path, thumb_path, MAX_FILEPATH_LEN, req_msg->uid); if (err == MS_MEDIA_ERR_NONE) { thumb_dbg_slog("Thumb path : %s", thumb_path); return MS_MEDIA_ERR_NONE; } else { if (strlen(thumb_path) == 0) { err = _media_thumb_get_hash_name(origin_path, thumb_path, MAX_FILEPATH_LEN, req_msg->uid); if (err != MS_MEDIA_ERR_NONE) { thumb_err("_media_thumb_get_hash_name failed - %d", err); SAFE_STRLCPY(thumb_path, THUMB_EMPTY_STR, MAX_FILEPATH_LEN); res_msg->status = err; return err; } } } thumb_dbg_slog("Thumb path : %s", thumb_path); err = _thumbnail_get_data(origin_path, thumb_path); if (err != MS_MEDIA_ERR_NONE) { thumb_err("_thumbnail_get_data failed - %d", err); SAFE_STRLCPY(thumb_path, THUMB_EMPTY_STR, MAX_FILEPATH_LEN); res_msg->status = err; goto DB_UPDATE; } res_msg->msg_type = THUMB_RESPONSE; DB_UPDATE: err = _media_thumb_update_db(origin_path, thumb_path, req_msg->uid); if (err != MS_MEDIA_ERR_NONE) { thumb_err("_media_thumb_update_db failed : %d", err); res_msg->status = err; } return err; } int _media_thumb_process_raw(thumbMsg *req_msg, thumbMsg *res_msg) { int err = MS_MEDIA_ERR_NONE; unsigned char *data = NULL; int thumb_size = 0; int thumb_w = 0; int thumb_h = 0; thumb_retvm_if(req_msg == NULL || res_msg == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid msg"); const char *origin_path = req_msg->org_path; if (req_msg->thumb_width > 0) thumb_w = req_msg->thumb_width; else thumb_w = THUMB_DEFAULT_WIDTH; if (req_msg->thumb_height > 0) thumb_h = req_msg->thumb_height; else thumb_h = THUMB_DEFAULT_HEIGHT; res_msg->status = MS_MEDIA_ERR_NONE; res_msg->msg_type = THUMB_RESPONSE_RAW_DATA; err = _thumbnail_get_raw_data(origin_path, &thumb_w, &thumb_h, &data, &thumb_size); if (err != MS_MEDIA_ERR_NONE) { thumb_err("_thumbnail_get_data failed - %d", err); res_msg->status = err; res_msg->thumb_size = 0; SAFE_FREE(data); return err; } res_msg->thumb_width = thumb_w; res_msg->thumb_height = thumb_h; res_msg->thumb_size = thumb_size; res_msg->thumb_data = malloc(thumb_size * sizeof(unsigned char)); if (res_msg->thumb_data != NULL) { memcpy(res_msg->thumb_data, data, thumb_size); } else { thumb_err("Allocation failed"); err = MS_MEDIA_ERR_OUT_OF_MEMORY; } SAFE_FREE(data); return err; }