Remove unused code.
[platform/core/multimedia/libmedia-thumbnail.git] / src / ipc / media-thumb-ipc.c
1 /*
2  * libmedia-thumbnail
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 "media-thumbnail.h"
23 #include "media-thumb-ipc.h"
24 #include "media-thumb-util.h"
25 #include "media-thumb-db.h"
26 #include "media-thumb-debug.h"
27 #include <glib.h>
28 #include <fcntl.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <grp.h>
32 #include <pwd.h>
33
34 #define GLOBAL_USER    0 //#define     tzplatform_getenv(TZ_GLOBAL) //TODO
35
36 static __thread GQueue *g_request_queue = NULL;
37 typedef struct {
38         GIOChannel *channel;
39         char *path;
40         int source_id;
41 } thumbReq;
42
43 int _media_thumb_create_socket(int sock_type, int *sock)
44 {
45         int sock_fd = 0;
46
47         if ((sock_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
48                 thumb_err("socket failed: %s", strerror(errno));
49                 return MS_MEDIA_ERR_SOCKET_CONN;
50         }
51
52         if (sock_type == CLIENT_SOCKET) {
53                 struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 };
54
55                 if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
56                         thumb_err("setsockopt failed: %s", strerror(errno));
57                         close(sock_fd);
58                         return MS_MEDIA_ERR_SOCKET_CONN;
59                 }
60         } else if (sock_type == SERVER_SOCKET) {
61
62                 int n_reuse = 1;
63
64                 if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &n_reuse, sizeof(n_reuse)) == -1) {
65                         thumb_err("setsockopt failed: %s", strerror(errno));
66                         close(sock_fd);
67                         return MS_MEDIA_ERR_SOCKET_CONN;
68                 }
69         }
70
71         *sock = sock_fd;
72
73         return MS_MEDIA_ERR_NONE;
74 }
75
76
77 int _media_thumb_create_udp_socket(int *sock)
78 {
79         int sock_fd = 0;
80
81         if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
82                 thumb_err("socket failed: %s", strerror(errno));
83                 return MS_MEDIA_ERR_SOCKET_CONN;
84         }
85
86         struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 };
87
88         if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
89                 thumb_err("setsockopt failed: %s", strerror(errno));
90                 close(sock_fd);
91                 return MS_MEDIA_ERR_SOCKET_CONN;
92         }
93
94         *sock = sock_fd;
95
96         return MS_MEDIA_ERR_NONE;
97 }
98
99 int _media_thumb_get_error()
100 {
101         if (errno == EWOULDBLOCK) {
102                 thumb_err("Timeout. Can't try any more");
103                 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
104         } else {
105                 thumb_err("recvfrom failed : %s", strerror(errno));
106                 return MS_MEDIA_ERR_SOCKET_RECEIVE;
107         }
108 }
109
110 int __media_thumb_pop_req_queue(const char *path, bool shutdown_channel)
111 {
112         int req_len = 0, i;
113
114         if (g_request_queue == NULL) return MS_MEDIA_ERR_INVALID_PARAMETER;
115         req_len = g_queue_get_length(g_request_queue);
116
117         if (req_len <= 0) {
118 //              thumb_dbg("There is no request in the queue");
119         } else {
120
121                 for (i = 0; i < req_len; i++) {
122                         thumbReq *req = NULL;
123                         req = (thumbReq *)g_queue_peek_nth(g_request_queue, i);
124                         if (req == NULL) continue;
125
126                         if (strncmp(path, req->path, strlen(path)) == 0) {
127                                 if (shutdown_channel) {
128                                         g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), req->source_id));
129
130                                         g_io_channel_shutdown(req->channel, TRUE, NULL);
131                                         g_io_channel_unref(req->channel);
132                                 }
133                                 g_queue_pop_nth(g_request_queue, i);
134
135                                 SAFE_FREE(req->path);
136                                 SAFE_FREE(req);
137
138                                 break;
139                         }
140                 }
141                 if (i == req_len) {
142 //                      thumb_dbg("There's no %s in the queue", path);
143                 }
144         }
145
146         return MS_MEDIA_ERR_NONE;
147 }
148
149 int __media_thumb_check_req_queue(const char *path)
150 {
151         int req_len = 0, i;
152
153         if (g_request_queue == NULL) return MS_MEDIA_ERR_NONE;
154         req_len = g_queue_get_length(g_request_queue);
155
156 //      thumb_dbg("Queue length : %d", req_len);
157 //      thumb_dbg("Queue path : %s", path);
158
159         if (req_len <= 0) {
160 //              thumb_dbg("There is no request in the queue");
161         } else {
162
163                 for (i = 0; i < req_len; i++) {
164                         thumbReq *req = NULL;
165                         req = (thumbReq *)g_queue_peek_nth(g_request_queue, i);
166                         if (req == NULL) continue;
167
168                         if (strncmp(path, req->path, strlen(path)) == 0) {
169                                 //thumb_dbg("Same Request - %s", path);
170                                 return MS_MEDIA_ERR_INVALID_PARAMETER;
171
172                                 break;
173                         }
174                 }
175         }
176
177         return MS_MEDIA_ERR_NONE;
178 }
179
180 int
181 _media_thumb_recv_msg(int sock, int header_size, thumbMsg *msg)
182 {
183         int recv_msg_len = 0;
184         unsigned char *buf = NULL;
185
186         buf = (unsigned char*)malloc(header_size);
187
188         if ((recv_msg_len = recv(sock, buf, header_size, 0)) <= 0) {
189                 thumb_err("recvfrom failed : %s", strerror(errno));
190                 SAFE_FREE(buf);
191                 return _media_thumb_get_error();
192         }
193
194         memcpy(msg, buf, header_size);
195         //thumb_dbg("origin_path_size : %d, dest_path_size : %d", msg->origin_path_size, msg->dest_path_size);
196
197         SAFE_FREE(buf);
198
199         buf = (unsigned char*)malloc(msg->origin_path_size);
200
201         if ((recv_msg_len = recv(sock, buf, msg->origin_path_size, 0)) < 0) {
202                 thumb_err("recvfrom failed : %s", strerror(errno));
203                 SAFE_FREE(buf);
204                 return _media_thumb_get_error();
205         }
206
207         strncpy(msg->org_path, (char*)buf, msg->origin_path_size);
208         //thumb_dbg("original path : %s", msg->org_path);
209
210         SAFE_FREE(buf);
211         buf = (unsigned char*)malloc(msg->dest_path_size);
212
213         if ((recv_msg_len = recv(sock, buf, msg->dest_path_size, 0)) < 0) {
214                 thumb_err("recvfrom failed : %s", strerror(errno));
215                 SAFE_FREE(buf);
216                 return _media_thumb_get_error();
217         }
218
219         strncpy(msg->dst_path, (char*)buf, msg->dest_path_size);
220         //thumb_dbg("destination path : %s", msg->dst_path);
221
222         SAFE_FREE(buf);
223         return MS_MEDIA_ERR_NONE;
224 }
225
226 int
227 _media_thumb_recv_udp_msg(int sock, int header_size, thumbMsg *msg, struct sockaddr_un *from_addr, unsigned int *from_size)
228 {
229         int recv_msg_len = 0;
230         unsigned int from_addr_size = sizeof(struct sockaddr_un);
231         unsigned char *buf = NULL;
232
233         buf = (unsigned char*)malloc(sizeof(thumbMsg));
234
235         if ((recv_msg_len = recvfrom(sock, buf, sizeof(thumbMsg), 0, (struct sockaddr *)from_addr, &from_addr_size)) < 0) {
236                 thumb_err("recvfrom failed : %s", strerror(errno));
237                 SAFE_FREE(buf);
238                 return _media_thumb_get_error();
239         }
240
241         memcpy(msg, buf, header_size);
242
243         if (msg->origin_path_size <= 0  || msg->origin_path_size > MAX_PATH_SIZE) {
244                 SAFE_FREE(buf);
245                 thumb_err("msg->origin_path_size is invalid %d", msg->origin_path_size );
246                 return MS_MEDIA_ERR_INVALID_PARAMETER;
247         }
248
249         strncpy(msg->org_path, (char*)buf + header_size, msg->origin_path_size);
250         //thumb_dbg("original path : %s", msg->org_path);
251
252         if (msg->dest_path_size <= 0  || msg->dest_path_size > MAX_PATH_SIZE) {
253                 SAFE_FREE(buf);
254                 thumb_err("msg->origin_path_size is invalid %d", msg->dest_path_size );
255                 return MS_MEDIA_ERR_INVALID_PARAMETER;
256         }
257
258         strncpy(msg->dst_path, (char*)buf + header_size + msg->origin_path_size, msg->dest_path_size);
259         //thumb_dbg("destination path : %s", msg->dst_path);
260
261         SAFE_FREE(buf);
262         *from_size = from_addr_size;
263
264         return MS_MEDIA_ERR_NONE;
265 }
266
267 int
268 _media_thumb_set_buffer(thumbMsg *req_msg, unsigned char **buf, int *buf_size)
269 {
270         if (req_msg == NULL || buf == NULL) {
271                 return MS_MEDIA_ERR_INVALID_PARAMETER;
272         }
273
274         int org_path_len = 0;
275         int dst_path_len = 0;
276         int size = 0;
277         int header_size = 0;
278
279         header_size = sizeof(thumbMsg) - MAX_PATH_SIZE*2;
280         org_path_len = strlen(req_msg->org_path) + 1;
281         dst_path_len = strlen(req_msg->dst_path) + 1;
282
283         //thumb_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);
284
285         size = header_size + org_path_len + dst_path_len;
286         *buf = malloc(size);
287         memcpy(*buf, req_msg, header_size);
288         memcpy((*buf)+header_size, req_msg->org_path, org_path_len);
289         memcpy((*buf)+header_size + org_path_len, req_msg->dst_path, dst_path_len);
290
291         *buf_size = size;
292
293         return MS_MEDIA_ERR_NONE;
294 }
295
296 int
297 _media_thumb_request(int msg_type, media_thumb_type thumb_type, const char *origin_path, char *thumb_path, int max_length, media_thumb_info *thumb_info, uid_t uid)
298 {
299         int sock;
300         struct sockaddr_un serv_addr;
301         int recv_str_len = 0;
302         int err = MS_MEDIA_ERR_NONE;
303         int pid;
304
305         if (ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_10, &sock, MS_THUMB_CREATOR_PORT) < 0) {
306                 thumb_err("ms_ipc_create_client_socket failed");
307                 return MS_MEDIA_ERR_SOCKET_CONN;
308         }
309
310         memset(&serv_addr, 0, sizeof(serv_addr));
311         serv_addr.sun_family = AF_UNIX;
312         strcpy(serv_addr.sun_path, "/var/run/media-server/media_ipc_thumbcreator.socket");
313
314         /* Connecting to the thumbnail server */
315         if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
316                 thumb_err("connect error : %s", strerror(errno));
317                 return MS_MEDIA_ERR_SOCKET_CONN;
318         }
319
320         thumbMsg req_msg;
321         thumbMsg recv_msg;
322
323         memset((void *)&req_msg, 0, sizeof(thumbMsg));
324         memset((void *)&recv_msg, 0, sizeof(thumbMsg));
325
326         /* Get PID of client*/
327         pid = getpid();
328         req_msg.pid = pid;
329
330         /* Set requset message */
331         req_msg.msg_type = msg_type;
332         req_msg.thumb_type = thumb_type;
333         req_msg.uid = uid;
334         strncpy(req_msg.org_path, origin_path, sizeof(req_msg.org_path));
335         req_msg.org_path[strlen(req_msg.org_path)] = '\0';
336
337         if (msg_type == THUMB_REQUEST_SAVE_FILE) {
338                 strncpy(req_msg.dst_path, thumb_path, sizeof(req_msg.dst_path));
339                 req_msg.dst_path[strlen(req_msg.dst_path)] = '\0';
340         }
341
342         req_msg.origin_path_size = strlen(req_msg.org_path) + 1;
343         req_msg.dest_path_size = strlen(req_msg.dst_path) + 1;
344
345         if (req_msg.origin_path_size > MAX_PATH_SIZE || req_msg.dest_path_size > MAX_PATH_SIZE) {
346                 thumb_err("path's length exceeds %d", MAX_PATH_SIZE);
347                 close(sock);
348                 return MS_MEDIA_ERR_INVALID_PARAMETER;
349         }
350
351         unsigned char *buf = NULL;
352         int buf_size = 0;
353         int header_size = 0;
354
355         header_size = sizeof(thumbMsg) - MAX_PATH_SIZE*2;
356         _media_thumb_set_buffer(&req_msg, &buf, &buf_size);
357
358         if (send(sock, buf, buf_size, 0) != buf_size) {
359                 thumb_err("sendto failed: %d\n", errno);
360                 SAFE_FREE(buf);
361                 close(sock);
362                 return MS_MEDIA_ERR_SOCKET_SEND;
363         }
364
365         thumb_dbg("Sending msg to thumbnail daemon is successful");
366
367         SAFE_FREE(buf);
368
369         if ((err = _media_thumb_recv_msg(sock, header_size, &recv_msg)) < 0) {
370                 thumb_err("_media_thumb_recv_msg failed ");
371                 close(sock);
372                 return err;
373         }
374
375         recv_str_len = strlen(recv_msg.org_path);
376         thumb_dbg("recv %s(%d) from thumb daemon is successful", recv_msg.org_path, recv_str_len);
377
378         close(sock);
379
380         if (recv_str_len > max_length) {
381                 thumb_err("user buffer is too small. Output's length is %d", recv_str_len);
382                 return MS_MEDIA_ERR_INVALID_PARAMETER;
383         }
384
385         if (recv_msg.status == THUMB_FAIL) {
386                 thumb_err("Failed to make thumbnail");
387                 return MS_MEDIA_ERR_INVALID_PARAMETER;
388         }
389
390         if (msg_type != THUMB_REQUEST_SAVE_FILE) {
391                 strncpy(thumb_path, recv_msg.dst_path, max_length);
392         }
393
394         thumb_info->origin_width = recv_msg.origin_width;
395         thumb_info->origin_height = recv_msg.origin_height;
396
397         return MS_MEDIA_ERR_NONE;
398 }
399
400 static int _mkdir(const char *dir, mode_t mode) {
401         char tmp[256];
402         char *p = NULL;
403         size_t len;
404
405         snprintf(tmp, sizeof(tmp),"%s",dir);
406         len = strlen(tmp);
407         if(tmp[len - 1] == '/')
408                 tmp[len - 1] = 0;
409         for(p = tmp + 1; *p; p++)
410                 if(*p == '/') {
411                         *p = 0;
412                         mkdir(tmp, mode);
413                         *p = '/';
414                 }
415         return mkdir(tmp, mode);
416 }
417
418 static char* _media_thumb_get_default_path(uid_t uid)
419 {
420         char *result_psswd = NULL;
421         struct group *grpinfo = NULL;
422         if(uid == getuid())
423         {
424                 result_psswd = strdup(THUMB_DEFAULT_PATH);
425                 grpinfo = getgrnam("users");
426                 if(grpinfo == NULL) {
427                         thumb_err("getgrnam(users) returns NULL !");
428                         return NULL;
429                 }
430         }
431         else
432         {
433                 struct passwd *userinfo = getpwuid(uid);
434                 if(userinfo == NULL) {
435                         thumb_err("getpwuid(%d) returns NULL !", uid);
436                         return NULL;
437                 }
438                 grpinfo = getgrnam("users");
439                 if(grpinfo == NULL) {
440                         thumb_err("getgrnam(users) returns NULL !");
441                         return NULL;
442                 }
443                 // Compare git_t type and not group name
444                 if (grpinfo->gr_gid != userinfo->pw_gid) {
445                         thumb_err("UID [%d] does not belong to 'users' group!", uid);
446                         return NULL;
447                 }
448                 asprintf(&result_psswd, "%s/data/file-manager-service/.thumb/phone", userinfo->pw_dir);
449         }
450
451         /* create dir */
452         _mkdir(result_psswd,S_IRWXU | S_IRWXG | S_IRWXO);
453
454         return result_psswd;
455 }
456
457 int _media_thumb_process(thumbMsg *req_msg, thumbMsg *res_msg, uid_t uid)
458 {
459         int err = -1;
460         GdkPixbuf *gdkdata = NULL;
461         int thumb_size = 0;
462         int thumb_w = 0;
463         int thumb_h = 0;
464         int origin_w = 0;
465         int origin_h = 0;
466         int max_length = 0;
467         char *thumb_path = NULL;
468         int need_update_db = 0;
469         int alpha = 0;
470
471         if (req_msg == NULL || res_msg == NULL) {
472                 thumb_err("Invalid msg!");
473                 return MS_MEDIA_ERR_INVALID_PARAMETER;
474         }
475
476         int msg_type = req_msg->msg_type;
477         media_thumb_type thumb_type = req_msg->thumb_type;
478         const char *origin_path = req_msg->org_path;
479
480         // Currently, The color space that is supported by the gdk-pixbuf is only RGB.
481         media_thumb_format thumb_format = MEDIA_THUMB_RGB888;
482
483         thumb_path = res_msg->dst_path;
484         thumb_path[0] = '\0';
485         max_length = sizeof(res_msg->dst_path);
486
487         err = _media_thumb_db_connect(uid);
488         if (err != MS_MEDIA_ERR_NONE) {
489                 thumb_err("_media_thumb_mb_svc_connect failed: %d", err);
490                 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
491         }
492
493         if (msg_type == THUMB_REQUEST_DB_INSERT) {
494                 err = _media_thumb_get_thumb_from_db_with_size(origin_path, thumb_path, max_length, &need_update_db, &origin_w, &origin_h);
495                 if (err == MS_MEDIA_ERR_NONE) {
496                         res_msg->origin_width = origin_w;
497                         res_msg->origin_height = origin_h;
498                         _media_thumb_db_disconnect();
499                         return MS_MEDIA_ERR_NONE;
500                 } else {
501                         if (strlen(thumb_path) == 0) {
502                                 err = _media_thumb_get_hash_name(origin_path, thumb_path, max_length,uid);
503                                 if (err != MS_MEDIA_ERR_NONE) {
504                                         thumb_err("_media_thumb_get_hash_name failed - %d\n", err);
505                                         strncpy(thumb_path, _media_thumb_get_default_path(uid), max_length);
506                                         _media_thumb_db_disconnect();
507                                         return err;
508                                 }
509
510                                 thumb_path[strlen(thumb_path)] = '\0';
511                         }
512                 }
513
514         } else if (msg_type == THUMB_REQUEST_SAVE_FILE) {
515                 strncpy(thumb_path, req_msg->dst_path, max_length);
516
517         } else if (msg_type == THUMB_REQUEST_ALL_MEDIA) {
518                 err = _media_thumb_get_hash_name(origin_path, thumb_path, max_length,uid);
519                 if (err < 0) {
520                         thumb_err("_media_thumb_get_hash_name failed - %d\n", err);
521                         strncpy(thumb_path, _media_thumb_get_default_path(uid), max_length);
522                         _media_thumb_db_disconnect();
523                         return err;
524                 }
525
526                 thumb_path[strlen(thumb_path)] = '\0';
527         }
528
529         if (g_file_test(thumb_path, 
530                                         G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
531                 thumb_warn("thumb path already exists in file system.. remove the existed file");
532                 _media_thumb_remove_file(thumb_path);
533         }
534
535         err = _thumbnail_get_data(origin_path, thumb_type, thumb_format, &gdkdata, &thumb_size, &thumb_w, &thumb_h, &origin_w, &origin_h, &alpha, uid);
536         if (err != MS_MEDIA_ERR_NONE) {
537                 thumb_err("_thumbnail_get_data failed - %d\n", err);
538                 if ( gdkdata != NULL ){
539                         g_object_unref(gdkdata);
540                 }
541                 strncpy(thumb_path, _media_thumb_get_default_path(uid), max_length);
542                 _media_thumb_db_disconnect();
543                 return err;
544         }
545
546         //thumb_dbg("Size : %d, W:%d, H:%d", thumb_size, thumb_w, thumb_h);
547         //thumb_dbg("Origin W:%d, Origin H:%d\n", origin_w, origin_h);
548         //thumb_dbg("Thumb : %s", thumb_path);
549
550         res_msg->msg_type = THUMB_RESPONSE;
551         res_msg->thumb_size = thumb_size;
552         res_msg->thumb_width = thumb_w;
553         res_msg->thumb_height = thumb_h;
554         res_msg->origin_width = origin_w;
555         res_msg->origin_height = origin_h;
556
557         /* If the image is transparent PNG format, make png file as thumbnail of this image */
558         if (alpha) {
559                 char file_ext[10];
560                 err = _media_thumb_get_file_ext(origin_path, file_ext, sizeof(file_ext));
561                 if (strncasecmp(file_ext, "png", 3) == 0) {
562                         int len = strlen(thumb_path);
563                         thumb_path[len - 3] = 'p';
564                         thumb_path[len - 2] = 'n';
565                         thumb_path[len - 1] = 'g';
566                 }
567                 thumb_dbg("Thumb path is changed : %s", thumb_path);
568         }
569
570         err = _media_thumb_save_to_file_with_gdk(gdkdata, thumb_w, thumb_h, alpha, thumb_path);
571         if (err < 0) {
572                 thumb_err("save_to_file_with_gdk failed - %d\n", err);
573                 if ( gdkdata != NULL ){
574                         g_object_unref(gdkdata);
575                 }
576
577                 if (msg_type == THUMB_REQUEST_DB_INSERT || msg_type == THUMB_REQUEST_ALL_MEDIA)
578                         strncpy(thumb_path, _media_thumb_get_default_path(uid), max_length);
579
580                 _media_thumb_db_disconnect();
581                 return err;
582         } else {
583                 thumb_dbg("file save success\n");
584         }
585
586         /* fsync */
587         int fd = 0;
588         fd = open(thumb_path, O_WRONLY);
589         if (fd < 0) {
590                 thumb_warn("open failed");
591         } else {
592                 err = fsync(fd);
593                 if (err == -1) {
594                         thumb_warn("fsync failed");
595                 }
596                 close(fd);
597         }
598         /* End of fsync */
599
600         g_object_unref(gdkdata);
601
602         /* DB update if needed */
603         if (need_update_db == 1) {
604                 err = _media_thumb_update_db(origin_path, thumb_path, res_msg->origin_width, res_msg->origin_height, uid);
605                 if (err != MS_MEDIA_ERR_NONE) {
606                         thumb_err("_media_thumb_update_db failed : %d", err);
607                 }
608         }
609
610         _media_thumb_db_disconnect();
611
612         return MS_MEDIA_ERR_NONE;
613 }
614
615 gboolean _media_thumb_write_socket(GIOChannel *src, GIOCondition condition, gpointer data)
616 {
617         thumbMsg recv_msg;
618         int header_size = 0;
619         int recv_str_len = 0;
620         int sock = 0;
621         int err = MS_MEDIA_ERR_NONE;
622
623         memset((void *)&recv_msg, 0, sizeof(thumbMsg));
624         sock = g_io_channel_unix_get_fd(src);
625
626         header_size = sizeof(thumbMsg) - MAX_PATH_SIZE*2;
627
628         thumb_err("_media_thumb_write_socket socket : %d", sock);
629
630         if ((err = _media_thumb_recv_msg(sock, header_size, &recv_msg)) < 0) {
631                 thumb_err("_media_thumb_recv_msg failed ");
632                 g_io_channel_shutdown(src, TRUE, NULL);
633                 return FALSE;
634         }
635
636         recv_str_len = strlen(recv_msg.dst_path);
637         thumb_dbg("recv %s(%d) in  [ %s ] from thumb daemon is successful", recv_msg.dst_path, recv_str_len, recv_msg.org_path);
638
639         g_io_channel_shutdown(src, TRUE, NULL);
640
641         //thumb_dbg("Completed..%s", recv_msg.org_path);
642         __media_thumb_pop_req_queue(recv_msg.org_path, FALSE);
643
644         if (recv_msg.status == THUMB_FAIL) {
645                 thumb_err("Failed to make thumbnail");
646                 err = MS_MEDIA_ERR_INTERNAL;
647                 goto callback;
648         }
649
650 callback:
651         if (data) {
652                 thumbUserData* cb = (thumbUserData*)data;
653                 cb->func(err, recv_msg.dst_path, cb->user_data);
654                 free(cb);
655                 cb = NULL;
656         }
657
658         thumb_dbg("Done");
659         return FALSE;
660 }
661
662 int
663 _media_thumb_request_async(int msg_type, media_thumb_type thumb_type, const char *origin_path, thumbUserData *userData, uid_t uid)
664 {
665         int sock;
666         struct sockaddr_un serv_addr;
667         int pid;
668
669         if ((msg_type == THUMB_REQUEST_DB_INSERT) && (__media_thumb_check_req_queue(origin_path) < 0)) {
670                 return MS_MEDIA_ERR_THUMB_DUPLICATED_REQUEST;
671         }
672
673         if (ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_10, &sock, MS_THUMB_CREATOR_PORT) < 0) {
674                 thumb_err("ms_ipc_create_client_socket failed");
675                 return MS_MEDIA_ERR_SOCKET_CONN;
676         }
677         GIOChannel *channel = NULL;
678         channel = g_io_channel_unix_new(sock);
679         int source_id = -1;
680
681
682         memset(&serv_addr, 0, sizeof(serv_addr));
683         serv_addr.sun_family = AF_UNIX;
684
685         strcpy(serv_addr.sun_path, "/var/run/media-server/media_ipc_thumbcreator.socket");
686
687         /* Connecting to the thumbnail server */
688         if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
689                 thumb_err("connect error : %s", strerror(errno));
690                 g_io_channel_shutdown(channel, TRUE, NULL);
691                 return MS_MEDIA_ERR_SOCKET_CONN;
692         }
693
694         if (msg_type != THUMB_REQUEST_CANCEL_MEDIA) {
695                 //source_id = g_io_add_watch(channel, G_IO_IN, _media_thumb_write_socket, userData );
696
697                 /* Create new channel to watch udp socket */
698                 GSource *source = NULL;
699                 source = g_io_create_watch(channel, G_IO_IN);
700
701                 /* Set callback to be called when socket is readable */
702                 g_source_set_callback(source, (GSourceFunc)_media_thumb_write_socket, userData, NULL);
703                 source_id = g_source_attach(source, g_main_context_get_thread_default());
704         }
705
706         thumbMsg req_msg;
707         memset((void *)&req_msg, 0, sizeof(thumbMsg));
708
709         pid = getpid();
710         req_msg.pid = pid;
711         req_msg.msg_type = msg_type;
712         req_msg.thumb_type = thumb_type;
713         req_msg.uid = uid;      
714
715         strncpy(req_msg.org_path, origin_path, sizeof(req_msg.org_path));
716         req_msg.org_path[strlen(req_msg.org_path)] = '\0';
717
718         req_msg.origin_path_size = strlen(req_msg.org_path) + 1;
719         req_msg.dest_path_size = strlen(req_msg.dst_path) + 1;
720
721         if (req_msg.origin_path_size > MAX_PATH_SIZE || req_msg.dest_path_size > MAX_PATH_SIZE) {
722                 thumb_err("path's length exceeds %d", MAX_PATH_SIZE);
723                 g_io_channel_shutdown(channel, TRUE, NULL);
724                 return MS_MEDIA_ERR_INVALID_PARAMETER;
725         }
726
727         unsigned char *buf = NULL;
728         int buf_size = 0;
729         _media_thumb_set_buffer(&req_msg, &buf, &buf_size);
730
731         if (send(sock, buf, buf_size, 0) != buf_size) {
732                 thumb_err("sendto failed: %d\n", errno);
733                 SAFE_FREE(buf);
734                 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), source_id));
735                 g_io_channel_shutdown(channel, TRUE, NULL);
736                 return MS_MEDIA_ERR_SOCKET_SEND;
737         }
738
739         SAFE_FREE(buf);
740         thumb_dbg("Sending msg to thumbnail daemon is successful");
741
742 #if 0
743         if (msg_type == THUMB_REQUEST_CANCEL_MEDIA) {
744                 g_io_channel_shutdown(channel, TRUE, NULL);
745         }
746 #else
747         if (msg_type == THUMB_REQUEST_CANCEL_MEDIA) {
748                 g_io_channel_shutdown(channel, TRUE, NULL);
749
750                 //thumb_dbg("Cancel : %s[%d]", origin_path, sock);
751                 __media_thumb_pop_req_queue(origin_path, TRUE);
752         } else if (msg_type == THUMB_REQUEST_DB_INSERT) {
753                 if (g_request_queue == NULL) {
754                         g_request_queue = g_queue_new();
755                 }
756
757                 thumbReq *thumb_req = NULL;
758                 thumb_req = calloc(1, sizeof(thumbReq));
759                 if (thumb_req == NULL) {
760                         thumb_err("Failed to create request element");
761                         return MS_MEDIA_ERR_NONE;
762                 }
763
764                 thumb_req->channel = channel;
765                 thumb_req->path = strdup(origin_path);
766                 thumb_req->source_id = source_id;
767
768                 //thumb_dbg("Push : %s [%d]", origin_path, sock);
769                 g_queue_push_tail(g_request_queue, (gpointer)thumb_req);
770         }
771 #endif
772
773         return MS_MEDIA_ERR_NONE;
774 }