Merge thumb request queue
[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 THUMB_SOCK_BLOCK_SIZE 512
35 #define THUMB_IPC_PATH tzplatform_mkpath(TZ_SYS_RUN, "media-server/media_ipc_thumbcreator.socket")
36
37 static GQueue *g_manage_queue = NULL;
38 static GQueue *g_request_raw_queue = NULL;
39 static GQueue *g_manage_raw_queue = NULL;
40
41
42 typedef struct {
43         GIOChannel *channel;
44         int msg_type;
45         unsigned int request_id;
46         bool isCanceled;
47         bool isRequested;
48         int source_id;
49         uid_t uid;
50         char *path;
51         thumbUserData *userData;
52 } thumbReq;
53
54 typedef struct {
55         GIOChannel *channel;
56         int msg_type;
57         bool isCanceled;
58         int request_id;
59         int source_id;
60         int width;
61         int height;
62         uid_t uid;
63         char *path;
64         thumbRawUserData *userData;
65 } thumbRawReq;
66
67 static int _media_thumb_send_request();
68 static int _media_thumb_raw_data_send_request();
69
70
71 int _media_thumb_get_error()
72 {
73         if (errno == EWOULDBLOCK) {
74                 thumb_err("Timeout. Can't try any more");
75                 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
76         } else {
77                 thumb_stderror("recvfrom failed");
78                 return MS_MEDIA_ERR_SOCKET_RECEIVE;
79         }
80 }
81
82 void __media_thumb_pop()
83 {
84         int len = 0;
85
86         if (g_manage_queue != NULL) {
87                 thumbReq *req = (thumbReq *)g_queue_pop_head(g_manage_queue);
88                 if (req != NULL) {
89                         GSource *source_id = g_main_context_find_source_by_id(g_main_context_get_thread_default(), req->source_id);
90
91                         g_io_channel_shutdown(req->channel, TRUE, NULL);
92                         g_io_channel_unref(req->channel);
93
94                         if (source_id != NULL) {
95                                 g_source_destroy(source_id);
96                         } else {
97                                 thumb_err("G_SOURCE_ID is NULL");
98                         }
99
100                         SAFE_FREE(req->path);
101                         SAFE_FREE(req->userData);
102                         SAFE_FREE(req);
103                 }
104
105                 /* Check manage queue */
106                 len = g_queue_get_length(g_manage_queue);
107                 if (len > 0)
108                         _media_thumb_send_request();
109         }
110 }
111
112 int __media_thumb_cancel(unsigned int request_id)
113 {
114         int len = 0, i;
115         bool flag = false;
116
117         if (g_manage_queue != NULL) {
118                 len = g_queue_get_length(g_manage_queue);
119
120                 for (i = 0; i < len; i++) {
121                         thumbReq *req = NULL;
122                         req = (thumbReq *)g_queue_peek_nth(g_manage_queue, i);
123                         if (req == NULL) continue;
124
125                         if (req->request_id == request_id) {
126                                 if (req->isRequested == true) {
127                                         req->isCanceled = true;
128                                 } else {
129                                         g_queue_pop_nth(g_manage_queue, i);
130
131                                         SAFE_FREE(req->path);
132                                         SAFE_FREE(req->userData);
133                                         SAFE_FREE(req);
134                                 }
135
136                                 flag = true;
137
138                                 break;
139                         }
140                 }
141         }
142
143         if (flag == false)
144                 return MS_MEDIA_ERR_INTERNAL;
145
146         return MS_MEDIA_ERR_NONE;
147 }
148
149 int __media_thumb_pop_raw_data_req_queue(int request_id, bool shutdown_channel)
150 {
151         int req_len = 0, i;
152
153         req_len = g_queue_get_length(g_request_raw_queue);
154
155         if (req_len <= 0) {
156 //              thumb_dbg("There is no request in the queue");
157         } else {
158
159                 for (i = 0; i < req_len; i++) {
160                         thumbRawReq *req = NULL;
161                         req = (thumbRawReq *)g_queue_peek_nth(g_request_raw_queue, i);
162                         if (req == NULL) continue;
163
164                         if (request_id == req->request_id) {
165                                 if (shutdown_channel) {
166                                         GSource *source_id = g_main_context_find_source_by_id(g_main_context_get_thread_default(), req->source_id);
167                                         if (source_id != NULL) {
168                                                 g_source_destroy(source_id);
169                                         } else {
170                                                 thumb_err("G_SOURCE_ID is NULL");
171                                         }
172
173                                         g_io_channel_shutdown(req->channel, TRUE, NULL);
174                                         g_io_channel_unref(req->channel);
175                                 }
176                                 g_queue_pop_nth(g_request_raw_queue, i);
177
178                                 SAFE_FREE(req->userData);
179                                 SAFE_FREE(req);
180
181                                 break;
182                         }
183                 }
184                 if (i == req_len) {
185 //                      thumb_dbg("There's no %s in the queue", path);
186                 }
187         }
188
189         return MS_MEDIA_ERR_NONE;
190 }
191
192 int __media_thumb_check_raw_data_req_queue_for_cancel(int request_id)
193 {
194         int req_len = 0;
195
196         req_len = g_queue_get_length(g_request_raw_queue);
197
198         if (req_len <= 0) {
199 //              thumb_dbg("There is no request in the queue");
200         } else {
201                 thumbRawReq *req = NULL;
202                 req = (thumbRawReq *)g_queue_peek_head(g_request_raw_queue);
203
204                 if (req != NULL && request_id == req->request_id) {
205                         req->isCanceled = true;
206                         return MS_MEDIA_ERR_NONE;
207                 }
208         }
209
210         return MS_MEDIA_ERR_INTERNAL;
211 }
212
213 int __media_thumb_pop_raw_data_manage_queue(int request_id)
214 {
215         int req_len = 0, i;
216         int flag = false;
217
218         req_len = g_queue_get_length(g_manage_raw_queue);
219
220         if (req_len < 0) {
221 //              thumb_dbg("There is no request in the queue");
222         } else {
223
224                 for (i = 0; i < req_len; i++) {
225                         thumbRawReq *req = NULL;
226                         req = (thumbRawReq *)g_queue_peek_nth(g_manage_raw_queue, i);
227                         if (req == NULL) continue;
228
229                         if (request_id == req->request_id) {
230                                 g_queue_pop_nth(g_manage_raw_queue, i);
231
232                                 SAFE_FREE(req->userData);
233                                 SAFE_FREE(req);
234                                 flag = true;
235                                 break;
236                         }
237                 }
238                 if (!flag) {
239                         return __media_thumb_check_raw_data_req_queue_for_cancel(request_id);
240                 }
241         }
242
243         return MS_MEDIA_ERR_NONE;
244 }
245
246 bool __media_thumb_check_cancel(void)
247 {
248         thumbReq *req = NULL;
249         req = (thumbReq *)g_queue_peek_head(g_manage_queue);
250
251         if (req == NULL) {
252                 return false;
253         } else {
254                 if (req->isCanceled)
255                         return false;
256                 else
257                         return true;
258         }
259 }
260
261 bool __media_thumb_check_cancel_for_raw(void)
262 {
263         thumbRawReq *req = NULL;
264         req = (thumbRawReq *)g_queue_peek_head(g_request_raw_queue);
265
266         if (req == NULL) {
267                 return false;
268         } else {
269                 if (req->isCanceled)
270                         return false;
271                 else
272                         return true;
273         }
274 }
275
276 int _media_thumb_recv_msg(int sock, int header_size, thumbMsg *msg)
277 {
278         int recv_msg_len = 0;
279         int remain_size = 0;
280         int block_size = THUMB_SOCK_BLOCK_SIZE;
281         int recv_block = 0;
282         unsigned char *buf = NULL;
283         unsigned char *block_buf = NULL;
284
285         THUMB_MALLOC(buf, header_size);
286         THUMB_MALLOC(block_buf, THUMB_SOCK_BLOCK_SIZE);
287         if (buf == NULL || block_buf == NULL) {
288                 thumb_err("memory allocation failed");
289                 SAFE_FREE(buf);
290                 SAFE_FREE(block_buf);
291                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
292         }
293
294         if ((recv_msg_len = recv(sock, buf, header_size, 0)) <= 0) {
295                 thumb_stderror("recv failed");
296                 SAFE_FREE(buf);
297                 SAFE_FREE(block_buf);
298                 return _media_thumb_get_error();
299         }
300
301         memcpy(msg, buf, header_size);
302         //thumb_dbg("origin_path_size : %d, dest_path_size : %d, thumb_size : %d", msg->origin_path_size, msg->dest_path_size, msg->thumb_size);
303
304         SAFE_FREE(buf);
305         if (msg->origin_path_size < 0 || msg->dest_path_size < 0 || msg->thumb_size < 0) {
306                 thumb_err("recv data is wrong");
307                 SAFE_FREE(block_buf);
308                 return MS_MEDIA_ERR_SOCKET_RECEIVE;
309         }
310
311         remain_size = msg->origin_path_size + msg->dest_path_size + msg->thumb_size;
312         THUMB_MALLOC(buf, remain_size);
313         if (buf == NULL) {
314                 SAFE_FREE(block_buf);
315                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
316         }
317
318         while (remain_size > 0) {
319                 if (remain_size < THUMB_SOCK_BLOCK_SIZE) {
320                         block_size = remain_size;
321                 }
322                 if ((recv_msg_len = recv(sock, block_buf, block_size, 0)) < 0) {
323                         thumb_stderror("recv failed");
324                         SAFE_FREE(buf);
325                         SAFE_FREE(block_buf);
326                         return _media_thumb_get_error();
327                 }
328                 memcpy(buf+recv_block, block_buf, block_size);
329                 recv_block += block_size;
330                 remain_size -= block_size;
331         }
332
333         SAFE_STRLCPY(msg->org_path, (char *)buf, sizeof(msg->org_path));
334         SAFE_STRLCPY(msg->dst_path, (char *)buf + msg->origin_path_size, sizeof(msg->dst_path));
335
336         SAFE_FREE(msg->thumb_data);
337         if (msg->thumb_size > 0) {
338                 THUMB_MALLOC(msg->thumb_data, msg->thumb_size);
339                 if (msg->thumb_data != NULL) {
340                         memcpy(msg->thumb_data, buf + msg->origin_path_size + msg->dest_path_size, msg->thumb_size);
341                 } else {
342                         SAFE_FREE(buf);
343                         SAFE_FREE(block_buf);
344
345                         return MS_MEDIA_ERR_OUT_OF_MEMORY;
346                 }
347         }
348
349         SAFE_FREE(buf);
350         SAFE_FREE(block_buf);
351
352         return MS_MEDIA_ERR_NONE;
353 }
354
355 int _media_thumb_set_buffer(thumbMsg *req_msg, unsigned char **buf, int *buf_size)
356 {
357         if (req_msg == NULL || buf == NULL) {
358                 return MS_MEDIA_ERR_INVALID_PARAMETER;
359         }
360
361         int org_path_len = 0;
362         int dst_path_len = 0;
363         int thumb_data_len = 0;
364         int size = 0;
365         int header_size = 0;
366
367         header_size = sizeof(thumbMsg) -(MAX_FILEPATH_LEN * 2) - sizeof(unsigned char *);
368         org_path_len = req_msg->origin_path_size;
369         dst_path_len = req_msg->dest_path_size;
370         thumb_data_len = req_msg->thumb_size;
371
372         //thumb_dbg("Basic Size : %d, org_path : %s[%d], dst_path : %s[%d], thumb_data_len : %d", header_size, req_msg->org_path, org_path_len, req_msg->dst_path, dst_path_len, thumb_data_len);
373
374         size = header_size + org_path_len + dst_path_len + thumb_data_len;
375         THUMB_MALLOC(*buf, size);
376         if (*buf == NULL) {
377                 *buf_size = 0;
378                 return 0;
379         }
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         if (thumb_data_len > 0)
384                 memcpy((*buf)+header_size + org_path_len + dst_path_len, req_msg->thumb_data, thumb_data_len);
385
386         *buf_size = size;
387
388         return MS_MEDIA_ERR_NONE;
389 }
390
391 int _media_thumb_request(int msg_type, const char *origin_path, char *thumb_path, int max_length, uid_t uid)
392 {
393         int sock = -1;
394         struct sockaddr_un serv_addr;
395         int recv_str_len = 0;
396         int err = MS_MEDIA_ERR_NONE;
397         int pid;
398
399         err = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sock);
400         if (err != MS_MEDIA_ERR_NONE) {
401                 thumb_err("ms_ipc_create_client_socket failed");
402                 return err;
403         }
404
405         memset(&serv_addr, 0, sizeof(serv_addr));
406         serv_addr.sun_family = AF_UNIX;
407         SAFE_STRLCPY(serv_addr.sun_path, THUMB_IPC_PATH, sizeof(serv_addr.sun_path));
408
409         /* Connecting to the thumbnail server */
410         if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
411                 thumb_stderror("connect");
412                 close(sock);
413                 return MS_MEDIA_ERR_SOCKET_CONN;
414         }
415
416         thumbMsg req_msg;
417         thumbMsg recv_msg;
418
419         memset((void *)&req_msg, 0, sizeof(thumbMsg));
420         memset((void *)&recv_msg, 0, sizeof(thumbMsg));
421
422         /* Get PID of client*/
423         pid = getpid();
424         req_msg.pid = pid;
425
426         /* Set requset message */
427         req_msg.msg_type = msg_type;
428         req_msg.uid = uid;
429         SAFE_STRLCPY(req_msg.org_path, origin_path, sizeof(req_msg.org_path));
430         req_msg.origin_path_size = strlen(req_msg.org_path) + 1;
431         req_msg.dest_path_size = strlen(req_msg.dst_path) + 1;
432         req_msg.thumb_size = 0;
433
434         if (req_msg.origin_path_size > MAX_PATH_SIZE || req_msg.dest_path_size > MAX_PATH_SIZE) {
435                 thumb_err("path's length exceeds %d", MAX_PATH_SIZE);
436                 close(sock);
437                 return MS_MEDIA_ERR_INVALID_PARAMETER;
438         }
439
440         unsigned char *buf = NULL;
441         int buf_size = 0;
442         int header_size = 0;
443
444         header_size = sizeof(thumbMsg) - MAX_PATH_SIZE*2 - sizeof(unsigned char *);
445         _media_thumb_set_buffer(&req_msg, &buf, &buf_size);
446
447         if (send(sock, buf, buf_size, 0) != buf_size) {
448                 thumb_err("sendto failed: %d", errno);
449                 SAFE_FREE(buf);
450                 close(sock);
451                 return MS_MEDIA_ERR_SOCKET_SEND;
452         }
453
454         thumb_dbg("Sending msg to thumbnail daemon is successful");
455
456         SAFE_FREE(buf);
457
458         if ((err = _media_thumb_recv_msg(sock, header_size, &recv_msg)) < 0) {
459                 thumb_err("_media_thumb_recv_msg failed ");
460                 close(sock);
461                 return err;
462         }
463
464         recv_str_len = strlen(recv_msg.org_path);
465         thumb_dbg_slog("recv %s(%d) from thumb daemon is successful", recv_msg.org_path, recv_str_len);
466
467         close(sock);
468         SAFE_FREE(recv_msg.thumb_data);
469
470         if (recv_str_len > max_length) {
471                 thumb_err("user buffer is too small. Output's length is %d", recv_str_len);
472                 return MS_MEDIA_ERR_INVALID_PARAMETER;
473         }
474
475         if (recv_msg.status != MS_MEDIA_ERR_NONE) {
476                 thumb_err("Failed to make thumbnail");
477                 return recv_msg.status;
478         }
479
480         SAFE_STRLCPY(thumb_path, recv_msg.dst_path, max_length);
481
482         return MS_MEDIA_ERR_NONE;
483 }
484
485 gboolean _media_thumb_write_socket(GIOChannel *src, GIOCondition condition, gpointer data)
486 {
487         thumbMsg recv_msg;
488         int header_size = 0;
489         int sock = 0;
490         int err = MS_MEDIA_ERR_NONE;
491
492         memset((void *)&recv_msg, 0, sizeof(thumbMsg));
493         sock = g_io_channel_unix_get_fd(src);
494
495         header_size = sizeof(thumbMsg) - MAX_PATH_SIZE*2 - sizeof(unsigned char *);
496
497         thumb_err("_media_thumb_write_socket socket : %d", sock);
498
499         if ((err = _media_thumb_recv_msg(sock, header_size, &recv_msg)) < 0) {
500                 thumb_err("_media_thumb_recv_msg failed ");
501                 __media_thumb_pop();
502
503                 return FALSE;
504         }
505
506         if (recv_msg.status != MS_MEDIA_ERR_NONE) {
507                 err = recv_msg.status;
508                 thumb_err("Failed to make thumbnail (%d)", err);
509         }
510
511         if (__media_thumb_check_cancel()) {
512                 if (data) {
513                         thumbUserData* cb = (thumbUserData*)data;
514                         if (cb->func != NULL)
515                                 cb->func(err, recv_msg.dst_path, cb->user_data);
516                 }
517         }
518
519         __media_thumb_pop();
520
521         thumb_dbg("Done");
522
523         return FALSE;
524 }
525
526 gboolean _media_thumb_raw_data_write_socket(GIOChannel *src, GIOCondition condition, gpointer data)
527 {
528         thumbMsg recv_msg;
529         int header_size = 0;
530         int sock = 0;
531         int len = -1;
532         int err = MS_MEDIA_ERR_NONE;
533
534         memset((void *)&recv_msg, 0, sizeof(thumbMsg));
535         sock = g_io_channel_unix_get_fd(src);
536
537         header_size = sizeof(thumbMsg) - MAX_PATH_SIZE*2 - sizeof(unsigned char *);
538
539         thumb_err("_media_thumb_write_socket socket : %d", sock);
540
541         if ((err = _media_thumb_recv_msg(sock, header_size, &recv_msg)) < 0) {
542                 thumb_err("_media_thumb_recv_msg failed ");
543                 if (recv_msg.request_id > 0) {
544                         __media_thumb_pop_raw_data_req_queue(recv_msg.request_id, TRUE);
545                 } else {
546                         thumb_err("origin path size is wrong.");
547                 }
548
549                 return FALSE;
550         }
551
552         g_io_channel_shutdown(src, TRUE, NULL);
553         g_io_channel_unref(src);
554
555         if (recv_msg.status != MS_MEDIA_ERR_NONE) {
556                 err = recv_msg.status;
557                 thumb_err("Failed to make thumbnail (%d)", err);
558         }
559
560         if (__media_thumb_check_cancel_for_raw()) {
561                 if (data) {
562                         thumbRawUserData* cb = (thumbRawUserData*)data;
563                         if (cb->func != NULL)
564                                 cb->func(err, recv_msg.request_id, recv_msg.org_path, recv_msg.thumb_width, recv_msg.thumb_height, recv_msg.thumb_data, recv_msg.thumb_size, cb->user_data);
565                 }
566         }
567
568         __media_thumb_pop_raw_data_req_queue(recv_msg.request_id, FALSE);
569
570         thumb_dbg("Done");
571
572         /* Check manage queue */
573         if (g_manage_raw_queue) {
574                 len = g_queue_get_length(g_manage_raw_queue);
575
576                 if (len > 0) {
577                         _media_thumb_raw_data_send_request();
578                 } else {
579                         g_queue_free(g_manage_raw_queue);
580                         g_manage_raw_queue = NULL;
581                 }
582         }
583
584         return FALSE;
585 }
586
587 static int _media_thumb_send_request()
588 {
589         int err = MS_MEDIA_ERR_NONE;
590         int sock = -1;
591         struct sockaddr_un serv_addr;
592         thumbReq *req_manager = NULL;
593         int pid;
594
595         err = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sock);
596         if (err != MS_MEDIA_ERR_NONE) {
597                 thumb_err("ms_ipc_create_client_socket failed");
598                 return err;
599         }
600
601         memset(&serv_addr, 0, sizeof(serv_addr));
602         serv_addr.sun_family = AF_UNIX;
603         SAFE_STRLCPY(serv_addr.sun_path, THUMB_IPC_PATH, sizeof(serv_addr.sun_path));
604
605         GIOChannel *channel = NULL;
606         channel = g_io_channel_unix_new(sock);
607         int source_id = -1;
608
609         /* Connecting to the thumbnail server */
610         if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
611                 thumb_stderror("connect");
612                 if (errno == EACCES)
613                         err = MS_MEDIA_ERR_PERMISSION_DENIED;
614                 else
615                         err = MS_MEDIA_ERR_SOCKET_CONN;
616
617                 g_io_channel_shutdown(channel, TRUE, NULL);
618                 g_io_channel_unref(channel);
619                 close(sock);
620
621                 return err;
622         }
623
624         req_manager = (thumbReq *)g_queue_peek_head(g_manage_queue);
625
626         if (req_manager == NULL) {
627                 thumb_err("queue peek fail");
628                 g_io_channel_shutdown(channel, TRUE, NULL);
629                 g_io_channel_unref(channel);
630                 close(sock);
631                 return MS_MEDIA_ERR_INVALID_PARAMETER;
632         }
633
634         GSource *source = NULL;
635         source = g_io_create_watch(channel, G_IO_IN);
636         g_source_set_callback(source, (GSourceFunc)_media_thumb_write_socket, req_manager->userData, NULL);
637         source_id = g_source_attach(source, g_main_context_get_thread_default());
638
639         thumbMsg req_msg;
640
641         memset((void *)&req_msg, 0, sizeof(thumbMsg));
642
643         pid = getpid();
644         req_msg.pid = pid;
645         req_msg.msg_type = req_manager->msg_type;
646         req_msg.request_id = 0;
647         req_msg.uid = req_manager->uid;
648         SAFE_STRLCPY(req_msg.org_path, req_manager->path, sizeof(req_msg.org_path));
649         req_msg.dst_path[0] = '\0';
650         req_msg.origin_path_size = strlen(req_msg.org_path) + 1;
651         req_msg.dest_path_size = 1;
652         req_msg.thumb_size = 0;
653
654         if (req_msg.origin_path_size > MAX_PATH_SIZE || req_msg.dest_path_size > MAX_PATH_SIZE) {
655                 thumb_err("path's length exceeds %d", MAX_PATH_SIZE);
656                 g_io_channel_shutdown(channel, TRUE, NULL);
657                 g_io_channel_unref(channel);
658                 close(sock);
659                 return MS_MEDIA_ERR_INVALID_PARAMETER;
660         }
661
662         unsigned char *buf = NULL;
663         int buf_size = 0;
664         _media_thumb_set_buffer(&req_msg, &buf, &buf_size);
665
666         if (send(sock, buf, buf_size, 0) != buf_size) {
667                 thumb_err("sendto failed: %d", errno);
668                 SAFE_FREE(buf);
669                 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), source_id));
670                 g_io_channel_shutdown(channel, TRUE, NULL);
671                 g_io_channel_unref(channel);
672                 close(sock);
673                 return MS_MEDIA_ERR_SOCKET_SEND;
674         }
675
676         SAFE_FREE(buf);
677         thumb_dbg("Sending msg to thumbnail daemon is successful");
678
679         if (req_manager->msg_type == THUMB_REQUEST_DB_INSERT) {
680                 req_manager->channel = channel;
681                 req_manager->source_id = source_id;
682                 req_manager->isRequested = true;
683         }
684
685         return err;
686 }
687
688 static int _media_thumb_raw_data_send_request()
689 {
690         int err = MS_MEDIA_ERR_NONE;
691         int sock = -1;
692         struct sockaddr_un serv_addr;
693         thumbRawReq *req_manager = NULL;
694         int pid;
695
696         err = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sock);
697         if (err != MS_MEDIA_ERR_NONE) {
698                 thumb_err("ms_ipc_create_client_socket failed");
699                 return err;
700         }
701
702         memset(&serv_addr, 0, sizeof(serv_addr));
703         serv_addr.sun_family = AF_UNIX;
704         SAFE_STRLCPY(serv_addr.sun_path, THUMB_IPC_PATH, sizeof(serv_addr.sun_path));
705
706         GIOChannel *channel = NULL;
707         channel = g_io_channel_unix_new(sock);
708         int source_id = -1;
709
710         /* Connecting to the thumbnail server */
711         if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
712                 thumb_stderror("connect error");
713                 if (errno == EACCES)
714                         err = MS_MEDIA_ERR_PERMISSION_DENIED;
715                 else
716                         err = MS_MEDIA_ERR_SOCKET_CONN;
717
718                 g_io_channel_shutdown(channel, TRUE, NULL);
719                 g_io_channel_unref(channel);
720                 close(sock);
721                 return err;
722         }
723
724         req_manager = (thumbRawReq *)g_queue_pop_head(g_manage_raw_queue);
725
726         if (req_manager == NULL) {
727                 thumb_err("queue pop fail");
728                 g_io_channel_shutdown(channel, TRUE, NULL);
729                 g_io_channel_unref(channel);
730                 close(sock);
731                 return MS_MEDIA_ERR_INVALID_PARAMETER;
732         }
733
734         GSource *source = NULL;
735         source = g_io_create_watch(channel, G_IO_IN);
736         g_source_set_callback(source, (GSourceFunc)_media_thumb_raw_data_write_socket, req_manager->userData, NULL);
737         source_id = g_source_attach(source, g_main_context_get_thread_default());
738
739         thumbMsg req_msg;
740         memset((void *)&req_msg, 0, sizeof(thumbMsg));
741
742         pid = getpid();
743         req_msg.pid = pid;
744         req_msg.msg_type = req_manager->msg_type;
745         req_msg.request_id = req_manager->request_id;
746         req_msg.thumb_width = req_manager->width;
747         req_msg.thumb_height = req_manager->height;
748         req_msg.uid = req_manager->uid;
749
750         SAFE_STRLCPY(req_msg.org_path, req_manager->path, sizeof(req_msg.org_path));
751         req_msg.dst_path[0] = '\0';
752
753         req_msg.origin_path_size = strlen(req_msg.org_path) + 1;
754         req_msg.dest_path_size = 1;
755         req_msg.thumb_size = 0;
756
757         if (req_msg.origin_path_size > MAX_PATH_SIZE) {
758                 thumb_err("path's length exceeds %d", MAX_PATH_SIZE);
759                 g_io_channel_shutdown(channel, TRUE, NULL);
760                 g_io_channel_unref(channel);
761                 return MS_MEDIA_ERR_INVALID_PARAMETER;
762         }
763
764         unsigned char *buf = NULL;
765         int buf_size = 0;
766         _media_thumb_set_buffer(&req_msg, &buf, &buf_size);
767
768         if (send(sock, buf, buf_size, 0) != buf_size) {
769                 thumb_err("sendto failed: %d", errno);
770                 SAFE_FREE(buf);
771                 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), source_id));
772                 g_io_channel_shutdown(channel, TRUE, NULL);
773                 g_io_channel_unref(channel);
774                 return MS_MEDIA_ERR_SOCKET_SEND;
775         }
776
777         SAFE_FREE(buf);
778
779         if (req_manager->msg_type == THUMB_REQUEST_RAW_DATA) {
780                 if (g_request_raw_queue == NULL) {
781                         g_request_raw_queue = g_queue_new();
782                 }
783                 thumbRawReq *thumb_req = NULL;
784                 THUMB_MALLOC(thumb_req, sizeof(thumbRawReq));
785                 if (thumb_req == NULL) {
786                         thumb_err("Failed to create request element");
787                         return MS_MEDIA_ERR_INVALID_PARAMETER;
788                 }
789                 thumb_req->channel = channel;
790                 thumb_req->request_id = req_manager->request_id;
791                 thumb_req->source_id = source_id;
792                 thumb_req->userData = req_manager->userData;
793
794                 g_queue_push_tail(g_request_raw_queue, (gpointer)thumb_req);
795         }
796         return MS_MEDIA_ERR_NONE;
797 }
798
799 int _media_thumb_request_async(int msg_type, unsigned int request_id, const char *origin_path, thumbUserData *userData, uid_t uid)
800 {
801         int err = MS_MEDIA_ERR_NONE;
802         int len = 0;
803
804         if (msg_type == THUMB_REQUEST_CANCEL_MEDIA)
805                 return __media_thumb_cancel(request_id);
806
807         if (g_manage_queue == NULL)
808                 g_manage_queue = g_queue_new();
809
810         thumbReq *thumb_req = NULL;
811         THUMB_MALLOC(thumb_req, sizeof(thumbReq));
812         thumb_retvm_if(thumb_req == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Failed to create request element");
813
814         thumb_req->msg_type = msg_type;
815         thumb_req->path = strdup(origin_path);
816         thumb_req->userData = userData;
817         thumb_req->isCanceled = false;
818         thumb_req->isRequested= false;
819         thumb_req->request_id = request_id;
820         thumb_req->uid = uid;
821
822         len = g_queue_get_length(g_manage_queue);
823         g_queue_push_tail(g_manage_queue, (gpointer)thumb_req);
824
825         if (len == 0)
826                 err = _media_thumb_send_request();
827
828         return err;
829 }
830
831 int _media_thumb_request_raw_data_async(int msg_type, int request_id, const char *origin_path, int width, int height, thumbRawUserData *userData, uid_t uid)
832 {
833         int err = MS_MEDIA_ERR_NONE;
834
835         if (g_manage_raw_queue == NULL) {
836                 if (msg_type == THUMB_REQUEST_CANCEL_RAW_DATA)
837                         return MS_MEDIA_ERR_INTERNAL;
838
839                 g_manage_raw_queue = g_queue_new();
840
841                 thumbRawReq *thumb_req = NULL;
842                 THUMB_MALLOC(thumb_req, sizeof(thumbRawReq));
843                 if (thumb_req == NULL) {
844                         thumb_err("Failed to create request element");
845                         return MS_MEDIA_ERR_INVALID_PARAMETER;
846                 }
847
848                 thumb_req->msg_type = msg_type;
849                 thumb_req->request_id = request_id;
850                 thumb_req->path = strdup(origin_path);
851                 thumb_req->width = width;
852                 thumb_req->height = height;
853                 thumb_req->userData = userData;
854                 thumb_req->isCanceled = false;
855                 thumb_req->uid = uid;
856
857                 g_queue_push_tail(g_manage_raw_queue, (gpointer)thumb_req);
858
859                 /* directly request at first time */
860                 err = _media_thumb_raw_data_send_request();
861
862         } else {
863                 if (msg_type != THUMB_REQUEST_CANCEL_RAW_DATA) {
864                         /* Enqueue */
865                         thumbRawReq *thumb_req = NULL;
866                         THUMB_MALLOC(thumb_req, sizeof(thumbRawReq));
867                         if (thumb_req == NULL) {
868                                 thumb_err("Failed to create request element");
869                                 return MS_MEDIA_ERR_INVALID_PARAMETER;
870                         }
871
872                         thumb_req->msg_type = msg_type;
873                         thumb_req->request_id = request_id;
874                         thumb_req->path = strdup(origin_path);
875                         thumb_req->width = width;
876                         thumb_req->height = height;
877                         thumb_req->userData = userData;
878                         thumb_req->isCanceled = false;
879                         thumb_req->uid = uid;
880
881                         g_queue_push_tail(g_manage_raw_queue, (gpointer)thumb_req);
882
883                 } else {
884                         /* Dequeue */
885                         err = __media_thumb_pop_raw_data_manage_queue(request_id);
886                 }
887         }
888
889         return err;
890 }
891
892 int _media_thumb_request_cancel_all()
893 {
894         int i;
895         int req_len = -1;
896         int len = 0;
897         thumbRawReq *tmp_raw_req = NULL;
898
899         if (g_manage_raw_queue == NULL) {
900                 thumb_err("manage_queue is NULL");
901                 if (g_request_raw_queue != NULL) {
902                         /* Check request queue */
903                         len = g_queue_get_length(g_request_raw_queue);
904                         if (len > 0) {
905                                 tmp_raw_req = g_queue_peek_head(g_request_raw_queue);
906                                 if (tmp_raw_req != NULL)
907                                         tmp_raw_req->isCanceled = true;
908                                 return MS_MEDIA_ERR_NONE;
909                         }
910                 }
911                 thumb_err("request_queue is NULL");
912                 return MS_MEDIA_ERR_INTERNAL;
913         }
914         req_len = g_queue_get_length(g_manage_raw_queue);
915         for (i = 0; i < req_len; i++) {
916                 tmp_raw_req = g_queue_pop_tail(g_manage_raw_queue);
917                 if (tmp_raw_req) {
918                         SAFE_FREE(tmp_raw_req->path);
919                         SAFE_FREE(tmp_raw_req->userData);
920                         SAFE_FREE(tmp_raw_req);
921                         tmp_raw_req = NULL;
922                 }
923         }
924         g_queue_free(g_manage_raw_queue);
925         g_manage_raw_queue = NULL;
926         if (g_request_raw_queue != NULL) {
927                 /* Check request queue */
928                 len = g_queue_get_length(g_request_raw_queue);
929                 if (len > 0) {
930                         tmp_raw_req = g_queue_peek_head(g_request_raw_queue);
931                         if (tmp_raw_req != NULL)
932                                 tmp_raw_req->isCanceled = true;
933                 }
934         }
935
936         return MS_MEDIA_ERR_NONE;
937 }