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