Modified TCP transfer
[platform/core/multimedia/libmedia-thumbnail.git] / server / thumb-server-internal.c
1 /*
2  * media-thumbnail-server
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyunjun Ko <zzoon.ko@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include "thumb-server-internal.h"
23 #include "media-thumb-util.h"
24 #include "media-thumb-debug.h"
25
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <dirent.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <tzplatform_config.h>
32
33 #ifdef LOG_TAG
34 #undef LOG_TAG
35 #endif
36
37 #define LOG_TAG "MEDIA_THUMBNAIL_SERVER"
38 #define THUMB_DEFAULT_WIDTH 320
39 #define THUMB_DEFAULT_HEIGHT 240
40 #define THUMB_COMM_SOCK_PATH tzplatform_mkpath(TZ_SYS_RUN, "media-server/media_ipc_thumbcomm.socket")
41 #define THUMB_EMPTY_STR ""
42
43 GMainLoop *g_thumb_server_mainloop; // defined in thumb-server.c as extern
44
45 static gboolean __thumb_server_send_msg_to_agent(int msg_type);
46 static gboolean _thumb_server_send_deny_message(int sockfd);
47
48 gboolean _thumb_daemon_start_jobs(gpointer data)
49 {
50         thumb_dbg("");
51         __thumb_server_send_msg_to_agent(MS_MSG_THUMB_SERVER_READY);
52
53         return FALSE;
54 }
55
56 int _thumb_daemon_process_job(thumbMsg *req_msg, thumbMsg *res_msg)
57 {
58         int err = MS_MEDIA_ERR_NONE;
59
60         if (req_msg->msg_type == THUMB_REQUEST_RAW_DATA) {
61                 err = _media_thumb_process_raw(req_msg, res_msg);
62                 if (err != MS_MEDIA_ERR_NONE)
63                         thumb_warn("_media_thumb_process_raw is failed: %d", err);
64         } else if (req_msg->msg_type == THUMB_REQUEST_DB_INSERT) {
65                 err = _media_thumb_process(req_msg, res_msg);
66                 if (err != MS_MEDIA_ERR_NONE)
67                         thumb_warn("_media_thumb_process is failed: %d", err);
68         }
69
70         return err;
71 }
72
73 gboolean _thumb_server_read_socket(GIOChannel *src, GIOCondition condition, gpointer data)
74 {
75         struct sockaddr_un client_addr;
76         unsigned int client_addr_len;
77         thumbMsg recv_msg;
78         thumbMsg res_msg;
79         ms_peer_credentials credentials;
80
81         int sock = -1;
82         int client_sock = -1;
83
84         memset((void *)&recv_msg, 0, sizeof(recv_msg));
85         memset((void *)&res_msg, 0, sizeof(res_msg));
86         memset((void *)&credentials, 0, sizeof(credentials));
87
88         sock = g_io_channel_unix_get_fd(src);
89         if (sock < 0) {
90                 thumb_err("sock fd is invalid!");
91                 return TRUE;
92         }
93
94         client_addr_len = sizeof(client_addr);
95
96         if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
97                 thumb_stderror("accept failed");
98                 return TRUE;
99         }
100
101         if (ms_cynara_receive_untrusted_message_thumb(client_sock, &recv_msg, &credentials) != MS_MEDIA_ERR_NONE) {
102                 thumb_err("ms_cynara_receive_untrusted_message_thumb failed");
103                 close(client_sock);
104                 return FALSE;
105         }
106
107         if (recv_msg.msg_type != THUMB_REQUEST_KILL_SERVER) {
108                 if (ms_cynara_check(&credentials, MEDIA_STORAGE_PRIVILEGE) != MS_MEDIA_ERR_NONE) {
109                         thumb_err("Cynara denied access to process request");
110                         _thumb_server_send_deny_message(client_sock);
111                         close(client_sock);
112                         return TRUE;
113                 }
114         } else {
115                 thumb_warn("Shutting down...");
116                 g_main_loop_quit(g_thumb_server_mainloop);
117                 close(client_sock);
118                 return TRUE;
119         }
120
121         SAFE_FREE(credentials.smack);
122         SAFE_FREE(credentials.uid);
123
124         thumb_warn_slog("Received [%d] %.*s(%d) from PID(%d)", recv_msg.msg_type, MAX_FILEPATH_LEN, recv_msg.org_path, strlen(recv_msg.org_path), recv_msg.pid);
125
126         _thumb_daemon_process_job(&recv_msg, &res_msg);
127
128         if (res_msg.msg_type == 0)
129                 res_msg.msg_type = recv_msg.msg_type;
130         res_msg.request_id = recv_msg.request_id;
131         SAFE_STRLCPY(res_msg.org_path, recv_msg.org_path, sizeof(res_msg.org_path));
132         if (res_msg.msg_type != THUMB_RESPONSE_RAW_DATA)
133                 res_msg.thumb_size = 0;
134         else
135                 res_msg.dst_path[0] = '\0';
136
137         int buf_size = 0;
138         int remain_size = 0;
139         int head_size = sizeof(res_msg) - sizeof(unsigned char *);
140         unsigned char *buf = NULL;
141         _media_thumb_set_buffer(&res_msg, &buf, &buf_size);
142         remain_size = buf_size - head_size;
143
144         if (send(client_sock, buf, head_size, 0) < 0) {
145                 thumb_stderror("send failed");
146         } else {
147                 if (remain_size > 0) {
148                         if (send(client_sock, buf + head_size, remain_size, 0) < 0) {
149                                 thumb_stderror("send failed");
150                         } else {
151                                 thumb_dbg_slog("Sent data(%d) from %s", res_msg.thumb_size, res_msg.org_path);
152                         }
153                 } else {
154                         thumb_dbg_slog("Sent thumbnail(%s) from %s", res_msg.dst_path, res_msg.org_path);
155                 }
156         }
157
158         SAFE_FREE(buf);
159         SAFE_FREE(res_msg.thumb_data);
160
161         close(client_sock);
162
163         return TRUE;
164 }
165
166 static gboolean __thumb_server_send_msg_to_agent(int msg_type)
167 {
168         int sock;
169         struct sockaddr_un serv_addr;
170         ms_thumb_server_msg send_msg;
171
172         if (ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sock) < 0) {
173                 thumb_err("ms_ipc_create_server_socket failed");
174                 return FALSE;
175         }
176
177         memset(&serv_addr, 0, sizeof(serv_addr));
178
179         serv_addr.sun_family = AF_UNIX;
180         SAFE_STRLCPY(serv_addr.sun_path, THUMB_COMM_SOCK_PATH, sizeof(serv_addr.sun_path));
181
182         /* Connecting to the thumbnail server */
183         if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
184                 thumb_stderror("connect");
185                 close(sock);
186                 return MS_MEDIA_ERR_SOCKET_CONN;
187         }
188
189         send_msg.msg_type = msg_type;
190
191         if (send(sock, &send_msg, sizeof(ms_thumb_server_msg), 0) < 0) {
192                 thumb_stderror("send failed");
193                 close(sock);
194                 return FALSE;
195         }
196
197         thumb_dbg("Sending msg to thumbnail agent[%d] is successful", send_msg.msg_type);
198         close(sock);
199
200         return TRUE;
201 }
202
203 static gboolean _thumb_server_send_deny_message(int sockfd)
204 {
205         thumbMsg msg = {0};
206         int bytes_to_send = sizeof(msg);
207
208         msg.msg_type = THUMB_RESPONSE;
209         msg.status = MS_MEDIA_ERR_PERMISSION_DENIED;
210
211         if (send(sockfd, &msg, bytes_to_send, 0) < 0) {
212                 thumb_stderror("send failed");
213                 return FALSE;
214         }
215
216         return TRUE;
217 }
218
219 gboolean _thumb_server_prepare_socket(int *sock_fd)
220 {
221         int sock;
222
223         if (ms_ipc_create_server_socket(MS_THUMB_DAEMON_PORT, &sock) < 0) {
224                 thumb_err("ms_ipc_create_server_socket failed");
225                 return FALSE;
226         }
227
228         if (ms_cynara_enable_credentials_passing(sock) != MS_MEDIA_ERR_NONE) {
229                 thumb_err("ms_cynara_enable_credentials_passing failed");
230                 close(sock);
231                 return FALSE;
232         }
233
234         *sock_fd = sock;
235
236         return TRUE;
237 }
238
239 int _thumbnail_get_data(const char *origin_path, char *thumb_path)
240 {
241         int err = MS_MEDIA_ERR_NONE;
242         int file_type = THUMB_NONE_TYPE;
243
244         if (origin_path == NULL) {
245                 thumb_err("Original path is null");
246                 return MS_MEDIA_ERR_INVALID_PARAMETER;
247         }
248
249         if (!g_file_test(origin_path, G_FILE_TEST_IS_REGULAR)) {
250                 thumb_err("Original path (%s) does not exist", origin_path);
251                 return MS_MEDIA_ERR_INVALID_PARAMETER;
252         }
253
254         thumb_dbg("Origin path : %s", origin_path);
255         file_type = _media_thumb_get_file_type(origin_path);
256
257         if (file_type == THUMB_IMAGE_TYPE) {
258                 err = _media_thumb_image(origin_path, thumb_path, THUMB_DEFAULT_WIDTH, THUMB_DEFAULT_HEIGHT, NULL);
259                 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_image failed");
260         } else if (file_type == THUMB_VIDEO_TYPE) {
261                 err = _media_thumb_video(origin_path, thumb_path, THUMB_DEFAULT_WIDTH, THUMB_DEFAULT_HEIGHT, NULL);
262                 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_video failed");
263         } else {
264                 thumb_err("invalid file type");
265                 return MS_MEDIA_ERR_THUMB_UNSUPPORTED;
266         }
267
268         thumb_dbg("Thumb data is generated successfully");
269
270         return MS_MEDIA_ERR_NONE;
271 }
272
273 int _thumbnail_get_raw_data(const char *origin_path, int *width, int *height, unsigned char **data, int *size)
274 {
275         int err = MS_MEDIA_ERR_NONE;
276         int thumb_width = -1;
277         int thumb_height = -1;
278
279         if (origin_path == NULL || *width <= 0 || *height <= 0) {
280                 thumb_err("Invalid parameter");
281                 return MS_MEDIA_ERR_INVALID_PARAMETER;
282         }
283
284         if (!g_file_test(origin_path, G_FILE_TEST_IS_REGULAR)) {
285                 thumb_err("Original path (%s) does not exist", origin_path);
286                 return MS_MEDIA_ERR_INVALID_PARAMETER;
287         }
288
289         int file_type = THUMB_NONE_TYPE;
290         media_thumb_info thumb_info = {0,};
291         file_type = _media_thumb_get_file_type(origin_path);
292         thumb_width = *width;
293         thumb_height = *height;
294
295         if (file_type == THUMB_IMAGE_TYPE) {
296                 err = _media_thumb_image(origin_path, NULL, thumb_width, thumb_height, &thumb_info);
297                 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_image failed");
298         } else if (file_type == THUMB_VIDEO_TYPE) {
299                 err = _media_thumb_video(origin_path, NULL, thumb_width, thumb_height, &thumb_info);
300                 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_video failed");
301         } else {
302                 thumb_err("invalid file type");
303                 return MS_MEDIA_ERR_THUMB_UNSUPPORTED;
304         }
305
306         if (size) *size = thumb_info.size;
307         *data = thumb_info.data;
308         *width = thumb_info.width;
309         *height = thumb_info.height;
310
311         return MS_MEDIA_ERR_NONE;
312 }
313
314 int _media_thumb_process(thumbMsg *req_msg, thumbMsg *res_msg)
315 {
316         int err = MS_MEDIA_ERR_NONE;
317         char *thumb_path = NULL;
318
319         thumb_retvm_if(req_msg == NULL || res_msg == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid msg");
320
321         const char *origin_path = req_msg->org_path;
322         memset(res_msg->dst_path, 0, MAX_FILEPATH_LEN);
323         thumb_path = res_msg->dst_path;
324         res_msg->status = MS_MEDIA_ERR_NONE;
325
326         if (!g_file_test(origin_path, G_FILE_TEST_IS_REGULAR)) {
327                 thumb_err("origin_path does not exist in file system.");
328                 res_msg->status = MS_MEDIA_ERR_FILE_NOT_EXIST;
329                 return MS_MEDIA_ERR_FILE_NOT_EXIST;
330         }
331
332         err = _media_thumb_get_thumb_from_db(origin_path, thumb_path, MAX_FILEPATH_LEN, req_msg->uid);
333         if (err == MS_MEDIA_ERR_NONE) {
334                 thumb_dbg_slog("Thumb path : %s", thumb_path);
335                 return MS_MEDIA_ERR_NONE;
336         } else {
337                 if (strlen(thumb_path) == 0) {
338                         err = _media_thumb_get_hash_name(origin_path, thumb_path, MAX_FILEPATH_LEN, req_msg->uid);
339                         if (err != MS_MEDIA_ERR_NONE) {
340                                 thumb_err("_media_thumb_get_hash_name failed - %d", err);
341                                 SAFE_STRLCPY(thumb_path, THUMB_EMPTY_STR, MAX_FILEPATH_LEN);
342                                 res_msg->status = err;
343                                 return err;
344                         }
345                 }
346         }
347
348         thumb_dbg_slog("Thumb path : %s", thumb_path);
349
350         err = _thumbnail_get_data(origin_path, thumb_path);
351         if (err != MS_MEDIA_ERR_NONE) {
352                 thumb_err("_thumbnail_get_data failed - %d", err);
353                 SAFE_STRLCPY(thumb_path, THUMB_EMPTY_STR, MAX_FILEPATH_LEN);
354                 res_msg->status = err;
355
356                 goto DB_UPDATE;
357         }
358
359         res_msg->msg_type = THUMB_RESPONSE;
360
361 DB_UPDATE:
362         err = _media_thumb_update_db(origin_path, thumb_path, req_msg->uid);
363         if (err != MS_MEDIA_ERR_NONE) {
364                 thumb_err("_media_thumb_update_db failed : %d", err);
365                 res_msg->status = err;
366         }
367
368         return err;
369 }
370
371 int
372 _media_thumb_process_raw(thumbMsg *req_msg, thumbMsg *res_msg)
373 {
374         int err = MS_MEDIA_ERR_NONE;
375         unsigned char *data = NULL;
376         int thumb_size = 0;
377         int thumb_w = 0;
378         int thumb_h = 0;
379
380         thumb_retvm_if(req_msg == NULL || res_msg == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid msg");
381
382         const char *origin_path = req_msg->org_path;
383         if (req_msg->thumb_width > 0)
384                 thumb_w = req_msg->thumb_width;
385         else
386                 thumb_w = THUMB_DEFAULT_WIDTH;
387
388         if (req_msg->thumb_height > 0)
389                 thumb_h = req_msg->thumb_height;
390         else
391                 thumb_h = THUMB_DEFAULT_HEIGHT;
392
393         res_msg->status = MS_MEDIA_ERR_NONE;
394         res_msg->msg_type = THUMB_RESPONSE_RAW_DATA;
395
396         err = _thumbnail_get_raw_data(origin_path, &thumb_w, &thumb_h, &data, &thumb_size);
397         if (err != MS_MEDIA_ERR_NONE) {
398                 thumb_err("_thumbnail_get_data failed - %d", err);
399                 res_msg->status = err;
400                 res_msg->thumb_size = 0;
401                 SAFE_FREE(data);
402
403                 return err;
404         }
405
406         res_msg->thumb_width = thumb_w;
407         res_msg->thumb_height = thumb_h;
408         res_msg->thumb_size = thumb_size;
409         res_msg->thumb_data = malloc(thumb_size * sizeof(unsigned char));
410         if (res_msg->thumb_data != NULL) {
411                 memcpy(res_msg->thumb_data, data, thumb_size);
412         } else {
413                 thumb_err("Allocation failed");
414                 err = MS_MEDIA_ERR_OUT_OF_MEMORY;
415         }
416
417         SAFE_FREE(data);
418
419         return err;
420 }