[FEATURE] Implement kernel -> user connection
[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 #include <linux/netlink.h>
41 #include <linux/connector.h>
42
43 #include <signal.h>                     // for signal
44 #include <unistd.h>                     // for unlink
45 #include <fcntl.h>                      // for open, fcntl
46 #include <errno.h>
47 #include <stdbool.h>
48 #include "daemon.h"
49 #include "da_protocol.h"
50 #include "sys_stat.h"
51 #include "buffer.h"
52 #include "debug.h"
53 #include "utils.h"
54 #include "smack.h"
55 #include "us_interaction_msg.h"
56
57 #define SINGLETON_LOCKFILE                      "/tmp/da_manager.lock"
58 #define PORTFILE                                        "/tmp/port.da"
59 #define UDS_NAME                                        "/tmp/da.socket"
60
61 #define INIT_PORT                               8001
62 #define LIMIT_PORT                              8100
63
64
65 // initialize global variable
66 __da_manager manager =
67 {
68         .host_server_socket = -1,
69         .target_server_socket = -1,
70         .kernel_socket = -1,
71         .target_count = 0,
72         .apps_to_run = 0,
73         .config_flag = 0,
74         .app_launch_timerfd = -1,
75         .connect_timeout_timerfd = -1,
76         .sampling_thread = -1,
77         .replay_thread = -1,
78         .transfer_thread = -1,
79         .buf_fd = -1,
80         .user_ev_fd = -1,
81         .efd = -1,
82
83         .host = {
84                 .control_socket = -1,
85                 .data_socket = -1,
86                 .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER
87         },
88
89         .target = {
90                 {0L, },
91         },
92         .fd = {
93                 .brightness = -1,
94                 .voltage = -1,
95                 .procmeminfo = -1,
96                 .video = NULL,
97                 .procstat = NULL,
98                 .networkstat = NULL,
99                 .diskstats = NULL
100         },
101         .appPath = {0, }
102
103         };
104 // =============================================================================
105 // util functions
106 // =============================================================================
107
108 static void write_int(FILE *fp, int code)
109 {
110         fprintf(fp, "%d", code);
111 }
112
113 // =============================================================================
114 // atexit functions
115 // =============================================================================
116
117 static void _close_server_socket(void)
118 {
119         LOGI("close_server_socket\n");
120         // close server socket
121         if(manager.host_server_socket != -1)
122                 close(manager.host_server_socket);
123         if(manager.target_server_socket != -1)
124                 close(manager.target_server_socket);
125         if (manager.kernel_socket != -1)
126                 close(manager.kernel_socket);
127 }
128
129 static void _unlink_files(void)
130 {
131         LOGI("unlink files start\n");
132         unlink(PORTFILE);
133         unlink(SINGLETON_LOCKFILE);
134         LOGI("unlink files done\n");
135 }
136
137 void unlink_portfile(void)
138 {
139         unlink(PORTFILE);
140 }
141
142 // =============================================================================
143 // making sockets
144 // =============================================================================
145
146 // return 0 for normal case
147 static int makeTargetServerSocket()
148 {
149         struct sockaddr_un serverAddrUn;
150
151         if(manager.target_server_socket != -1)
152                 return -1;      // should be never happend
153
154         // remove existed unix domain socket file
155         unlink(UDS_NAME);
156
157         if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
158         {
159                 LOGE("Target server socket creation failed\n");
160                 return -1;
161         }
162
163         fd_setup_attributes(manager.target_server_socket);
164
165         memset(&serverAddrUn, '\0', sizeof(serverAddrUn));
166         serverAddrUn.sun_family = AF_UNIX;
167         sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
168
169         if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
170                                         sizeof(serverAddrUn)))
171         {
172                 LOGE("Target server socket binding failed\n");
173                 return -1;
174         }
175
176         if(chmod(serverAddrUn.sun_path, 0777) < 0)
177         {
178                 LOGE("Failed to change mode for socket file : errno(%d)\n", errno);
179         }
180
181
182         if (-1 == listen(manager.target_server_socket, 5))
183         {
184                 LOGE("Target server socket listening failed\n");
185                 return -1;
186         }
187
188         LOGI("Created TargetSock %d\n", manager.target_server_socket);
189         return 0;
190 }
191
192 // return port number for normal case
193 // return negative value for error case
194 static int makeHostServerSocket()
195 {
196         struct sockaddr_in serverAddrIn;
197         int opt = 1;
198         int port;
199
200         if(manager.host_server_socket != -1)
201                 return -1;      // should be never happened
202
203         if ((manager.host_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
204         {
205                 LOGE("Host server socket creation failed\n");
206                 return -1;
207         }
208
209         if(setsockopt(manager.host_server_socket,
210            SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
211         {
212                 LOGE("Failed to set socket option : errno(%d)\n", errno);
213         }
214
215         memset(&serverAddrIn, 0, sizeof(serverAddrIn));
216         serverAddrIn.sin_family = AF_INET;
217         serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
218
219         // bind address to server socket
220         for(port = INIT_PORT; port < LIMIT_PORT; port++)
221         {
222                 serverAddrIn.sin_port = htons(port);
223                 if (0 == bind(manager.host_server_socket,
224                                         (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
225                         break;
226         }
227
228         if(port == LIMIT_PORT)
229         {
230                 LOGE("Host server socket binding failed\n");
231                 return -1;
232         }
233
234         // enter listen state from client
235         if (-1 == listen(manager.host_server_socket, 5))
236         {
237                 LOGE("Host server socket listening failed\n");
238                 return -1;
239         }
240
241         LOGI("Created HostSock %d\n", manager.host_server_socket);
242         return port;
243 }
244
245 // return 0 for normal case
246 static int makeKernelSocket(void)
247 {
248         struct sockaddr_nl nlAddr;
249         int ret;
250
251         if (manager.kernel_socket != -1)
252                 return -1;      // should be never happend
253
254         manager.kernel_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
255         if (manager.kernel_socket < 0) {
256                 LOGE("Kernel socket creation failed\n");
257                 return -1;
258         }
259
260         nlAddr.nl_family = AF_NETLINK;
261         nlAddr.nl_groups = CN_DAEMON_GROUP;
262         nlAddr.nl_pid = 0;
263
264         if (-1 == bind(manager.kernel_socket, (struct sockaddr*) &nlAddr,
265                    sizeof(nlAddr))) {
266                 LOGE("Kernel socket binding failed\n");
267                 return -1;
268         }
269
270         LOGI("Created KernelSock %d\n", manager.kernel_socket);
271         return 0;
272 }
273
274 // =============================================================================
275 // initializing / finalizing functions
276 // =============================================================================
277
278 static bool ensure_singleton(const char *lockfile)
279 {
280         if (access(lockfile, F_OK) == 0)        /* File exists */
281                 return false;
282
283         int lockfd = open(lockfile, O_WRONLY | O_CREAT, 0600);
284         if (lockfd < 0) {
285                 LOGE("singleton lock file creation failed");
286                 return false;
287         }
288         /* To prevent race condition, also check for lock availiability. */
289         bool locked = flock(lockfd, LOCK_EX | LOCK_NB) == 0;
290
291         if (!locked) {
292                 LOGE("another instance of daemon is already running");
293         }
294         close(lockfd);
295         return locked;
296 }
297
298 static void inititialize_manager_targets(__da_manager * mng)
299 {
300         int index;
301         __da_target_info target_init_value = {
302                 .pid = -1,
303                 .socket = -1,
304                 .event_fd = -1,
305                 .recv_thread = -1,
306                 .initial_log = 0,
307                 .allocmem = 0
308         };
309
310         for (index = 0; index < MAX_TARGET_COUNT; index++)
311                 mng->target[index] = target_init_value;
312
313         manager.target_count = 0;
314 }
315
316 static bool initialize_pthread_sigmask()
317 {
318         sigset_t newsigmask;
319
320         sigemptyset(&newsigmask);
321         sigaddset(&newsigmask, SIGALRM);
322         sigaddset(&newsigmask, SIGUSR1);
323         return pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) == 0;
324 }
325
326 // return 0 for normal case
327 static int initializeManager(FILE *portfile)
328 {
329         if (init_buf() != 0) {
330                 LOGE("Cannot init buffer\n");
331                 return -1;
332         }
333
334         if (initialize_system_info() < 0) {
335                 write_int(portfile, ERR_INITIALIZE_SYSTEM_INFO_FAILED);
336                 return -1;
337         }
338         // make server socket
339         if (makeTargetServerSocket() != 0) {
340                 write_int(portfile, ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
341                 return -1;
342         }
343         if (!initialize_pthread_sigmask()) {
344                 write_int(portfile, ERR_SIGNAL_MASK_SETTING_FAILED);
345                 return -1;
346         }
347
348         if (makeKernelSocket() != 0)
349                 return -1;
350
351         int port = makeHostServerSocket();
352         if (port < 0) {
353                 write_int(portfile, ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
354                 return -1;
355         } else {
356                 write_int(portfile, port);
357         }
358
359         LOGI("SUCCESS to write port\n");
360
361         inititialize_manager_targets(&manager);
362
363         // initialize sendMutex
364         pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
365
366         return 0;
367 }
368
369
370 static int finalizeManager()
371 {
372         LOGI("Finalize daemon\n");
373         LOGI("finalize system info\n");
374         finalize_system_info();
375
376         // close host client socket
377         if(manager.host.control_socket != -1){
378                 LOGI("close host control socket (%d)\n", manager.host.control_socket);
379                 close(manager.host.control_socket);
380         }
381         if(manager.host.data_socket != -1){
382                 LOGI("close host data socket (%d)\n", manager.host.data_socket);
383                 close(manager.host.data_socket);
384         }
385
386         LOGI("return\n");
387         return 0;
388 }
389
390 static void remove_buf_modules(void)
391 {
392         LOGI("rmmod buffer start\n");
393         if (system("cd /opt/swap/sdk && ./stop.sh")) {
394                 LOGW("Cannot remove swap modules\n");
395         }
396         LOGI("rmmod buffer done\n");
397 }
398
399 static void terminate(int sig)
400 {
401         LOGI("terminate! sig = %d\n", sig);
402         if (!stop_all_in_process()) {
403                 // we are up there if signal accept and stop_all func was not
404                 // called yet.
405
406                 // so we need stop_all firstly (if profiling was
407                 // not started it will be dummy call) and release other sources
408                 stop_all_no_lock();
409                 _unlink_files();
410                 _close_server_socket();
411                 exit_buf();
412                 remove_buf_modules();
413                 if (sig != 0) {
414                         LOGW("Terminating due signal %s\n", strsignal(sig));
415                         signal(sig, SIG_DFL);
416                         raise(sig);
417                 }
418                 stop_all_done();
419         } else {
420                 // we are there if stop_all function was called by some reasons
421
422                 // if stop_all called we cannot call remove_buf_modules and
423                 // other funcs because of threads are not stopped yet
424                 LOGW("Stop in progress\n");
425                 if (sig != 0) {
426                         LOGW("ignore signal %s\n", strsignal(sig));
427                         signal(sig, SIG_IGN);
428                 }
429         }
430 }
431
432 static void terminate0()
433 {
434         terminate(0);
435 }
436
437
438 static void setup_signals()
439 {
440         struct sigaction sigact = {
441                 .sa_handler = terminate,
442                 .sa_flags = 0
443         };
444         sigemptyset(&sigact.sa_mask);
445         sigaction(SIGTERM, &sigact, 0);
446         sigaction(SIGINT, &sigact, 0);
447
448         signal(SIGHUP, SIG_IGN);
449         signal(SIGPIPE,SIG_IGN);
450 }
451
452 // main function
453 int main()
454 {
455         if (!ensure_singleton(SINGLETON_LOCKFILE))
456                 return 1;
457
458         initialize_log();
459
460         LOGI("da_started\n");
461         atexit(terminate0);
462
463
464         //for terminal exit
465         setup_signals();
466         daemon(0, 1);
467         LOGI("--- daemonized (pid %d) ---\n", getpid());
468
469         FILE *portfile = fopen(PORTFILE, "w");
470         if (!portfile) {
471                 LOGE("cannot create portfile");
472                 return 1;
473         }
474
475         int err = initializeManager(portfile);
476         fclose(portfile);
477         if (err)
478                 return 1;
479
480         //init all file descriptors
481         init_system_file_descriptors();
482         //daemon work
483         //FIX ME remove samplingThread it is only for debug
484         //samplingThread(NULL);
485         daemonLoop();
486         LOGI("daemon loop finished\n");
487         stop_all();
488         finalizeManager();
489
490         close_system_file_descriptors();
491
492         LOGI("main finished\n");
493         return 0;
494 }