summaryrefslogtreecommitdiff
path: root/server/thumb-server-internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/thumb-server-internal.c')
-rwxr-xr-xserver/thumb-server-internal.c380
1 files changed, 380 insertions, 0 deletions
diff --git a/server/thumb-server-internal.c b/server/thumb-server-internal.c
new file mode 100755
index 0000000..7e749a3
--- /dev/null
+++ b/server/thumb-server-internal.c
@@ -0,0 +1,380 @@
+/*
+ * media-thumbnail-server
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hyunjun Ko <zzoon.ko@samsung.com>
+ *
+ * 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 <unistd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "Thumb-Daemon"
+
+static int sock;
+GAsyncQueue *g_req_queue = NULL;
+
+static __thread _server_mode_e g_server_mode = BLOCK_MODE;
+static __thread int g_media_svr_pid = 0;
+
+int _thumb_daemon_get_sockfd()
+{
+ return sock;
+}
+
+
+GAsyncQueue *_thumb_daemon_get_queue()
+{
+ return g_req_queue;
+}
+
+void _thumb_daemon_destroy_queue_msg(queueMsg *msg)
+{
+ if (msg != NULL) {
+ if (msg->recv_msg != NULL) {
+ free(msg->recv_msg);
+ msg->recv_msg = NULL;
+ }
+
+ if (msg->res_msg != NULL) {
+ free(msg->res_msg);
+ msg->res_msg = NULL;
+ }
+
+ msg = NULL;
+ }
+}
+
+int _thumb_daemon_compare_pid_with_mediaserver_fast(int pid)
+{
+ int find_pid = -1;
+
+ char path[128];
+ char buff[128];
+ snprintf(path, sizeof(path), "/proc/%d/status", g_media_svr_pid);
+
+ FILE *fp = NULL;
+ fp = fopen(path, "rt");
+ if (fp) {
+ fgets(buff, sizeof(buff), fp);
+ fclose(fp);
+
+ if (strstr(buff, "media-server")) {
+ find_pid = g_media_svr_pid;
+ thumb_dbg(" find_pid : %d", find_pid);
+ } else {
+ g_media_svr_pid = 0;
+ return GETPID_FAIL;
+ }
+ } else {
+ thumb_err("Can't read file [%s]", path);
+ g_media_svr_pid = 0;
+ return GETPID_FAIL;
+ }
+
+ if (find_pid == pid) {
+ thumb_dbg("This is a request from media-server");
+ return MEDIA_SERVER_PID;
+ } else {
+ thumb_dbg("This is a request from other apps");
+ return OTHERS_PID;
+ }
+}
+
+int _thumb_daemon_compare_pid_with_mediaserver(int pid)
+{
+ DIR *pdir;
+ struct dirent pinfo;
+ struct dirent *result = NULL;
+
+ pdir = opendir("/proc");
+ if (pdir == NULL) {
+ thumb_err("err: NO_DIR");
+ return GETPID_FAIL;
+ }
+
+ while (!readdir_r(pdir, &pinfo, &result)) {
+ if (result == NULL)
+ break;
+
+ if (pinfo.d_type != 4 || pinfo.d_name[0] == '.'
+ || pinfo.d_name[0] > 57)
+ continue;
+
+ FILE *fp;
+ char buff[128];
+ char path[128];
+
+ snprintf(path, sizeof(path), "/proc/%s/status", pinfo.d_name);
+
+ fp = fopen(path, "rt");
+ if (fp) {
+ fgets(buff, sizeof(buff), fp);
+ fclose(fp);
+
+ if (strstr(buff, "media-server")) {
+ thumb_dbg("pinfo->d_name : %s", pinfo.d_name);
+ g_media_svr_pid = atoi(pinfo.d_name);
+ thumb_dbg("Media Server PID : %d", g_media_svr_pid);
+ }
+ }
+ }
+
+ closedir(pdir);
+
+ if (g_media_svr_pid == pid) {
+ thumb_dbg("This is a request from media-server");
+ return MEDIA_SERVER_PID;
+ } else {
+ thumb_dbg("This is a request from other apps");
+ return OTHERS_PID;
+ }
+}
+
+int _thumb_daemon_recv_by_select(int fd, gboolean is_timeout)
+{
+ thumb_err("");
+ fd_set fds;
+ int ret = -1;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ if (is_timeout) {
+ struct timeval timeout;
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ ret = select(fd + 1, &fds, 0, 0, &timeout);
+ } else {
+ ret = select(fd + 1, &fds, 0, 0, NULL);
+ }
+
+ return ret;
+}
+
+int _thumb_daemon_process_job(thumbMsg *req_msg, thumbMsg *res_msg)
+{
+ int err = -1;
+
+ err = _media_thumb_process(req_msg, res_msg);
+ if (err < 0) {
+ if (req_msg->msg_type == THUMB_REQUEST_SAVE) {
+ thumb_err("_media_thumb_process is failed: %d", err);
+ res_msg->status = THUMB_FAIL;
+ } else {
+ thumb_warn("_media_thumb_process is failed: %d, So use default thumb", err);
+ res_msg->status = THUMB_SUCCESS;
+ }
+ } else {
+ res_msg->status = THUMB_SUCCESS;
+ }
+
+ return err;
+}
+
+int _thumb_daemon_process_queue_jobs()
+{
+ int length = 0;
+
+ while(1) {
+ length = g_async_queue_length(g_req_queue);
+ if (length > 0) {
+ thumb_dbg("There are %d jobs in the queue", length);
+ queueMsg *data = g_async_queue_pop(g_req_queue);
+
+ _thumb_daemon_process_job(data->recv_msg, data->res_msg);
+
+ if (sendto(sock, data->res_msg, sizeof(thumbMsg), 0, (struct sockaddr *)data->client_addr, sizeof(struct sockaddr_in)) != sizeof(thumbMsg)) {
+ thumb_err("sendto failed\n");
+ } else {
+ thumb_dbg("Sent %s(%d) \n", data->res_msg->dst_path, strlen(data->res_msg->dst_path));
+ }
+
+ _thumb_daemon_destroy_queue_msg(data);
+ } else {
+ break;
+ }
+ }
+
+ g_server_mode = BLOCK_MODE;
+
+ return 0;
+}
+
+gboolean _thumb_daemon_udp_thread(void *data)
+{
+ int err = -1;
+ gboolean is_timeout = FALSE;
+
+ struct sockaddr_in serv_addr;
+ struct sockaddr_in client_addr;
+ unsigned short serv_port;
+ unsigned int client_addr_len;
+
+ queueMsg *queue_msg = NULL;
+ thumbMsg recv_msg;
+ thumbMsg res_msg;
+ int recv_msg_size;
+ char thumb_path[MAX_PATH_SIZE + 1];
+
+ memset((void *)&recv_msg, 0, sizeof(recv_msg));
+ memset((void *)&res_msg, 0, sizeof(res_msg));
+ serv_port = THUMB_DAEMON_PORT;
+
+ if (!g_req_queue) {
+ g_req_queue = g_async_queue_new();
+ }
+
+ /* Creaete a datagram/UDP socket */
+ if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ thumb_err("socket failed");
+ return FALSE;
+ }
+
+ memset(thumb_path, 0, sizeof(thumb_path));
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ serv_addr.sin_port = htons(serv_port);
+
+ /* Bind to the local address */
+ if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+ thumb_err("bind failed");
+ return FALSE;
+ }
+
+ thumb_dbg("bind success");
+
+ while(1) {
+ if (g_server_mode == TIMEOUT_MODE) {
+ thumb_dbg("Wait for other app's request for 1 sec");
+ is_timeout = TRUE;
+ } else {
+ is_timeout = FALSE;
+ }
+
+ err = _thumb_daemon_recv_by_select(sock, is_timeout);
+
+ if (err == 0) {
+ /* timeout in select() */
+ err = _thumb_daemon_process_queue_jobs();
+ continue;
+
+ } else if (err == -1) {
+ /* error in select() */
+ thumb_err("ERROR in select()");
+ continue;
+
+ } else {
+ _pid_e pid_type = 0;
+ /* Socket is readable */
+ client_addr_len = sizeof(client_addr);
+ if ((recv_msg_size = recvfrom(sock, &recv_msg, sizeof(recv_msg), 0, (struct sockaddr *)&client_addr, &client_addr_len)) < 0) {
+ thumb_err("recvfrom failed\n");
+ continue;
+ }
+
+ thumb_dbg("Received [%d] %s(%d) from PID(%d) \n", recv_msg.msg_type, recv_msg.org_path, strlen(recv_msg.org_path), recv_msg.pid);
+
+ if (g_media_svr_pid > 0) {
+ pid_type = _thumb_daemon_compare_pid_with_mediaserver_fast(recv_msg.pid);
+ }
+
+ if (g_media_svr_pid <= 0) {
+ pid_type = _thumb_daemon_compare_pid_with_mediaserver(recv_msg.pid);
+ }
+
+ if (pid_type == GETPID_FAIL) {
+ thumb_err("Failed to get media svr pid. So This req is regarded as other app's request.");
+ pid_type = OTHERS_PID;
+ }
+
+ if (g_server_mode == BLOCK_MODE || pid_type == OTHERS_PID) {
+ long start = thumb_get_debug_time();
+
+ _thumb_daemon_process_job(&recv_msg, &res_msg);
+
+ long end = thumb_get_debug_time();
+ thumb_dbg("Time : %f (%s)\n", ((double)(end - start) / (double)CLOCKS_PER_SEC), recv_msg.org_path);
+
+ if (sendto(sock, &res_msg, sizeof(res_msg), 0, (struct sockaddr *)&client_addr, sizeof(client_addr)) != sizeof(res_msg)) {
+ thumb_err("sendto failed\n");
+ } else {
+ thumb_dbg("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path));
+ }
+
+ memset((void *)&recv_msg, 0, sizeof(recv_msg));
+ memset((void *)&res_msg, 0, sizeof(res_msg));
+
+ if (pid_type == OTHERS_PID) {
+ g_server_mode = TIMEOUT_MODE;
+ }
+ } else {
+ /* This is a request from media-server on TIMEOUT mode.
+ So this req is going to be pushed to the queue */
+
+ queue_msg = malloc(sizeof(queueMsg));
+ if (queue_msg == NULL) {
+ thumb_err("malloc failed");
+ continue;
+ }
+ queue_msg->recv_msg = malloc(sizeof(thumbMsg));
+ if (queue_msg->recv_msg == NULL) {
+ thumb_err("malloc failed");
+ SAFE_FREE(queue_msg);
+ continue;
+ }
+ queue_msg->res_msg = malloc(sizeof(thumbMsg));
+ if (queue_msg->res_msg == NULL) {
+ thumb_err("malloc failed");
+ SAFE_FREE(queue_msg->recv_msg);
+ SAFE_FREE(queue_msg);
+ continue;
+ }
+ queue_msg->client_addr = malloc(sizeof(struct sockaddr_in));
+ if (queue_msg->client_addr == NULL) {
+ thumb_err("malloc failed");
+ SAFE_FREE(queue_msg->recv_msg);
+ SAFE_FREE(queue_msg->res_msg);
+ SAFE_FREE(queue_msg);
+ continue;
+ }
+
+ memcpy(queue_msg->recv_msg, &recv_msg, sizeof(thumbMsg));
+ memcpy(queue_msg->res_msg, &res_msg, sizeof(thumbMsg));
+ memcpy(queue_msg->client_addr, &client_addr, sizeof(struct sockaddr_in));
+
+ g_async_queue_push(g_req_queue, GINT_TO_POINTER(queue_msg));
+ g_server_mode = TIMEOUT_MODE;
+ }
+ }
+ }
+
+ close(sock);
+
+ return TRUE;
+}
+