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
41 #include <signal.h> // for signal
42 #include <unistd.h> // for unlink
43 #include <fcntl.h> // for open, fcntl
46 #include <attr/xattr.h> // for fsetxattr
49 #include "da_protocol.h"
54 #define SINGLETON_LOCKFILE "/tmp/da_manager.lock"
55 #define PORTFILE "/tmp/port.da"
56 #define UDS_NAME "/tmp/da.socket"
58 #define INIT_PORT 8001
59 #define LIMIT_PORT 8100
62 // initialize global variable
63 __da_manager manager =
66 .host_server_socket = -1,
67 .target_server_socket = -1,
70 .app_launch_timerfd = -1,
71 .connect_timeout_timerfd = -1,
72 .sampling_thread = -1,
74 .transfer_thread = -1,
81 .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER
100 // =============================================================================
102 // =============================================================================
104 static void writeToPortfile(int code)
106 if(unlikely(manager.portfile == 0))
109 fprintf(manager.portfile, "%d", code);
112 // =============================================================================
114 // =============================================================================
116 void _close_server_socket(void)
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);
126 static void _unlink_files(void)
128 LOGI("unlink files start\n");
130 unlink(SINGLETON_LOCKFILE);
131 LOGI("unlink files done\n");
134 void unlink_portfile(void)
139 // =============================================================================
141 // =============================================================================
143 // return 0 for normal case
144 static int makeTargetServerSocket()
146 struct sockaddr_un serverAddrUn;
148 if(manager.target_server_socket != -1)
149 return -1; // should be never happend
151 // remove existed unix domain socket file
154 if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
156 LOGE("Target server socket creation failed\n");
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 */
166 bzero(&serverAddrUn, 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 chmod(serverAddrUn.sun_path, 0777);
179 if (-1 == listen(manager.target_server_socket, 5))
181 LOGE("Target server socket listening failed\n");
185 LOGI("Created TargetSock %d\n", manager.target_server_socket);
189 // return port number for normal case
190 // return negative value for error case
191 static int makeHostServerSocket()
193 struct sockaddr_in serverAddrIn;
197 if(manager.host_server_socket != -1)
198 return -1; // should be never happened
200 if ((manager.host_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
202 LOGE("Host server socket creation failed\n");
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);
211 // bind address to server socket
212 for(port = INIT_PORT; port < LIMIT_PORT; port++)
214 serverAddrIn.sin_port = htons(port);
215 if (0 == bind(manager.host_server_socket,
216 (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
220 if(port == LIMIT_PORT)
222 LOGE("Host server socket binding failed\n");
226 // enter listen state from client
227 if (-1 == listen(manager.host_server_socket, 5))
229 LOGE("Host server socket listening failed\n");
233 LOGI("Created HostSock %d\n", manager.host_server_socket);
237 // =============================================================================
238 // initializing / finalizing functions
239 // =============================================================================
241 static bool ensure_singleton(const char *lockfile)
243 if (access(lockfile, F_OK) == 0) /* File exists */
246 int lockfd = open(lockfile, O_WRONLY | O_CREAT, 0600);
248 writeToPortfile(ERR_LOCKFILE_CREATE_FAILED);
249 LOGE("singleton lock file creation failed");
252 /* To prevent race condition, also check for lock availiability. */
253 bool locked = flock(lockfd, LOCK_EX | LOCK_NB) == 0;
256 writeToPortfile(ERR_ALREADY_RUNNING);
257 LOGE("another instance of daemon is already running");
263 static void inititialize_manager_targets(__da_manager * mng)
266 __da_target_info target_init_value = {
276 for (index = 0; index < MAX_TARGET_COUNT; index++)
277 mng->target[index] = target_init_value;
279 manager.target_count = 0;
282 static bool initialize_pthread_sigmask()
286 sigemptyset(&newsigmask);
287 sigaddset(&newsigmask, SIGALRM);
288 sigaddset(&newsigmask, SIGUSR1);
289 if (pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) != 0) {
290 writeToPortfile(ERR_SIGNAL_MASK_SETTING_FAILED);
296 static bool initialize_host_server_socket()
298 int port = makeHostServerSocket();
301 writeToPortfile(ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
304 writeToPortfile(port);
308 // return 0 for normal case
309 static int initializeManager()
311 if (init_buf() != 0) {
312 LOGE("Cannot init buffer\n");
316 atexit(_close_server_socket);
317 if(initialize_system_info() < 0)
319 writeToPortfile(ERR_INITIALIZE_SYSTEM_INFO_FAILED);
323 // make server socket
324 if(makeTargetServerSocket() != 0)
326 writeToPortfile(ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
330 if (!initialize_host_server_socket())
333 LOGI("SUCCESS to write port\n");
335 inititialize_manager_targets(&manager);
336 if (!initialize_pthread_sigmask())
338 // initialize sendMutex
339 pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
344 static int finalizeManager()
346 LOGI("Finalize daemon\n");
348 LOGI("finalize system info\n");
349 finalize_system_info();
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);
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);
372 if (!ensure_singleton(SINGLETON_LOCKFILE))
377 LOGI("da_started\n");
378 atexit(_unlink_files);
380 manager.portfile = fopen(PORTFILE, "w");
381 if (manager.portfile == NULL) {
382 LOGE("cannot create portfile");
386 signal(SIGHUP, SIG_IGN);
392 // initialize manager
393 int err = initializeManager();
394 fclose(manager.portfile);
399 //FIX ME remove samplingThread it is only for debug
400 //samplingThread(NULL);
402 LOGI("daemon loop finished\n");
405 LOGI("main finished\n");