5c5317c724794283efd73e59730304270dcbdab9
[platform/core/system/swap-manager.git] / daemon / main.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 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  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12  * Nikita Kalyazin    <n.kalyazin@samsung.com>
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * - Samsung RnD Institute Russia
29  *
30  */
31
32 #include <stdio.h>                      // for fopen, fprintf
33 #include <stdlib.h>                     // for atexit
34 #include <sys/types.h>          // for open
35 #include <sys/file.h>
36 #include <sys/stat.h>           // for open
37 #include <sys/socket.h>         // for socket
38 #include <sys/un.h>                     // for sockaddr_un
39 #include <arpa/inet.h>          // for sockaddr_in, socklen_t
40
41 #include <signal.h>                     // for signal
42 #include <unistd.h>                     // for unlink
43 #include <fcntl.h>                      // for open, fcntl
44 #include <stdbool.h>
45 #ifndef LOCALTEST
46 #include <attr/xattr.h>         // for fsetxattr
47 #endif
48 #include "daemon.h"
49 #include "da_protocol.h"
50 #include "sys_stat.h"
51 #include "buffer.h"
52 #include "debug.h"
53
54 #define SINGLETON_LOCKFILE                      "/tmp/da_manager.lock"
55 #define PORTFILE                                        "/tmp/port.da"
56 #define UDS_NAME                                        "/tmp/da.socket"
57
58 #define INIT_PORT                               8001
59 #define LIMIT_PORT                              8100
60
61
62 // initialize global variable
63 __da_manager manager =
64 {
65         .host_server_socket = -1,
66         .target_server_socket = -1,
67         .target_count = 0,
68         .config_flag = 0,
69         .app_launch_timerfd = -1,
70         .connect_timeout_timerfd = -1,
71         .sampling_thread = -1,
72         .replay_thread = -1,
73         .transfer_thread = -1,
74         .buf_fd = -1,
75         .efd = -1,
76
77         .host = {
78                 .control_socket = -1,
79                 .data_socket = -1,
80                 .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER
81         },
82
83         .target = {
84                 {0L, },
85         },
86         .fd = {
87                 .brightness = -1,
88                 .voltage = -1,
89                 .procmeminfo = -1,
90                 .video = NULL,
91                 .audio_status = NULL,
92                 .procstat = NULL,
93                 .networkstat = NULL,
94                 .diskstats = NULL
95         },
96         .appPath = {0, }
97
98         };
99 // =============================================================================
100 // util functions
101 // =============================================================================
102
103 static void write_int(FILE *fp, int code)
104 {
105         fprintf(fp, "%d", code);
106 }
107
108 // =============================================================================
109 // atexit functions
110 // =============================================================================
111
112 void _close_server_socket(void)
113 {
114         LOGI("close_server_socket\n");
115         // close server socket
116         if(manager.host_server_socket != -1)
117                 close(manager.host_server_socket);
118         if(manager.target_server_socket != -1)
119                 close(manager.target_server_socket);
120 }
121
122 static void _unlink_files(void)
123 {
124         LOGI("unlink files start\n");
125         unlink(PORTFILE);
126         unlink(SINGLETON_LOCKFILE);
127         LOGI("unlink files done\n");
128 }
129
130 void unlink_portfile(void)
131 {
132         unlink(PORTFILE);
133 }
134
135 // =============================================================================
136 // making sockets
137 // =============================================================================
138
139 // return 0 for normal case
140 static int makeTargetServerSocket()
141 {
142         struct sockaddr_un serverAddrUn;
143
144         if(manager.target_server_socket != -1)
145                 return -1;      // should be never happend
146
147         // remove existed unix domain socket file
148         unlink(UDS_NAME);
149
150         if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
151         {
152                 LOGE("Target server socket creation failed\n");
153                 return -1;
154         }
155
156 #ifndef LOCALTEST
157         // set smack attribute for certification
158         fsetxattr(manager.target_server_socket, "security.SMACK64IPIN", "*", 1, 0);
159         fsetxattr(manager.target_server_socket, "security.SMACK64IPOUT", "*", 1, 0);
160 #endif /* LOCALTEST */
161
162         bzero(&serverAddrUn, sizeof(serverAddrUn));
163         serverAddrUn.sun_family = AF_UNIX;
164         sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
165
166         if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
167                                         sizeof(serverAddrUn)))
168         {
169                 LOGE("Target server socket binding failed\n");
170                 return -1;
171         }
172
173         if(chmod(serverAddrUn.sun_path, 0777) < 0)
174         {
175                 LOGE("Failed to change mode for socket file : errno(%d)\n", errno);
176         }
177
178
179         if (-1 == listen(manager.target_server_socket, 5))
180         {
181                 LOGE("Target server socket listening failed\n");
182                 return -1;
183         }
184
185         LOGI("Created TargetSock %d\n", manager.target_server_socket);
186         return 0;
187 }
188
189 // return port number for normal case
190 // return negative value for error case
191 static int makeHostServerSocket()
192 {
193         struct sockaddr_in serverAddrIn;
194         int opt = 1;
195         int port;
196
197         if(manager.host_server_socket != -1)
198                 return -1;      // should be never happened
199
200         if ((manager.host_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
201         {
202                 LOGE("Host server socket creation failed\n");
203                 return -1;
204         }
205
206         if(setsockopt(manager.host_server_socket,
207            SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
208         {
209                 LOGE("Failed to set socket option : errno(%d)\n", errno);
210         }
211
212         memset(&serverAddrIn, 0, sizeof(serverAddrIn));
213         serverAddrIn.sin_family = AF_INET;
214         serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
215
216         // bind address to server socket
217         for(port = INIT_PORT; port < LIMIT_PORT; port++)
218         {
219                 serverAddrIn.sin_port = htons(port);
220                 if (0 == bind(manager.host_server_socket,
221                                         (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
222                         break;
223         }
224
225         if(port == LIMIT_PORT)
226         {
227                 LOGE("Host server socket binding failed\n");
228                 return -1;
229         }
230
231         // enter listen state from client
232         if (-1 == listen(manager.host_server_socket, 5))
233         {
234                 LOGE("Host server socket listening failed\n");
235                 return -1;
236         }
237
238         LOGI("Created HostSock %d\n", manager.host_server_socket);
239         return port;
240 }
241
242 // =============================================================================
243 // initializing / finalizing functions
244 // =============================================================================
245
246 static bool ensure_singleton(const char *lockfile)
247 {
248         if (access(lockfile, F_OK) == 0)        /* File exists */
249                 return false;
250
251         int lockfd = open(lockfile, O_WRONLY | O_CREAT, 0600);
252         if (lockfd < 0) {
253                 LOGE("singleton lock file creation failed");
254                 return false;
255         }
256         /* To prevent race condition, also check for lock availiability. */
257         bool locked = flock(lockfd, LOCK_EX | LOCK_NB) == 0;
258
259         if (!locked) {
260                 LOGE("another instance of daemon is already running");
261         }
262         close(lockfd);
263         return locked;
264 }
265
266 static void inititialize_manager_targets(__da_manager * mng)
267 {
268         int index;
269         __da_target_info target_init_value = {
270                 .pid = -1,
271                 .socket = -1,
272                 .event_fd = -1,
273                 .recv_thread = -1,
274                 .initial_log = 0,
275                 .allocmem = 0,
276                 .starttime = 0
277         };
278
279         for (index = 0; index < MAX_TARGET_COUNT; index++)
280                 mng->target[index] = target_init_value;
281
282         manager.target_count = 0;
283 }
284
285 static bool initialize_pthread_sigmask()
286 {
287         sigset_t newsigmask;
288
289         sigemptyset(&newsigmask);
290         sigaddset(&newsigmask, SIGALRM);
291         sigaddset(&newsigmask, SIGUSR1);
292         return pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) == 0;
293 }
294
295 // return 0 for normal case
296 static int initializeManager(FILE *portfile)
297 {
298         if (init_buf() != 0) {
299                 LOGE("Cannot init buffer\n");
300                 return -1;
301         }
302
303         if (initialize_system_info() < 0) {
304                 write_int(portfile, ERR_INITIALIZE_SYSTEM_INFO_FAILED);
305                 return -1;
306         }
307         // make server socket
308         if (makeTargetServerSocket() != 0) {
309                 write_int(portfile, ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
310                 return -1;
311         }
312         if (!initialize_pthread_sigmask()) {
313                 write_int(portfile, ERR_SIGNAL_MASK_SETTING_FAILED);
314                 return -1;
315         }
316
317         int port = makeHostServerSocket();
318         if (port < 0) {
319                 write_int(portfile, ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
320                 return -1;
321         } else {
322                 write_int(portfile, port);
323         }
324
325         LOGI("SUCCESS to write port\n");
326
327         inititialize_manager_targets(&manager);
328
329         // initialize sendMutex
330         pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
331
332         return 0;
333 }
334
335
336 static int finalizeManager()
337 {
338         LOGI("Finalize daemon\n");
339 #ifndef LOCALTEST
340         LOGI("finalize system info\n");
341         finalize_system_info();
342 #endif
343
344         // close host client socket
345         if(manager.host.control_socket != -1){
346                 LOGI("close host control socket (%d)\n", manager.host.control_socket);
347                 close(manager.host.control_socket);
348         }
349         if(manager.host.data_socket != -1){
350                 LOGI("close host data socket (%d)\n", manager.host.data_socket);
351                 close(manager.host.data_socket);
352         }
353
354         LOGI("exit buf\n");
355         exit_buf();
356
357         LOGI("return\n");
358         return 0;
359 }
360
361 static void remove_buf_modules(void)
362 {
363         LOGI("rmmod buffer start\n");
364         if (system("cd /opt/swap/sdk && ./stop.sh")) {
365                 LOGW("Cannot remove swap modules\n");
366         }
367         LOGI("rmmod buffer done\n");
368 }
369
370 static void terminate(int sig)
371 {
372         _unlink_files();
373         _close_server_socket();
374         remove_buf_modules();
375         if (sig != 0) {
376                 LOGW("Terminating due signal %s\n", strsignal(sig));
377                 signal(sig, SIG_DFL);
378                 raise(sig);
379         }
380 }
381
382 static void terminate0()
383 {
384         terminate(0);
385 }
386
387
388 static void setup_signals()
389 {
390         struct sigaction sigact = {
391                 .sa_handler = terminate,
392                 .sa_flags = 0
393         };
394         sigemptyset(&sigact.sa_mask);
395         sigaction(SIGTERM, &sigact, 0);
396         sigaction(SIGINT, &sigact, 0);
397
398         signal(SIGHUP, SIG_IGN);
399         signal(SIGPIPE,SIG_IGN);
400 }
401
402 // main function
403 int main()
404 {
405         if (!ensure_singleton(SINGLETON_LOCKFILE))
406                 return 1;
407
408         initialize_log();
409
410         LOGI("da_started\n");
411         atexit(terminate0);
412
413
414         //for terminal exit
415         setup_signals();
416         daemon(0, 1);
417         LOGI("--- daemonized (pid %d) ---\n", getpid());
418
419         FILE *portfile = fopen(PORTFILE, "w");
420         if (!portfile) {
421                 LOGE("cannot create portfile");
422                 return 1;
423         }
424
425         int err = initializeManager(portfile);
426         fclose(portfile);
427         if (err)
428                 return 1;
429
430         //init all file descriptors
431         init_system_file_descriptors();
432         //daemon work
433         //FIX ME remove samplingThread it is only for debug
434         //samplingThread(NULL);
435         daemonLoop();
436         LOGI("daemon loop finished\n");
437         stop_all();
438         finalizeManager();
439
440         close_system_file_descriptors();
441
442         LOGI("main finished\n");
443         return 0;
444 }