2 * Copyright (C) 2011, BMW AG
4 * GeniviAudioMananger AudioManagerDaemon
8 * \date 20-Oct-2011 3:42:04 PM
9 * \author Christian Mueller (christian.ei.mueller@bmw.de)
12 * GNU Lesser General Public License, version 2.1, with special exception (GENIVI clause)
13 * Copyright (C) 2011, BMW AG Christian Mueller Christian.ei.mueller@bmw.de
15 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License, version 2.1, as published by the Free Software Foundation.
16 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License, version 2.1, for more details.
17 * You should have received a copy of the GNU Lesser General Public License, version 2.1, along with this program; if not, see <http://www.gnu.org/licenses/lgpl-2.1.html>.
18 * Note that the copyright holders assume that the GNU Lesser General Public License, version 2.1, may also be applicable to programs even in cases in which the program is not a library in the technical sense.
19 * Linking AudioManager statically or dynamically with other modules is making a combined work based on AudioManager. You may license such other modules under the GNU Lesser General Public License, version 2.1. If you do not want to license your linked modules under the GNU Lesser General Public License, version 2.1, you may use the program under the following exception.
20 * As a special exception, the copyright holders of AudioManager give you permission to combine AudioManager with software programs or libraries that are released under any license unless such a combination is not permitted by the license of such a software program or library. You may copy and distribute such a system following the terms of the GNU Lesser General Public License, version 2.1, including this special exception, for AudioManager and the licenses of the other code concerned.
21 * Note that people who make modified versions of AudioManager are not obligated to grant this special exception for their modified versions; it is their choice whether to do so. The GNU Lesser General Public License, version 2.1, gives permission to release a modified version without this exception; this exception also makes it possible to release a modified version which carries forward this exception.
26 * Please make sure to have read the documentation on genivi.org!
29 //todo: create systemd compatibility
30 //todo: all communication like all plugins loaded etc...
31 //todo: seperate documentation of test from normal project
32 //todo: check the startup sequence. Dbus shall be activated last...
33 //todo: there is a bug in the visible flags of sinks and sources. fix it.
34 //todo: make sure all configurations are tested
35 //todo: clean up startup sequences controller, command and routing interfaces----
37 #include <SocketHandler.h>
38 #ifdef WITH_DBUS_WRAPPER
39 #include <dbus/DBusWrapper.h>
41 #include "DatabaseHandler.h"
42 #include "ControlSender.h"
43 #include "CommandSender.h"
44 #include "RoutingSender.h"
45 #include "RoutingReceiver.h"
46 #include "CommandReceiver.h"
47 #include "ControlReceiver.h"
48 #include "DatabaseObserver.h"
49 #include "TelnetServer.h"
51 #include "DLTWrapper.h"
52 #include <sys/resource.h>
64 DLT_DECLARE_CONTEXT(AudioManager)
68 const char* USAGE_DESCRIPTION = "Usage:\tAudioManagerDaemon [options]\n"
70 "\t-h: print this message\t\n"
71 "\t-i: info about current settings \t\n"
72 "\t-v: print version\t\n"
73 "\t-d: daemonize AudioManager \t\n"
74 "\t-p<path> path for sqlite database (default is in memory)\t\n"
75 "\t-t<port> port for telnetconnection\t\n"
76 "\t-m<max> number of max telnetconnections\t\n"
77 "\t-c<Name> use controllerPlugin <Name> (full path with .so ending)\t\n"
78 "\t-l<Name> replace command plugin directory with <Name> (full path)\t\n"
79 "\t-r<Name> replace routing plugin directory with <Name> (full path)\t\n"
80 "\t-L<Name> add command plugin directory with <Name> (full path)\t\n"
81 "\t-R<Name> add routing plugin directory with <Name> (full path)\t\n";
83 std::string controllerPlugin = std::string(CONTROLLER_PLUGIN);
84 std::vector<std::string> listCommandPluginDirs;
85 std::vector<std::string> listRoutingPluginDirs;
86 std::string databasePath = std::string(":memory:");
87 unsigned int telnetport = DEFAULT_TELNETPORT;
88 unsigned int maxConnections = MAX_TELNETCONNECTIONS;
91 void OutOfMemoryHandler ()
93 logError("No more memory - bye");
94 //todo: add gracefull dead here. Do what can be done persistence wise
101 std::string dir = "/";
104 if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
106 logError("can't get file limit ");
110 if ((pid = fork()) < 0)
112 logError("cannot fork!");
121 if (!dir.empty() && chdir(dir.c_str()) < 0)
123 logError("couldn't chdir to the new directory");
126 if (rl.rlim_max == RLIM_INFINITY)
131 for (unsigned int i = 0; i < rl.rlim_max; i++)
136 fd0 = open("/dev/null", O_RDONLY);
137 fd1 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
138 fd2 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
140 if (fd0 != STDIN_FILENO || fd1 != STDOUT_FILENO || fd2 != STDERR_FILENO)
142 logError("new standard file descriptors were not opened");
146 void parseCommandLine(int argc, char **argv)
148 while (optind < argc)
150 int option = getopt(argc, argv, "h::v::c::l::r::L::R::d::t::m::i::p::");
155 printf("Current settings:\n");
156 printf("\tAudioManagerDaemon Version:\t\t%s\n", DAEMONVERSION);
157 printf("\tTelnet portNumber:\t\t\t%i\n", telnetport);
158 printf("\tTelnet maxConnections:\t\t\t%i\n", maxConnections);
159 printf("\tSqlite Database path:\t\t\t%s\n", databasePath.c_str());
160 printf("\tControllerPlugin: \t\t\t%s\n", controllerPlugin.c_str());
161 printf("\tDirectory of CommandPlugins: \t\t%s\n", listCommandPluginDirs.front().c_str());
162 printf("\tDirectory of RoutingPlugins: \t\t%s\n", listRoutingPluginDirs.front().c_str());
166 assert(atoi(optarg)!=0);
167 telnetport = atoi(optarg);
170 assert(atoi(optarg)!=0);
171 maxConnections = atoi(optarg);
174 assert(!controllerPlugin.empty());
175 databasePath = std::string(optarg);
181 listCommandPluginDirs.clear();
182 listCommandPluginDirs.push_back(std::string(optarg));
185 listRoutingPluginDirs.clear();
186 listRoutingPluginDirs.push_back(std::string(optarg));
189 listCommandPluginDirs.push_back(std::string(optarg));
192 listRoutingPluginDirs.push_back(std::string(optarg));
195 controllerPlugin = std::string(optarg);
196 assert(!controllerPlugin.empty());
197 assert(controllerPlugin.find(".so")!=std::string::npos);
200 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
205 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
206 puts(USAGE_DESCRIPTION);
212 static void signalHandler(int sig, siginfo_t *siginfo, void *context)
217 logError("signal handler was called, exit now...");
219 //todo: maually fire the mainloop
220 //todo: ifdef no sockethandler
224 int main(int argc, char *argv[])
226 DLTWrapper::instance()->registerApp("AudioManagerDeamon", "AudioManagerDeamon");
227 DLTWrapper::instance()->registerContext(AudioManager,"Main", "Main Context");
228 logInfo("The Audiomanager is started");
229 log(&AudioManager,DLT_LOG_ERROR,"The version of the Audiomanager",DAEMONVERSION);
231 listCommandPluginDirs.push_back(std::string(DEFAULT_PLUGIN_COMMAND_DIR));
232 listRoutingPluginDirs.push_back(std::string(DEFAULT_PLUGIN_ROUTING_DIR));
234 //parse the commandline options
235 parseCommandLine(argc, (char**) argv);
237 //now the signal handler:
238 struct sigaction signalAction;
239 memset(&signalAction, '\0', sizeof(signalAction));
240 signalAction.sa_sigaction = &signalHandler;
241 signalAction.sa_flags = SA_SIGINFO;
242 sigaction(SIGINT, &signalAction, NULL);
243 sigaction(SIGQUIT, &signalAction, NULL);
244 sigaction(SIGTERM, &signalAction, NULL);
245 sigaction(SIGHUP, &signalAction, NULL);
246 sigaction(SIGQUIT, &signalAction, NULL);
248 struct sigaction signalChildAction;
249 memset(&signalChildAction, '\0', sizeof(signalChildAction));
250 signalChildAction.sa_flags = SA_NOCLDWAIT;
251 sigaction(SIGCHLD, &signalChildAction, NULL);
253 //register new out of memory handler
254 std::set_new_handler(&OutOfMemoryHandler);
256 //Instantiate all classes. Keep in same order !
257 #ifdef WITH_SOCKETHANDLER_LOOP
258 SocketHandler iSocketHandler;
261 #ifdef WITH_DBUS_WRAPPER
262 #ifdef WITH_SOCKETHANDLER_LOOP
263 DBusWrapper iDBusWrapper(&iSocketHandler);
264 #else /*WITH_SOCKETHANDLER_LOOP*/
265 DBusWrapper iDBusWrapper;
266 #endif /*WITH_SOCKETHANDLER_LOOP*/
267 #endif /*WITH_DBUS_WRAPPER */
269 DatabaseHandler iDatabaseHandler(databasePath);
270 RoutingSender iRoutingSender(listRoutingPluginDirs);
271 CommandSender iCommandSender(listCommandPluginDirs);
272 ControlSender iControlSender(controllerPlugin);
273 Router iRouter(&iDatabaseHandler, &iControlSender);
275 #ifdef WITH_DBUS_WRAPPER
276 #ifdef WITH_SOCKETHANDLER_LOOP
277 CommandReceiver iCommandReceiver(&iDatabaseHandler, &iControlSender, &iSocketHandler, &iDBusWrapper);
278 RoutingReceiver iRoutingReceiver(&iDatabaseHandler, &iRoutingSender, &iControlSender, &iSocketHandler, &iDBusWrapper);
279 ControlReceiver iControlReceiver(&iDatabaseHandler, &iRoutingSender, &iCommandSender, &iSocketHandler, &iRouter);
281 TelnetServer iTelnetServer(&iSocketHandler,&iCommandSender,&iCommandReceiver,&iRoutingSender,&iRoutingReceiver,&iControlSender,&iControlReceiver,&iDatabaseHandler,telnetport,maxConnections);
283 #else /*WITH_SOCKETHANDLER_LOOP */
284 CommandReceiver iCommandReceiver(&iDatabaseHandler,&iControlSender,&iDBusWrapper);
285 RoutingReceiver iRoutingReceiver(&iDatabaseHandler,&iRoutingSender,&iControlSender,&iDBusWrapper);
286 ControlReceiver iControlReceiver(&iDatabaseHandler,&iRoutingSender,&iCommandSender, &iRouter);
287 #endif /*WITH_SOCKETHANDLER_LOOP*/
288 #else /*WITH_DBUS_WRAPPER*/
289 CommandReceiver iCommandReceiver(&iDatabaseHandler,&iControlSender,&iSocketHandler);
290 RoutingReceiver iRoutingReceiver(&iDatabaseHandler,&iRoutingSender,&iControlSender,&iSocketHandler);
291 ControlReceiver iControlReceiver(&iDatabaseHandler,&iRoutingSender,&iCommandSender,&iSocketHandler, &iRouter);
293 TelnetServer iTelnetServer(&iSocketHandler,telnetport,maxConnections);
295 #endif /*WITH_DBUS_WRAPPER*/
298 DatabaseObserver iObserver(&iCommandSender, &iRoutingSender,&iTelnetServer);
300 DatabaseObserver iObserver(&iCommandSender, &iRoutingSender);
303 //since the plugins have been loaded by the *Senders before, we can tell the Controller this:
304 iControlSender.hookAllPluginsLoaded();
306 //the controller should startup the interfaces - this is just for testing
307 iCommandSender.startupInterface(&iCommandReceiver);
308 iRoutingSender.startupRoutingInterface(&iRoutingReceiver);
309 iRoutingSender.routingInterfacesReady();
311 #ifdef WITH_SOCKETHANDLER_LOOP
312 iSocketHandler.start_listenting();
313 #endif /*WITH_SOCKETHANDLER_LOOP*/
315 #ifdef WITH_DBUS_WRAPPER
316 #ifdef WITH_SIMPLEDBUS_LOOP
317 iDBusWrapper.dbusMainLoop();
318 #endif/*WITH_SIMPLEDBUS_LOOP*/
319 #endif /*WITH_DBUS_WRAPPER*/