2 * media-thumbnail-server
4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hyunjun Ko <zzoon.ko@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include "thumb-server-internal.h"
34 #define LOG_TAG "Thumb-Daemon"
37 GAsyncQueue *g_req_queue = NULL;
39 static __thread _server_mode_e g_server_mode = BLOCK_MODE;
40 static __thread int g_media_svr_pid = 0;
42 int _thumb_daemon_get_sockfd()
48 GAsyncQueue *_thumb_daemon_get_queue()
53 void _thumb_daemon_destroy_queue_msg(queueMsg *msg)
56 if (msg->recv_msg != NULL) {
61 if (msg->res_msg != NULL) {
70 int _thumb_daemon_compare_pid_with_mediaserver_fast(int pid)
76 snprintf(path, sizeof(path), "/proc/%d/status", g_media_svr_pid);
79 fp = fopen(path, "rt");
81 fgets(buff, sizeof(buff), fp);
84 if (strstr(buff, "media-server")) {
85 find_pid = g_media_svr_pid;
86 thumb_dbg(" find_pid : %d", find_pid);
92 thumb_err("Can't read file [%s]", path);
97 if (find_pid == pid) {
98 thumb_dbg("This is a request from media-server");
99 return MEDIA_SERVER_PID;
101 thumb_dbg("This is a request from other apps");
106 int _thumb_daemon_compare_pid_with_mediaserver(int pid)
110 struct dirent *result = NULL;
112 pdir = opendir("/proc");
114 thumb_err("err: NO_DIR");
118 while (!readdir_r(pdir, &pinfo, &result)) {
122 if (pinfo.d_type != 4 || pinfo.d_name[0] == '.'
123 || pinfo.d_name[0] > 57)
130 snprintf(path, sizeof(path), "/proc/%s/status", pinfo.d_name);
132 fp = fopen(path, "rt");
134 fgets(buff, sizeof(buff), fp);
137 if (strstr(buff, "media-server")) {
138 thumb_dbg("pinfo->d_name : %s", pinfo.d_name);
139 g_media_svr_pid = atoi(pinfo.d_name);
140 thumb_dbg("Media Server PID : %d", g_media_svr_pid);
147 if (g_media_svr_pid == pid) {
148 thumb_dbg("This is a request from media-server");
149 return MEDIA_SERVER_PID;
151 thumb_dbg("This is a request from other apps");
156 int _thumb_daemon_recv_by_select(int fd, gboolean is_timeout)
166 struct timeval timeout;
170 ret = select(fd + 1, &fds, 0, 0, &timeout);
172 ret = select(fd + 1, &fds, 0, 0, NULL);
178 int _thumb_daemon_process_job(thumbMsg *req_msg, thumbMsg *res_msg)
182 err = _media_thumb_process(req_msg, res_msg);
184 if (req_msg->msg_type == THUMB_REQUEST_SAVE) {
185 thumb_err("_media_thumb_process is failed: %d", err);
186 res_msg->status = THUMB_FAIL;
188 thumb_warn("_media_thumb_process is failed: %d, So use default thumb", err);
189 res_msg->status = THUMB_SUCCESS;
192 res_msg->status = THUMB_SUCCESS;
198 int _thumb_daemon_process_queue_jobs()
203 length = g_async_queue_length(g_req_queue);
205 thumb_dbg("There are %d jobs in the queue", length);
206 queueMsg *data = g_async_queue_pop(g_req_queue);
208 _thumb_daemon_process_job(data->recv_msg, data->res_msg);
210 if (sendto(sock, data->res_msg, sizeof(thumbMsg), 0, (struct sockaddr *)data->client_addr, sizeof(struct sockaddr_in)) != sizeof(thumbMsg)) {
211 thumb_err("sendto failed\n");
213 thumb_dbg("Sent %s(%d) \n", data->res_msg->dst_path, strlen(data->res_msg->dst_path));
216 _thumb_daemon_destroy_queue_msg(data);
222 g_server_mode = BLOCK_MODE;
227 gboolean _thumb_daemon_udp_thread(void *data)
230 gboolean is_timeout = FALSE;
232 struct sockaddr_in serv_addr;
233 struct sockaddr_in client_addr;
234 unsigned short serv_port;
235 unsigned int client_addr_len;
237 queueMsg *queue_msg = NULL;
241 char thumb_path[MAX_PATH_SIZE + 1];
243 memset((void *)&recv_msg, 0, sizeof(recv_msg));
244 memset((void *)&res_msg, 0, sizeof(res_msg));
245 serv_port = THUMB_DAEMON_PORT;
248 g_req_queue = g_async_queue_new();
251 /* Creaete a datagram/UDP socket */
252 if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
253 thumb_err("socket failed");
257 memset(thumb_path, 0, sizeof(thumb_path));
258 memset(&serv_addr, 0, sizeof(serv_addr));
259 serv_addr.sin_family = AF_INET;
260 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
261 serv_addr.sin_port = htons(serv_port);
263 /* Bind to the local address */
264 if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
265 thumb_err("bind failed");
269 thumb_dbg("bind success");
272 if (g_server_mode == TIMEOUT_MODE) {
273 thumb_dbg("Wait for other app's request for 1 sec");
279 err = _thumb_daemon_recv_by_select(sock, is_timeout);
282 /* timeout in select() */
283 err = _thumb_daemon_process_queue_jobs();
286 } else if (err == -1) {
287 /* error in select() */
288 thumb_err("ERROR in select()");
293 /* Socket is readable */
294 client_addr_len = sizeof(client_addr);
295 if ((recv_msg_size = recvfrom(sock, &recv_msg, sizeof(recv_msg), 0, (struct sockaddr *)&client_addr, &client_addr_len)) < 0) {
296 thumb_err("recvfrom failed\n");
300 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);
302 if (g_media_svr_pid > 0) {
303 pid_type = _thumb_daemon_compare_pid_with_mediaserver_fast(recv_msg.pid);
306 if (g_media_svr_pid <= 0) {
307 pid_type = _thumb_daemon_compare_pid_with_mediaserver(recv_msg.pid);
310 if (pid_type == GETPID_FAIL) {
311 thumb_err("Failed to get media svr pid. So This req is regarded as other app's request.");
312 pid_type = OTHERS_PID;
315 if (g_server_mode == BLOCK_MODE || pid_type == OTHERS_PID) {
316 long start = thumb_get_debug_time();
318 _thumb_daemon_process_job(&recv_msg, &res_msg);
320 long end = thumb_get_debug_time();
321 thumb_dbg("Time : %f (%s)\n", ((double)(end - start) / (double)CLOCKS_PER_SEC), recv_msg.org_path);
323 if (sendto(sock, &res_msg, sizeof(res_msg), 0, (struct sockaddr *)&client_addr, sizeof(client_addr)) != sizeof(res_msg)) {
324 thumb_err("sendto failed\n");
326 thumb_dbg("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path));
329 memset((void *)&recv_msg, 0, sizeof(recv_msg));
330 memset((void *)&res_msg, 0, sizeof(res_msg));
332 if (pid_type == OTHERS_PID) {
333 g_server_mode = TIMEOUT_MODE;
336 /* This is a request from media-server on TIMEOUT mode.
337 So this req is going to be pushed to the queue */
339 queue_msg = malloc(sizeof(queueMsg));
340 if (queue_msg == NULL) {
341 thumb_err("malloc failed");
344 queue_msg->recv_msg = malloc(sizeof(thumbMsg));
345 if (queue_msg->recv_msg == NULL) {
346 thumb_err("malloc failed");
347 SAFE_FREE(queue_msg);
350 queue_msg->res_msg = malloc(sizeof(thumbMsg));
351 if (queue_msg->res_msg == NULL) {
352 thumb_err("malloc failed");
353 SAFE_FREE(queue_msg->recv_msg);
354 SAFE_FREE(queue_msg);
357 queue_msg->client_addr = malloc(sizeof(struct sockaddr_in));
358 if (queue_msg->client_addr == NULL) {
359 thumb_err("malloc failed");
360 SAFE_FREE(queue_msg->recv_msg);
361 SAFE_FREE(queue_msg->res_msg);
362 SAFE_FREE(queue_msg);
366 memcpy(queue_msg->recv_msg, &recv_msg, sizeof(thumbMsg));
367 memcpy(queue_msg->res_msg, &res_msg, sizeof(thumbMsg));
368 memcpy(queue_msg->client_addr, &client_addr, sizeof(struct sockaddr_in));
370 g_async_queue_push(g_req_queue, GINT_TO_POINTER(queue_msg));
371 g_server_mode = TIMEOUT_MODE;