[REFACTOR] make function naming more consistent
[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         .portfile = NULL,
66         .host_server_socket = -1,
67         .target_server_socket = -1,
68         .target_count = 0,
69         .config_flag = 0,
70         .app_launch_timerfd = -1,
71         .connect_timeout_timerfd = -1,
72         .sampling_thread = -1,
73         .replay_thread = -1,
74         .transfer_thread = -1,
75         .buf_fd = -1,
76         .efd = -1,
77
78         .host = {
79                 .control_socket = -1,
80                 .data_socket = -1,
81                 .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER
82         },
83
84         .target = {
85                 {0L, },
86         },
87         .fd = {
88                 .brightness = -1,
89                 .voltage = -1,
90                 .procmeminfo = -1,
91                 .video = NULL,
92                 .audio_status = NULL,
93                 .procstat = NULL,
94                 .networkstat = NULL,
95                 .diskstats = NULL
96         },
97         .appPath = {0, }
98
99         };
100 // =============================================================================
101 // util functions
102 // =============================================================================
103
104 static void write_to_portfile(int code)
105 {
106         if(unlikely(manager.portfile == 0))
107                 return;
108
109         fprintf(manager.portfile, "%d", code);
110 }
111
112 // =============================================================================
113 // atexit functions
114 // =============================================================================
115
116 void _close_server_socket(void)
117 {
118         LOGI("close_server_socket\n");
119         // close server socket
120         if(manager.host_server_socket != -1)
121                 close(manager.host_server_socket);
122         if(manager.target_server_socket != -1)
123                 close(manager.target_server_socket);
124 }
125
126 static void _unlink_files(void)
127 {
128         LOGI("unlink files start\n");
129         unlink(PORTFILE);
130         unlink(SINGLETON_LOCKFILE);
131         LOGI("unlink files done\n");
132 }
133
134 void unlink_portfile(void)
135 {
136         unlink(PORTFILE);
137 }
138
139 // =============================================================================
140 // making sockets
141 // =============================================================================
142
143 // return 0 for normal case
144 static int makeTargetServerSocket()
145 {
146         struct sockaddr_un serverAddrUn;
147
148         if(manager.target_server_socket != -1)
149                 return -1;      // should be never happend
150
151         // remove existed unix domain socket file
152         unlink(UDS_NAME);
153
154         if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
155         {
156                 LOGE("Target server socket creation failed\n");
157                 return -1;
158         }
159
160 #ifndef LOCALTEST
161         // set smack attribute for certification
162         fsetxattr(manager.target_server_socket, "security.SMACK64IPIN", "*", 1, 0);
163         fsetxattr(manager.target_server_socket, "security.SMACK64IPOUT", "*", 1, 0);
164 #endif /* LOCALTEST */
165
166         bzero(&serverAddrUn, 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         chmod(serverAddrUn.sun_path, 0777);
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         setsockopt(manager.host_server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
207         memset(&serverAddrIn, 0, sizeof(serverAddrIn));
208         serverAddrIn.sin_family = AF_INET;
209         serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
210
211         // bind address to server socket
212         for(port = INIT_PORT; port < LIMIT_PORT; port++)
213         {
214                 serverAddrIn.sin_port = htons(port);
215                 if (0 == bind(manager.host_server_socket,
216                                         (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
217                         break;
218         }
219
220         if(port == LIMIT_PORT)
221         {
222                 LOGE("Host server socket binding failed\n");
223                 return -1;
224         }
225
226         // enter listen state from client
227         if (-1 == listen(manager.host_server_socket, 5))
228         {
229                 LOGE("Host server socket listening failed\n");
230                 return -1;
231         }
232
233         LOGI("Created HostSock %d\n", manager.host_server_socket);
234         return port;
235 }
236
237 // =============================================================================
238 // initializing / finalizing functions
239 // =============================================================================
240
241 static bool ensure_singleton(const char *lockfile)
242 {
243         if (access(lockfile, F_OK) == 0)        /* File exists */
244                 return false;
245
246         int lockfd = open(lockfile, O_WRONLY | O_CREAT, 0600);
247         if (lockfd < 0) {
248                 write_to_portfile(ERR_LOCKFILE_CREATE_FAILED);
249                 LOGE("singleton lock file creation failed");
250                 return false;
251         }
252         /* To prevent race condition, also check for lock availiability. */
253         bool locked = flock(lockfd, LOCK_EX | LOCK_NB) == 0;
254
255         if (!locked) {
256                 write_to_portfile(ERR_ALREADY_RUNNING);
257                 LOGE("another instance of daemon is already running");
258         }
259         close(lockfd);
260         return locked;
261 }
262
263 static void inititialize_manager_targets(__da_manager * mng)
264 {
265         int index;
266         __da_target_info target_init_value = {
267                 .pid = -1,
268                 .socket = -1,
269                 .event_fd = -1,
270                 .recv_thread = -1,
271                 .initial_log = 0,
272                 .allocmem = 0,
273                 .starttime = 0
274         };
275
276         for (index = 0; index < MAX_TARGET_COUNT; index++)
277                 mng->target[index] = target_init_value;
278
279         manager.target_count = 0;
280 }
281
282 static bool initialize_pthread_sigmask()
283 {
284         sigset_t newsigmask;
285
286         sigemptyset(&newsigmask);
287         sigaddset(&newsigmask, SIGALRM);
288         sigaddset(&newsigmask, SIGUSR1);
289         if (pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) != 0) {
290                 write_to_portfile(ERR_SIGNAL_MASK_SETTING_FAILED);
291                 return false;
292         }
293         return true;
294 }
295
296 static bool initialize_host_server_socket()
297 {
298         int port = makeHostServerSocket();
299
300         if (port < 0) {
301                 write_to_portfile(ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
302                 return false;
303         }
304         write_to_portfile(port);
305         return true;
306 }
307
308 // return 0 for normal case
309 static int initializeManager()
310 {
311         if (init_buf() != 0) {
312                 LOGE("Cannot init buffer\n");
313                 return -1;
314         }
315
316         atexit(_close_server_socket);
317         if(initialize_system_info() < 0)
318         {
319                 write_to_portfile(ERR_INITIALIZE_SYSTEM_INFO_FAILED);
320                 return -1;
321         }
322
323         // make server socket
324         if(makeTargetServerSocket() != 0)
325         {
326                 write_to_portfile(ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
327                 return -1;
328         }
329
330         if (!initialize_host_server_socket())
331           return -1;
332
333         LOGI("SUCCESS to write port\n");
334
335         inititialize_manager_targets(&manager);
336         if (!initialize_pthread_sigmask())
337           return -1;
338         // initialize sendMutex
339         pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
340
341         return 0;
342 }
343
344 static int finalizeManager()
345 {
346         LOGI("Finalize daemon\n");
347 #ifndef LOCALTEST
348         LOGI("finalize system info\n");
349         finalize_system_info();
350 #endif
351
352         // close host client socket
353         if(manager.host.control_socket != -1){
354                 LOGI("close host control socket (%d)\n", manager.host.control_socket);
355                 close(manager.host.control_socket);
356         }
357         if(manager.host.data_socket != -1){
358                 LOGI("close host data socket (%d)\n", manager.host.data_socket);
359                 close(manager.host.data_socket);
360         }
361
362         LOGI("exit buf\n");
363         exit_buf();
364
365         LOGI("return\n");
366         return 0;
367 }
368
369 // main function
370 int main()
371 {
372         if (!ensure_singleton(SINGLETON_LOCKFILE))
373                 return 1;
374
375         initialize_log();
376
377         LOGI("da_started\n");
378         atexit(_unlink_files);
379
380         manager.portfile = fopen(PORTFILE, "w");
381         if (manager.portfile == NULL) {
382                 LOGE("cannot create portfile");
383                 return 1;
384         }
385         //for terminal exit
386         signal(SIGHUP, SIG_IGN);
387         chdir("/");
388
389         //new session reader
390         setsid();
391
392         // initialize manager
393         int err = initializeManager();
394         fclose(manager.portfile);
395         if (err)
396                 return 1;
397
398         //daemon work
399         //FIX ME remove samplingThread it is only for debug
400         //samplingThread(NULL);
401         daemonLoop();
402         LOGI("daemon loop finished\n");
403         stop_all();
404         finalizeManager();
405         LOGI("main finished\n");
406         return 0;
407 }