Tizen 2.1 base
[framework/multimedia/media-server.git] / common / media-server-socket.c
1 /*
2  *  Media Server
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Yong Yeon Kim <yy9875.kim@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 /**
23  * This file defines api utilities of contents manager engines.
24  *
25  * @file                media-server-thumb.c
26  * @author      Yong Yeon Kim(yy9875.kim@samsung.com)
27  * @version     1.0
28  * @brief
29  */
30 #include <arpa/inet.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <errno.h>
34 #include <malloc.h>
35 #include <vconf.h>
36
37 #include "media-util.h"
38 #include "media-util-internal.h"
39 #include "media-server-dbg.h"
40 #include "media-server-ipc.h"
41 #include "media-server-db-svc.h"
42 #include "media-server-utils.h"
43 #include "media-server-scanner.h"
44 #include "media-server-socket.h"
45 #include "media-server-db.h"
46
47 extern GAsyncQueue *scan_queue;
48 GAsyncQueue* ret_queue;
49 GArray *owner_list;
50 extern GMutex *scanner_mutex;
51
52 typedef struct ms_req_owner_data
53 {
54         int pid;
55         struct sockaddr_in *client_addr;
56 }ms_req_owner_data;
57
58 int _ms_add_owner(ms_req_owner_data *owner_data)
59 {
60 //      MS_DBG("the length of array : %d", owner_list->len);
61 //      MS_DBG("pid : %d", owner_data->pid);
62 //      MS_DBG("client_addr : %p", owner_data->client_addr);
63
64         g_array_append_val(owner_list, owner_data);
65
66         return MS_MEDIA_ERR_NONE;
67 }
68
69 int _ms_find_owner(int pid, ms_req_owner_data **owner_data)
70 {
71         int i;
72         int len = owner_list->len;
73         bool find_flag = false;
74         ms_req_owner_data *data = NULL;
75
76         MS_DBG("length list :  %d", len);
77
78         for (i=0; i < len; i++) {
79                 data = g_array_index(owner_list, ms_req_owner_data*, i);
80                 MS_DBG("%d %d", data->pid, pid);
81                 if (data->pid == pid) {
82                         find_flag = true;
83                         break;
84                 }
85         }
86
87         if (find_flag == true) {
88                 *owner_data = data;
89                 MS_DBG("FIND OWNER");
90         } else {
91                 *owner_data = NULL;
92                 MS_DBG("DO NOT FIND OWNER");
93         }
94
95         return MS_MEDIA_ERR_NONE;
96 }
97
98 int _ms_delete_owner(ms_req_owner_data *owner_data)
99 {
100         int i;
101         int len = owner_list->len;
102         ms_req_owner_data *data = NULL;
103
104         for (i=0; i < len; i++) {
105                 data = g_array_index(owner_list, ms_req_owner_data*, i);
106                 if (data->pid == owner_data->pid) {
107                         if (data->client_addr == owner_data->client_addr) {
108                                 g_array_remove_index(owner_list, i);
109                                 MS_SAFE_FREE(owner_data->client_addr);
110                                 MS_SAFE_FREE(owner_data);
111                         }
112                         break;
113                 }
114         }
115
116         return MS_MEDIA_ERR_NONE;
117 }
118
119 gboolean ms_read_socket(GIOChannel *src, GIOCondition condition, gpointer data)
120 {
121         struct sockaddr_in *client_addr = NULL;
122         socklen_t client_addr_len;
123         ms_comm_msg_s recv_msg;
124         ms_comm_msg_s result_msg;
125         ms_comm_msg_s scan_msg;
126         int msg_size;
127         int sockfd = MS_SOCK_NOT_ALLOCATE;
128         int ret;
129         int pid;
130         int req_num;
131         int path_size;
132         void **handle = data;
133         char *path = NULL;
134
135         g_mutex_lock(scanner_mutex);
136
137         sockfd = g_io_channel_unix_get_fd(src);
138         if (sockfd < 0) {
139                 MS_DBG_ERR("sock fd is invalid!");
140                 g_mutex_unlock(scanner_mutex);
141                 return TRUE;
142         }
143
144         /* Socket is readable */
145         MS_MALLOC(client_addr, sizeof(struct sockaddr_in));
146         if (client_addr == NULL) {
147                 MS_DBG_ERR("malloc failed");
148                 g_mutex_unlock(scanner_mutex);
149                 return TRUE;
150         }
151
152         client_addr_len = sizeof(struct sockaddr_in);
153         ret = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(recv_msg), client_addr, NULL);
154         if (ret != MS_MEDIA_ERR_NONE) {
155                 MS_DBG_ERR("ms_ipc_receive_message failed");
156                 MS_SAFE_FREE(client_addr);
157                 g_mutex_unlock(scanner_mutex);
158                 return TRUE;
159         }
160
161         MS_DBG("receive msg from [%d] %d, %s", recv_msg.pid, recv_msg.msg_type, recv_msg.msg);
162
163         if (recv_msg.msg_size > 0 && recv_msg.msg_size < MS_FILE_PATH_LEN_MAX) {
164                 msg_size = recv_msg.msg_size;
165                 path_size = msg_size + 1;
166         } else {
167                 /*NEED IMPLEMETATION*/
168                 MS_SAFE_FREE(client_addr);
169                 g_mutex_unlock(scanner_mutex);
170                 return TRUE;
171         }
172
173         /* copy received data */
174         req_num = recv_msg.msg_type;
175         pid = recv_msg.pid;
176
177         /* register file request
178          * media server inserts the meta data of one file into media db */
179         if (req_num == MS_MSG_DB_UPDATE) {
180                 MS_MALLOC(path, path_size);
181                 if  (path !=  NULL) {
182                         ret = ms_strcopy(path, path_size, "%s", recv_msg.msg);
183                         if (ret != MS_MEDIA_ERR_NONE) {
184                                 MS_SAFE_FREE(path);
185                                 MS_SAFE_FREE(client_addr);
186                                 g_mutex_unlock(scanner_mutex);
187                                 return TRUE;
188                         }
189
190                         MS_DBG("REQUEST FILE REGISTER");
191 #if MS_INOTI_ENABLE
192                         ret = ms_register_file(handle, path, ret_queue);
193                         if (ret == MS_MEDIA_ERR_NOW_REGISTER_FILE) {
194                                 ret= GPOINTER_TO_INT(g_async_queue_pop(ret_queue)) - MS_MEDIA_ERR_MAX;
195                         }
196 #else
197                         ret = ms_register_file(handle, path);
198 #endif
199                         MS_DBG_INFO("register result : %d", ret);
200                         /* the result of inserting to db */
201                         result_msg.result = ret;
202                 } else {
203                         MS_DBG_ERR("malloc failed");
204                         result_msg.result = MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL;
205                 }
206
207                 ms_ipc_send_msg_to_client(sockfd, &result_msg, client_addr);
208
209                 MS_SAFE_FREE(path);
210                 MS_SAFE_FREE(client_addr);
211
212                 g_mutex_unlock(scanner_mutex);
213         } else if (req_num == MS_MSG_DIRECTORY_SCANNING
214                 ||req_num == MS_MSG_BULK_INSERT
215                 ||req_num == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) {
216                 /* this request process in media scanner */
217
218                 ms_req_owner_data *owner_data = NULL;
219
220                 /* If owner list is NULL, create it */
221                 /* pid and client address are stored in ower list */
222                 /* These are used for sending result of scanning */
223                 if (owner_list == NULL) {
224                         /*create array for processing overlay data*/
225                         owner_list = g_array_new (FALSE, FALSE, sizeof (ms_req_owner_data *));
226                         if (owner_list == NULL) {
227                                 MS_DBG_ERR("g_array_new error");
228                                 MS_SAFE_FREE(client_addr);
229                                 g_mutex_unlock(scanner_mutex);
230                                 return TRUE;
231                         }
232                 }
233
234                 /* store pid and client address */
235                 MS_MALLOC(owner_data, sizeof(ms_req_owner_data));
236                 owner_data->pid = recv_msg.pid;
237                 owner_data->client_addr = client_addr;
238
239                 _ms_add_owner(owner_data);
240
241                 /* create send message for media scanner */
242                 scan_msg.msg_type = req_num;
243                 scan_msg.pid = pid;
244                 scan_msg.msg_size = msg_size;
245                 ms_strcopy(scan_msg.msg, path_size, "%s", recv_msg.msg);
246
247                 /* change the status of media scanner for directory scanning */
248                 if (req_num == MS_MSG_DIRECTORY_SCANNING
249                         || req_num == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) {
250                         MS_DBG("DIRECTORY SCANNING IS START");
251                         if (!ms_config_set_int(MS_SCAN_STATUS_DIRECTORY, P_VCONF_SCAN_DOING)) {
252                                 MS_DBG_ERR("ms_config_set_int failed");
253                         }
254                 }
255
256                 g_mutex_unlock(scanner_mutex);
257
258                 if (ms_get_scanner_status()) {
259                         MS_DBG("Scanner is ready");
260                         ms_send_scan_request(&scan_msg);
261                 } else {
262                         MS_DBG("Scanner starts");
263                         ret = ms_scanner_start();
264                         if(ret == MS_MEDIA_ERR_NONE) {
265                                 ms_send_scan_request(&scan_msg);
266                         } else {
267                                 MS_DBG("Scanner starting failed. %d", ret);
268                         }
269                 }
270         } else {
271                 /* NEED IMPLEMENTATION */
272                 MS_SAFE_FREE(client_addr);
273                 g_mutex_unlock(scanner_mutex);
274         }
275
276         /*Active flush */
277         malloc_trim(0);
278
279         return TRUE;
280 }
281 gboolean ms_receive_message_from_scanner(GIOChannel *src, GIOCondition condition, gpointer data)
282 {
283         ms_comm_msg_s recv_msg;
284         int sockfd = MS_SOCK_NOT_ALLOCATE;
285         int msg_type;
286         int ret;
287
288         sockfd = g_io_channel_unix_get_fd(src);
289         if (sockfd < 0) {
290                 MS_DBG_ERR("sock fd is invalid!");
291                 return TRUE;
292         }
293
294         /* Socket is readable */
295         ret = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(recv_msg), NULL, NULL);
296         if (ret != MS_MEDIA_ERR_NONE) {
297                 MS_DBG_ERR("ms_ipc_receive_message failed [%s]", strerror(errno));
298                 return TRUE;
299         }
300
301         MS_DBG("receive msg from [%d] %d, %s", recv_msg.pid, recv_msg.msg_type, recv_msg.msg);
302
303         msg_type = recv_msg.msg_type;
304         if ((msg_type == MS_MSG_SCANNER_RESULT) ||
305                 (msg_type == MS_MSG_SCANNER_BULK_RESULT)) {
306                 if (owner_list != NULL) {
307                         /* If the owner of result message is not media-server, media-server notify to the owner */
308                         /* The owner of message is distingushied by pid in received message*/
309                         /* find owner data */
310                         ms_req_owner_data *owner_data = NULL;
311
312                         _ms_find_owner(recv_msg.pid, &owner_data);
313                         if (owner_data != NULL) {
314                                 MS_DBG("PID : %d", owner_data->pid);
315                                 ms_comm_msg_s *result_msg;
316
317                                 if (msg_type == MS_MSG_SCANNER_RESULT) {
318                                         MS_DBG("DIRECTORY SCANNING IS DONE");
319                                         if (!ms_config_set_int(MS_SCAN_STATUS_DIRECTORY, P_VCONF_SCAN_DONE)) {
320                                                 MS_DBG_ERR("ms_config_set_int failed");
321                                         }
322                                 }
323
324                                 MS_MALLOC(result_msg, sizeof(ms_comm_msg_s));
325                                 /* owner data exists */
326                                 /* send result to the owner of request */
327                                 ms_ipc_send_msg_to_client(sockfd, &recv_msg, owner_data->client_addr);
328
329                                 /* free owner data*/
330                                 _ms_delete_owner(owner_data);
331
332                                 MS_SAFE_FREE(result_msg);
333                         }
334                 } else {
335                         /* owner data does not exist*/
336                         /*  this is result of request of media server*/
337                 }
338         } else {
339                 MS_DBG_ERR("This result message is wrong : %d", recv_msg.msg_type );
340         }
341
342         return TRUE;
343 }
344
345 int ms_send_scan_request(ms_comm_msg_s *send_msg)
346 {
347         int ret;
348         int res = MS_MEDIA_ERR_NONE;
349         int sockfd = -1;
350
351         /*Create Socket*/
352         ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, 0, &sockfd);
353         if (ret != MS_MEDIA_ERR_NONE)
354                 return MS_MEDIA_ERR_SOCKET_CONN;
355
356         ret = ms_ipc_send_msg_to_server(sockfd, MS_SCAN_DAEMON_PORT, send_msg, NULL);
357         if (ret != MS_MEDIA_ERR_NONE)
358                 res = ret;
359
360         close(sockfd);
361
362         return res;
363 }
364
365 int ms_send_storage_scan_request(ms_storage_type_t storage_type, ms_dir_scan_type_t scan_type)
366 {
367         int ret = MS_MEDIA_ERR_NONE;
368         ms_comm_msg_s scan_msg = {
369                 .msg_type = MS_MSG_STORAGE_INVALID,
370                 .pid = 0, /* pid 0 means media-server */
371                 .result = -1,
372                 .msg_size = 0,
373                 .msg = {0},
374         };
375
376         /* msg_type */
377         switch (scan_type) {
378                 case MS_SCAN_PART:
379                         scan_msg.msg_type = MS_MSG_STORAGE_PARTIAL;
380                         break;
381                 case MS_SCAN_ALL:
382                         scan_msg.msg_type = MS_MSG_STORAGE_ALL;
383                         break;
384                 case MS_SCAN_INVALID:
385                         scan_msg.msg_type = MS_MSG_STORAGE_INVALID;
386                         break;
387                 default :
388                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
389                         MS_DBG_ERR("ms_send_storage_scan_request invalid parameter");
390                         goto ERROR;
391                         break;
392         }
393
394         /* msg_size & msg */
395         switch (storage_type) {
396                 case MS_STORAGE_INTERNAL:
397                         scan_msg.msg_size = strlen(MEDIA_ROOT_PATH_INTERNAL);
398                         strncpy(scan_msg.msg, MEDIA_ROOT_PATH_INTERNAL, scan_msg.msg_size );
399                         break;
400                 case MS_STORAGE_EXTERNAL:
401                         scan_msg.msg_size = strlen(MEDIA_ROOT_PATH_SDCARD);
402                         strncpy(scan_msg.msg, MEDIA_ROOT_PATH_SDCARD, scan_msg.msg_size );
403                         break;
404                 default :
405                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
406                         MS_DBG_ERR("ms_send_storage_scan_request invalid parameter");
407                         goto ERROR;
408                         break;
409         }
410
411         g_mutex_lock(scanner_mutex);
412
413         if (ms_get_scanner_status()) {
414                 ms_send_scan_request(&scan_msg);
415                 g_mutex_unlock(scanner_mutex);
416         } else {
417                 g_mutex_unlock(scanner_mutex);
418
419                 ret = ms_scanner_start();
420                 if(ret == MS_MEDIA_ERR_NONE) {
421                         ms_send_scan_request(&scan_msg);
422                 } else {
423                         MS_DBG("Scanner starting failed. ");
424                 }
425         }
426
427 ERROR:
428
429         return ret;
430 }
431
432 gboolean ms_read_db_socket(GIOChannel *src, GIOCondition condition, gpointer data)
433 {
434         struct sockaddr_in client_addr;
435
436         ms_comm_msg_s recv_msg;
437         int send_msg = MS_MEDIA_ERR_NONE;
438         int sockfd = MS_SOCK_NOT_ALLOCATE;
439         int ret = MS_MEDIA_ERR_NONE;
440         MediaDBHandle *db_handle = (MediaDBHandle *)data;
441         ms_comm_msg_s msg;
442         char * sql_query = NULL;
443         size_t sql_query_size = 0;
444
445         memset(&recv_msg, 0, sizeof(recv_msg));
446
447         sockfd = g_io_channel_unix_get_fd(src);
448         if (sockfd < 0) {
449                 MS_DBG_ERR("sock fd is invalid!");
450                 return TRUE;
451         }
452
453         ret = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(recv_msg), &client_addr, NULL);
454         if (ret != MS_MEDIA_ERR_NONE) {
455                 MS_DBG_ERR("ms_ipc_receive_message failed");
456                 return TRUE;
457         }
458
459 //      MS_DBG("msg_type[%d], msg_size[%d] msg[%s]", recv_msg.msg_type, recv_msg.msg_size, recv_msg.msg);
460
461         if((recv_msg.msg_size <= 0) ||(recv_msg.msg_size > MS_FILE_PATH_LEN_MAX)  || (!MS_STRING_VALID(recv_msg.msg))) {
462                 MS_DBG_ERR("invalid query. size[%d]", recv_msg.msg_size);
463                 return TRUE;
464         }
465
466         sql_query_size = recv_msg.msg_size + 1;
467         MS_MALLOC(sql_query, sql_query_size);
468         if (sql_query != NULL) {
469                 ret = ms_strcopy(sql_query, sql_query_size, "%s", recv_msg.msg);
470                 if (ret != MS_MEDIA_ERR_NONE) {
471                         MS_DBG_ERR("ms_strcopy failed");
472                         MS_SAFE_FREE(sql_query);
473                         return TRUE;
474                 }
475
476                 ret = media_db_update_db(db_handle, sql_query);
477                 if (ret != MS_MEDIA_ERR_NONE)
478                         MS_DBG_ERR("media_db_update_db error : %d", ret);
479
480                 send_msg = ret;
481                 MS_SAFE_FREE(sql_query);
482         } else {
483                 send_msg = MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL;
484         }
485
486         memset(&msg, 0x0, sizeof(ms_comm_msg_s));
487         msg.result = send_msg;
488
489         ms_ipc_send_msg_to_client(sockfd, &msg, &client_addr);
490
491         /*Active flush */
492         malloc_trim(0);
493
494         return TRUE;
495 }
496
497 gboolean ms_read_db_tcp_socket(GIOChannel *src, GIOCondition condition, gpointer data)
498 {
499         struct sockaddr_in client_addr;
500         unsigned int client_addr_len;
501
502         ms_comm_msg_s recv_msg;
503         int sock = -1;
504         int client_sock = -1;
505         int send_msg = MS_MEDIA_ERR_NONE;
506         int recv_msg_size = -1;
507         int ret = MS_MEDIA_ERR_NONE;
508         char * sql_query = NULL;
509         size_t sql_query_size = 0;
510         MediaDBHandle *db_handle = (MediaDBHandle *)data;
511
512         sock = g_io_channel_unix_get_fd(src);
513         if (sock < 0) {
514                 MS_DBG_ERR("sock fd is invalid!");
515                 return TRUE;
516         }
517         memset((void *)&recv_msg, 0, sizeof(ms_comm_msg_s));
518
519         if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
520                 MS_DBG_ERR("accept failed : %s", strerror(errno));
521                 return TRUE;
522         }
523
524         MS_DBG("Client[%d] is accepted", client_sock);
525
526         while(1) {
527                 if ((recv_msg_size = recv(client_sock, &recv_msg, sizeof(ms_comm_msg_s), 0)) < 0) {
528                         MS_DBG_ERR("recv failed : %s", strerror(errno));
529
530                         close(client_sock);
531                         if (errno == EWOULDBLOCK) {
532                                 MS_DBG_ERR("Timeout. Can't try any more");
533                                 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
534                         } else {
535                                 MS_DBG_ERR("recv failed : %s", strerror(errno));
536                                 return MS_MEDIA_ERR_SOCKET_RECEIVE;
537                         }
538                 }
539
540                 MS_DBG("Received [%d](%d) [%s]", recv_msg.msg_type, recv_msg.msg_size, recv_msg.msg);
541
542                 if((recv_msg.msg_size <= 0) ||(recv_msg.msg_size > MS_FILE_PATH_LEN_MAX)  || (!MS_STRING_VALID(recv_msg.msg))) {
543                         MS_DBG_ERR("invalid query. size[%d]", recv_msg.msg_size);
544                         close(client_sock);
545                         return TRUE;
546                 }
547
548                 sql_query_size = recv_msg.msg_size + 1;
549                 MS_MALLOC(sql_query, sql_query_size);
550                 if (sql_query != NULL) {
551                         ret = ms_strcopy(sql_query, sql_query_size, "%s", recv_msg.msg);
552                         if (ret != MS_MEDIA_ERR_NONE) {
553                                 MS_DBG_ERR("ms_strcopy failed");
554                                 MS_SAFE_FREE(sql_query);
555                                 close(client_sock);
556                                 return TRUE;
557                         }
558
559                         if (recv_msg.msg_type == MS_MSG_DB_UPDATE_BATCH_START) {
560                                 ret = media_db_update_db_batch_start(sql_query);
561                         } else if(recv_msg.msg_type == MS_MSG_DB_UPDATE_BATCH_END) {
562                                 ret = media_db_update_db_batch_end(db_handle, sql_query);
563                         } else if(recv_msg.msg_type == MS_MSG_DB_UPDATE_BATCH) {
564                                 ret = media_db_update_db_batch(sql_query);
565                         } else {
566
567                         }
568
569                         MS_SAFE_FREE(sql_query);
570                         send_msg = ret;
571
572                         if (send(client_sock, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
573                                 MS_DBG_ERR("send failed : %s", strerror(errno));
574                         } else {
575                                 MS_DBG("Sent successfully");
576                         }
577
578                         if (recv_msg.msg_type == MS_MSG_DB_UPDATE_BATCH_END)
579                                 break;
580
581                         memset((void *)&recv_msg, 0, sizeof(ms_comm_msg_s));
582                 } else {
583                         MS_DBG_ERR("MS_MALLOC failed");
584                         close(client_sock);
585                         return TRUE;
586                 }
587
588         }
589
590         close(client_sock);
591         return TRUE;
592 }