Change from INET tcp to Unix domain socket
[framework/multimedia/media-server.git] / lib / media-util-ipc.c
1 /*
2  *  Media Utility
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 IPC.
24  *
25  * @file                media-util-ipc.c
26  * @author      Haejeong Kim(backto.kim@samsung.com)
27  * @version     1.0
28  * @brief
29  */
30
31 #include <string.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36
37 #include "media-util-dbg.h"
38 #include "media-util.h"
39
40 #ifdef _USE_UDS_SOCKET_
41 char MEDIA_IPC_PATH[][50] ={
42         {"/tmp/media_ipc_dbbatchupdate.dat"},
43         {"/tmp/media_ipc_scandaemon.dat"},
44         {"/tmp/media_ipc_scancomm.dat"},
45         {"/tmp/media_ipc_scanner.dat"},
46         {"/tmp/media_ipc_dbupdate.dat"},
47         {"/tmp/media_ipc_thumbcreator.dat"},
48         {"/tmp/media_ipc_thumbcomm.dat"},
49         {"/tmp/media_ipc_thumbdaemon.dat"},
50 };
51
52 char MEDIA_IPC_PATH_CLIENT[][50] ={
53         {"/tmp/media_ipc_dbbatchupdate_client.dat"},
54         {"/tmp/media_ipc_scandaemon_client.dat"},
55         {"/tmp/media_ipc_scancomm_client.dat"},
56         {"/tmp/media_ipc_scanner_client.dat"},
57         {"/tmp/media_ipc_dbupdate_client.dat"},
58         {"/tmp/media_ipc_thumbcreator_client.dat"},
59         {"/tmp/media_ipc_thumbcomm_client.dat"},
60         {"/tmp/media_ipc_thumbdaemon_client.dat"},
61 };
62 #elif defined(_USE_UDS_SOCKET_TCP_)
63 char MEDIA_IPC_PATH[][50] ={
64         {"/tmp/media_ipc_dbbatchupdate.dat"},
65         {"/tmp/media_ipc_thumbcreator.dat"},
66 };
67 #endif
68
69 #ifdef _USE_UDS_SOCKET_
70 int ms_ipc_create_client_socket(ms_protocol_e protocol, int timeout_sec, int *sock_fd, int port)
71 #else
72 int ms_ipc_create_client_socket(ms_protocol_e protocol, int timeout_sec, int *sock_fd)
73 #endif
74 {
75         int sock = -1;
76
77         struct timeval tv_timeout = { timeout_sec, 0 };
78
79         if(protocol == MS_PROTOCOL_UDP)
80         {
81 #ifdef _USE_UDS_SOCKET_
82                 struct sockaddr_un serv_addr;
83 #endif
84
85                 /* Create a datagram/UDP socket */
86 #ifdef _USE_UDS_SOCKET_
87                 if ((sock = socket(PF_FILE, SOCK_DGRAM, 0)) < 0) {
88 #else
89                 if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
90 #endif
91                         MSAPI_DBG_ERR("socket failed: %s", strerror(errno));
92                         return MS_MEDIA_ERR_SOCKET_CONN;
93                 }
94
95 #ifdef _USE_UDS_SOCKET_
96                 memset(&serv_addr, 0, sizeof(serv_addr));
97                 serv_addr.sun_family = AF_UNIX;
98                 MSAPI_DBG("%s", MEDIA_IPC_PATH_CLIENT[port]);
99                 unlink(MEDIA_IPC_PATH_CLIENT[port]);
100                 strcpy(serv_addr.sun_path, MEDIA_IPC_PATH_CLIENT[port]);
101
102                 /* Bind to the local address */
103                 if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
104                         MSAPI_DBG_ERR("bind failed : %s", strerror(errno));
105                         close(sock);
106                         return MS_MEDIA_ERR_SOCKET_CONN;
107                 }
108 #endif
109         }
110         else
111         {
112                 /*Create TCP Socket*/
113 #ifdef _USE_UDS_SOCKET_
114                 if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
115 #else
116                 if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
117 #endif
118                         MSAPI_DBG_ERR("socket failed: %s", strerror(errno));
119                         return MS_MEDIA_ERR_SOCKET_CONN;
120                 }
121         }
122
123         if (timeout_sec > 0) {
124                 if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
125                         MSAPI_DBG_ERR("setsockopt failed: %s", strerror(errno));
126                         close(sock);
127                         return MS_MEDIA_ERR_SOCKET_CONN;
128                 }
129         }
130
131         *sock_fd = sock;
132
133         return MS_MEDIA_ERR_NONE;
134 }
135
136 #ifdef _USE_UDS_SOCKET_TCP_
137 int ms_ipc_create_client_tcp_socket(ms_protocol_e protocol, int timeout_sec, int *sock_fd, int port)
138 {
139         int sock = -1;
140
141         struct timeval tv_timeout = { timeout_sec, 0 };
142
143         /*Create TCP Socket*/
144         if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
145                         MSAPI_DBG_ERR("socket failed: %s", strerror(errno));
146                         return MS_MEDIA_ERR_SOCKET_CONN;
147         }
148
149         if (timeout_sec > 0) {
150                 if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
151                         MSAPI_DBG_ERR("setsockopt failed: %s", strerror(errno));
152                         close(sock);
153                         return MS_MEDIA_ERR_SOCKET_CONN;
154                 }
155         }
156
157         *sock_fd = sock;
158
159         return MS_MEDIA_ERR_NONE;
160 }
161
162 int ms_ipc_create_server_tcp_socket(ms_protocol_e protocol, int port, int *sock_fd)
163 {
164         int i;
165         bool bind_success = false;
166         int sock = -1;
167
168         struct sockaddr_un serv_addr;
169         mode_t orig_mode;
170         orig_mode = umask(0);
171
172         /* Create a TCP socket */
173         if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
174                 MSAPI_DBG_ERR("socket failed: %s", strerror(errno));
175                 return MS_MEDIA_ERR_SOCKET_CONN;
176         }
177
178         memset(&serv_addr, 0, sizeof(serv_addr));
179
180         serv_addr.sun_family = AF_UNIX;
181         MSAPI_DBG("%s", MEDIA_IPC_PATH[port]);
182         unlink(MEDIA_IPC_PATH[port]);
183         strcpy(serv_addr.sun_path, MEDIA_IPC_PATH[port]);
184
185         /* Bind to the local address */
186         for (i = 0; i < 20; i ++) {
187                 if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) {
188                         bind_success = true;
189                         break;
190                 }
191                 MSAPI_DBG("%d",i);
192                 usleep(250000);
193         }
194
195         if (bind_success == false) {
196                 MSAPI_DBG_ERR("bind failed : %s %d_", strerror(errno), errno);
197                 close(sock);
198                 return MS_MEDIA_ERR_SOCKET_CONN;
199         }
200
201         MSAPI_DBG("bind success");
202
203         /* Listening */
204         if (listen(sock, SOMAXCONN) < 0) {
205                 MSAPI_DBG_ERR("listen failed : %s", strerror(errno));
206                 close(sock);
207                 return MS_MEDIA_ERR_SOCKET_CONN;
208         }
209
210         MSAPI_DBG("Listening...");
211
212         *sock_fd = sock;
213
214         umask(orig_mode);
215         return MS_MEDIA_ERR_NONE;
216 }
217
218 #endif
219
220 int ms_ipc_create_server_socket(ms_protocol_e protocol, int port, int *sock_fd)
221 {
222         int i;
223         bool bind_success = false;
224         int sock = -1;
225         int n_reuse = 1;
226 #ifdef _USE_UDS_SOCKET_
227         struct sockaddr_un serv_addr;
228 #else
229         struct sockaddr_in serv_addr;
230 #endif
231         unsigned short serv_port;
232
233         serv_port = port;
234
235         if(protocol == MS_PROTOCOL_UDP)
236         {
237                 /* Create a datagram/UDP socket */
238 #ifdef _USE_UDS_SOCKET_
239                 if ((sock = socket(PF_FILE, SOCK_DGRAM, 0)) < 0) {
240 #else
241                 if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
242 #endif
243                         MSAPI_DBG_ERR("socket failed: %s", strerror(errno));
244                         return MS_MEDIA_ERR_SOCKET_CONN;
245                 }
246         }
247         else
248         {
249                 /* Create a TCP socket */
250 #ifdef _USE_UDS_SOCKET_
251                 if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
252 #else
253                 if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
254 #endif
255                         MSAPI_DBG_ERR("socket failed: %s", strerror(errno));
256                         return MS_MEDIA_ERR_SOCKET_CONN;
257                 }
258         }
259 #ifdef _USE_UDS_SOCKET_
260 #else
261         if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &n_reuse, sizeof(n_reuse)) == -1) {
262                 MSAPI_DBG_ERR("setsockopt failed: %s", strerror(errno));
263                 close(sock);
264                 return MS_MEDIA_ERR_SOCKET_INTERNAL;
265         }
266 #endif
267         memset(&serv_addr, 0, sizeof(serv_addr));
268 #ifdef _USE_UDS_SOCKET_
269         serv_addr.sun_family = AF_UNIX;
270         MSAPI_DBG("%s", MEDIA_IPC_PATH[serv_port]);
271         unlink(MEDIA_IPC_PATH[serv_port]);
272         strcpy(serv_addr.sun_path, MEDIA_IPC_PATH[serv_port]);
273 #else
274         serv_addr.sin_family = AF_INET;
275         serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
276 //      serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
277         serv_addr.sin_port = htons(serv_port);
278 #endif
279         /* Bind to the local address */
280         for (i = 0; i < 20; i ++) {
281                 if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) {
282                         bind_success = true;
283                         break;
284                 }
285                 MSAPI_DBG("%d",i);
286                 usleep(250000);
287         }
288
289         if (bind_success == false) {
290                 MSAPI_DBG_ERR("bind failed : %s %d_", strerror(errno), errno);
291                 close(sock);
292                 return MS_MEDIA_ERR_SOCKET_CONN;
293         }
294
295         MSAPI_DBG("bind success");
296
297         /* Listening */
298         if (protocol == MS_PROTOCOL_TCP) {
299                 if (listen(sock, SOMAXCONN) < 0) {
300                         MSAPI_DBG_ERR("listen failed : %s", strerror(errno));
301                         close(sock);
302                         return MS_MEDIA_ERR_SOCKET_CONN;
303                 }
304
305                 MSAPI_DBG("Listening...");
306         }
307
308         *sock_fd = sock;
309
310         return MS_MEDIA_ERR_NONE;
311 }
312
313 #ifdef _USE_UDS_SOCKET_
314 int ms_ipc_send_msg_to_server(int sockfd, int port, ms_comm_msg_s *send_msg, struct sockaddr_un *serv_addr)
315 #else
316 int ms_ipc_send_msg_to_server(int sockfd, int port, ms_comm_msg_s *send_msg, struct sockaddr_in *serv_addr)
317 #endif
318 {
319         int res = MS_MEDIA_ERR_NONE;
320 #ifdef _USE_UDS_SOCKET_
321         struct sockaddr_un addr;
322 #else
323         struct sockaddr_in addr;
324 #endif
325
326         /* Set server Address */
327         memset(&addr, 0, sizeof(addr));
328 #ifdef _USE_UDS_SOCKET_
329         addr.sun_family = AF_UNIX;
330         strcpy(addr.sun_path, MEDIA_IPC_PATH[port]);
331         MSAPI_DBG("%s", addr.sun_path);
332 #else
333         addr.sin_family = AF_INET;
334         addr.sin_addr.s_addr = inet_addr(SERVER_IP);
335         addr.sin_port = htons(port);
336 #endif
337
338         if (sendto(sockfd, send_msg, sizeof(*(send_msg)), 0, (struct sockaddr *)&addr, sizeof(addr)) != sizeof(*(send_msg))) {
339                 MSAPI_DBG_ERR("sendto failed [%s]", strerror(errno));
340                 res = MS_MEDIA_ERR_SOCKET_SEND;
341         } else {
342                 MSAPI_DBG("sent %d", send_msg->result);
343                 MSAPI_DBG("sent %s", send_msg->msg);
344                 if (serv_addr != NULL)
345                         *serv_addr = addr;
346         }
347
348         return res;
349 }
350
351 #ifdef _USE_UDS_SOCKET_
352 int ms_ipc_send_msg_to_client(int sockfd, ms_comm_msg_s *send_msg, struct sockaddr_un *client_addr)
353 #else
354 int ms_ipc_send_msg_to_client(int sockfd, ms_comm_msg_s *send_msg, struct sockaddr_in *client_addr)
355 #endif
356 {
357         int res = MS_MEDIA_ERR_NONE;
358
359 #ifdef _USE_UDS_SOCKET_
360         MSAPI_DBG("the path of client address : %s", client_addr->sun_path);
361 #endif
362         if (sendto(sockfd, send_msg, sizeof(*(send_msg)), 0, (struct sockaddr *)client_addr, sizeof(*(client_addr))) != sizeof(*(send_msg))) {
363                 MSAPI_DBG_ERR("sendto failed [%s]", strerror(errno));
364                 res = MS_MEDIA_ERR_SOCKET_SEND;
365         } else {
366                 MSAPI_DBG("sent %d", send_msg->result);
367                 MSAPI_DBG("sent %s", send_msg->msg);
368         }
369
370         return MS_MEDIA_ERR_NONE;
371 }
372
373 #ifdef _USE_UDS_SOCKET_
374 int ms_ipc_receive_message(int sockfd, void *recv_msg, unsigned int msg_size, struct sockaddr_un *recv_addr, unsigned int *addr_size)
375 #else
376 int ms_ipc_receive_message(int sockfd, void *recv_msg, unsigned int msg_size, struct sockaddr_in *recv_addr, unsigned int *addr_size)
377 #endif
378 {
379         int recv_msg_size;
380 #ifdef _USE_UDS_SOCKET_
381         struct sockaddr_un addr;
382 #else
383         struct sockaddr_in addr;
384 #endif
385         socklen_t addr_len;
386
387         if (!recv_msg)
388                 return MS_MEDIA_ERR_INVALID_PARAMETER;
389
390 #ifdef _USE_UDS_SOCKET_
391         addr_len = sizeof(addr);
392 #else
393         addr_len = sizeof(struct sockaddr_in);
394 #endif
395
396         if ((recv_msg_size = recvfrom(sockfd, recv_msg, msg_size, 0, (struct sockaddr *)&addr, &addr_len)) < 0) {
397                 MSAPI_DBG_ERR("recvfrom failed [%s]", strerror(errno));
398                 return MS_MEDIA_ERR_SOCKET_RECEIVE;
399         }
400
401 #ifdef _USE_UDS_SOCKET_
402         MSAPI_DBG("the path of received client address : %s", addr.sun_path);
403 #endif
404
405         if (recv_addr != NULL)
406                 *recv_addr = addr;
407         if (addr_size != NULL)
408                 *addr_size  = addr_len;
409
410         return MS_MEDIA_ERR_NONE;
411 }
412
413 #ifdef _USE_UDS_SOCKET_
414 int ms_ipc_wait_message(int sockfd, void *recv_msg, unsigned int msg_size, struct sockaddr_un *recv_addr, unsigned int *addr_size)
415 #else
416 int ms_ipc_wait_message(int sockfd, void *recv_msg, unsigned int msg_size, struct sockaddr_in *recv_addr, unsigned int *addr_size)
417 #endif
418 {
419         int recv_msg_size;
420         socklen_t addr_len;
421
422         if (!recv_msg ||!recv_addr)
423                 return MS_MEDIA_ERR_INVALID_PARAMETER;
424
425 #ifdef _USE_UDS_SOCKET_
426         addr_len = sizeof(struct sockaddr_un);
427 #else
428         addr_len = sizeof(struct sockaddr_in);
429 #endif
430
431         if ((recv_msg_size = recvfrom(sockfd, recv_msg, msg_size, 0, (struct sockaddr *)recv_addr, &addr_len)) < 0) {
432                 MSAPI_DBG_ERR("recvfrom failed [%s]", strerror(errno));
433                 if (errno == EWOULDBLOCK) {
434                         MSAPI_DBG_ERR("recvfrom Timeout.");
435                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
436                 } else {
437                         MSAPI_DBG_ERR("recvfrom error [%s]", strerror(errno));
438                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
439                 }
440         }
441
442         if (addr_size != NULL)
443                 *addr_size  = addr_len;
444
445         return MS_MEDIA_ERR_NONE;
446 }
447