2 * Copyright (C) 2012, BMW AG
4 * This file is part of GENIVI Project AudioManager.
6 * Contributions are licensed to the GENIVI Alliance under one or more
7 * Contribution License Agreements.
10 * This Source Code Form is subject to the terms of the
11 * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
12 * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 * \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012
16 * \author Frank Herchet, frank.fh.herchet@bmw.de BMW 2012
19 * For further information see http://www.genivi.org/.
24 * \todo create systemd compatibility
25 * \todo all communication like all plugins loaded etc...
26 * \todo check the startup sequence. Dbus shall be activated last...
27 * \bug package generation only works if package directory exists...
33 #include "CAmTelnetServer.h"
36 #ifdef WITH_CAPI_WRAPPER
37 #include "shared/CAmCommonAPIWrapper.h"
39 #ifdef WITH_DBUS_WRAPPER
40 #include "shared/CAmDbusWrapper.h"
45 #ifdef WITH_DBUS_WRAPPER
46 #include "CAmNodeStateCommunicatorDBus.h"
48 #include "CAmNodeStateCommunicatorCAPI.h"
52 #ifdef WITH_DATABASE_STORAGE
53 #include "CAmDatabaseHandlerSQLite.h"
55 #include "CAmDatabaseHandlerMap.h"
58 #ifdef WITH_SYSTEMD_WATCHDOG
59 #include "CAmWatchdog.h"
62 #include <sys/resource.h>
74 #include "CAmRouter.h"
75 #include "CAmControlSender.h"
76 #include "CAmCommandSender.h"
77 #include "CAmRoutingSender.h"
78 #include "CAmRoutingReceiver.h"
79 #include "CAmCommandReceiver.h"
80 #include "CAmControlReceiver.h"
81 #include "CAmDatabaseObserver.h"
82 #include "shared/CAmDltWrapper.h"
83 #include "shared/CAmSocketHandler.h"
87 DLT_DECLARE_CONTEXT(AudioManager)
89 const char* USAGE_DESCRIPTION = "Usage:\tAudioManagerDaemon [options]\n"
91 "\t-h: print this message\t\n"
92 "\t-i: info about current settings \t\n"
93 "\t-v: print version\t\n"
95 "\t-V: print DLT logs to stdout\t\n"
97 "\t-d: daemonize AudioManager \t\n"
98 #ifdef WITH_DBUS_WRAPPER
99 "\t-T: DbusType to be used by CAmDbusWrapper (0=DBUS_SESSION[default], 1=DBUS_SYSTEM)\t\n"
101 "\t-p<path> path for sqlite database (default is in memory)\t\n"
102 "\t-t<port> port for telnetconnection\t\n"
103 "\t-m<max> number of max telnetconnections\t\n"
104 "\t-c<Name> use controllerPlugin <Name> (full path with .so ending)\t\n"
105 "\t-l<Name> replace command plugin directory with <Name> (full path)\t\n"
106 "\t-r<Name> replace routing plugin directory with <Name> (full path)\t\n"
107 "\t-L<Name> add command plugin directory with <Name> (full path)\t\n"
108 "\t-R<Name> add routing plugin directory with <Name> (full path)\t\n";
110 std::string controllerPlugin = std::string(CONTROLLER_PLUGIN);
111 std::vector<std::string> listCommandPluginDirs;
112 std::vector<std::string> listRoutingPluginDirs;
113 std::string databasePath = std::string(":memory:");
114 unsigned int telnetport = DEFAULT_TELNETPORT;
115 unsigned int maxConnections = MAX_TELNETCONNECTIONS;
117 bool enableNoDLTDebug = false;
119 #ifdef WITH_DBUS_WRAPPER
120 DBusBusType dbusWrapperType=DBUS_BUS_SESSION;
124 * the out of memory handler
126 void OutOfMemoryHandler()
128 logError("No more memory - bye");
129 //todo: add gracefull dead here. Do what can be done persistence wise
134 * daemonizes the AudioManager
139 std::string dir = "/";
142 if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
144 logError("can't get file limit ");
148 if ((pid = fork()) < 0)
150 logError("cannot fork!");
159 if (!dir.empty() && chdir(dir.c_str()) < 0)
161 logError("couldn't chdir to the new directory");
164 if (rl.rlim_max == RLIM_INFINITY)
169 for (unsigned int i = 0; i < rl.rlim_max; i++)
174 fd0 = open("/dev/null", O_RDONLY);
175 fd1 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
176 fd2 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
178 if (fd0 != STDIN_FILENO || fd1 != STDOUT_FILENO || fd2 != STDERR_FILENO)
180 logError("new standard file descriptors were not opened");
185 * parses the command line
189 void parseCommandLine(int argc, char **argv)
191 while (optind < argc)
194 #ifdef WITH_DBUS_WRAPPER
195 int option = getopt(argc, argv, "h::v::c::l::r::L::R::d::t::m::i::p::T::");
197 int option = getopt(argc, argv, "h::v::c::l::r::L::R::d::t::m::i::p::");
198 #endif //WITH_DBUS_WRAPPER
200 #ifdef WITH_DBUS_WRAPPER
201 int option = getopt(argc, argv, "h::v::V::c::l::r::L::R::d::t::m::i::p::T::");
203 int option = getopt(argc, argv, "h::v::V::c::l::r::L::R::d::t::m::i::p::");
204 #endif //WITH_DBUS_WRAPPER
210 printf("Current settings:\n");
211 printf("\tAudioManagerDaemon Version:\t\t%s\n", DAEMONVERSION);
212 printf("\tTelnet portNumber:\t\t\t%i\n", telnetport);
213 printf("\tTelnet maxConnections:\t\t\t%i\n", maxConnections);
214 printf("\tSqlite Database path:\t\t\t%s\n", databasePath.c_str());
215 printf("\tControllerPlugin: \t\t\t%s\n", controllerPlugin.c_str());
216 printf("\tDirectory of CommandPlugins: \t\t%s\n", listCommandPluginDirs.front().c_str());
217 printf("\tDirectory of RoutingPlugins: \t\t%s\n", listRoutingPluginDirs.front().c_str());
221 assert(atoi(optarg)!=0);
222 telnetport = atoi(optarg);
225 assert(atoi(optarg)!=0);
226 maxConnections = atoi(optarg);
229 assert(!controllerPlugin.empty());
230 databasePath = std::string(optarg);
236 listCommandPluginDirs.clear();
237 listCommandPluginDirs.push_back(std::string(optarg));
240 listRoutingPluginDirs.clear();
241 listRoutingPluginDirs.push_back(std::string(optarg));
244 listCommandPluginDirs.push_back(std::string(optarg));
247 listRoutingPluginDirs.push_back(std::string(optarg));
250 controllerPlugin = std::string(optarg);
251 assert(!controllerPlugin.empty());
252 assert(controllerPlugin.find(".so")!=std::string::npos);
255 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
260 printf("\e[0;34m[DLT]\e[0;30m\tDebug output to stdout enabled\n");
261 enableNoDLTDebug = true;
264 #ifdef WITH_DBUS_WRAPPER
266 dbusWrapperType=static_cast<DBusBusType>(atoi(optarg));
271 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
272 puts(USAGE_DESCRIPTION);
284 static void signalHandler(int sig, siginfo_t *siginfo, void *context)
289 logInfo("signal handler was called, signal",sig);
293 /*ctl +c lets call direct controllerRundown, because we might be blocked at the moment.
294 But there is the risk of interrupting something important */
296 CAmControlSender::CallsetControllerRundown(sig);
299 /* huch- we are getting killed. Better take the fast but risky way: */
301 CAmControlSender::CallsetControllerRundown(sig);
304 /* more friendly here assuming systemd wants to stop us, so we can use the mainloop */
306 CAmControlSender::CallsetControllerRundownSafe(sig);
309 /* looks friendly, too, so lets take the long run */
311 CAmControlSender::CallsetControllerRundownSafe(sig);
320 //Instantiate all classes. Keep in same order !
321 CAmSocketHandler iSocketHandler;
323 #ifdef WITH_CAPI_WRAPPER
324 //We instantiate a singleton with the current socket handler, which loads the common-api runtime.
325 CAmCommonAPIWrapper *pCAPIWrapper = CAmCommonAPIWrapper::instantiateOnce(&iSocketHandler);
326 CAmCommonAPIWrapper iDBusWrapper = *pCAPIWrapper;
328 CAmNodeStateCommunicatorCAPI iNodeStateCommunicator(&iDBusWrapper);
330 #endif /*WITH_CAPI_WRAPPER */
332 #ifdef WITH_DBUS_WRAPPER
333 CAmDbusWrapper iDBusWrapper(&iSocketHandler,dbusWrapperType);
335 CAmNodeStateCommunicatorDBus iNodeStateCommunicator(&iDBusWrapper);
337 #endif /*WITH_DBUS_WRAPPER */
339 #ifdef WITH_SYSTEMD_WATCHDOG
340 CAmWatchdog iWatchdog(&iSocketHandler);
341 #endif /*WITH_SYSTEMD_WATCHDOG*/
343 #ifdef WITH_DATABASE_STORAGE
344 CAmDatabaseHandlerSQLite iDatabaseHandler(databasePath);
346 CAmDatabaseHandlerMap iDatabaseHandler;
347 #endif /*WITH_DATABASE_STORAGE*/
348 IAmDatabaseHandler *pDatabaseHandler = dynamic_cast<IAmDatabaseHandler*>( &iDatabaseHandler );
350 CAmRoutingSender iRoutingSender(listRoutingPluginDirs);
351 CAmCommandSender iCommandSender(listCommandPluginDirs);
352 CAmControlSender iControlSender(controllerPlugin,&iSocketHandler);
353 CAmRouter iRouter(pDatabaseHandler, &iControlSender);
355 #ifdef WITH_DBUS_WRAPPER
356 CAmCommandReceiver iCommandReceiver(pDatabaseHandler, &iControlSender, &iSocketHandler, &iDBusWrapper);
357 CAmRoutingReceiver iRoutingReceiver(pDatabaseHandler, &iRoutingSender, &iControlSender, &iSocketHandler, &iDBusWrapper);
358 #else /*WITH_DBUS_WRAPPER*/
359 CAmCommandReceiver iCommandReceiver(pDatabaseHandler,&iControlSender,&iSocketHandler);
360 CAmRoutingReceiver iRoutingReceiver(pDatabaseHandler,&iRoutingSender,&iControlSender,&iSocketHandler);
361 #endif /*WITH_DBUS_WRAPPER*/
364 CAmControlReceiver iControlReceiver(pDatabaseHandler,&iRoutingSender,&iCommandSender,&iSocketHandler, &iRouter, &iNodeStateCommunicator);
365 iNodeStateCommunicator.registerControlSender(&iControlSender);
367 #ifdef WITH_DBUS_WRAPPER
368 CAmControlReceiver iControlReceiver(pDatabaseHandler,&iRoutingSender,&iCommandSender,&iSocketHandler, &iRouter, &iDBusWrapper);
369 #else /*WITH_DBUS_WRAPPER*/
370 CAmControlReceiver iControlReceiver(pDatabaseHandler,&iRoutingSender,&iCommandSender,&iSocketHandler, &iRouter);
371 #endif /*WITH_DBUS_WRAPPER*/
375 CAmTelnetServer iTelnetServer(&iSocketHandler, &iCommandSender, &iCommandReceiver, &iRoutingSender, &iRoutingReceiver, &iControlSender, &iControlReceiver, pDatabaseHandler, &iRouter, telnetport, maxConnections);
376 CAmDatabaseObserver iObserver(&iCommandSender, &iRoutingSender, &iSocketHandler, &iTelnetServer);
377 #else /*WITH_TELNET*/
378 CAmDatabaseObserver iObserver(&iCommandSender,&iRoutingSender, &iSocketHandler);
381 iDatabaseHandler.registerObserver(&iObserver);
383 //startup all the Plugins and Interfaces
384 iControlSender.startupController(&iControlReceiver);
385 iCommandSender.startupInterfaces(&iCommandReceiver);
386 iRoutingSender.startupInterfaces(&iRoutingReceiver);
388 //when the routingInterface is done, all plugins are loaded:
389 iControlSender.setControllerReady();
391 #ifdef WITH_SYSTEMD_WATCHDOG
392 iWatchdog.startWatchdog();
393 #endif /*WITH_SYSTEMD_WATCHDOG*/
395 //start the mainloop here....
396 iSocketHandler.start_listenting();
405 int main(int argc, char *argv[], char** envp)
408 listCommandPluginDirs.push_back(std::string(DEFAULT_PLUGIN_COMMAND_DIR));
409 listRoutingPluginDirs.push_back(std::string(DEFAULT_PLUGIN_ROUTING_DIR));
411 //parse the commandline options
412 parseCommandLine(argc, (char**) argv);
414 CAmDltWrapper::instance(enableNoDLTDebug)->registerApp("AudioManagerDeamon", "AudioManagerDeamon");
415 CAmDltWrapper::instance()->registerContext(AudioManager, "Main", "Main Context");
416 logInfo("The Audiomanager is started");
417 logInfo("The version of the Audiomanager", DAEMONVERSION);
419 //now the signal handler:
420 struct sigaction signalAction;
421 memset(&signalAction, '\0', sizeof(signalAction));
422 signalAction.sa_sigaction = &signalHandler;
423 signalAction.sa_flags = SA_SIGINFO;
424 sigaction(SIGINT, &signalAction, NULL);
425 sigaction(SIGQUIT, &signalAction, NULL);
426 sigaction(SIGTERM, &signalAction, NULL);
427 sigaction(SIGHUP, &signalAction, NULL);
429 struct sigaction signalChildAction;
430 memset(&signalChildAction, '\0', sizeof(signalChildAction));
431 signalChildAction.sa_flags = SA_NOCLDWAIT;
432 sigaction(SIGCHLD, &signalChildAction, NULL);
434 //register new out of memory handler
435 std::set_new_handler(&OutOfMemoryHandler);
439 //we do this to catch all exceptions and have a graceful ending just in case
443 catch (std::exception& exc)
445 logError("The AudioManager ended by throwing the exception", exc.what());
446 std::cerr<<"The AudioManager ended by throwing an exception "<<exc.what()<<std::endl;
455 CAmDltWrapper* inst(getWrapper());