[FIX] segmentation fault on disconnet without stop message
[platform/core/system/swap-manager.git] / daemon / main.c
1 /*
2 *  DA manager
3 *
4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5 *
6 * Contact:
7 *
8 * Jaewon Lim <jaewon81.lim@samsung.com>
9 * Woojin Jung <woojin2.jung@samsung.com>
10 * Juyoung Kim <j0.kim@samsung.com>
11 *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 * Contributors:
25 * - S-Core Co., Ltd
26 *
27 */
28
29 #include <stdio.h>                      // for fopen, fprintf
30 #include <stdlib.h>                     // for atexit
31 #include <sys/types.h>          // for open
32 #include <sys/stat.h>           // for open
33 #include <sys/socket.h>         // for socket
34 #include <sys/un.h>                     // for sockaddr_un
35 #include <arpa/inet.h>          // for sockaddr_in, socklen_t
36
37 #include <signal.h>                     // for signal
38 #include <unistd.h>                     // for unlink
39 #include <fcntl.h>                      // for open, fcntl
40 #ifndef LOCALTEST
41 #include <attr/xattr.h>         // for fsetxattr
42 #endif
43 #include "daemon.h"
44 #include "da_protocol.h"
45 #include "sys_stat.h"
46 #include "buffer.h"
47 #include "debug.h"
48
49 #define SINGLETON_LOCKFILE                      "/tmp/lockfile.da"
50 #define PORTFILE                                        "/tmp/port.da"
51 #define UDS_NAME                                        "/tmp/da.socket"
52
53 #define INIT_PORT                               8001
54 #define LIMIT_PORT                              8100
55
56
57 // initialize global variable
58 __da_manager manager =
59 {
60         // TODO: rewrite this with . notation
61         NULL, -1, -1, // portfile pointer, host / target server socket
62         0, // target count
63         0, // config_flag
64         -1, // app launch timerfd
65         -1, // sampling_thread handle
66         -1, // replay_thread
67         -1, // transfer_thread
68         -1, // buf_fd
69         -1, // epoll fd
70         {-1, -1, PTHREAD_MUTEX_INITIALIZER}, // host
71         {{0L, }, }, // target
72         {0, } // appPath
73 };
74
75 // ==============================================================================
76 // util functions
77 // ==============================================================================
78
79 static void writeToPortfile(int code)
80 {
81         if(unlikely(manager.portfile == 0))
82                 return;
83
84         fprintf(manager.portfile, "%d", code);
85 }
86
87 // ==============================================================================
88 // atexit functions
89 // ==============================================================================
90
91 void _close_server_socket(void)
92 {
93         LOGI("close_server_socket\n");
94         // close server socket
95         if(manager.host_server_socket != -1)
96                 close(manager.host_server_socket);
97         if(manager.target_server_socket != -1)
98                 close(manager.target_server_socket);
99 }
100
101 static void _unlink_file(void)
102 {
103         LOGI("unlink files\n");
104         unlink(PORTFILE);
105         unlink(SINGLETON_LOCKFILE);
106 }
107
108 void unlink_portfile(void)
109 {
110         unlink(PORTFILE);
111 }
112
113 // ===============================================================================
114 // making sockets
115 // ===============================================================================
116
117 // return 0 for normal case
118 static int makeTargetServerSocket()
119 {
120         struct sockaddr_un serverAddrUn;
121
122         if(manager.target_server_socket != -1)
123                 return -1;      // should be never happend
124
125         // remove existed unix domain socket file
126         unlink(UDS_NAME);
127
128         if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
129         {
130                 LOGE("Target server socket creation failed\n");
131                 return -1;
132         }
133
134 #ifndef LOCALTEST
135         // set smack attribute for certification
136         fsetxattr(manager.target_server_socket, "security.SMACK64IPIN", "*", 1, 0);
137         fsetxattr(manager.target_server_socket, "security.SMACK64IPOUT", "*", 1, 0);
138 #endif /* LOCALTEST */
139
140         bzero(&serverAddrUn, sizeof(serverAddrUn));
141         serverAddrUn.sun_family = AF_UNIX;
142         sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
143
144         if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
145                                         sizeof(serverAddrUn)))
146         {
147                 LOGE("Target server socket binding failed\n");
148                 return -1;
149         }
150
151         chmod(serverAddrUn.sun_path, 0777);
152
153         if (-1 == listen(manager.target_server_socket, 5))
154         {
155                 LOGE("Target server socket listening failed\n");
156                 return -1;
157         }
158
159         LOGI("Created TargetSock %d\n", manager.target_server_socket);
160         return 0;
161 }
162
163 // return port number for normal case
164 // return negative value for error case
165 static int makeHostServerSocket()
166 {
167         struct sockaddr_in serverAddrIn;
168         int opt = 1;
169         int port;
170
171         if(manager.host_server_socket != -1)
172                 return -1;      // should be never happened
173
174         if ((manager.host_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
175         {
176                 LOGE("Host server socket creation failed\n");
177                 return -1;
178         }
179
180         setsockopt(manager.host_server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
181         memset(&serverAddrIn, 0, sizeof(serverAddrIn));
182         serverAddrIn.sin_family = AF_INET;
183         serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
184
185         // bind address to server socket
186         for(port = INIT_PORT; port < LIMIT_PORT; port++)
187         {
188                 serverAddrIn.sin_port = htons(port);
189                 if (0 == bind(manager.host_server_socket, (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
190                         break;
191         }
192
193         if(port == LIMIT_PORT)
194         {
195                 LOGE("Host server socket binding failed\n");
196                 return -1;
197         }
198
199         // enter listen state from client
200         if (-1 == listen(manager.host_server_socket, 5))
201         {
202                 LOGE("Host server socket listening failed\n");
203                 return -1;
204         }
205
206         LOGI("Created HostSock %d\n", manager.host_server_socket);
207         return port;
208 }
209
210 // ===============================================================================
211 // initializing / finalizing functions
212 // ===============================================================================
213
214 static int singleton(void)
215 {
216         struct flock fl;
217         int fd;
218
219         fd = open(SINGLETON_LOCKFILE, O_RDWR | O_CREAT, 0600);
220         if(fd < 0)
221         {
222                 writeToPortfile(ERR_LOCKFILE_CREATE_FAILED);
223                 LOGE("singleton lock file creation failed");
224                 return -1;
225         }
226
227         fl.l_start = 0;
228         fl.l_len = 0;
229         fl.l_type = F_WRLCK;
230         fl.l_whence = SEEK_SET;
231         if(fcntl(fd, F_SETLK, &fl) < 0)
232         {
233                 writeToPortfile(ERR_ALREADY_RUNNING);
234                 LOGE("another instance of daemon is already running");
235                 close(fd);
236                 return -1;
237         }
238
239         close(fd);
240         return 0;
241 }
242
243 // return 0 for normal case
244 static int initializeManager()
245 {
246         int i;
247         sigset_t newsigmask;
248
249         if (init_buf() != 0) {
250                 LOGE("Cannot init buffer\n");
251                 return -1;
252         }
253
254         atexit(_close_server_socket);
255         if(initialize_system_info() < 0)
256         {
257                 writeToPortfile(ERR_INITIALIZE_SYSTEM_INFO_FAILED);
258                 return -1;
259         }
260
261         // make server socket
262         if(makeTargetServerSocket() != 0)
263         {
264                 writeToPortfile(ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
265                 return -1;
266         }
267
268         i = makeHostServerSocket();
269         if(i < 0)
270         {
271                 writeToPortfile(ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
272                 return -1;
273         }
274         else    // host server socket creation succeed
275         {
276                 writeToPortfile(i);
277         }
278
279         // initialize signal mask
280         sigemptyset(&newsigmask);
281         sigaddset(&newsigmask, SIGALRM);
282         sigaddset(&newsigmask, SIGUSR1);
283         if(pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) != 0)
284         {
285                 writeToPortfile(ERR_SIGNAL_MASK_SETTING_FAILED);
286                 return -1;
287         }
288
289         LOGI("SUCCESS to write port\n");
290
291         // initialize target client sockets
292         for (i = 0; i < MAX_TARGET_COUNT; i++)
293         {
294                 manager.target[i].pid = -1;
295                 manager.target[i].socket = -1;
296                 manager.target[i].event_fd = -1;
297                 manager.target[i].recv_thread = -1;
298                 manager.target[i].initial_log = 0;
299                 manager.target[i].allocmem = 0;
300                 manager.target[i].starttime = 0;
301         }
302         manager.target_count = 0;
303
304         // initialize sendMutex
305         pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
306
307         return 0;
308 }
309
310 static int finalizeManager()
311 {
312         LOGI("Finalize daemon\n");
313 #ifndef LOCALTEST
314         LOGI("finalize system info\n");
315         finalize_system_info();
316 #endif
317
318         // close host client socket
319         if(manager.host.control_socket != -1){
320                 LOGI("close host control socket (%d)\n", manager.host.control_socket);
321                 close(manager.host.control_socket);
322         }
323         if(manager.host.data_socket != -1){
324                 LOGI("close host data socket (%d)\n", manager.host.data_socket);
325                 close(manager.host.data_socket);
326         }
327
328         LOGI("exit buf\n");
329         exit_buf();
330
331         LOGI("return\n");
332         return 0;
333 }
334
335 // main function
336 int main()
337 {
338         int result;
339         initialize_log();
340
341         LOGE("da_started\n");
342         atexit(_unlink_file);
343
344         manager.portfile = fopen(PORTFILE, "w");
345         if(manager.portfile == NULL)
346         {
347                 LOGE("cannot create portfile");
348                 return 1;
349         }
350
351         if(singleton() < 0)
352                 return 1;
353
354         //for terminal exit
355         signal(SIGHUP, SIG_IGN);
356         chdir("/");
357
358         //new session reader
359         setsid();
360
361         // initialize manager
362         result = initializeManager();
363         fclose(manager.portfile);
364         if(result == 0)
365         {
366                 //daemon work
367                 //FIX ME remove samplingThread it is only for debug
368                 //samplingThread(NULL);
369                 daemonLoop();
370                 stop_all();
371                 finalizeManager();
372                 return 0;
373         }
374         else
375         {
376                 return 1;
377         }
378 }