4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
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>
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
18 * http://www.apache.org/licenses/LICENSE-2.0
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.
28 * - Samsung RnD Institute Russia
32 #include <stdio.h> // for fopen, fprintf
33 #include <stdlib.h> // for atexit
34 #include <sys/types.h> // for open
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>
43 #include <signal.h> // for signal
44 #include <unistd.h> // for unlink
45 #include <fcntl.h> // for open, fcntl
49 #include "da_protocol.h"
55 #include "us_interaction_msg.h"
58 #define SINGLETON_LOCKFILE "/tmp/da_manager.lock"
59 #define PORTFILE "/tmp/port.da"
60 #define UDS_NAME "/tmp/da.socket"
62 #define INIT_PORT 8001
63 #define LIMIT_PORT 8100
66 // initialize global variable
67 __da_manager manager =
69 .host_server_socket = -1,
70 .target_server_socket = -1,
75 .app_launch_timerfd = -1,
76 .connect_timeout_timerfd = -1,
77 .sampling_thread = -1,
79 .transfer_thread = -1,
87 .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER
105 // =============================================================================
107 // =============================================================================
109 static void write_int(FILE *fp, int code)
111 fprintf(fp, "%d", code);
114 // =============================================================================
116 // =============================================================================
118 static void _close_server_socket(void)
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);
130 static void _unlink_files(void)
132 LOGI("unlink files start\n");
134 unlink(SINGLETON_LOCKFILE);
135 LOGI("unlink files done\n");
138 void unlink_portfile(void)
143 // =============================================================================
145 // =============================================================================
147 // return 0 for normal case
148 static int makeTargetServerSocket()
150 struct sockaddr_un serverAddrUn;
152 if(manager.target_server_socket != -1)
153 return -1; // should be never happend
155 // remove existed unix domain socket file
158 if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
160 LOGE("Target server socket creation failed\n");
164 fd_setup_attributes(manager.target_server_socket);
166 memset(&serverAddrUn, '\0', sizeof(serverAddrUn));
167 serverAddrUn.sun_family = AF_UNIX;
168 sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
170 if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
171 sizeof(serverAddrUn)))
173 LOGE("Target server socket binding failed\n");
177 if(chmod(serverAddrUn.sun_path, 0777) < 0)
179 LOGE("Failed to change mode for socket file : errno(%d)\n", errno);
183 if (-1 == listen(manager.target_server_socket, 5))
185 LOGE("Target server socket listening failed\n");
189 LOGI("Created TargetSock %d\n", manager.target_server_socket);
193 // return port number for normal case
194 // return negative value for error case
195 static int makeHostServerSocket()
197 struct sockaddr_in serverAddrIn;
201 if(manager.host_server_socket != -1)
202 return -1; // should be never happened
204 if ((manager.host_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
206 LOGE("Host server socket creation failed\n");
210 if(setsockopt(manager.host_server_socket,
211 SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
213 LOGE("Failed to set socket option : errno(%d)\n", errno);
216 memset(&serverAddrIn, 0, sizeof(serverAddrIn));
217 serverAddrIn.sin_family = AF_INET;
218 serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
220 // bind address to server socket
221 for(port = INIT_PORT; port < LIMIT_PORT; port++)
223 serverAddrIn.sin_port = htons(port);
224 if (0 == bind(manager.host_server_socket,
225 (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
229 if(port == LIMIT_PORT)
231 LOGE("Host server socket binding failed\n");
235 // enter listen state from client
236 if (-1 == listen(manager.host_server_socket, 5))
238 LOGE("Host server socket listening failed\n");
242 LOGI("Created HostSock %d\n", manager.host_server_socket);
246 // return 0 for normal case
247 static int makeKernelSocket(void)
249 struct sockaddr_nl nlAddr;
252 if (manager.kernel_socket != -1)
253 return -1; // should never happend
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));
261 nlAddr.nl_family = AF_NETLINK;
262 nlAddr.nl_groups = CN_DAEMON_GROUP;
265 if (-1 == bind(manager.kernel_socket, (struct sockaddr*) &nlAddr,
267 LOGE("Kernel socket binding failed\n");
271 LOGI("Created KernelSock %d\n", manager.kernel_socket);
275 // =============================================================================
276 // initializing / finalizing functions
277 // =============================================================================
279 static bool ensure_singleton(const char *lockfile)
281 if (access(lockfile, F_OK) == 0) /* File exists */
284 int lockfd = open(lockfile, O_WRONLY | O_CREAT, 0600);
286 LOGE("singleton lock file creation failed");
289 /* To prevent race condition, also check for lock availiability. */
290 bool locked = flock(lockfd, LOCK_EX | LOCK_NB) == 0;
293 LOGE("another instance of daemon is already running");
299 static void inititialize_manager_targets(__da_manager * mng)
302 __da_target_info target_init_value = {
311 for (index = 0; index < MAX_TARGET_COUNT; index++)
312 mng->target[index] = target_init_value;
314 manager.target_count = 0;
317 static bool initialize_pthread_sigmask()
321 sigemptyset(&newsigmask);
322 sigaddset(&newsigmask, SIGALRM);
323 sigaddset(&newsigmask, SIGUSR1);
324 return pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) == 0;
327 // return 0 for normal case
328 static int initializeManager(FILE *portfile)
330 if (init_buf() != 0) {
331 LOGE("Cannot init buffer\n");
335 if (initialize_system_info() < 0) {
336 write_int(portfile, ERR_INITIALIZE_SYSTEM_INFO_FAILED);
339 // make server socket
340 if (makeTargetServerSocket() != 0) {
341 write_int(portfile, ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
344 if (!initialize_pthread_sigmask()) {
345 write_int(portfile, ERR_SIGNAL_MASK_SETTING_FAILED);
351 int port = makeHostServerSocket();
353 write_int(portfile, ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
356 write_int(portfile, port);
359 LOGI("SUCCESS to write port\n");
361 inititialize_manager_targets(&manager);
363 // initialize sendMutex
364 pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
370 static int finalizeManager()
372 LOGI("Finalize daemon\n");
373 LOGI("finalize system info\n");
374 finalize_system_info();
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);
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);
390 static void remove_buf_modules(void)
392 LOGI("rmmod buffer start\n");
393 if (system("cd /opt/swap/sdk && ./stop.sh")) {
394 LOGW("Cannot remove swap modules\n");
396 LOGI("rmmod buffer done\n");
399 static void terminate(int sig)
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
406 // so we need stop_all firstly (if profiling was
407 // not started it will be dummy call) and release other sources
410 _close_server_socket();
412 remove_buf_modules();
414 LOGW("Terminating due signal %s\n", strsignal(sig));
415 signal(sig, SIG_DFL);
420 // we are there if stop_all function was called by some reasons
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");
426 LOGW("ignore signal %s\n", strsignal(sig));
427 signal(sig, SIG_IGN);
432 static void terminate0()
438 static void setup_signals()
440 struct sigaction sigact = {
441 .sa_handler = terminate,
444 sigemptyset(&sigact.sa_mask);
445 sigaction(SIGTERM, &sigact, 0);
446 sigaction(SIGINT, &sigact, 0);
448 signal(SIGHUP, SIG_IGN);
449 signal(SIGPIPE,SIG_IGN);
455 if (!ensure_singleton(SINGLETON_LOCKFILE))
460 LOGI("da_started\n");
467 LOGI("--- daemonized (pid %d) ---\n", getpid());
469 FILE *portfile = fopen(PORTFILE, "w");
471 LOGE("cannot create portfile");
475 int err = initializeManager(portfile);
480 err = create_freezer_subgroup();
482 LOGE("cannot create freezer subgroup");
486 //init all file descriptors
487 init_system_file_descriptors();
489 //FIX ME remove samplingThread it is only for debug
490 //samplingThread(NULL);
492 LOGI("daemon loop finished\n");
494 destroy_freezer_subgroup();
497 close_system_file_descriptors();
499 LOGI("main finished\n");