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"
35 #ifdef WITH_DBUS_WRAPPER
36 #include <shared/CAmDbusWrapper.h>
39 #include <sys/resource.h>
50 #include "CAmRouter.h"
51 #include "CAmDatabaseHandler.h"
52 #include "CAmControlSender.h"
53 #include "CAmCommandSender.h"
54 #include "CAmRoutingSender.h"
55 #include "CAmRoutingReceiver.h"
56 #include "CAmCommandReceiver.h"
57 #include "CAmControlReceiver.h"
58 #include "CAmDatabaseObserver.h"
59 #include "shared/CAmDltWrapper.h"
60 #include "shared/CAmSocketHandler.h"
64 DLT_DECLARE_CONTEXT(AudioManager)
67 const char* USAGE_DESCRIPTION = "Usage:\tAudioManagerDaemon [options]\n"
69 "\t-h: print this message\t\n"
70 "\t-i: info about current settings \t\n"
71 "\t-v: print version\t\n"
73 "\t-V: print DLT logs to stdout\t\n"
75 "\t-d: daemonize AudioManager \t\n"
76 #ifdef WITH_DBUS_WRAPPER
77 "\t-T: DbusType to be used by CAmDbusWrapper (0=DBUS_SESSION[default], 1=DBUS_SYSTEM)\t\n"
79 "\t-p<path> path for sqlite database (default is in memory)\t\n"
80 "\t-t<port> port for telnetconnection\t\n"
81 "\t-m<max> number of max telnetconnections\t\n"
82 "\t-c<Name> use controllerPlugin <Name> (full path with .so ending)\t\n"
83 "\t-l<Name> replace command plugin directory with <Name> (full path)\t\n"
84 "\t-r<Name> replace routing plugin directory with <Name> (full path)\t\n"
85 "\t-L<Name> add command plugin directory with <Name> (full path)\t\n"
86 "\t-R<Name> add routing plugin directory with <Name> (full path)\t\n";
88 std::string controllerPlugin = std::string(CONTROLLER_PLUGIN);
89 std::vector<std::string> listCommandPluginDirs;
90 std::vector<std::string> listRoutingPluginDirs;
91 std::string databasePath = std::string(":memory:");
92 unsigned int telnetport = DEFAULT_TELNETPORT;
93 unsigned int maxConnections = MAX_TELNETCONNECTIONS;
95 bool enableNoDLTDebug = false;
97 #ifdef WITH_DBUS_WRAPPER
98 DBusBusType dbusWrapperType=DBUS_BUS_SESSION;
102 * the out of memory handler
104 void OutOfMemoryHandler()
106 logError("No more memory - bye");
107 //todo: add gracefull dead here. Do what can be done persistence wise
112 * daemonizes the AudioManager
117 std::string dir = "/";
120 if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
122 logError("can't get file limit ");
126 if ((pid = fork()) < 0)
128 logError("cannot fork!");
137 if (!dir.empty() && chdir(dir.c_str()) < 0)
139 logError("couldn't chdir to the new directory");
142 if (rl.rlim_max == RLIM_INFINITY)
147 for (unsigned int i = 0; i < rl.rlim_max; i++)
152 fd0 = open("/dev/null", O_RDONLY);
153 fd1 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
154 fd2 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
156 if (fd0 != STDIN_FILENO || fd1 != STDOUT_FILENO || fd2 != STDERR_FILENO)
158 logError("new standard file descriptors were not opened");
163 * parses the command line
167 void parseCommandLine(int argc, char **argv)
169 while (optind < argc)
172 #ifdef WITH_DBUS_WRAPPER
173 int option = getopt(argc, argv, "h::v::c::l::r::L::R::d::t::m::i::p::T::");
175 int option = getopt(argc, argv, "h::v::c::l::r::L::R::d::t::m::i::p::");
176 #endif WITH_DBUS_WRAPPER
178 #ifdef WITH_DBUS_WRAPPER
179 int option = getopt(argc, argv, "h::v::V::c::l::r::L::R::d::t::m::i::p::T::");
181 int option = getopt(argc, argv, "h::v::V::c::l::r::L::R::d::t::m::i::p::");
182 #endif //WITH_DBUS_WRAPPER
188 printf("Current settings:\n");
189 printf("\tAudioManagerDaemon Version:\t\t%s\n", DAEMONVERSION);
190 printf("\tTelnet portNumber:\t\t\t%i\n", telnetport);
191 printf("\tTelnet maxConnections:\t\t\t%i\n", maxConnections);
192 printf("\tSqlite Database path:\t\t\t%s\n", databasePath.c_str());
193 printf("\tControllerPlugin: \t\t\t%s\n", controllerPlugin.c_str());
194 printf("\tDirectory of CommandPlugins: \t\t%s\n", listCommandPluginDirs.front().c_str());
195 printf("\tDirectory of RoutingPlugins: \t\t%s\n", listRoutingPluginDirs.front().c_str());
199 assert(atoi(optarg)!=0);
200 telnetport = atoi(optarg);
203 assert(atoi(optarg)!=0);
204 maxConnections = atoi(optarg);
207 assert(!controllerPlugin.empty());
208 databasePath = std::string(optarg);
214 listCommandPluginDirs.clear();
215 listCommandPluginDirs.push_back(std::string(optarg));
218 listRoutingPluginDirs.clear();
219 listRoutingPluginDirs.push_back(std::string(optarg));
222 listCommandPluginDirs.push_back(std::string(optarg));
225 listRoutingPluginDirs.push_back(std::string(optarg));
228 controllerPlugin = std::string(optarg);
229 assert(!controllerPlugin.empty());
230 assert(controllerPlugin.find(".so")!=std::string::npos);
233 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
238 printf("[DLT] debug output to stdout enabled\n");
239 enableNoDLTDebug = true;
242 #ifdef WITH_DBUS_WRAPPER
244 dbusWrapperType=static_cast<DBusBusType>(atoi(optarg));
249 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
250 puts(USAGE_DESCRIPTION);
262 static void signalHandler(int sig, siginfo_t *siginfo, void *context)
267 logError("signal handler was called, exit now...");
269 //todo: maually fire the mainloop
279 int main(int argc, char *argv[])
281 listCommandPluginDirs.push_back(std::string(DEFAULT_PLUGIN_COMMAND_DIR));
282 listRoutingPluginDirs.push_back(std::string(DEFAULT_PLUGIN_ROUTING_DIR));
284 //parse the commandline options
285 parseCommandLine(argc, (char**) argv);
287 CAmDltWrapper::instance(enableNoDLTDebug)->registerApp("AudioManagerDeamon", "AudioManagerDeamon");
288 CAmDltWrapper::instance()->registerContext(AudioManager, "Main", "Main Context");
289 logInfo("The Audiomanager is started");
290 logInfo("The version of the Audiomanager", DAEMONVERSION);
292 //now the signal handler:
293 struct sigaction signalAction;
294 memset(&signalAction, '\0', sizeof(signalAction));
295 signalAction.sa_sigaction = &signalHandler;
296 signalAction.sa_flags = SA_SIGINFO;
297 sigaction(SIGINT, &signalAction, NULL);
298 sigaction(SIGQUIT, &signalAction, NULL);
299 sigaction(SIGTERM, &signalAction, NULL);
300 sigaction(SIGHUP, &signalAction, NULL);
301 sigaction(SIGQUIT, &signalAction, NULL);
303 struct sigaction signalChildAction;
304 memset(&signalChildAction, '\0', sizeof(signalChildAction));
305 signalChildAction.sa_flags = SA_NOCLDWAIT;
306 sigaction(SIGCHLD, &signalChildAction, NULL);
308 //register new out of memory handler
309 std::set_new_handler(&OutOfMemoryHandler);
311 //Instantiate all classes. Keep in same order !
312 CAmSocketHandler iSocketHandler;
314 #ifdef WITH_DBUS_WRAPPER
315 CAmDbusWrapper iDBusWrapper(&iSocketHandler,dbusWrapperType);
316 #endif /*WITH_DBUS_WRAPPER */
318 CAmDatabaseHandler iDatabaseHandler(databasePath);
319 CAmRoutingSender iRoutingSender(listRoutingPluginDirs);
320 CAmCommandSender iCommandSender(listCommandPluginDirs);
321 CAmControlSender iControlSender(controllerPlugin);
322 CAmRouter iRouter(&iDatabaseHandler, &iControlSender);
324 #ifdef WITH_DBUS_WRAPPER
325 CAmCommandReceiver iCommandReceiver(&iDatabaseHandler, &iControlSender, &iSocketHandler, &iDBusWrapper);
326 CAmRoutingReceiver iRoutingReceiver(&iDatabaseHandler, &iRoutingSender, &iControlSender, &iSocketHandler, &iDBusWrapper);
327 CAmControlReceiver iControlReceiver(&iDatabaseHandler, &iRoutingSender, &iCommandSender, &iSocketHandler, &iRouter);
328 #else /*WITH_DBUS_WRAPPER*/
329 CAmCommandReceiver iCommandReceiver(&iDatabaseHandler,&iControlSender,&iSocketHandler);
330 CAmRoutingReceiver iRoutingReceiver(&iDatabaseHandler,&iRoutingSender,&iControlSender,&iSocketHandler);
331 CAmControlReceiver iControlReceiver(&iDatabaseHandler,&iRoutingSender,&iCommandSender,&iSocketHandler, &iRouter);
332 #endif /*WITH_DBUS_WRAPPER*/
335 CAmTelnetServer iTelnetServer(&iSocketHandler, &iCommandSender, &iCommandReceiver, &iRoutingSender, &iRoutingReceiver, &iControlSender, &iControlReceiver, &iDatabaseHandler, &iRouter, telnetport, maxConnections);
336 CAmDatabaseObserver iObserver(&iCommandSender, &iRoutingSender, &iSocketHandler, &iTelnetServer);
337 #else /*WITH_TELNET*/
338 CAmDatabaseObserver iObserver(&iCommandSender,&iRoutingSender, &iSocketHandler);
341 iDatabaseHandler.registerObserver(&iObserver);
343 //startup all the Plugins and Interfaces
344 iControlSender.startupController(&iControlReceiver);
345 iCommandSender.startupInterfaces(&iCommandReceiver);
346 iRoutingSender.startupInterfaces(&iRoutingReceiver);
348 //when the routingInterface is done, all plugins are loaded:
349 iControlSender.setControllerReady();
351 //start the mainloop here....
352 iSocketHandler.start_listenting();