[FIX] Working w/o netlink
[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 #include "freezing.h"
57
58 #define SINGLETON_LOCKFILE                      "/tmp/da_manager.lock"
59 #define PORTFILE                                        "/tmp/port.da"
60 #define UDS_NAME                                        "/tmp/da.socket"
61
62 #define INIT_PORT                               8001
63 #define LIMIT_PORT                              8100
64
65
66 // initialize global variable
67 __da_manager manager =
68 {
69         .host_server_socket = -1,
70         .target_server_socket = -1,
71         .kernel_socket = -1,
72         .target_count = 0,
73         .apps_to_run = 0,
74         .config_flag = 0,
75         .app_launch_timerfd = -1,
76         .connect_timeout_timerfd = -1,
77         .sampling_thread = -1,
78         .replay_thread = -1,
79         .transfer_thread = -1,
80         .buf_fd = -1,
81         .user_ev_fd = -1,
82         .efd = -1,
83
84         .host = {
85                 .control_socket = -1,
86                 .data_socket = -1,
87                 .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER
88         },
89
90         .target = {
91                 {0L, },
92         },
93         .fd = {
94                 .brightness = -1,
95                 .voltage = -1,
96                 .procmeminfo = -1,
97                 .video = NULL,
98                 .procstat = NULL,
99                 .networkstat = NULL,
100                 .diskstats = NULL
101         },
102         .appPath = {0, }
103
104         };
105 // =============================================================================
106 // util functions
107 // =============================================================================
108
109 static void write_int(FILE *fp, int code)
110 {
111         fprintf(fp, "%d", code);
112 }
113
114 // =============================================================================
115 // atexit functions
116 // =============================================================================
117
118 static void _close_server_socket(void)
119 {
120         LOGI("close_server_socket\n");
121         // close server socket
122         if(manager.host_server_socket != -1)
123                 close(manager.host_server_socket);
124         if(manager.target_server_socket != -1)
125                 close(manager.target_server_socket);
126         if (manager.kernel_socket != -1)
127                 close(manager.kernel_socket);
128 }
129
130 static void _unlink_files(void)
131 {
132         LOGI("unlink files start\n");
133         unlink(PORTFILE);
134         unlink(SINGLETON_LOCKFILE);
135         LOGI("unlink files done\n");
136 }
137
138 void unlink_portfile(void)
139 {
140         unlink(PORTFILE);
141 }
142
143 // =============================================================================
144 // making sockets
145 // =============================================================================
146
147 // return 0 for normal case
148 static int makeTargetServerSocket()
149 {
150         struct sockaddr_un serverAddrUn;
151
152         if(manager.target_server_socket != -1)
153                 return -1;      // should be never happend
154
155         // remove existed unix domain socket file
156         unlink(UDS_NAME);
157
158         if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
159         {
160                 LOGE("Target server socket creation failed\n");
161                 return -1;
162         }
163
164         fd_setup_attributes(manager.target_server_socket);
165
166         memset(&serverAddrUn, '\0', sizeof(serverAddrUn));
167         serverAddrUn.sun_family = AF_UNIX;
168         sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
169
170         if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
171                                         sizeof(serverAddrUn)))
172         {
173                 LOGE("Target server socket binding failed\n");
174                 return -1;
175         }
176
177         if(chmod(serverAddrUn.sun_path, 0777) < 0)
178         {
179                 LOGE("Failed to change mode for socket file : errno(%d)\n", errno);
180         }
181
182
183         if (-1 == listen(manager.target_server_socket, 5))
184         {
185                 LOGE("Target server socket listening failed\n");
186                 return -1;
187         }
188
189         LOGI("Created TargetSock %d\n", manager.target_server_socket);
190         return 0;
191 }
192
193 // return port number for normal case
194 // return negative value for error case
195 static int makeHostServerSocket()
196 {
197         struct sockaddr_in serverAddrIn;
198         int opt = 1;
199         int port;
200
201         if(manager.host_server_socket != -1)
202                 return -1;      // should be never happened
203
204         if ((manager.host_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
205         {
206                 LOGE("Host server socket creation failed\n");
207                 return -1;
208         }
209
210         if(setsockopt(manager.host_server_socket,
211            SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
212         {
213                 LOGE("Failed to set socket option : errno(%d)\n", errno);
214         }
215
216         memset(&serverAddrIn, 0, sizeof(serverAddrIn));
217         serverAddrIn.sin_family = AF_INET;
218         serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
219
220         // bind address to server socket
221         for(port = INIT_PORT; port < LIMIT_PORT; port++)
222         {
223                 serverAddrIn.sin_port = htons(port);
224                 if (0 == bind(manager.host_server_socket,
225                                         (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
226                         break;
227         }
228
229         if(port == LIMIT_PORT)
230         {
231                 LOGE("Host server socket binding failed\n");
232                 return -1;
233         }
234
235         // enter listen state from client
236         if (-1 == listen(manager.host_server_socket, 5))
237         {
238                 LOGE("Host server socket listening failed\n");
239                 return -1;
240         }
241
242         LOGI("Created HostSock %d\n", manager.host_server_socket);
243         return port;
244 }
245
246 // return 0 for normal case
247 static int makeKernelSocket(void)
248 {
249         struct sockaddr_nl nlAddr;
250         int ret;
251
252         if (manager.kernel_socket != -1)
253                 return -1;      // should never happend
254
255         manager.kernel_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
256         if (manager.kernel_socket < 0) {
257                 LOGW("Kernel socket creation failed: %s\n", strerror(errno));
258                 return -1;
259         }
260
261         nlAddr.nl_family = AF_NETLINK;
262         nlAddr.nl_groups = CN_DAEMON_GROUP;
263         nlAddr.nl_pid = 0;
264
265         if (-1 == bind(manager.kernel_socket, (struct sockaddr*) &nlAddr,
266                    sizeof(nlAddr))) {
267                 LOGE("Kernel socket binding failed\n");
268                 return -1;
269         }
270
271         LOGI("Created KernelSock %d\n", manager.kernel_socket);
272         return 0;
273 }
274
275 // =============================================================================
276 // initializing / finalizing functions
277 // =============================================================================
278
279 static bool ensure_singleton(const char *lockfile)
280 {
281         if (access(lockfile, F_OK) == 0)        /* File exists */
282                 return false;
283
284         int lockfd = open(lockfile, O_WRONLY | O_CREAT, 0600);
285         if (lockfd < 0) {
286                 LOGE("singleton lock file creation failed");
287                 return false;
288         }
289         /* To prevent race condition, also check for lock availiability. */
290         bool locked = flock(lockfd, LOCK_EX | LOCK_NB) == 0;
291
292         if (!locked) {
293                 LOGE("another instance of daemon is already running");
294         }
295         close(lockfd);
296         return locked;
297 }
298
299 static void inititialize_manager_targets(__da_manager * mng)
300 {
301         int index;
302         __da_target_info target_init_value = {
303                 .pid = -1,
304                 .socket = -1,
305                 .event_fd = -1,
306                 .recv_thread = -1,
307                 .initial_log = 0,
308                 .allocmem = 0
309         };
310
311         for (index = 0; index < MAX_TARGET_COUNT; index++)
312                 mng->target[index] = target_init_value;
313
314         manager.target_count = 0;
315 }
316
317 static bool initialize_pthread_sigmask()
318 {
319         sigset_t newsigmask;
320
321         sigemptyset(&newsigmask);
322         sigaddset(&newsigmask, SIGALRM);
323         sigaddset(&newsigmask, SIGUSR1);
324         return pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) == 0;
325 }
326
327 // return 0 for normal case
328 static int initializeManager(FILE *portfile)
329 {
330         if (init_buf() != 0) {
331                 LOGE("Cannot init buffer\n");
332                 return -1;
333         }
334
335         if (initialize_system_info() < 0) {
336                 write_int(portfile, ERR_INITIALIZE_SYSTEM_INFO_FAILED);
337                 return -1;
338         }
339         // make server socket
340         if (makeTargetServerSocket() != 0) {
341                 write_int(portfile, ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
342                 return -1;
343         }
344         if (!initialize_pthread_sigmask()) {
345                 write_int(portfile, ERR_SIGNAL_MASK_SETTING_FAILED);
346                 return -1;
347         }
348
349         makeKernelSocket();
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         err = create_freezer_subgroup();
481         if (err) {
482                 LOGE("cannot create freezer subgroup");
483                 return 1;
484         }
485
486         //init all file descriptors
487         init_system_file_descriptors();
488         //daemon work
489         //FIX ME remove samplingThread it is only for debug
490         //samplingThread(NULL);
491         daemonLoop();
492         LOGI("daemon loop finished\n");
493         stop_all();
494         destroy_freezer_subgroup();
495         finalizeManager();
496
497         close_system_file_descriptors();
498
499         LOGI("main finished\n");
500         return 0;
501 }