Change from INET tcp to Unix domain socket
[framework/multimedia/media-server.git] / src / server / 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-common-utils.h"
27 #include "media-server-dbg.h"
28 #include "media-server-thumb.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 #ifdef _USE_UDS_SOCKET_
57 extern char MEDIA_IPC_PATH[][50];
58 #endif
59
60 gboolean _ms_thumb_agent_start_jobs(gpointer data)
61 {
62         MS_DBG("");
63
64         return FALSE;
65 }
66
67 void _ms_thumb_agent_finish_jobs()
68 {
69         MS_DBG("");
70
71         return;
72 }
73
74 GMainLoop *
75 ms_get_thumb_thread_mainloop(void)
76 {
77         return g_thumb_agent_loop;
78 }
79
80 int ms_thumb_get_server_pid()
81 {
82         return g_server_pid;
83 }
84
85 void ms_thumb_reset_server_status()
86 {
87         g_folk_thumb_server = FALSE;
88
89         if (g_timer_id > 0) {
90                 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), g_timer_id));
91                 g_timer_id = 0;
92         }
93
94         if (g_thumb_server_extracting) {
95                 /* Need to inplement when crash happens */
96 #if 0
97                 /* Restart thumbnail server */
98                 if (_ms_thumb_agent_execute_server() < 0) {
99                         MS_DBG_ERR("starting thumbnail-server failed");
100                 } else {
101                         MS_DBG("Thumbnail-server is started");
102                 }
103
104                 thumbMsg msg;
105                 thumbMsg recv_msg;
106                 memset((void *)&msg, 0, sizeof(msg));
107                 memset((void *)&recv_msg, 0, sizeof(recv_msg));
108
109                 msg.msg_type = 2; // THUMB_REQUEST_ALL_MEDIA
110                 msg.org_path[0] = '\0';
111                 msg.origin_path_size = 1;
112                 msg.dst_path[0] = '\0';
113                 msg.dest_path_size = 1;
114
115                 /* Command all thumbnail extraction to thumbnail server */
116                 if (!_ms_thumb_agent_send_msg_to_thumb_server(&msg, &recv_msg)) {
117                         MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed");
118                 }
119
120                 _ms_thumb_create_timer(g_timer_id);
121 #else
122                 MS_DBG_ERR("Thumbnail server is dead when processing all-thumbs extraction");
123                 g_thumb_server_extracting = FALSE;
124                 g_server_pid = 0;
125 #endif
126         } else {
127                 g_thumb_server_extracting = FALSE;
128                 g_server_pid = 0;
129         }
130
131         return;
132 }
133
134 void _ms_thumb_create_timer(int id)
135 {
136         if (id > 0)
137                 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), id));
138
139         GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_20);
140         g_source_set_callback (timer_src, _ms_thumb_agent_timer, NULL, NULL);
141         g_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default());
142
143 }
144
145 /* This checks if thumbnail server is running */
146 bool _ms_thumb_check_process()
147 {
148         DIR *pdir;
149         struct dirent pinfo;
150         struct dirent *result = NULL;
151         bool ret = FALSE;
152
153         pdir = opendir("/proc");
154         if (pdir == NULL) {
155                 MS_DBG_ERR("err: NO_DIR\n");
156                 return 0;
157         }
158
159         while (!readdir_r(pdir, &pinfo, &result)) {
160                 if (result == NULL)
161                         break;
162
163                 if (pinfo.d_type != 4 || pinfo.d_name[0] == '.'
164                     || pinfo.d_name[0] > 57)
165                         continue;
166
167                 FILE *fp;
168                 char buff[128];
169                 char path[128];
170
171                 ms_strcopy(path, sizeof(path), "/proc/%s/status", pinfo.d_name);
172                 fp = fopen(path, "rt");
173                 if (fp) {
174                         if (fgets(buff, 128, fp) == NULL)
175                                 MS_DBG_ERR("fgets failed");
176                         fclose(fp);
177
178                         if (strstr(buff, THUMB_SERVER_NAME)) {
179                                 ret = TRUE;
180                                 break;
181                         }
182                 } else {
183                         MS_DBG_ERR("Can't read file [%s]", path);
184                 }
185         }
186
187         closedir(pdir);
188
189         return ret;
190 }
191 int
192 _ms_thumb_create_socket(int sock_type, int *sock)
193 {
194         int sock_fd = 0;
195
196 #ifdef _USE_UDS_SOCKET_
197         if ((sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
198 #elif defined(_USE_UDS_SOCKET_TCP_)
199         if ((sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
200 #else
201         if ((sock_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
202 #endif
203                 MS_DBG_ERR("socket failed: %s", strerror(errno));
204                 return MS_MEDIA_ERR_SOCKET_CONN;
205         }
206
207         if (sock_type == CLIENT_SOCKET) {
208
209                 struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 };
210
211                 if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
212                         MS_DBG_ERR("setsockopt failed: %s", strerror(errno));
213                         close(sock_fd);
214                         return MS_MEDIA_ERR_SOCKET_INTERNAL;
215                 }
216         } else if (sock_type == SERVER_SOCKET) {
217
218                 int n_reuse = 1;
219
220                 if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &n_reuse, sizeof(n_reuse)) == -1) {
221                         MS_DBG_ERR("setsockopt failed: %s", strerror(errno));
222                         close(sock_fd);
223                         return MS_MEDIA_ERR_SOCKET_INTERNAL;
224                 }
225         }
226
227         *sock = sock_fd;
228
229         return MS_MEDIA_ERR_NONE;
230 }
231
232
233 int
234 _ms_thumb_create_udp_socket(int *sock)
235 {
236         int sock_fd = 0;
237
238 #ifdef _USE_UDS_SOCKET_
239         if ((sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
240 #else
241         if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
242 #endif
243                 MS_DBG_ERR("socket failed: %s", strerror(errno));
244                 return MS_MEDIA_ERR_SOCKET_CONN;
245         }
246
247         struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 };
248
249         if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
250                 MS_DBG_ERR("setsockopt failed: %s", strerror(errno));
251                 close(sock_fd);
252                 return MS_MEDIA_ERR_SOCKET_INTERNAL;
253         }
254
255         *sock = sock_fd;
256
257         return MS_MEDIA_ERR_NONE;
258 }
259
260 int _media_thumb_get_error()
261 {
262         if (errno == EWOULDBLOCK) {
263                 MS_DBG_ERR("Timeout. Can't try any more");
264                 if (!_ms_thumb_check_process()) {
265                         MS_DBG_ERR("Thumbnail server is not running!. Reset info for thumb server to execute");
266                         ms_thumb_reset_server_status();
267                 }
268
269                 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
270         } else {
271                 MS_DBG_ERR("recvfrom failed : %s", strerror(errno));
272                 return MS_MEDIA_ERR_SOCKET_RECEIVE;
273         }
274 }
275
276 int
277 _ms_thumb_recv_msg(int sock, int header_size, thumbMsg *msg)
278 {
279         int recv_msg_len = 0;
280         unsigned char *buf = NULL;
281
282         buf = (unsigned char*)malloc(header_size);
283
284         if ((recv_msg_len = recv(sock, buf, header_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         memcpy(msg, buf, header_size);
291         //MS_DBG("origin_path_size : %d, dest_path_size : %d", msg->origin_path_size, msg->dest_path_size);
292
293         MS_SAFE_FREE(buf);
294
295         if (msg->origin_path_size <= 0  || msg->origin_path_size > MS_FILE_PATH_LEN_MAX) {
296                 MS_SAFE_FREE(buf);
297                 MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->origin_path_size );
298                 return MS_MEDIA_ERR_DATA_TAINTED;
299         }
300
301         buf = (unsigned char*)malloc(msg->origin_path_size);
302
303         if ((recv_msg_len = recv(sock, buf, msg->origin_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->org_path, (char*)buf, msg->origin_path_size);
310         //MS_DBG("original path : %s", msg->org_path);
311
312         MS_SAFE_FREE(buf);
313
314         if (msg->dest_path_size <= 0  || msg->dest_path_size > MS_FILE_PATH_LEN_MAX) {
315                 MS_SAFE_FREE(buf);
316                 MS_DBG_ERR("msg->dest_path_size is invalid %d", msg->dest_path_size );
317                 return MS_MEDIA_ERR_DATA_TAINTED;
318         }
319
320         buf = (unsigned char*)malloc(msg->dest_path_size);
321
322         if ((recv_msg_len = recv(sock, buf, msg->dest_path_size, 0)) < 0) {
323                 MS_DBG_ERR("recv failed : %s", strerror(errno));
324                 MS_SAFE_FREE(buf);
325                 return _media_thumb_get_error();
326         }
327
328         strncpy(msg->dst_path, (char*)buf, msg->dest_path_size);
329         //MS_DBG("destination path : %s", msg->dst_path);
330
331         MS_SAFE_FREE(buf);
332         return MS_MEDIA_ERR_NONE;
333 }
334
335
336 int
337 #ifdef _USE_UDS_SOCKET_
338 _ms_thumb_recv_udp_msg(int sock, int header_size, thumbMsg *msg, struct sockaddr_un *from_addr, unsigned int *from_size)
339 #else
340 _ms_thumb_recv_udp_msg(int sock, int header_size, thumbMsg *msg, struct sockaddr_in *from_addr, unsigned int *from_size)
341 #endif
342 {
343         int recv_msg_len = 0;
344 #ifdef _USE_UDS_SOCKET_
345         unsigned int from_addr_size = sizeof(struct sockaddr_un);
346 #else
347         unsigned int from_addr_size = sizeof(struct sockaddr_in);
348 #endif
349         unsigned char *buf = NULL;
350
351         buf = (unsigned char*)malloc(sizeof(thumbMsg));
352
353         recv_msg_len = ms_ipc_wait_message(sock, buf, sizeof(thumbMsg), from_addr, &from_addr_size);
354         if (recv_msg_len != MS_MEDIA_ERR_NONE) {
355                 MS_DBG_ERR("ms_ipc_wait_message failed : %s", strerror(errno));
356                 MS_SAFE_FREE(buf);
357                 return _media_thumb_get_error();
358         }
359
360         memcpy(msg, buf, header_size);
361         //MS_DBG("origin_path_size : %d, dest_path_size : %d", msg->origin_path_size, msg->dest_path_size);
362
363         if (msg->origin_path_size <= 0  || msg->origin_path_size > MS_FILE_PATH_LEN_MAX) {
364                 MS_SAFE_FREE(buf);
365                 MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->origin_path_size );
366                 return MS_MEDIA_ERR_DATA_TAINTED;
367         }
368
369         strncpy(msg->org_path, (char*)buf + header_size, msg->origin_path_size);
370         //MS_DBG("original path : %s", msg->org_path);
371
372         if (msg->dest_path_size <= 0  || msg->dest_path_size > MS_FILE_PATH_LEN_MAX) {
373                 MS_SAFE_FREE(buf);
374                 MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->dest_path_size );
375                 return MS_MEDIA_ERR_DATA_TAINTED;
376         }
377
378         strncpy(msg->dst_path, (char*)buf + header_size + msg->origin_path_size, msg->dest_path_size);
379         //MS_DBG("destination path : %s", msg->dst_path);
380
381         MS_SAFE_FREE(buf);
382         *from_size = from_addr_size;
383
384         return MS_MEDIA_ERR_NONE;
385 }
386
387 int
388 _ms_thumb_set_buffer(thumbMsg *req_msg, unsigned char **buf, int *buf_size)
389 {
390         if (req_msg == NULL || buf == NULL) {
391                 return -1;
392         }
393
394         int org_path_len = 0;
395         int dst_path_len = 0;
396         int size = 0;
397         int header_size = 0;
398
399         header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
400         org_path_len = strlen(req_msg->org_path) + 1;
401         dst_path_len = strlen(req_msg->dst_path) + 1;
402
403         //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);
404
405         size = header_size + org_path_len + dst_path_len;
406         *buf = malloc(size);
407         memcpy(*buf, req_msg, header_size);
408         memcpy((*buf)+header_size, req_msg->org_path, org_path_len);
409         memcpy((*buf)+header_size + org_path_len, req_msg->dst_path, dst_path_len);
410
411         *buf_size = size;
412
413         return 0;
414 }
415
416 /*
417 void _ms_thumb_agent_child_handler(GPid pid, gint status, gpointer user_data)
418 {
419         MS_DBG_WARN("media-thumbnail-server[%d] is shutdown : %d", pid, status);
420         g_folk_thumb_server = FALSE;
421 }
422 */
423 gboolean _ms_thumb_agent_child_handler(gpointer data)
424 {
425         int pid = GPOINTER_TO_INT(data);
426         MS_DBG("media-thumbnail-server[%d] is killed", pid);
427         return FALSE;
428 }
429
430 gboolean _ms_thumb_agent_recv_msg_from_server()
431 {
432         if (g_communicate_sock <= 0) {
433                 _ms_thumb_agent_prepare_udp_socket();
434         }
435
436         ms_thumb_server_msg recv_msg;
437         int recv_msg_size = 0;
438
439         recv_msg_size = ms_ipc_receive_message(g_communicate_sock, & 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_SERVER_READY) {
447                 MS_DBG("Thumbnail server is ready");
448         }
449
450         return TRUE;
451 }
452
453 gboolean _ms_thumb_agent_recv_thumb_done_from_server(GIOChannel *src, GIOCondition condition, gpointer data)
454 {
455         int sockfd = -1;
456
457         sockfd = g_io_channel_unix_get_fd(src);
458         if (sockfd < 0) {
459                 MS_DBG_ERR("sock fd is invalid!");
460                 return FALSE;
461         }
462
463         ms_thumb_server_msg recv_msg;
464         int recv_msg_size = 0;
465
466         recv_msg_size = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(ms_thumb_server_msg), NULL, NULL);
467         if (recv_msg_size != MS_MEDIA_ERR_NONE) {
468                 MS_DBG_ERR("ms_ipc_receive_message failed : %s\n", strerror(errno));
469                 return FALSE;
470         }
471
472         MS_DBG("Receive : %d(%d)", recv_msg.msg_type, recv_msg_size);
473         if (recv_msg.msg_type == MS_MSG_THUMB_EXTRACT_ALL_DONE) {
474                 MS_DBG("Thumbnail extracting done");
475                 g_thumb_server_extracting = FALSE;
476
477                 return FALSE;
478         }
479
480         return FALSE;
481 }
482
483 gboolean _ms_thumb_agent_execute_server()
484 {
485         int pid;
486         pid = fork();
487
488         if (pid < 0) {
489                 return FALSE;
490         } else if (pid == 0) {
491                 execl("/usr/bin/media-thumbnail-server", "media-thumbnail-server", NULL);
492         } else {
493                 MS_DBG("Child process is %d", pid);
494                 g_folk_thumb_server = TRUE;
495         }
496 #if 0
497         GSource *child_watch_src =  g_child_watch_source_new(pid);
498         g_source_set_callback(child_watch_src, _ms_thumb_agent_child_handler, GINT_TO_POINTER(pid), NULL);
499         g_source_attach(child_watch_src, g_main_context_get_thread_default());
500 #endif
501         //g_child_watch_add(pid, _ms_thumb_agent_child_handler, NULL);
502         g_server_pid = pid;
503
504         if (!_ms_thumb_agent_recv_msg_from_server()) {
505                 MS_DBG_ERR("_ms_thumb_agent_recv_msg_from_server is failed");
506                 return FALSE;
507         }
508
509         return TRUE;
510 }
511
512 gboolean _ms_thumb_agent_send_msg_to_thumb_server(thumbMsg *recv_msg, thumbMsg *res_msg)
513 {
514         int sock;
515         const char *serv_ip = "127.0.0.1";
516 #ifdef _USE_UDS_SOCKET_
517         struct sockaddr_un serv_addr;
518 #else
519         struct sockaddr_in serv_addr;
520 #endif
521
522         int send_str_len = strlen(recv_msg->org_path);
523
524         if (send_str_len > MAX_MSG_SIZE) {
525                 MS_DBG_ERR("original path's length exceeds %d(max packet size)", MAX_MSG_SIZE);
526                 return FALSE;
527         }
528
529 #if 0
530         /* Creaete a datagram/UDP socket */
531         if (_ms_thumb_create_udp_socket(&sock) < 0) {
532                 MS_DBG_ERR("_ms_thumb_create_udp_socket failed");
533                 return FALSE;
534         }
535 #endif
536 #ifdef _USE_UDS_SOCKET_
537         if (ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sock, MS_THUMB_DAEMON_PORT) < 0) {
538 #else
539         if (ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sock) < 0) {
540 #endif
541                 MS_DBG_ERR("ms_ipc_create_client_socket failed");
542                 return FALSE;
543         }
544
545         memset(&serv_addr, 0, sizeof(serv_addr));
546 #ifdef _USE_UDS_SOCKET_
547         serv_addr.sun_family = AF_UNIX;
548         MS_DBG("%s", MEDIA_IPC_PATH[MS_THUMB_DAEMON_PORT]);
549         strcpy(serv_addr.sun_path, MEDIA_IPC_PATH[MS_THUMB_DAEMON_PORT]);
550 #else
551         serv_addr.sin_family = AF_INET;
552         serv_addr.sin_addr.s_addr = inet_addr(serv_ip);
553         serv_addr.sin_port = htons(MS_THUMB_DAEMON_PORT);
554 #endif
555
556         int buf_size = 0;
557         int header_size = 0;
558         unsigned char *buf = NULL;
559         _ms_thumb_set_buffer(recv_msg, &buf, &buf_size);
560
561         //MS_DBG("buffer size : %d", buf_size);
562         if (sendto(sock, buf, buf_size, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != buf_size) {
563                 MS_DBG_ERR("sendto failed: %s\n", strerror(errno));
564                 MS_SAFE_FREE(buf);
565                 close(sock);
566                 return FALSE;
567         }
568
569         MS_SAFE_FREE(buf);
570         MS_DBG("Sending msg to thumbnail server is successful");
571
572 #ifdef _USE_UDS_SOCKET_
573         struct sockaddr_un client_addr;
574 #else
575         struct sockaddr_in client_addr;
576 #endif
577         unsigned int client_addr_len;
578         header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
579
580         if (_ms_thumb_recv_udp_msg(sock, header_size, res_msg, &client_addr, &client_addr_len) < 0) {
581                 MS_DBG_ERR("_ms_thumb_recv_udp_msg failed");
582                 close(sock);
583                 return FALSE;
584         }
585
586         MS_DBG("recv %s from thumb daemon is successful", res_msg->dst_path);
587         close(sock);
588
589         if (res_msg->msg_type == 2 && g_communicate_sock > 0) { // THUMB_REQUEST_ALL_MEDIA
590                 /* Create new channel to watch udp socket */
591                 GSource *source = NULL;
592                 if (g_udp_channel == NULL)
593                         g_udp_channel = g_io_channel_unix_new(g_communicate_sock);
594                 source = g_io_create_watch(g_udp_channel, G_IO_IN);
595
596                 /* Set callback to be called when socket is readable */
597                 g_source_set_callback(source, (GSourceFunc)_ms_thumb_agent_recv_thumb_done_from_server, NULL, NULL);
598                 g_source_attach(source, g_main_context_get_thread_default());
599
600                 g_thumb_server_extracting = TRUE;
601         }
602
603         return TRUE;
604 }
605
606 gboolean _ms_thumb_agent_timer()
607 {
608         if (g_thumb_server_extracting) {
609                 MS_DBG("Timer is called.. But media-thumbnail-server[%d] is busy.. so timer is recreated", g_server_pid);
610
611                 _ms_thumb_create_timer(g_timer_id);
612                 return FALSE;
613         }
614
615         g_timer_id = 0;
616         MS_DBG("Timer is called.. Now killing media-thumbnail-server[%d]", g_server_pid);
617
618         if (g_server_pid > 0) {
619 #if 0
620                 if (kill(g_server_pid, SIGKILL) < 0) {
621                         MS_DBG_ERR("kill failed : %s", strerror(errno));
622                 }
623 #else
624                 /* Kill thumbnail server */
625                 thumbMsg msg;
626                 thumbMsg recv_msg;
627                 memset((void *)&msg, 0, sizeof(msg));
628                 memset((void *)&recv_msg, 0, sizeof(recv_msg));
629
630                 msg.msg_type = 5; // THUMB_REQUEST_KILL_SERVER
631                 msg.org_path[0] = '\0';
632                 msg.origin_path_size = 1;
633                 msg.dst_path[0] = '\0';
634                 msg.dest_path_size = 1;
635
636                 /* Command Kill to thumbnail server */
637                 if (!_ms_thumb_agent_send_msg_to_thumb_server(&msg, &recv_msg)) {
638                         MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed");
639                 }
640 #endif
641                 usleep(200000);
642         } else {
643                 MS_DBG_ERR("g_server_pid is %d. Maybe there's problem in thumbnail-server", g_server_pid);
644         }
645
646         return FALSE;
647 }
648
649 #if 0
650 gboolean _ms_thumb_agent_read_socket(GIOChannel *src,
651                                                                         GIOCondition condition,
652                                                                         gpointer data)
653 {
654 #ifdef _USE_UDS_SOCKET_
655         struct sockaddr_un client_addr;
656 #else
657         struct sockaddr_in client_addr;
658 #endif
659         unsigned int client_addr_len;
660
661         thumbMsg recv_msg;
662         thumbMsg res_msg;
663         int header_size = 0;
664         int sock = -1;
665         int client_sock = -1;
666
667         sock = g_io_channel_unix_get_fd(src);
668         if (sock < 0) {
669                 MS_DBG_ERR("sock fd is invalid!");
670                 return TRUE;
671         }
672
673         memset((void *)&recv_msg, 0, sizeof(thumbMsg));
674         memset((void *)&res_msg, 0, sizeof(res_msg));
675         header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
676
677         if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
678                 MS_DBG_ERR("accept failed : %s", strerror(errno));
679                 return TRUE;
680         }
681
682         MS_DBG("Client[%d] is accepted", client_sock);
683
684         if (_ms_thumb_recv_msg(client_sock, header_size, &recv_msg) < 0) {
685                 MS_DBG_ERR("_ms_thumb_recv_msg failed ");
686                 close(client_sock);
687                 return TRUE;
688         }
689
690         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);
691
692         if (g_folk_thumb_server == FALSE && g_thumb_server_extracting == FALSE) {
693                 if(_ms_thumb_check_process() == FALSE) { // This logic is temporary
694                 MS_DBG_WARN("Thumb server is not running.. so start it");
695                 if (!_ms_thumb_agent_execute_server()) {
696                         MS_DBG_ERR("_ms_thumb_agent_execute_server is failed");
697                         return TRUE;
698                 } else {
699
700                         GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_20);
701                         g_source_set_callback (timer_src, _ms_thumb_agent_timer, NULL, NULL);
702                         g_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default());
703                 }
704                 }
705         } else {
706                 if (g_timer_id > 0) {
707                         g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), g_timer_id));
708                         //MS_DBG("Timer is recreated");
709                         GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_20);
710                         g_source_set_callback (timer_src, _ms_thumb_agent_timer, NULL, NULL);
711                         g_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default());
712                 }
713         }
714
715         if (!_ms_thumb_agent_send_msg_to_thumb_server(&recv_msg, &res_msg)) {
716                 MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed");
717
718                 return TRUE;
719         }
720
721         strncpy(res_msg.org_path, recv_msg.org_path, recv_msg.origin_path_size);
722         res_msg.origin_path_size = recv_msg.origin_path_size;
723         res_msg.dest_path_size = strlen(res_msg.dst_path) + 1;
724
725         int buf_size = 0;
726         unsigned char *buf = NULL;
727         _ms_thumb_set_buffer(&res_msg, &buf, &buf_size);
728
729         //MS_DBG("buffer size : %d", buf_size);
730
731         if (send(client_sock, buf, buf_size, 0) != buf_size) {
732                 MS_DBG_ERR("sendto failed : %s", strerror(errno));
733         } else {
734                 MS_DBG("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path));
735         }
736
737         close(client_sock);
738         MS_SAFE_FREE(buf);
739         return TRUE;
740 }
741 #else
742 int _ms_thumb_cancel_media(const char *path, int pid)
743 {
744         int ret = -1;
745         int i = 0;
746         int req_len = 0;
747
748         req_len = g_queue_get_length(g_request_queue);
749
750         MS_DBG("Queue length : %d", req_len);
751
752         for (i = 0; i < req_len; i++) {
753                 thumbRequest *req = NULL;
754                 req = (thumbRequest *)g_queue_peek_nth(g_request_queue, i);
755                 if (req == NULL) continue;
756
757                 if ((req->recv_msg->pid) == pid && (strncmp(path, req->recv_msg->org_path, strlen(path))) == 0) {
758                         MS_DBG("Remove %s from queue", req->recv_msg->org_path);
759                         g_queue_pop_nth(g_request_queue, i);
760
761                         close(req->client_sock);
762                         MS_SAFE_FREE(req->recv_msg);
763                         MS_SAFE_FREE(req);
764                         ret = 0;
765
766                         break;
767                 }
768         }
769
770         return ret;
771 }
772
773 int _ms_thumb_cancel_all(int pid)
774 {
775         int ret = -1;
776         int i = 0;
777         int req_len = 0;
778
779         req_len = g_queue_get_length(g_request_queue);
780
781         MS_DBG("Queue length : %d", req_len);
782
783         for (i = 0; i < req_len; i++) {
784                 thumbRequest *req = NULL;
785                 req = (thumbRequest *)g_queue_peek_nth(g_request_queue, i);
786                 if (req == NULL) continue;
787
788                 if (req->recv_msg->pid == pid) {
789                         MS_DBG("Remove [%d] %s from queue", req->recv_msg->pid, req->recv_msg->org_path);
790                         g_queue_pop_nth(g_request_queue, i);
791                         i--;
792                         req_len--;
793
794                         close(req->client_sock);
795                         MS_SAFE_FREE(req->recv_msg);
796                         MS_SAFE_FREE(req);
797                         ret = 0;
798                 }
799         }
800
801         return ret;
802 }
803
804 void _ms_thumb_cancle_request(thumbRequest *thumb_req)
805 {
806         MS_DBG("");
807         int ret = -1;
808
809         if (thumb_req == NULL) return;
810
811         thumbMsg *recv_msg = thumb_req->recv_msg;
812         if (recv_msg == NULL) {
813                 MS_SAFE_FREE(thumb_req);
814                 return;
815         }
816
817         if (recv_msg->msg_type == 3)
818                 ret = _ms_thumb_cancel_media(recv_msg->org_path, recv_msg->pid);
819         else if (recv_msg->msg_type == 4)
820                 ret = _ms_thumb_cancel_all(recv_msg->pid);
821
822         if (ret == 0) {
823                 recv_msg->status = 0;  // THUMB_SUCCESS
824         } else {
825                 recv_msg->status = 0;  // THUMB_SUCCESS
826         }
827
828         if (recv_msg->origin_path_size <= 0  || recv_msg->origin_path_size > MS_FILE_PATH_LEN_MAX) {
829                 MS_DBG_ERR("recv_msg->origin_path_size is invalid %d", recv_msg->origin_path_size );
830                 return;
831         }
832
833         recv_msg->dest_path_size = recv_msg->origin_path_size;
834         strncpy(recv_msg->dst_path, recv_msg->org_path, recv_msg->dest_path_size);
835 /*
836         int buf_size = 0;
837         unsigned char *buf = NULL;
838         _ms_thumb_set_buffer(recv_msg, &buf, &buf_size);
839
840         if (send(thumb_req->client_sock, buf, buf_size, 0) != buf_size) {
841                 MS_DBG_ERR("sendto failed : %s", strerror(errno));
842         } else {
843                 MS_DBG("Sent response");
844         }
845 */
846         close(thumb_req->client_sock);
847         //MS_SAFE_FREE(buf);
848         MS_SAFE_FREE(thumb_req->recv_msg);
849         MS_SAFE_FREE(thumb_req);
850
851         return;
852 }
853
854 gboolean _ms_thumb_request_to_server(gpointer data)
855 {
856         int req_len = 0;
857
858         req_len = g_queue_get_length(g_request_queue);
859
860         MS_DBG("Queue length : %d", req_len);
861
862         if (req_len <= 0) {
863                 MS_DBG("There is no request job in the queue");
864                 g_queue_work = 0;
865                 return FALSE;
866         }
867
868         if (g_folk_thumb_server == FALSE && g_thumb_server_extracting == FALSE) {
869                 if(_ms_thumb_check_process() == FALSE) { // This logic is temporary
870                         MS_DBG_WARN("Thumb server is not running.. so start it");
871                         if (!_ms_thumb_agent_execute_server()) {
872                                 MS_DBG_ERR("_ms_thumb_agent_execute_server is failed");
873                                 g_queue_work = 0;
874                                 return FALSE;
875                         } else {
876                                 _ms_thumb_create_timer(g_timer_id);
877                         }
878                 }
879         } else {
880                 /* Timer is re-created*/
881                 _ms_thumb_create_timer(g_timer_id);
882         }
883
884         thumbRequest *req = NULL;
885         req = (thumbRequest *)g_queue_pop_head(g_request_queue);
886
887         if (req == NULL) {
888                 MS_DBG_ERR("Failed to get a request job from queue");
889                 return TRUE;
890         }
891
892         int client_sock = -1;
893         thumbMsg *recv_msg = NULL;
894         thumbMsg res_msg;
895         memset((void *)&res_msg, 0, sizeof(res_msg));
896
897         client_sock = req->client_sock;
898         recv_msg = req->recv_msg;
899
900         if (req->client_sock <=0 || req->recv_msg == NULL) {
901                 MS_DBG_ERR("client sock is below 0 or recv msg is NULL");
902                 MS_SAFE_FREE(req->recv_msg);
903                 MS_SAFE_FREE(req);
904                 return TRUE;
905         }
906
907         if (recv_msg) {
908                 if (!_ms_thumb_agent_send_msg_to_thumb_server(recv_msg, &res_msg)) {
909                         MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed");
910
911                         close(client_sock);
912                         MS_SAFE_FREE(req->recv_msg);
913                         MS_SAFE_FREE(req);
914                         return TRUE;
915                 }
916         } else {
917                 MS_DBG_ERR("recv_msg is NULL from queue request");
918         }
919
920         strncpy(res_msg.org_path, recv_msg->org_path, recv_msg->origin_path_size);
921         res_msg.origin_path_size = recv_msg->origin_path_size;
922         res_msg.dest_path_size = strlen(res_msg.dst_path) + 1;
923
924         int buf_size = 0;
925         unsigned char *buf = NULL;
926         _ms_thumb_set_buffer(&res_msg, &buf, &buf_size);
927
928         if (send(client_sock, buf, buf_size, 0) != buf_size) {
929                 MS_DBG_ERR("sendto failed : %s", strerror(errno));
930         } else {
931                 MS_DBG("Sent %s(%d) from %s \n", res_msg.dst_path, strlen(res_msg.dst_path), res_msg.org_path);
932         }
933
934         close(client_sock);
935         MS_SAFE_FREE(buf);
936         MS_SAFE_FREE(req->recv_msg);
937         MS_SAFE_FREE(req);
938
939         return TRUE;
940 }
941
942 gboolean _ms_thumb_agent_read_socket(GIOChannel *src,
943                                                                         GIOCondition condition,
944                                                                         gpointer data)
945 {
946 #ifdef _USE_UDS_SOCKET_
947         struct sockaddr_un client_addr;
948 #elif defined(_USE_UDS_SOCKET_TCP_)
949         struct sockaddr_un client_addr;
950 #else
951         struct sockaddr_in client_addr;
952 #endif
953         unsigned int client_addr_len;
954
955         thumbMsg *recv_msg = NULL;
956         int header_size = 0;
957         int sock = -1;
958         int client_sock = -1;
959
960         sock = g_io_channel_unix_get_fd(src);
961         if (sock < 0) {
962                 MS_DBG_ERR("sock fd is invalid!");
963                 return TRUE;
964         }
965
966         header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2;
967         client_addr_len = sizeof(client_addr);
968
969         if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
970                 MS_DBG_ERR("accept failed : %s", strerror(errno));
971                 return TRUE;
972         }
973
974         MS_DBG("Client[%d] is accepted", client_sock);
975
976         recv_msg = calloc(1, sizeof(thumbMsg));
977         if (recv_msg == NULL) {
978                 MS_DBG_ERR("Failed to allocate memory");
979                 close(client_sock);
980                 return TRUE;
981         }
982
983         if (_ms_thumb_recv_msg(client_sock, header_size, recv_msg) < 0) {
984                 MS_DBG_ERR("_ms_thumb_recv_msg failed ");
985                 close(client_sock);
986                 MS_SAFE_FREE(recv_msg);
987                 return TRUE;
988         }
989
990         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);
991
992         thumbRequest *thumb_req = NULL;
993         thumb_req = calloc(1, sizeof(thumbRequest));
994         if (thumb_req == NULL) {
995                 MS_DBG_ERR("Failed to create request element");
996                 close(client_sock);
997                 MS_SAFE_FREE(recv_msg);
998                 return TRUE;
999         }
1000
1001         thumb_req->client_sock = client_sock;
1002         thumb_req->recv_msg = recv_msg;
1003
1004         if (recv_msg->msg_type == 3 || recv_msg->msg_type == 4) { // THUMB_REQUEST_CANCEL_MEDIA || THUMB_REQUEST_CANCEL_ALL
1005                 _ms_thumb_cancle_request(thumb_req);
1006                 return TRUE;
1007         }
1008
1009         if (g_request_queue == NULL) {
1010                 MS_DBG_WARN("queue is init");
1011                  g_request_queue = g_queue_new();
1012         }
1013
1014         if (g_queue_get_length(g_request_queue) >= MAX_THUMB_REQUEST) {
1015                 MS_DBG_WARN("Request Queue is full");
1016                 thumbMsg res_msg;
1017                 memset((void *)&res_msg, 0, sizeof(res_msg));
1018
1019                 res_msg.msg_type = 6; // THUMB_RESPONSE
1020                 res_msg.status = 1; //THUMB_FAIL
1021                 res_msg.org_path[0] = '\0';
1022                 res_msg.origin_path_size = 0;
1023                 res_msg.dst_path[0] = '\0';
1024                 res_msg.dest_path_size = 0;
1025
1026                 int buf_size = 0;
1027                 unsigned char *buf = NULL;
1028                 _ms_thumb_set_buffer(&res_msg, &buf, &buf_size);
1029
1030                 if (send(client_sock, buf, buf_size, 0) != buf_size) {
1031                         MS_DBG_ERR("sendto failed : %s", strerror(errno));
1032                 } else {
1033                         MS_DBG("Sent Refuse msg from %s \n", recv_msg->org_path);
1034                 }
1035
1036                 close(client_sock);
1037                 MS_SAFE_FREE(buf);
1038                 MS_SAFE_FREE(thumb_req->recv_msg);
1039                 MS_SAFE_FREE(thumb_req);
1040
1041                 return TRUE;
1042         }
1043
1044         MS_DBG("%s is queued", recv_msg->org_path);
1045         g_queue_push_tail(g_request_queue, (gpointer)thumb_req);
1046
1047         if (!g_queue_work) {
1048                 GSource *src_request = NULL;
1049                 src_request = g_idle_source_new ();
1050                 g_source_set_callback (src_request, _ms_thumb_request_to_server, NULL, NULL);
1051                 //g_source_set_priority(src_request, G_PRIORITY_LOW);
1052                 g_source_attach (src_request, g_main_context_get_thread_default());
1053                 g_queue_work = 1;
1054         }
1055
1056         return TRUE;
1057 }
1058 #endif
1059
1060
1061 gboolean _ms_thumb_agent_prepare_tcp_socket(int *sock_fd)
1062 {
1063         int sock;
1064         unsigned short serv_port;
1065
1066 #ifdef _USE_UDS_SOCKET_TCP_
1067         serv_port = MS_THUMB_CREATOR_TCP_PORT;
1068 #else
1069         serv_port = MS_THUMB_CREATOR_PORT;
1070 #endif
1071
1072 #if 0
1073 #ifdef _USE_UDS_SOCKET_
1074         struct sockaddr_un serv_addr;
1075 #else
1076         struct sockaddr_in serv_addr;
1077 #endif
1078
1079         /* Create a TCP socket */
1080         if (_ms_thumb_create_socket(SERVER_SOCKET, &sock) < 0) {
1081                 MS_DBG_ERR("_ms_thumb_create_socket failed");
1082                 return FALSE;
1083         }
1084
1085         memset(&serv_addr, 0, sizeof(serv_addr));
1086 #ifdef _USE_UDS_SOCKET_
1087         serv_addr.sun_family = AF_UNIX;
1088         strcpy(serv_addr.sun_path, MEDIA_IPC_PATH[serv_port]);
1089 #else
1090         serv_addr.sin_family = AF_INET;
1091         serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1092         serv_addr.sin_port = htons(serv_port);
1093 #endif
1094
1095         /* Bind to the local address */
1096         if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
1097                 MS_DBG_ERR("bind failed");
1098                 return FALSE;
1099         }
1100
1101         MS_DBG("bind success");
1102
1103         /* Listening */
1104         if (listen(sock, SOMAXCONN) < 0) {
1105                 MS_DBG_ERR("listen failed : %s", strerror(errno));
1106                 return FALSE;
1107         }
1108
1109         MS_DBG("Listening...");
1110 #endif
1111
1112 #ifdef _USE_UDS_SOCKET_TCP_
1113         if (ms_ipc_create_server_tcp_socket(MS_PROTOCOL_TCP, serv_port, &sock) < 0) {
1114 #else
1115         if (ms_ipc_create_server_socket(MS_PROTOCOL_TCP, serv_port, &sock) < 0) {
1116 #endif
1117                 MS_DBG_ERR("_ms_thumb_create_socket failed");
1118                 return FALSE;
1119         }
1120
1121         *sock_fd = sock;
1122
1123         return TRUE;
1124 }
1125
1126 gboolean _ms_thumb_agent_prepare_udp_socket()
1127 {
1128         int sock;
1129         unsigned short serv_port;
1130
1131         serv_port = MS_THUMB_COMM_PORT;
1132
1133         if (ms_ipc_create_server_socket(MS_PROTOCOL_UDP, serv_port, &sock) < 0) {
1134                 MS_DBG_ERR("ms_ipc_create_server_socket failed");
1135                 return FALSE;
1136         }
1137 #if 0
1138 #ifdef _USE_UDS_SOCKET_
1139         struct sockaddr_un serv_addr;
1140 #else
1141         struct sockaddr_in serv_addr;
1142 #endif
1143
1144         /* Creaete a UDP socket */
1145         if (_ms_thumb_create_udp_socket(&sock) < 0) {
1146                 MS_DBG_ERR("_ms_thumb_create_udp_socket failed");
1147                 return FALSE;
1148         }
1149
1150         memset(&serv_addr, 0, sizeof(serv_addr));
1151 #ifdef _USE_UDS_SOCKET_
1152         serv_addr.sun_family = AF_UNIX;
1153         strcpy(serv_addr.sun_path, MEDIA_IPC_PATH[serv_port]);
1154 #else
1155         serv_addr.sin_family = AF_INET;
1156         serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1157         serv_addr.sin_port = htons(serv_port);
1158 #endif
1159
1160         /* Bind to the local address */
1161         if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
1162                 MS_DBG_ERR("bind failed");
1163                 return FALSE;
1164         }
1165
1166         MS_DBG("bind success");
1167 #endif
1168         g_communicate_sock = sock;
1169
1170         return TRUE;
1171 }
1172
1173 gpointer ms_thumb_agent_start_thread(gpointer data)
1174 {
1175         MS_DBG("");
1176         int sockfd = -1;
1177
1178     GSource *source = NULL;
1179         GIOChannel *channel = NULL;
1180         GMainContext *context = NULL;
1181
1182         /* Create and bind new TCP socket */
1183         if (!_ms_thumb_agent_prepare_tcp_socket(&sockfd)) {
1184                 MS_DBG_ERR("Failed to create socket\n");
1185                 return NULL;
1186         }
1187
1188         context = g_main_context_new();
1189
1190         if (context == NULL) {
1191                 MS_DBG_ERR("g_main_context_new failed");
1192         } else {
1193                 MS_DBG("g_main_context_new success");
1194         }
1195
1196         g_thumb_agent_loop = g_main_loop_new(context, FALSE);
1197         g_main_context_push_thread_default(context);
1198
1199         /* Create new channel to watch udp socket */
1200         channel = g_io_channel_unix_new(sockfd);
1201         source = g_io_create_watch(channel, G_IO_IN);
1202
1203         /* Set callback to be called when socket is readable */
1204         g_source_set_callback(source, (GSourceFunc)_ms_thumb_agent_read_socket, NULL, NULL);
1205         g_source_attach(source, context);
1206
1207
1208         MS_DBG("************************************");
1209         MS_DBG("*** Thumbnail Agent thread is running ***");
1210         MS_DBG("************************************");
1211
1212         g_main_loop_run(g_thumb_agent_loop);
1213
1214         MS_DBG("Thumbnail Agent thread is shutting down...");
1215         _ms_thumb_agent_finish_jobs();
1216
1217         /*close an IO channel*/
1218         g_io_channel_shutdown(channel,  FALSE, NULL);
1219         g_io_channel_shutdown(g_udp_channel,  FALSE, NULL);
1220         g_io_channel_unref(channel);
1221         close(g_communicate_sock);
1222
1223         g_main_loop_unref(g_thumb_agent_loop);
1224
1225         return NULL;
1226 }
1227