upload tizen1.0 source
[framework/appfw/app-checker.git] / src / ac_sock.c
1 /*
2  *  app-checker
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@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 #include <sys/types.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <errno.h>
29 #include <fcntl.h>
30
31
32 #include "ac_sock.h"
33 #include "internal.h"
34
35 static int __connect_client_sock(int sockfd, const struct sockaddr *saptr, socklen_t salen,
36                    int nsec);
37
38 static inline void __set_sock_option(int fd, int cli)
39 {
40         int size;
41         struct timeval tv = { 5, 200 * 1000 };  /*  5.2 sec */
42
43         size = AC_SOCK_MAXBUFF;
44         setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
45         setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
46         if (cli)
47                 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
48 }
49
50 int _create_server_sock()
51 {
52         struct sockaddr_un saddr;
53         int fd;
54
55         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
56         /*  support above version 2.6.27*/
57         if (fd < 0) {
58                 if(errno == EINVAL) {
59                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
60                         if(fd < 0) {
61                                 _E("second chance - socket create error");
62                                 return -1;
63                         }
64                 } else {
65                         _E("socket error");
66                         return -1;
67                 }
68         }
69
70         bzero(&saddr, sizeof(saddr));
71         saddr.sun_family = AF_UNIX;
72         snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s",AC_SOCK_NAME);
73         unlink(saddr.sun_path);
74         
75         if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
76                 _E("bind error");
77                 return -1;
78         }
79
80         if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
81                 /* Flawfinder: ignore*/
82                 _E("failed to change the socket permission");
83                 return -1;
84         }
85
86         __set_sock_option(fd, 0);
87
88         if (listen(fd, 10) == -1) {
89                 _E("listen error");
90                 return -1;
91         }       
92
93         return fd;
94 }
95
96 int _create_client_sock()
97 {
98         int fd = -1;
99         struct sockaddr_un saddr = { 0, };
100         int retry = 1;
101         int ret = -1;
102
103         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);    
104         /*  support above version 2.6.27*/
105         if (fd < 0) {
106                 if (errno == EINVAL) {
107                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
108                         if (fd < 0) {
109                                 _E("second chance - socket create error");
110                                 return -1;
111                         }
112                 } else {
113                         _E("socket error");
114                         return -1;
115                 }
116         }
117
118         saddr.sun_family = AF_UNIX;
119         snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s", AC_SOCK_NAME);
120  retry_con:
121         ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
122                         100 * 1000);
123         if (ret < -1) {
124                 _E("maybe peer not launched or peer daed\n");
125                 if (retry > 0) {
126                         usleep(100 * 1000);
127                         retry--;
128                         goto retry_con;
129                 }
130         }
131         if (ret < 0) {
132                 close(fd);
133                 return -1;
134         }
135
136         __set_sock_option(fd, 1);
137
138         return fd;
139 }
140
141 static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen,
142                    int nsec)
143 {
144         int flags;
145         int ret;
146         int error;
147         socklen_t len;
148         fd_set readfds;
149         fd_set writefds;
150         struct timeval timeout;
151
152         flags = fcntl(fd, F_GETFL, 0);
153         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
154
155         error = 0;
156         if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) {
157                 if (errno != EAGAIN && errno != EINPROGRESS) {
158                         fcntl(fd, F_SETFL, flags);      
159                         return (-2);
160                 }
161         }
162
163         /* Do whatever we want while the connect is taking place. */
164         if (ret == 0)
165                 goto done;      /* connect completed immediately */
166
167         FD_ZERO(&readfds);
168         FD_SET(fd, &readfds);
169         writefds = readfds;
170         timeout.tv_sec = 0;
171         timeout.tv_usec = nsec;
172
173         if ((ret = select(fd + 1, &readfds, &writefds, NULL, 
174                         nsec ? &timeout : NULL)) == 0) {
175                 close(fd);      /* timeout */
176                 errno = ETIMEDOUT;
177                 return (-1);
178         }
179
180         if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
181                 len = sizeof(error);
182                 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
183                         return (-1);    /* Solaris pending error */
184         } else
185                 return (-1);    /* select error: sockfd not set*/
186
187  done:
188         fcntl(fd, F_SETFL, flags);      
189         if (error) {
190                 close(fd);      
191                 errno = error;
192                 return (-1);
193         }
194         return (0);
195 }
196
197 /**
198  * @brief       Send data (in raw) to the process with 'pid' via socket
199  */
200 int _app_send_raw(int cmd, unsigned char *data, int datalen)
201 {
202         int fd;
203         int len;
204         int res = 0;
205         ac_pkt_t *pkt = NULL;
206
207         if (data == NULL || datalen > AC_SOCK_MAXBUFF - 8) {
208                 _E("keybundle error\n");
209                 return -EINVAL;
210         }
211
212         fd = _create_client_sock();
213         if (fd < 0)
214                 return -ECOMM;
215
216         pkt = (ac_pkt_t *) malloc(sizeof(char) * AC_SOCK_MAXBUFF);
217         if (NULL == pkt) {
218                 _E("Malloc Failed!");
219                 return -ENOMEM;
220         }
221         memset(pkt, 0, AC_SOCK_MAXBUFF);
222
223         pkt->cmd = cmd;
224         pkt->len = datalen;
225         memcpy(pkt->data, data, datalen);
226
227         if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
228                 _E("sendto() failed - %d %d", len, datalen + 8);
229                 if (errno == EPIPE) {
230                         _E("fd:%d\n", fd);
231                 }
232                 close(fd);
233                 if (pkt) {
234                         free(pkt);
235                         pkt = NULL;
236                 }
237                 return -ECOMM;
238         }
239         if (pkt) {
240                 free(pkt);
241                 pkt = NULL;
242         }
243
244         len = recv(fd, &res, sizeof(int), 0);
245         if (len == -1) {
246                 if (errno == EAGAIN) {
247                         _E("recv timeout \n");
248                         res = -EAGAIN;
249                 } else {
250                         _E("recv error\n");
251                         res = -ECOMM;
252                 }
253         } else
254                 _D("recv result  = %d (%d)", res, len);
255         close(fd);
256
257         return res;
258 }
259
260 ac_pkt_t *_app_recv_raw(int fd, int *clifd, struct ucred *cr)
261 {
262         int len;
263         struct sockaddr_un aul_addr = { 0, };
264         int sun_size;
265         ac_pkt_t *pkt = NULL;
266         int cl = sizeof(struct ucred);
267
268         sun_size = sizeof(struct sockaddr_un);
269
270         if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
271                              (socklen_t *) &sun_size)) == -1) {
272                 if (errno != EINTR)
273                         _E("accept error");
274                 return NULL;
275         }
276
277         if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
278                        (socklen_t *) &cl) < 0) {
279                 _E("peer information error");
280                 close(*clifd);
281                 return NULL;
282         }
283
284         pkt = (ac_pkt_t *) malloc(sizeof(char) * AC_SOCK_MAXBUFF);
285         if(pkt == NULL) {
286                 close(*clifd);
287                 return NULL;
288         }
289         memset(pkt, 0, AC_SOCK_MAXBUFF);
290
291         __set_sock_option(*clifd, 1);
292
293  retry_recv:
294         /* receive single packet from socket */
295         len = recv(*clifd, pkt, AC_SOCK_MAXBUFF, 0);
296         if (len < 0)
297                 if (errno == EINTR)
298                         goto retry_recv;
299
300         if ((len < 8) || (len != (pkt->len + 8))) {
301                 _E("recv error %d %d", len, pkt->len);
302                 free(pkt);
303                 close(*clifd);
304                 return NULL;
305         }
306
307         return pkt;
308 }
309
310 int _send_result_to_server(int fd, int res)
311 {
312         if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {
313                 if (errno == EPIPE)
314                         _E("send failed due to EPIPE.\n");
315                 _E("send fail to client");
316         }
317         close(fd);
318         return 0;
319 }