Tizen 2.1 base
[framework/multimedia/media-server.git] / common / media-server-thumb.c
1 /*
2  * media-thumbnail-server
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyunjun Ko <zzoon.ko@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <dirent.h>
23 #include <errno.h>
24
25 #include "media-util.h"
26 #include "media-server-dbg.h"
27 #include "media-server-thumb.h"
28 #include "media-server-utils.h"
29
30 #ifdef LOG_TAG
31 #undef LOG_TAG
32 #endif
33
34 #define LOG_TAG "MEDIA_SERVER_THUMB"
35
36 #define THUMB_SERVER_NAME "media-thumbnail"
37
38 gboolean _ms_thumb_agent_timer();
39
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;
47
48 static GQueue *g_request_queue = NULL;
49 static int g_queue_work = 0;
50
51 typedef struct {
52         int client_sock;
53         thumbMsg *recv_msg;
54 } thumbRequest;
55
56 gboolean _ms_thumb_agent_start_jobs(gpointer data)
57 {
58         MS_DBG("");
59
60         return FALSE;
61 }
62
63 void _ms_thumb_agent_finish_jobs()
64 {
65         MS_DBG("");
66
67         return;
68 }
69
70 GMainLoop *
71 ms_get_thumb_thread_mainloop(void)
72 {
73         return g_thumb_agent_loop;
74 }
75
76 int ms_thumb_get_server_pid()
77 {
78         return g_server_pid;
79 }
80
81 void ms_thumb_reset_server_status()
82 {
83         g_folk_thumb_server = FALSE;
84
85         if (g_timer_id > 0) {
86                 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), g_timer_id));
87                 g_timer_id = 0;
88         }
89
90         if (g_thumb_server_extracting) {
91                 /* Need to inplement when crash happens */
92 #if 0
93                 /* Restart thumbnail server */
94                 if (_ms_thumb_agent_execute_server() < 0) {
95                         MS_DBG_ERR("starting thumbnail-server failed");
96                 } else {
97                         MS_DBG("Thumbnail-server is started");
98                 }
99
100                 thumbMsg msg;
101                 thumbMsg recv_msg;
102                 memset((void *)&msg, 0, sizeof(msg));
103                 memset((void *)&recv_msg, 0, sizeof(recv_msg));
104
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;
110
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");
114                 }
115
116                 _ms_thumb_create_timer(g_timer_id);
117 #else
118                 MS_DBG_ERR("Thumbnail server is dead when processing all-thumbs extraction");
119                 g_thumb_server_extracting = FALSE;
120                 g_server_pid = 0;
121 #endif
122         } else {
123                 g_thumb_server_extracting = FALSE;
124                 g_server_pid = 0;
125         }
126
127         return;
128 }
129
130 void _ms_thumb_create_timer(int id)
131 {
132         if (id > 0)
133                 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), id));
134
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());
138
139 }
140
141 /* This checks if thumbnail server is running */
142 bool _ms_thumb_check_process()
143 {
144         DIR *pdir;
145         struct dirent pinfo;
146         struct dirent *result = NULL;
147         bool ret = FALSE;
148
149         pdir = opendir("/proc");
150         if (pdir == NULL) {
151                 MS_DBG_ERR("err: NO_DIR\n");
152                 return 0;
153         }
154
155         while (!readdir_r(pdir, &pinfo, &result)) {
156                 if (result == NULL)
157                         break;
158
159                 if (pinfo.d_type != 4 || pinfo.d_name[0] == '.'
160                     || pinfo.d_name[0] > 57)
161                         continue;
162
163                 FILE *fp;
164                 char buff[128];
165                 char path[128];
166
167                 ms_strcopy(path, sizeof(path), "/proc/%s/status", pinfo.d_name);
168                 fp = fopen(path, "rt");
169                 if (fp) {
170                         if (fgets(buff, 128, fp) == NULL)
171                                 MS_DBG_ERR("fgets failed");
172                         fclose(fp);
173
174                         if (strstr(buff, THUMB_SERVER_NAME)) {
175                                 ret = TRUE;
176                                 break;
177                         }
178                 } else {
179                         MS_DBG_ERR("Can't read file [%s]", path);
180                 }
181         }
182
183         closedir(pdir);
184
185         return ret;
186 }
187 int
188 _ms_thumb_create_socket(int sock_type, int *sock)
189 {
190         int sock_fd = 0;
191
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;
195         }
196
197         if (sock_type == CLIENT_SOCKET) {
198
199                 struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 };
200
201                 if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
202                         MS_DBG_ERR("setsockopt failed: %s", strerror(errno));
203                         close(sock_fd);
204                         return MS_MEDIA_ERR_SOCKET_INTERNAL;
205                 }
206         } else if (sock_type == SERVER_SOCKET) {
207
208                 int n_reuse = 1;
209
210                 if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &n_reuse, sizeof(n_reuse)) == -1) {
211                         MS_DBG_ERR("setsockopt failed: %s", strerror(errno));
212                         close(sock_fd);
213                         return MS_MEDIA_ERR_SOCKET_INTERNAL;
214                 }
215         }
216
217         *sock = sock_fd;
218
219         return MS_MEDIA_ERR_NONE;
220 }
221
222
223 int
224 _ms_thumb_create_udp_socket(int *sock)
225 {
226         int sock_fd = 0;
227
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;
231         }
232
233         struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 };
234
235         if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
236                 MS_DBG_ERR("setsockopt failed: %s", strerror(errno));
237                 close(sock_fd);
238                 return MS_MEDIA_ERR_SOCKET_INTERNAL;
239         }
240
241         *sock = sock_fd;
242
243         return MS_MEDIA_ERR_NONE;
244 }
245
246 int _media_thumb_get_error()
247 {
248         if (errno == EWOULDBLOCK) {
249                 MS_DBG_ERR("Timeout. Can't try any more");
250                 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
251         } else {
252                 MS_DBG_ERR("recvfrom failed : %s", strerror(errno));
253                 return MS_MEDIA_ERR_SOCKET_RECEIVE;
254         }
255 }
256
257 int
258 _ms_thumb_recv_msg(int sock, int header_size, thumbMsg *msg)
259 {
260         int recv_msg_len = 0;
261         unsigned char *buf = NULL;
262
263         buf = (unsigned char*)malloc(header_size);
264
265         if ((recv_msg_len = recv(sock, buf, header_size, 0)) < 0) {
266                 MS_DBG_ERR("recv failed : %s", strerror(errno));
267                 MS_SAFE_FREE(buf);
268                 return _media_thumb_get_error();
269         }
270
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);
273
274         MS_SAFE_FREE(buf);
275
276         if (msg->origin_path_size <= 0  || msg->origin_path_size > MS_FILE_PATH_LEN_MAX) {
277                 MS_SAFE_FREE(buf);
278                 MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->origin_path_size );
279                 return MS_MEDIA_ERR_DATA_TAINTED;
280         }
281
282         buf = (unsigned char*)malloc(msg->origin_path_size);
283
284         if ((recv_msg_len = recv(sock, buf, msg->origin_path_size, 0)) < 0) {
285                 MS_DBG_ERR("recv failed : %s", strerror(errno));
286                 MS_SAFE_FREE(buf);
287                 return _media_thumb_get_error();
288         }
289
290         strncpy(msg->org_path, (char*)buf, msg->origin_path_size);
291         //MS_DBG("original path : %s", msg->org_path);
292
293         MS_SAFE_FREE(buf);
294
295         if (msg->dest_path_size <= 0  || msg->dest_path_size > MS_FILE_PATH_LEN_MAX) {
296                 MS_SAFE_FREE(buf);
297                 MS_DBG_ERR("msg->dest_path_size is invalid %d", msg->dest_path_size );
298                 return MS_MEDIA_ERR_DATA_TAINTED;
299         }
300
301         buf = (unsigned char*)malloc(msg->dest_path_size);
302
303         if ((recv_msg_len = recv(sock, buf, msg->dest_path_size, 0)) < 0) {
304                 MS_DBG_ERR("recv failed : %s", strerror(errno));
305                 MS_SAFE_FREE(buf);
306                 return _media_thumb_get_error();
307         }
308
309         strncpy(msg->dst_path, (char*)buf, msg->dest_path_size);
310         //MS_DBG("destination path : %s", msg->dst_path);
311
312         MS_SAFE_FREE(buf);
313         return MS_MEDIA_ERR_NONE;
314 }
315
316
317 int
318 _ms_thumb_recv_udp_msg(int sock, int header_size, thumbMsg *msg, struct sockaddr_in *from_addr, unsigned int *from_size)
319 {
320         int recv_msg_len = 0;
321         unsigned int from_addr_size = sizeof(struct sockaddr_in);
322         unsigned char *buf = NULL;
323
324         buf = (unsigned char*)malloc(sizeof(thumbMsg));
325
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));
329                 MS_SAFE_FREE(buf);
330                 return _media_thumb_get_error();
331         }
332
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);
335
336         if (msg->origin_path_size <= 0  || msg->origin_path_size > MS_FILE_PATH_LEN_MAX) {
337                 MS_SAFE_FREE(buf);
338                 MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->origin_path_size );
339                 return MS_MEDIA_ERR_DATA_TAINTED;
340         }
341
342         strncpy(msg->org_path, (char*)buf + header_size, msg->origin_path_size);
343         //MS_DBG("original path : %s", msg->org_path);
344
345         if (msg->dest_path_size <= 0  || msg->dest_path_size > MS_FILE_PATH_LEN_MAX) {
346                 MS_SAFE_FREE(buf);
347                 MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->dest_path_size );
348                 return MS_MEDIA_ERR_DATA_TAINTED;
349         }
350
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);
353
354         MS_SAFE_FREE(buf);
355         *from_size = from_addr_size;
356
357         return MS_MEDIA_ERR_NONE;
358 }
359
360 int
361 _ms_thumb_set_buffer(thumbMsg *req_msg, unsigned char **buf, int *buf_size)
362 {
363         if (req_msg == NULL || buf == NULL) {
364                 return -1;
365         }
366
367         int org_path_len = 0;
368         int dst_path_len = 0;
369         int size = 0;
370         int header_size = 0;
371
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;
375
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);
377
378         size = header_size + org_path_len + dst_path_len;
379         *buf = malloc(size);
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);
383
384         *buf_size = size;
385
386         return 0;
387 }
388
389 /*
390 void _ms_thumb_agent_child_handler(GPid pid, gint status, gpointer user_data)
391 {
392         MS_DBG_WARN("media-thumbnail-server[%d] is shutdown : %d", pid, status);
393         g_folk_thumb_server = FALSE;
394 }
395 */
396 gboolean _ms_thumb_agent_child_handler(gpointer data)
397 {
398         int pid = GPOINTER_TO_INT(data);
399         MS_DBG("media-thumbnail-server[%d] is killed", pid);
400         return FALSE;
401 }
402
403 gboolean _ms_thumb_agent_recv_msg_from_server()
404 {
405         if (g_communicate_sock <= 0) {
406                 _ms_thumb_agent_prepare_udp_socket();
407         }
408
409         ms_thumb_server_msg recv_msg;
410         int recv_msg_size = 0;
411
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));
415                 return FALSE;
416         }
417
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");
421         }
422
423         return TRUE;
424 }
425
426 gboolean _ms_thumb_agent_recv_thumb_done_from_server(GIOChannel *src, GIOCondition condition, gpointer data)
427 {
428         int sockfd = -1;
429
430         sockfd = g_io_channel_unix_get_fd(src);
431         if (sockfd < 0) {
432                 MS_DBG_ERR("sock fd is invalid!");
433                 return FALSE;
434         }
435
436         ms_thumb_server_msg recv_msg;
437         int recv_msg_size = 0;
438
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));
442                 return FALSE;
443         }
444
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;
449
450                 return FALSE;
451         }
452
453         return FALSE;
454 }
455
456 gboolean _ms_thumb_agent_execute_server()
457 {
458         int pid;
459         pid = fork();
460
461         if (pid < 0) {
462                 return FALSE;
463         } else if (pid == 0) {
464                 execl("/usr/bin/media-thumbnail-server", "media-thumbnail-server", NULL);
465         } else {
466                 MS_DBG("Child process is %d", pid);
467                 g_folk_thumb_server = TRUE;
468         }
469 #if 0
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());
473 #endif
474         //g_child_watch_add(pid, _ms_thumb_agent_child_handler, NULL);
475         g_server_pid = pid;
476
477         if (!_ms_thumb_agent_recv_msg_from_server()) {
478                 MS_DBG_ERR("_ms_thumb_agent_recv_msg_from_server is failed");
479                 return FALSE;
480         }
481
482         return TRUE;
483 }
484
485 gboolean _ms_thumb_agent_send_msg_to_thumb_server(thumbMsg *recv_msg, thumbMsg *res_msg)
486 {
487         int sock;
488         const char *serv_ip = "127.0.0.1";
489         struct sockaddr_in serv_addr;
490
491         int send_str_len = strlen(recv_msg->org_path);
492
493         if (send_str_len > MAX_MSG_SIZE) {
494                 MS_DBG_ERR("original path's length exceeds %d(max packet size)", MAX_MSG_SIZE);
495                 return FALSE;
496         }
497
498 #if 0
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");
502                 return FALSE;
503         }
504 #endif
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");
507                 return FALSE;
508         }
509
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);
514
515         int buf_size = 0;
516         int header_size = 0;
517         unsigned char *buf = NULL;
518         _ms_thumb_set_buffer(recv_msg, &buf, &buf_size);
519
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));
523                 MS_SAFE_FREE(buf);
524                 close(sock);
525                 return FALSE;
526         }
527
528         MS_SAFE_FREE(buf);
529         MS_DBG("Sending msg to thumbnail server is successful");
530
531         struct sockaddr_in client_addr;
532         unsigned int client_addr_len;
533         header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
534
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");
537                 close(sock);
538                 return FALSE;
539         }
540
541         MS_DBG("recv %s from thumb daemon is successful", res_msg->dst_path);
542         close(sock);
543
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);
550
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());
554
555                 g_thumb_server_extracting = TRUE;
556         }
557
558         return TRUE;
559 }
560
561 gboolean _ms_thumb_agent_timer()
562 {
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);
565
566                 _ms_thumb_create_timer(g_timer_id);
567                 return FALSE;
568         }
569
570         g_timer_id = 0;
571         MS_DBG("Timer is called.. Now killing media-thumbnail-server[%d]", g_server_pid);
572
573         if (g_server_pid > 0) {
574 #if 0
575                 if (kill(g_server_pid, SIGKILL) < 0) {
576                         MS_DBG_ERR("kill failed : %s", strerror(errno));
577                 }
578 #else
579                 /* Kill thumbnail server */
580                 thumbMsg msg;
581                 thumbMsg recv_msg;
582                 memset((void *)&msg, 0, sizeof(msg));
583                 memset((void *)&recv_msg, 0, sizeof(recv_msg));
584
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;
590
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");
594                 }
595 #endif
596                 usleep(200000);
597         } else {
598                 MS_DBG_ERR("g_server_pid is %d. Maybe there's problem in thumbnail-server", g_server_pid);
599         }
600
601         return FALSE;
602 }
603
604 #if 0
605 gboolean _ms_thumb_agent_read_socket(GIOChannel *src,
606                                                                         GIOCondition condition,
607                                                                         gpointer data)
608 {
609         struct sockaddr_in client_addr;
610         unsigned int client_addr_len;
611
612         thumbMsg recv_msg;
613         thumbMsg res_msg;
614         int header_size = 0;
615         int sock = -1;
616         int client_sock = -1;
617
618         sock = g_io_channel_unix_get_fd(src);
619         if (sock < 0) {
620                 MS_DBG_ERR("sock fd is invalid!");
621                 return TRUE;
622         }
623
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;
627
628         if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
629                 MS_DBG_ERR("accept failed : %s", strerror(errno));
630                 return TRUE;
631         }
632
633         MS_DBG("Client[%d] is accepted", client_sock);
634
635         if (_ms_thumb_recv_msg(client_sock, header_size, &recv_msg) < 0) {
636                 MS_DBG_ERR("_ms_thumb_recv_msg failed ");
637                 close(client_sock);
638                 return TRUE;
639         }
640
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);
642
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");
648                         return TRUE;
649                 } else {
650
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());
654                 }
655                 }
656         } else {
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());
663                 }
664         }
665
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");
668
669                 return TRUE;
670         }
671
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;
675
676         int buf_size = 0;
677         unsigned char *buf = NULL;
678         _ms_thumb_set_buffer(&res_msg, &buf, &buf_size);
679
680         //MS_DBG("buffer size : %d", buf_size);
681
682         if (send(client_sock, buf, buf_size, 0) != buf_size) {
683                 MS_DBG_ERR("sendto failed : %s", strerror(errno));
684         } else {
685                 MS_DBG("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path));
686         }
687
688         close(client_sock);
689         MS_SAFE_FREE(buf);
690         return TRUE;
691 }
692 #else
693 int _ms_thumb_cancel_media(const char *path, int pid)
694 {
695         int ret = -1;
696         int i = 0;
697         int req_len = 0;
698
699         req_len = g_queue_get_length(g_request_queue);
700
701         MS_DBG("Queue length : %d", req_len);
702
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;
707
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);
711
712                         close(req->client_sock);
713                         MS_SAFE_FREE(req->recv_msg);
714                         MS_SAFE_FREE(req);
715                         ret = 0;
716
717                         break;
718                 }
719         }
720
721         return ret;
722 }
723
724 int _ms_thumb_cancel_all(int pid)
725 {
726         int ret = -1;
727         int i = 0;
728         int req_len = 0;
729
730         req_len = g_queue_get_length(g_request_queue);
731
732         MS_DBG("Queue length : %d", req_len);
733
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;
738
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);
742                         i--;
743                         req_len--;
744
745                         close(req->client_sock);
746                         MS_SAFE_FREE(req->recv_msg);
747                         MS_SAFE_FREE(req);
748                         ret = 0;
749                 }
750         }
751
752         return ret;
753 }
754
755 void _ms_thumb_cancle_request(thumbRequest *thumb_req)
756 {
757         MS_DBG("");
758         int ret = -1;
759
760         if (thumb_req == NULL) return;
761
762         thumbMsg *recv_msg = thumb_req->recv_msg;
763         if (recv_msg == NULL) {
764                 MS_SAFE_FREE(thumb_req);
765                 return;
766         }
767
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);
772
773         if (ret == 0) {
774                 recv_msg->status = 0;  // THUMB_SUCCESS
775         } else {
776                 recv_msg->status = 0;  // THUMB_SUCCESS
777         }
778
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 );
781                 return;
782         }
783
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);
786 /*
787         int buf_size = 0;
788         unsigned char *buf = NULL;
789         _ms_thumb_set_buffer(recv_msg, &buf, &buf_size);
790
791         if (send(thumb_req->client_sock, buf, buf_size, 0) != buf_size) {
792                 MS_DBG_ERR("sendto failed : %s", strerror(errno));
793         } else {
794                 MS_DBG("Sent response");
795         }
796 */
797         close(thumb_req->client_sock);
798         //MS_SAFE_FREE(buf);
799         MS_SAFE_FREE(thumb_req->recv_msg);
800         MS_SAFE_FREE(thumb_req);
801
802         return;
803 }
804
805 gboolean _ms_thumb_request_to_server(gpointer data)
806 {
807         int req_len = 0;
808
809         req_len = g_queue_get_length(g_request_queue);
810
811         MS_DBG("Queue length : %d", req_len);
812
813         if (req_len <= 0) {
814                 MS_DBG("There is no request job in the queue");
815                 g_queue_work = 0;
816                 return FALSE;
817         }
818
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");
824                                 g_queue_work = 0;
825                                 return FALSE;
826                         } else {
827                                 _ms_thumb_create_timer(g_timer_id);
828                         }
829                 }
830         } else {
831                 /* Timer is re-created*/
832                 _ms_thumb_create_timer(g_timer_id);
833         }
834
835         thumbRequest *req = NULL;
836         req = (thumbRequest *)g_queue_pop_head(g_request_queue);
837
838         if (req == NULL) {
839                 MS_DBG_ERR("Failed to get a request job from queue");
840                 return TRUE;
841         }
842
843         int client_sock = -1;
844         thumbMsg *recv_msg = NULL;
845         thumbMsg res_msg;
846         memset((void *)&res_msg, 0, sizeof(res_msg));
847
848         client_sock = req->client_sock;
849         recv_msg = req->recv_msg;
850
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);
854                 MS_SAFE_FREE(req);
855                 return TRUE;
856         }
857
858         if (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");
861
862                         close(client_sock);
863                         MS_SAFE_FREE(req->recv_msg);
864                         MS_SAFE_FREE(req);
865                         return TRUE;
866                 }
867         } else {
868                 MS_DBG_ERR("recv_msg is NULL from queue request");
869         }
870
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;
874
875         int buf_size = 0;
876         unsigned char *buf = NULL;
877         _ms_thumb_set_buffer(&res_msg, &buf, &buf_size);
878
879         if (send(client_sock, buf, buf_size, 0) != buf_size) {
880                 MS_DBG_ERR("sendto failed : %s", strerror(errno));
881         } else {
882                 MS_DBG("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path));
883         }
884
885         close(client_sock);
886         MS_SAFE_FREE(buf);
887         MS_SAFE_FREE(req->recv_msg);
888         MS_SAFE_FREE(req);
889
890         return TRUE;
891 }
892
893 gboolean _ms_thumb_agent_read_socket(GIOChannel *src,
894                                                                         GIOCondition condition,
895                                                                         gpointer data)
896 {
897         struct sockaddr_in client_addr;
898         unsigned int client_addr_len;
899
900         thumbMsg *recv_msg = NULL;
901         int header_size = 0;
902         int sock = -1;
903         int client_sock = -1;
904
905         sock = g_io_channel_unix_get_fd(src);
906         if (sock < 0) {
907                 MS_DBG_ERR("sock fd is invalid!");
908                 return TRUE;
909         }
910
911         header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
912         client_addr_len = sizeof(client_addr);
913
914         if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
915                 MS_DBG_ERR("accept failed : %s", strerror(errno));
916                 return TRUE;
917         }
918
919         MS_DBG("Client[%d] is accepted", client_sock);
920
921         recv_msg = calloc(1, sizeof(thumbMsg));
922         if (recv_msg == NULL) {
923                 MS_DBG_ERR("Failed to allocate memory");
924                 close(client_sock);
925                 return TRUE;
926         }
927
928         if (_ms_thumb_recv_msg(client_sock, header_size, recv_msg) < 0) {
929                 MS_DBG_ERR("_ms_thumb_recv_msg failed ");
930                 close(client_sock);
931                 MS_SAFE_FREE(recv_msg);
932                 return TRUE;
933         }
934
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);
936
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");
941                 close(client_sock);
942                 MS_SAFE_FREE(recv_msg);
943                 return TRUE;
944         }
945
946         thumb_req->client_sock = client_sock;
947         thumb_req->recv_msg = recv_msg;
948
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);
951                 return TRUE;
952         }
953
954         if (g_request_queue == NULL) {
955                 MS_DBG_WARN("queue is init");
956                  g_request_queue = g_queue_new();
957         }
958
959         MS_DBG("%s is queued", recv_msg->org_path);
960         g_queue_push_tail(g_request_queue, (gpointer)thumb_req);
961
962         if (!g_queue_work) {
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());
968                 g_queue_work = 1;
969         }
970
971         return TRUE;
972 }
973 #endif
974
975
976 gboolean _ms_thumb_agent_prepare_tcp_socket(int *sock_fd)
977 {
978         int sock;
979         unsigned short serv_port;
980
981         serv_port = MS_THUMB_CREATOR_PORT;
982
983 #if 0
984         struct sockaddr_in serv_addr;
985
986         /* Create a TCP socket */
987         if (_ms_thumb_create_socket(SERVER_SOCKET, &sock) < 0) {
988                 MS_DBG_ERR("_ms_thumb_create_socket failed");
989                 return FALSE;
990         }
991
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);
996
997         /* Bind to the local address */
998         if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
999                 MS_DBG_ERR("bind failed");
1000                 return FALSE;
1001         }
1002
1003         MS_DBG("bind success");
1004
1005         /* Listening */
1006         if (listen(sock, SOMAXCONN) < 0) {
1007                 MS_DBG_ERR("listen failed : %s", strerror(errno));
1008                 return FALSE;
1009         }
1010
1011         MS_DBG("Listening...");
1012 #endif
1013         if (ms_ipc_create_server_socket(MS_PROTOCOL_TCP, serv_port, &sock) < 0) {
1014                 MS_DBG_ERR("_ms_thumb_create_socket failed");
1015                 return FALSE;
1016         }
1017
1018         *sock_fd = sock;
1019
1020         return TRUE;
1021 }
1022
1023 gboolean _ms_thumb_agent_prepare_udp_socket()
1024 {
1025         int sock;
1026         unsigned short serv_port;
1027
1028         serv_port = MS_THUMB_COMM_PORT;
1029
1030         if (ms_ipc_create_server_socket(MS_PROTOCOL_UDP, serv_port, &sock) < 0) {
1031                 MS_DBG_ERR("ms_ipc_create_client_socket failed");
1032                 return FALSE;
1033         }
1034 #if 0
1035         struct sockaddr_in serv_addr;
1036
1037         /* Creaete a UDP socket */
1038         if (_ms_thumb_create_udp_socket(&sock) < 0) {
1039                 MS_DBG_ERR("_ms_thumb_create_udp_socket failed");
1040                 return FALSE;
1041         }
1042
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);
1047
1048         /* Bind to the local address */
1049         if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
1050                 MS_DBG_ERR("bind failed");
1051                 return FALSE;
1052         }
1053
1054         MS_DBG("bind success");
1055 #endif
1056         g_communicate_sock = sock;
1057
1058         return TRUE;
1059 }
1060
1061 gpointer ms_thumb_agent_start_thread(gpointer data)
1062 {
1063         MS_DBG("");
1064         int sockfd = -1;
1065
1066     GSource *source = NULL;
1067         GIOChannel *channel = NULL;
1068         GMainContext *context = NULL;
1069
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");
1073                 return NULL;
1074         }
1075
1076         context = g_main_context_new();
1077
1078         if (context == NULL) {
1079                 MS_DBG_ERR("g_main_context_new failed");
1080         } else {
1081                 MS_DBG("g_main_context_new success");
1082         }
1083
1084         g_thumb_agent_loop = g_main_loop_new(context, FALSE);
1085         g_main_context_push_thread_default(context);
1086
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);
1090
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);
1094
1095
1096         MS_DBG("************************************");
1097         MS_DBG("*** Thumbnail Agent thread is running ***");
1098         MS_DBG("************************************");
1099
1100         g_main_loop_run(g_thumb_agent_loop);
1101
1102         MS_DBG("Thumbnail Agent thread is shutting down...");
1103         _ms_thumb_agent_finish_jobs();
1104
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);
1110
1111         g_main_loop_unref(g_thumb_agent_loop);
1112
1113         return NULL;
1114 }
1115