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.
25 #include "media-util.h"
26 #include "media-server-dbg.h"
27 #include "media-server-thumb.h"
28 #include "media-server-utils.h"
34 #define LOG_TAG "MEDIA_SERVER_THUMB"
36 #define THUMB_SERVER_NAME "media-thumbnail"
38 gboolean _ms_thumb_agent_timer();
40 static GMainLoop *g_thumb_agent_loop = NULL;
41 static GIOChannel *g_udp_channel = NULL;
42 static gboolean g_folk_thumb_server = FALSE;
43 static gboolean g_thumb_server_extracting = FALSE;
44 static int g_communicate_sock = 0;
45 static int g_timer_id = 0;
46 static int g_server_pid = 0;
48 static GQueue *g_request_queue = NULL;
49 static int g_queue_work = 0;
56 gboolean _ms_thumb_agent_start_jobs(gpointer data)
63 void _ms_thumb_agent_finish_jobs()
71 ms_get_thumb_thread_mainloop(void)
73 return g_thumb_agent_loop;
76 int ms_thumb_get_server_pid()
81 void ms_thumb_reset_server_status()
83 g_folk_thumb_server = FALSE;
86 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), g_timer_id));
90 if (g_thumb_server_extracting) {
91 /* Need to inplement when crash happens */
93 /* Restart thumbnail server */
94 if (_ms_thumb_agent_execute_server() < 0) {
95 MS_DBG_ERR("starting thumbnail-server failed");
97 MS_DBG("Thumbnail-server is started");
102 memset((void *)&msg, 0, sizeof(msg));
103 memset((void *)&recv_msg, 0, sizeof(recv_msg));
105 msg.msg_type = 2; // THUMB_REQUEST_ALL_MEDIA
106 msg.org_path[0] = '\0';
107 msg.origin_path_size = 1;
108 msg.dst_path[0] = '\0';
109 msg.dest_path_size = 1;
111 /* Command all thumbnail extraction to thumbnail server */
112 if (!_ms_thumb_agent_send_msg_to_thumb_server(&msg, &recv_msg)) {
113 MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed");
116 _ms_thumb_create_timer(g_timer_id);
118 MS_DBG_ERR("Thumbnail server is dead when processing all-thumbs extraction");
119 g_thumb_server_extracting = FALSE;
123 g_thumb_server_extracting = FALSE;
130 void _ms_thumb_create_timer(int id)
133 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), id));
135 GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_20);
136 g_source_set_callback (timer_src, _ms_thumb_agent_timer, NULL, NULL);
137 g_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default());
141 /* This checks if thumbnail server is running */
142 bool _ms_thumb_check_process()
146 struct dirent *result = NULL;
149 pdir = opendir("/proc");
151 MS_DBG_ERR("err: NO_DIR\n");
155 while (!readdir_r(pdir, &pinfo, &result)) {
159 if (pinfo.d_type != 4 || pinfo.d_name[0] == '.'
160 || pinfo.d_name[0] > 57)
167 ms_strcopy(path, sizeof(path), "/proc/%s/status", pinfo.d_name);
168 fp = fopen(path, "rt");
170 if (fgets(buff, 128, fp) == NULL)
171 MS_DBG_ERR("fgets failed");
174 if (strstr(buff, THUMB_SERVER_NAME)) {
179 MS_DBG_ERR("Can't read file [%s]", path);
188 _ms_thumb_create_socket(int sock_type, int *sock)
192 if ((sock_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
193 MS_DBG_ERR("socket failed: %s", strerror(errno));
194 return MS_MEDIA_ERR_SOCKET_CONN;
197 if (sock_type == CLIENT_SOCKET) {
199 struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 };
201 if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
202 MS_DBG_ERR("setsockopt failed: %s", strerror(errno));
204 return MS_MEDIA_ERR_SOCKET_INTERNAL;
206 } else if (sock_type == SERVER_SOCKET) {
210 if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &n_reuse, sizeof(n_reuse)) == -1) {
211 MS_DBG_ERR("setsockopt failed: %s", strerror(errno));
213 return MS_MEDIA_ERR_SOCKET_INTERNAL;
219 return MS_MEDIA_ERR_NONE;
224 _ms_thumb_create_udp_socket(int *sock)
228 if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
229 MS_DBG_ERR("socket failed: %s", strerror(errno));
230 return MS_MEDIA_ERR_SOCKET_CONN;
233 struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 };
235 if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
236 MS_DBG_ERR("setsockopt failed: %s", strerror(errno));
238 return MS_MEDIA_ERR_SOCKET_INTERNAL;
243 return MS_MEDIA_ERR_NONE;
246 int _media_thumb_get_error()
248 if (errno == EWOULDBLOCK) {
249 MS_DBG_ERR("Timeout. Can't try any more");
250 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
252 MS_DBG_ERR("recvfrom failed : %s", strerror(errno));
253 return MS_MEDIA_ERR_SOCKET_RECEIVE;
258 _ms_thumb_recv_msg(int sock, int header_size, thumbMsg *msg)
260 int recv_msg_len = 0;
261 unsigned char *buf = NULL;
263 buf = (unsigned char*)malloc(header_size);
265 if ((recv_msg_len = recv(sock, buf, header_size, 0)) < 0) {
266 MS_DBG_ERR("recv failed : %s", strerror(errno));
268 return _media_thumb_get_error();
271 memcpy(msg, buf, header_size);
272 //MS_DBG("origin_path_size : %d, dest_path_size : %d", msg->origin_path_size, msg->dest_path_size);
276 if (msg->origin_path_size <= 0 || msg->origin_path_size > MS_FILE_PATH_LEN_MAX) {
278 MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->origin_path_size );
279 return MS_MEDIA_ERR_DATA_TAINTED;
282 buf = (unsigned char*)malloc(msg->origin_path_size);
284 if ((recv_msg_len = recv(sock, buf, msg->origin_path_size, 0)) < 0) {
285 MS_DBG_ERR("recv failed : %s", strerror(errno));
287 return _media_thumb_get_error();
290 strncpy(msg->org_path, (char*)buf, msg->origin_path_size);
291 //MS_DBG("original path : %s", msg->org_path);
295 if (msg->dest_path_size <= 0 || msg->dest_path_size > MS_FILE_PATH_LEN_MAX) {
297 MS_DBG_ERR("msg->dest_path_size is invalid %d", msg->dest_path_size );
298 return MS_MEDIA_ERR_DATA_TAINTED;
301 buf = (unsigned char*)malloc(msg->dest_path_size);
303 if ((recv_msg_len = recv(sock, buf, msg->dest_path_size, 0)) < 0) {
304 MS_DBG_ERR("recv failed : %s", strerror(errno));
306 return _media_thumb_get_error();
309 strncpy(msg->dst_path, (char*)buf, msg->dest_path_size);
310 //MS_DBG("destination path : %s", msg->dst_path);
313 return MS_MEDIA_ERR_NONE;
318 _ms_thumb_recv_udp_msg(int sock, int header_size, thumbMsg *msg, struct sockaddr_in *from_addr, unsigned int *from_size)
320 int recv_msg_len = 0;
321 unsigned int from_addr_size = sizeof(struct sockaddr_in);
322 unsigned char *buf = NULL;
324 buf = (unsigned char*)malloc(sizeof(thumbMsg));
326 recv_msg_len = ms_ipc_wait_message(sock, buf, sizeof(thumbMsg), from_addr, &from_addr_size);
327 if (recv_msg_len != MS_MEDIA_ERR_NONE) {
328 MS_DBG_ERR("ms_ipc_wait_message failed : %s", strerror(errno));
330 return _media_thumb_get_error();
333 memcpy(msg, buf, header_size);
334 //MS_DBG("origin_path_size : %d, dest_path_size : %d", msg->origin_path_size, msg->dest_path_size);
336 if (msg->origin_path_size <= 0 || msg->origin_path_size > MS_FILE_PATH_LEN_MAX) {
338 MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->origin_path_size );
339 return MS_MEDIA_ERR_DATA_TAINTED;
342 strncpy(msg->org_path, (char*)buf + header_size, msg->origin_path_size);
343 //MS_DBG("original path : %s", msg->org_path);
345 if (msg->dest_path_size <= 0 || msg->dest_path_size > MS_FILE_PATH_LEN_MAX) {
347 MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->dest_path_size );
348 return MS_MEDIA_ERR_DATA_TAINTED;
351 strncpy(msg->dst_path, (char*)buf + header_size + msg->origin_path_size, msg->dest_path_size);
352 //MS_DBG("destination path : %s", msg->dst_path);
355 *from_size = from_addr_size;
357 return MS_MEDIA_ERR_NONE;
361 _ms_thumb_set_buffer(thumbMsg *req_msg, unsigned char **buf, int *buf_size)
363 if (req_msg == NULL || buf == NULL) {
367 int org_path_len = 0;
368 int dst_path_len = 0;
372 header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
373 org_path_len = strlen(req_msg->org_path) + 1;
374 dst_path_len = strlen(req_msg->dst_path) + 1;
376 //MS_DBG("Basic Size : %d, org_path : %s[%d], dst_path : %s[%d]", header_size, req_msg->org_path, org_path_len, req_msg->dst_path, dst_path_len);
378 size = header_size + org_path_len + dst_path_len;
380 memcpy(*buf, req_msg, header_size);
381 memcpy((*buf)+header_size, req_msg->org_path, org_path_len);
382 memcpy((*buf)+header_size + org_path_len, req_msg->dst_path, dst_path_len);
390 void _ms_thumb_agent_child_handler(GPid pid, gint status, gpointer user_data)
392 MS_DBG_WARN("media-thumbnail-server[%d] is shutdown : %d", pid, status);
393 g_folk_thumb_server = FALSE;
396 gboolean _ms_thumb_agent_child_handler(gpointer data)
398 int pid = GPOINTER_TO_INT(data);
399 MS_DBG("media-thumbnail-server[%d] is killed", pid);
403 gboolean _ms_thumb_agent_recv_msg_from_server()
405 if (g_communicate_sock <= 0) {
406 _ms_thumb_agent_prepare_udp_socket();
409 ms_thumb_server_msg recv_msg;
410 int recv_msg_size = 0;
412 recv_msg_size = ms_ipc_receive_message(g_communicate_sock, & recv_msg, sizeof(ms_thumb_server_msg), NULL, NULL);
413 if (recv_msg_size != MS_MEDIA_ERR_NONE) {
414 MS_DBG_ERR("ms_ipc_receive_message failed : %s\n", strerror(errno));
418 //MS_DBG("Receive : %d(%d)", recv_msg.msg_type, recv_msg_size);
419 if (recv_msg.msg_type == MS_MSG_THUMB_SERVER_READY) {
420 MS_DBG("Thumbnail server is ready");
426 gboolean _ms_thumb_agent_recv_thumb_done_from_server(GIOChannel *src, GIOCondition condition, gpointer data)
430 sockfd = g_io_channel_unix_get_fd(src);
432 MS_DBG_ERR("sock fd is invalid!");
436 ms_thumb_server_msg recv_msg;
437 int recv_msg_size = 0;
439 recv_msg_size = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(ms_thumb_server_msg), NULL, NULL);
440 if (recv_msg_size != MS_MEDIA_ERR_NONE) {
441 MS_DBG_ERR("ms_ipc_receive_message failed : %s\n", strerror(errno));
445 MS_DBG("Receive : %d(%d)", recv_msg.msg_type, recv_msg_size);
446 if (recv_msg.msg_type == MS_MSG_THUMB_EXTRACT_ALL_DONE) {
447 MS_DBG("Thumbnail extracting done");
448 g_thumb_server_extracting = FALSE;
456 gboolean _ms_thumb_agent_execute_server()
463 } else if (pid == 0) {
464 execl("/usr/bin/media-thumbnail-server", "media-thumbnail-server", NULL);
466 MS_DBG("Child process is %d", pid);
467 g_folk_thumb_server = TRUE;
470 GSource *child_watch_src = g_child_watch_source_new(pid);
471 g_source_set_callback(child_watch_src, _ms_thumb_agent_child_handler, GINT_TO_POINTER(pid), NULL);
472 g_source_attach(child_watch_src, g_main_context_get_thread_default());
474 //g_child_watch_add(pid, _ms_thumb_agent_child_handler, NULL);
477 if (!_ms_thumb_agent_recv_msg_from_server()) {
478 MS_DBG_ERR("_ms_thumb_agent_recv_msg_from_server is failed");
485 gboolean _ms_thumb_agent_send_msg_to_thumb_server(thumbMsg *recv_msg, thumbMsg *res_msg)
488 const char *serv_ip = "127.0.0.1";
489 struct sockaddr_in serv_addr;
491 int send_str_len = strlen(recv_msg->org_path);
493 if (send_str_len > MAX_MSG_SIZE) {
494 MS_DBG_ERR("original path's length exceeds %d(max packet size)", MAX_MSG_SIZE);
499 /* Creaete a datagram/UDP socket */
500 if (_ms_thumb_create_udp_socket(&sock) < 0) {
501 MS_DBG_ERR("_ms_thumb_create_udp_socket failed");
505 if (ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sock) < 0) {
506 MS_DBG_ERR("ms_ipc_create_client_socket failed");
510 memset(&serv_addr, 0, sizeof(serv_addr));
511 serv_addr.sin_family = AF_INET;
512 serv_addr.sin_addr.s_addr = inet_addr(serv_ip);
513 serv_addr.sin_port = htons(MS_THUMB_DAEMON_PORT);
517 unsigned char *buf = NULL;
518 _ms_thumb_set_buffer(recv_msg, &buf, &buf_size);
520 //MS_DBG("buffer size : %d", buf_size);
521 if (sendto(sock, buf, buf_size, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != buf_size) {
522 MS_DBG_ERR("sendto failed: %s\n", strerror(errno));
529 MS_DBG("Sending msg to thumbnail server is successful");
531 struct sockaddr_in client_addr;
532 unsigned int client_addr_len;
533 header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
535 if (_ms_thumb_recv_udp_msg(sock, header_size, res_msg, &client_addr, &client_addr_len) < 0) {
536 MS_DBG_ERR("_ms_thumb_recv_udp_msg failed");
541 MS_DBG("recv %s from thumb daemon is successful", res_msg->dst_path);
544 if (res_msg->msg_type == 2 && g_communicate_sock > 0) { // THUMB_REQUEST_ALL_MEDIA
545 /* Create new channel to watch udp socket */
546 GSource *source = NULL;
547 if (g_udp_channel == NULL)
548 g_udp_channel = g_io_channel_unix_new(g_communicate_sock);
549 source = g_io_create_watch(g_udp_channel, G_IO_IN);
551 /* Set callback to be called when socket is readable */
552 g_source_set_callback(source, (GSourceFunc)_ms_thumb_agent_recv_thumb_done_from_server, NULL, NULL);
553 g_source_attach(source, g_main_context_get_thread_default());
555 g_thumb_server_extracting = TRUE;
561 gboolean _ms_thumb_agent_timer()
563 if (g_thumb_server_extracting) {
564 MS_DBG("Timer is called.. But media-thumbnail-server[%d] is busy.. so timer is recreated", g_server_pid);
566 _ms_thumb_create_timer(g_timer_id);
571 MS_DBG("Timer is called.. Now killing media-thumbnail-server[%d]", g_server_pid);
573 if (g_server_pid > 0) {
575 if (kill(g_server_pid, SIGKILL) < 0) {
576 MS_DBG_ERR("kill failed : %s", strerror(errno));
579 /* Kill thumbnail server */
582 memset((void *)&msg, 0, sizeof(msg));
583 memset((void *)&recv_msg, 0, sizeof(recv_msg));
585 msg.msg_type = 5; // THUMB_REQUEST_KILL_SERVER
586 msg.org_path[0] = '\0';
587 msg.origin_path_size = 1;
588 msg.dst_path[0] = '\0';
589 msg.dest_path_size = 1;
591 /* Command Kill to thumbnail server */
592 if (!_ms_thumb_agent_send_msg_to_thumb_server(&msg, &recv_msg)) {
593 MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed");
598 MS_DBG_ERR("g_server_pid is %d. Maybe there's problem in thumbnail-server", g_server_pid);
605 gboolean _ms_thumb_agent_read_socket(GIOChannel *src,
606 GIOCondition condition,
609 struct sockaddr_in client_addr;
610 unsigned int client_addr_len;
616 int client_sock = -1;
618 sock = g_io_channel_unix_get_fd(src);
620 MS_DBG_ERR("sock fd is invalid!");
624 memset((void *)&recv_msg, 0, sizeof(thumbMsg));
625 memset((void *)&res_msg, 0, sizeof(res_msg));
626 header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
628 if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
629 MS_DBG_ERR("accept failed : %s", strerror(errno));
633 MS_DBG("Client[%d] is accepted", client_sock);
635 if (_ms_thumb_recv_msg(client_sock, header_size, &recv_msg) < 0) {
636 MS_DBG_ERR("_ms_thumb_recv_msg failed ");
641 MS_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);
643 if (g_folk_thumb_server == FALSE && g_thumb_server_extracting == FALSE) {
644 if(_ms_thumb_check_process() == FALSE) { // This logic is temporary
645 MS_DBG_WARN("Thumb server is not running.. so start it");
646 if (!_ms_thumb_agent_execute_server()) {
647 MS_DBG_ERR("_ms_thumb_agent_execute_server is failed");
651 GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_20);
652 g_source_set_callback (timer_src, _ms_thumb_agent_timer, NULL, NULL);
653 g_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default());
657 if (g_timer_id > 0) {
658 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), g_timer_id));
659 //MS_DBG("Timer is recreated");
660 GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_20);
661 g_source_set_callback (timer_src, _ms_thumb_agent_timer, NULL, NULL);
662 g_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default());
666 if (!_ms_thumb_agent_send_msg_to_thumb_server(&recv_msg, &res_msg)) {
667 MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed");
672 strncpy(res_msg.org_path, recv_msg.org_path, recv_msg.origin_path_size);
673 res_msg.origin_path_size = recv_msg.origin_path_size;
674 res_msg.dest_path_size = strlen(res_msg.dst_path) + 1;
677 unsigned char *buf = NULL;
678 _ms_thumb_set_buffer(&res_msg, &buf, &buf_size);
680 //MS_DBG("buffer size : %d", buf_size);
682 if (send(client_sock, buf, buf_size, 0) != buf_size) {
683 MS_DBG_ERR("sendto failed : %s", strerror(errno));
685 MS_DBG("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path));
693 int _ms_thumb_cancel_media(const char *path, int pid)
699 req_len = g_queue_get_length(g_request_queue);
701 MS_DBG("Queue length : %d", req_len);
703 for (i = 0; i < req_len; i++) {
704 thumbRequest *req = NULL;
705 req = (thumbRequest *)g_queue_peek_nth(g_request_queue, i);
706 if (req == NULL) continue;
708 if ((req->recv_msg->pid) == pid && (strncmp(path, req->recv_msg->org_path, strlen(path))) == 0) {
709 MS_DBG("Remove %s from queue", req->recv_msg->org_path);
710 g_queue_pop_nth(g_request_queue, i);
712 close(req->client_sock);
713 MS_SAFE_FREE(req->recv_msg);
724 int _ms_thumb_cancel_all(int pid)
730 req_len = g_queue_get_length(g_request_queue);
732 MS_DBG("Queue length : %d", req_len);
734 for (i = 0; i < req_len; i++) {
735 thumbRequest *req = NULL;
736 req = (thumbRequest *)g_queue_peek_nth(g_request_queue, i);
737 if (req == NULL) continue;
739 if (req->recv_msg->pid == pid) {
740 MS_DBG("Remove [%d] %s from queue", req->recv_msg->pid, req->recv_msg->org_path);
741 g_queue_pop_nth(g_request_queue, i);
745 close(req->client_sock);
746 MS_SAFE_FREE(req->recv_msg);
755 void _ms_thumb_cancle_request(thumbRequest *thumb_req)
760 if (thumb_req == NULL) return;
762 thumbMsg *recv_msg = thumb_req->recv_msg;
763 if (recv_msg == NULL) {
764 MS_SAFE_FREE(thumb_req);
768 if (recv_msg->msg_type == 3)
769 ret = _ms_thumb_cancel_media(recv_msg->org_path, recv_msg->pid);
770 else if (recv_msg->msg_type == 4)
771 ret = _ms_thumb_cancel_all(recv_msg->pid);
774 recv_msg->status = 0; // THUMB_SUCCESS
776 recv_msg->status = 0; // THUMB_SUCCESS
779 if (recv_msg->origin_path_size <= 0 || recv_msg->origin_path_size > MS_FILE_PATH_LEN_MAX) {
780 MS_DBG_ERR("recv_msg->origin_path_size is invalid %d", recv_msg->origin_path_size );
784 recv_msg->dest_path_size = recv_msg->origin_path_size;
785 strncpy(recv_msg->dst_path, recv_msg->org_path, recv_msg->dest_path_size);
788 unsigned char *buf = NULL;
789 _ms_thumb_set_buffer(recv_msg, &buf, &buf_size);
791 if (send(thumb_req->client_sock, buf, buf_size, 0) != buf_size) {
792 MS_DBG_ERR("sendto failed : %s", strerror(errno));
794 MS_DBG("Sent response");
797 close(thumb_req->client_sock);
799 MS_SAFE_FREE(thumb_req->recv_msg);
800 MS_SAFE_FREE(thumb_req);
805 gboolean _ms_thumb_request_to_server(gpointer data)
809 req_len = g_queue_get_length(g_request_queue);
811 MS_DBG("Queue length : %d", req_len);
814 MS_DBG("There is no request job in the queue");
819 if (g_folk_thumb_server == FALSE && g_thumb_server_extracting == FALSE) {
820 if(_ms_thumb_check_process() == FALSE) { // This logic is temporary
821 MS_DBG_WARN("Thumb server is not running.. so start it");
822 if (!_ms_thumb_agent_execute_server()) {
823 MS_DBG_ERR("_ms_thumb_agent_execute_server is failed");
827 _ms_thumb_create_timer(g_timer_id);
831 /* Timer is re-created*/
832 _ms_thumb_create_timer(g_timer_id);
835 thumbRequest *req = NULL;
836 req = (thumbRequest *)g_queue_pop_head(g_request_queue);
839 MS_DBG_ERR("Failed to get a request job from queue");
843 int client_sock = -1;
844 thumbMsg *recv_msg = NULL;
846 memset((void *)&res_msg, 0, sizeof(res_msg));
848 client_sock = req->client_sock;
849 recv_msg = req->recv_msg;
851 if (req->client_sock <=0 || req->recv_msg == NULL) {
852 MS_DBG_ERR("client sock is below 0 or recv msg is NULL");
853 MS_SAFE_FREE(req->recv_msg);
859 if (!_ms_thumb_agent_send_msg_to_thumb_server(recv_msg, &res_msg)) {
860 MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed");
863 MS_SAFE_FREE(req->recv_msg);
868 MS_DBG_ERR("recv_msg is NULL from queue request");
871 strncpy(res_msg.org_path, recv_msg->org_path, recv_msg->origin_path_size);
872 res_msg.origin_path_size = recv_msg->origin_path_size;
873 res_msg.dest_path_size = strlen(res_msg.dst_path) + 1;
876 unsigned char *buf = NULL;
877 _ms_thumb_set_buffer(&res_msg, &buf, &buf_size);
879 if (send(client_sock, buf, buf_size, 0) != buf_size) {
880 MS_DBG_ERR("sendto failed : %s", strerror(errno));
882 MS_DBG("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path));
887 MS_SAFE_FREE(req->recv_msg);
893 gboolean _ms_thumb_agent_read_socket(GIOChannel *src,
894 GIOCondition condition,
897 struct sockaddr_in client_addr;
898 unsigned int client_addr_len;
900 thumbMsg *recv_msg = NULL;
903 int client_sock = -1;
905 sock = g_io_channel_unix_get_fd(src);
907 MS_DBG_ERR("sock fd is invalid!");
911 header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
912 client_addr_len = sizeof(client_addr);
914 if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
915 MS_DBG_ERR("accept failed : %s", strerror(errno));
919 MS_DBG("Client[%d] is accepted", client_sock);
921 recv_msg = calloc(1, sizeof(thumbMsg));
922 if (recv_msg == NULL) {
923 MS_DBG_ERR("Failed to allocate memory");
928 if (_ms_thumb_recv_msg(client_sock, header_size, recv_msg) < 0) {
929 MS_DBG_ERR("_ms_thumb_recv_msg failed ");
931 MS_SAFE_FREE(recv_msg);
935 MS_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);
937 thumbRequest *thumb_req = NULL;
938 thumb_req = calloc(1, sizeof(thumbRequest));
939 if (thumb_req == NULL) {
940 MS_DBG_ERR("Failed to create request element");
942 MS_SAFE_FREE(recv_msg);
946 thumb_req->client_sock = client_sock;
947 thumb_req->recv_msg = recv_msg;
949 if (recv_msg->msg_type == 3 || recv_msg->msg_type == 4) { // THUMB_REQUEST_CANCEL_MEDIA || THUMB_REQUEST_CANCEL_ALL
950 _ms_thumb_cancle_request(thumb_req);
954 if (g_request_queue == NULL) {
955 MS_DBG_WARN("queue is init");
956 g_request_queue = g_queue_new();
959 MS_DBG("%s is queued", recv_msg->org_path);
960 g_queue_push_tail(g_request_queue, (gpointer)thumb_req);
963 GSource *src_request = NULL;
964 src_request = g_idle_source_new ();
965 g_source_set_callback (src_request, _ms_thumb_request_to_server, NULL, NULL);
966 //g_source_set_priority(src_request, G_PRIORITY_LOW);
967 g_source_attach (src_request, g_main_context_get_thread_default());
976 gboolean _ms_thumb_agent_prepare_tcp_socket(int *sock_fd)
979 unsigned short serv_port;
981 serv_port = MS_THUMB_CREATOR_PORT;
984 struct sockaddr_in serv_addr;
986 /* Create a TCP socket */
987 if (_ms_thumb_create_socket(SERVER_SOCKET, &sock) < 0) {
988 MS_DBG_ERR("_ms_thumb_create_socket failed");
992 memset(&serv_addr, 0, sizeof(serv_addr));
993 serv_addr.sin_family = AF_INET;
994 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
995 serv_addr.sin_port = htons(serv_port);
997 /* Bind to the local address */
998 if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
999 MS_DBG_ERR("bind failed");
1003 MS_DBG("bind success");
1006 if (listen(sock, SOMAXCONN) < 0) {
1007 MS_DBG_ERR("listen failed : %s", strerror(errno));
1011 MS_DBG("Listening...");
1013 if (ms_ipc_create_server_socket(MS_PROTOCOL_TCP, serv_port, &sock) < 0) {
1014 MS_DBG_ERR("_ms_thumb_create_socket failed");
1023 gboolean _ms_thumb_agent_prepare_udp_socket()
1026 unsigned short serv_port;
1028 serv_port = MS_THUMB_COMM_PORT;
1030 if (ms_ipc_create_server_socket(MS_PROTOCOL_UDP, serv_port, &sock) < 0) {
1031 MS_DBG_ERR("ms_ipc_create_client_socket failed");
1035 struct sockaddr_in serv_addr;
1037 /* Creaete a UDP socket */
1038 if (_ms_thumb_create_udp_socket(&sock) < 0) {
1039 MS_DBG_ERR("_ms_thumb_create_udp_socket failed");
1043 memset(&serv_addr, 0, sizeof(serv_addr));
1044 serv_addr.sin_family = AF_INET;
1045 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1046 serv_addr.sin_port = htons(serv_port);
1048 /* Bind to the local address */
1049 if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
1050 MS_DBG_ERR("bind failed");
1054 MS_DBG("bind success");
1056 g_communicate_sock = sock;
1061 gpointer ms_thumb_agent_start_thread(gpointer data)
1066 GSource *source = NULL;
1067 GIOChannel *channel = NULL;
1068 GMainContext *context = NULL;
1070 /* Create and bind new TCP socket */
1071 if (!_ms_thumb_agent_prepare_tcp_socket(&sockfd)) {
1072 MS_DBG_ERR("Failed to create socket\n");
1076 context = g_main_context_new();
1078 if (context == NULL) {
1079 MS_DBG_ERR("g_main_context_new failed");
1081 MS_DBG("g_main_context_new success");
1084 g_thumb_agent_loop = g_main_loop_new(context, FALSE);
1085 g_main_context_push_thread_default(context);
1087 /* Create new channel to watch udp socket */
1088 channel = g_io_channel_unix_new(sockfd);
1089 source = g_io_create_watch(channel, G_IO_IN);
1091 /* Set callback to be called when socket is readable */
1092 g_source_set_callback(source, (GSourceFunc)_ms_thumb_agent_read_socket, NULL, NULL);
1093 g_source_attach(source, context);
1096 MS_DBG("************************************");
1097 MS_DBG("*** Thumbnail Agent thread is running ***");
1098 MS_DBG("************************************");
1100 g_main_loop_run(g_thumb_agent_loop);
1102 MS_DBG("Thumbnail Agent thread is shutting down...");
1103 _ms_thumb_agent_finish_jobs();
1105 /*close an IO channel*/
1106 g_io_channel_shutdown(channel, FALSE, NULL);
1107 g_io_channel_shutdown(g_udp_channel, FALSE, NULL);
1108 g_io_channel_unref(channel);
1109 close(g_communicate_sock);
1111 g_main_loop_unref(g_thumb_agent_loop);