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 "\t-p<path> path for sqlite database (default is in memory)\t\n"
77 "\t-t<port> port for telnetconnection\t\n"
78 "\t-m<max> number of max telnetconnections\t\n"
79 "\t-c<Name> use controllerPlugin <Name> (full path with .so ending)\t\n"
80 "\t-l<Name> replace command plugin directory with <Name> (full path)\t\n"
81 "\t-r<Name> replace routing plugin directory with <Name> (full path)\t\n"
82 "\t-L<Name> add command plugin directory with <Name> (full path)\t\n"
83 "\t-R<Name> add routing plugin directory with <Name> (full path)\t\n";
85 std::string controllerPlugin = std::string(CONTROLLER_PLUGIN);
86 std::vector<std::string> listCommandPluginDirs;
87 std::vector<std::string> listRoutingPluginDirs;
88 std::string databasePath = std::string(":memory:");
89 unsigned int telnetport = DEFAULT_TELNETPORT;
90 unsigned int maxConnections = MAX_TELNETCONNECTIONS;
92 bool enableNoDLTDebug = false;
95 * the out of memory handler
97 void OutOfMemoryHandler()
99 logError("No more memory - bye");
100 //todo: add gracefull dead here. Do what can be done persistence wise
105 * daemonizes the AudioManager
110 std::string dir = "/";
113 if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
115 logError("can't get file limit ");
119 if ((pid = fork()) < 0)
121 logError("cannot fork!");
130 if (!dir.empty() && chdir(dir.c_str()) < 0)
132 logError("couldn't chdir to the new directory");
135 if (rl.rlim_max == RLIM_INFINITY)
140 for (unsigned int i = 0; i < rl.rlim_max; i++)
145 fd0 = open("/dev/null", O_RDONLY);
146 fd1 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
147 fd2 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
149 if (fd0 != STDIN_FILENO || fd1 != STDOUT_FILENO || fd2 != STDERR_FILENO)
151 logError("new standard file descriptors were not opened");
156 * parses the command line
160 void parseCommandLine(int argc, char **argv)
162 while (optind < argc)
165 int option = getopt(argc, argv, "h::v::c::l::r::L::R::d::t::m::i::p::");
167 int option = getopt(argc, argv, "h::v::V::c::l::r::L::R::d::t::m::i::p::");
173 printf("Current settings:\n");
174 printf("\tAudioManagerDaemon Version:\t\t%s\n", DAEMONVERSION);
175 printf("\tTelnet portNumber:\t\t\t%i\n", telnetport);
176 printf("\tTelnet maxConnections:\t\t\t%i\n", maxConnections);
177 printf("\tSqlite Database path:\t\t\t%s\n", databasePath.c_str());
178 printf("\tControllerPlugin: \t\t\t%s\n", controllerPlugin.c_str());
179 printf("\tDirectory of CommandPlugins: \t\t%s\n", listCommandPluginDirs.front().c_str());
180 printf("\tDirectory of RoutingPlugins: \t\t%s\n", listRoutingPluginDirs.front().c_str());
184 assert(atoi(optarg)!=0);
185 telnetport = atoi(optarg);
188 assert(atoi(optarg)!=0);
189 maxConnections = atoi(optarg);
192 assert(!controllerPlugin.empty());
193 databasePath = std::string(optarg);
199 listCommandPluginDirs.clear();
200 listCommandPluginDirs.push_back(std::string(optarg));
203 listRoutingPluginDirs.clear();
204 listRoutingPluginDirs.push_back(std::string(optarg));
207 listCommandPluginDirs.push_back(std::string(optarg));
210 listRoutingPluginDirs.push_back(std::string(optarg));
213 controllerPlugin = std::string(optarg);
214 assert(!controllerPlugin.empty());
215 assert(controllerPlugin.find(".so")!=std::string::npos);
218 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
223 printf("[DLT] debug output to stdout enabled\n");
224 enableNoDLTDebug = true;
229 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
230 puts(USAGE_DESCRIPTION);
242 static void signalHandler(int sig, siginfo_t *siginfo, void *context)
247 logError("signal handler was called, exit now...");
249 //todo: maually fire the mainloop
259 int main(int argc, char *argv[])
261 listCommandPluginDirs.push_back(std::string(DEFAULT_PLUGIN_COMMAND_DIR));
262 listRoutingPluginDirs.push_back(std::string(DEFAULT_PLUGIN_ROUTING_DIR));
264 //parse the commandline options
265 parseCommandLine(argc, (char**) argv);
267 CAmDltWrapper::instance(enableNoDLTDebug)->registerApp("AudioManagerDeamon", "AudioManagerDeamon");
268 CAmDltWrapper::instance()->registerContext(AudioManager, "Main", "Main Context");
269 logInfo("The Audiomanager is started");
270 logInfo("The version of the Audiomanager", DAEMONVERSION);
272 //now the signal handler:
273 struct sigaction signalAction;
274 memset(&signalAction, '\0', sizeof(signalAction));
275 signalAction.sa_sigaction = &signalHandler;
276 signalAction.sa_flags = SA_SIGINFO;
277 sigaction(SIGINT, &signalAction, NULL);
278 sigaction(SIGQUIT, &signalAction, NULL);
279 sigaction(SIGTERM, &signalAction, NULL);
280 sigaction(SIGHUP, &signalAction, NULL);
281 sigaction(SIGQUIT, &signalAction, NULL);
283 struct sigaction signalChildAction;
284 memset(&signalChildAction, '\0', sizeof(signalChildAction));
285 signalChildAction.sa_flags = SA_NOCLDWAIT;
286 sigaction(SIGCHLD, &signalChildAction, NULL);
288 //register new out of memory handler
289 std::set_new_handler(&OutOfMemoryHandler);
291 //Instantiate all classes. Keep in same order !
292 CAmSocketHandler iSocketHandler;
294 #ifdef WITH_DBUS_WRAPPER
295 CAmDbusWrapper iDBusWrapper(&iSocketHandler);
296 #endif /*WITH_DBUS_WRAPPER */
298 CAmDatabaseHandler iDatabaseHandler(databasePath);
299 CAmRoutingSender iRoutingSender(listRoutingPluginDirs);
300 CAmCommandSender iCommandSender(listCommandPluginDirs);
301 CAmControlSender iControlSender(controllerPlugin);
302 CAmRouter iRouter(&iDatabaseHandler, &iControlSender);
304 #ifdef WITH_DBUS_WRAPPER
305 CAmCommandReceiver iCommandReceiver(&iDatabaseHandler, &iControlSender, &iSocketHandler, &iDBusWrapper);
306 CAmRoutingReceiver iRoutingReceiver(&iDatabaseHandler, &iRoutingSender, &iControlSender, &iSocketHandler, &iDBusWrapper);
307 CAmControlReceiver iControlReceiver(&iDatabaseHandler, &iRoutingSender, &iCommandSender, &iSocketHandler, &iRouter);
308 #else /*WITH_DBUS_WRAPPER*/
309 CAmCommandReceiver iCommandReceiver(&iDatabaseHandler,&iControlSender,&iSocketHandler);
310 CAmRoutingReceiver iRoutingReceiver(&iDatabaseHandler,&iRoutingSender,&iControlSender,&iSocketHandler);
311 ControlReceiver iControlReceiver(&iDatabaseHandler,&iRoutingSender,&iCommandSender,&iSocketHandler, &iRouter);
312 #endif /*WITH_DBUS_WRAPPER*/
315 CAmTelnetServer iTelnetServer(&iSocketHandler, &iCommandSender, &iCommandReceiver, &iRoutingSender, &iRoutingReceiver, &iControlSender, &iControlReceiver, &iDatabaseHandler, &iRouter, telnetport, maxConnections);
316 CAmDatabaseObserver iObserver(&iCommandSender, &iRoutingSender, &iSocketHandler, &iTelnetServer);
317 #else /*WITH_TELNET*/
318 CAmDatabaseObserver iObserver(&iCommandSender,&iRoutingSender, &iSocketHandler);
321 iDatabaseHandler.registerObserver(&iObserver);
323 //startup all the Plugins and Interfaces
324 iControlSender.startupController(&iControlReceiver);
325 iCommandSender.startupInterfaces(&iCommandReceiver);
326 iRoutingSender.startupInterfaces(&iRoutingReceiver);
328 //when the routingInterface is done, all plugins are loaded:
329 iControlSender.setControllerReady();
331 //start the mainloop here....
332 iSocketHandler.start_listenting();