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: check the startup sequence. Dbus shall be activated last...
32 //todo: there is a bug in the visible flags of sinks and sources. fix it.
33 //todo: clean up startup sequences controller, command and routing interfaces----
34 //todo: package generation only works if package directory exists...
38 #include "TelnetServer.h"
40 #ifdef WITH_SOCKETHANDLER_LOOP
41 #include <SocketHandler.h>
43 #ifdef WITH_DBUS_WRAPPER
44 #include <dbus/DBusWrapper.h>
46 #include "DatabaseHandler.h"
47 #include "ControlSender.h"
48 #include "CommandSender.h"
49 #include "RoutingSender.h"
50 #include "RoutingReceiver.h"
51 #include "CommandReceiver.h"
52 #include "ControlReceiver.h"
53 #include "DatabaseObserver.h"
55 #include "DLTWrapper.h"
56 #include <sys/resource.h>
68 DLT_DECLARE_CONTEXT(AudioManager)
72 const char* USAGE_DESCRIPTION = "Usage:\tAudioManagerDaemon [options]\n"
74 "\t-h: print this message\t\n"
75 "\t-i: info about current settings \t\n"
76 "\t-v: print version\t\n"
77 "\t-d: daemonize AudioManager \t\n"
78 "\t-p<path> path for sqlite database (default is in memory)\t\n"
79 "\t-t<port> port for telnetconnection\t\n"
80 "\t-m<max> number of max telnetconnections\t\n"
81 "\t-c<Name> use controllerPlugin <Name> (full path with .so ending)\t\n"
82 "\t-l<Name> replace command plugin directory with <Name> (full path)\t\n"
83 "\t-r<Name> replace routing plugin directory with <Name> (full path)\t\n"
84 "\t-L<Name> add command plugin directory with <Name> (full path)\t\n"
85 "\t-R<Name> add routing plugin directory with <Name> (full path)\t\n";
87 std::string controllerPlugin = std::string(CONTROLLER_PLUGIN);
88 std::vector<std::string> listCommandPluginDirs;
89 std::vector<std::string> listRoutingPluginDirs;
90 std::string databasePath = std::string(":memory:");
91 unsigned int telnetport = DEFAULT_TELNETPORT;
92 unsigned int maxConnections = MAX_TELNETCONNECTIONS;
95 void OutOfMemoryHandler()
97 logError("No more memory - bye");
98 //todo: add gracefull dead here. Do what can be done persistence wise
105 std::string dir = "/";
108 if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
110 logError("can't get file limit ");
114 if ((pid = fork()) < 0)
116 logError("cannot fork!");
125 if (!dir.empty() && chdir(dir.c_str()) < 0)
127 logError("couldn't chdir to the new directory");
130 if (rl.rlim_max == RLIM_INFINITY)
135 for (unsigned int i = 0; i < rl.rlim_max; i++)
140 fd0 = open("/dev/null", O_RDONLY);
141 fd1 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
142 fd2 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
144 if (fd0 != STDIN_FILENO || fd1 != STDOUT_FILENO || fd2 != STDERR_FILENO)
146 logError("new standard file descriptors were not opened");
150 void parseCommandLine(int argc, char **argv)
152 while (optind < argc)
154 int option = getopt(argc, argv, "h::v::c::l::r::L::R::d::t::m::i::p::");
159 printf("Current settings:\n");
160 printf("\tAudioManagerDaemon Version:\t\t%s\n", DAEMONVERSION);
161 printf("\tTelnet portNumber:\t\t\t%i\n", telnetport);
162 printf("\tTelnet maxConnections:\t\t\t%i\n", maxConnections);
163 printf("\tSqlite Database path:\t\t\t%s\n", databasePath.c_str());
164 printf("\tControllerPlugin: \t\t\t%s\n", controllerPlugin.c_str());
165 printf("\tDirectory of CommandPlugins: \t\t%s\n", listCommandPluginDirs.front().c_str());
166 printf("\tDirectory of RoutingPlugins: \t\t%s\n", listRoutingPluginDirs.front().c_str());
170 assert(atoi(optarg)!=0);
171 telnetport = atoi(optarg);
174 assert(atoi(optarg)!=0);
175 maxConnections = atoi(optarg);
178 assert(!controllerPlugin.empty());
179 databasePath = std::string(optarg);
185 listCommandPluginDirs.clear();
186 listCommandPluginDirs.push_back(std::string(optarg));
189 listRoutingPluginDirs.clear();
190 listRoutingPluginDirs.push_back(std::string(optarg));
193 listCommandPluginDirs.push_back(std::string(optarg));
196 listRoutingPluginDirs.push_back(std::string(optarg));
199 controllerPlugin = std::string(optarg);
200 assert(!controllerPlugin.empty());
201 assert(controllerPlugin.find(".so")!=std::string::npos);
204 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
209 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
210 puts(USAGE_DESCRIPTION);
216 static void signalHandler(int sig, siginfo_t *siginfo, void *context)
221 logError("signal handler was called, exit now...");
223 //todo: maually fire the mainloop
224 //todo: ifdef no sockethandler
228 int main(int argc, char *argv[])
230 DLTWrapper::instance()->registerApp("AudioManagerDeamon", "AudioManagerDeamon");
231 DLTWrapper::instance()->registerContext(AudioManager, "Main", "Main Context");
232 logInfo("The Audiomanager is started");
233 log(&AudioManager, DLT_LOG_ERROR, "The version of the Audiomanager", DAEMONVERSION);
235 listCommandPluginDirs.push_back(std::string(DEFAULT_PLUGIN_COMMAND_DIR));
236 listRoutingPluginDirs.push_back(std::string(DEFAULT_PLUGIN_ROUTING_DIR));
238 //parse the commandline options
239 parseCommandLine(argc, (char**) argv);
241 //now the signal handler:
242 struct sigaction signalAction;
243 memset(&signalAction, '\0', sizeof(signalAction));
244 signalAction.sa_sigaction = &signalHandler;
245 signalAction.sa_flags = SA_SIGINFO;
246 sigaction(SIGINT, &signalAction, NULL);
247 sigaction(SIGQUIT, &signalAction, NULL);
248 sigaction(SIGTERM, &signalAction, NULL);
249 sigaction(SIGHUP, &signalAction, NULL);
250 sigaction(SIGQUIT, &signalAction, NULL);
252 struct sigaction signalChildAction;
253 memset(&signalChildAction, '\0', sizeof(signalChildAction));
254 signalChildAction.sa_flags = SA_NOCLDWAIT;
255 sigaction(SIGCHLD, &signalChildAction, NULL);
257 //register new out of memory handler
258 std::set_new_handler(&OutOfMemoryHandler);
260 //Instantiate all classes. Keep in same order !
261 #ifdef WITH_SOCKETHANDLER_LOOP
262 SocketHandler iSocketHandler;
265 #ifdef WITH_DBUS_WRAPPER
266 #ifdef WITH_SOCKETHANDLER_LOOP
267 DBusWrapper iDBusWrapper(&iSocketHandler);
268 #else /*WITH_SOCKETHANDLER_LOOP*/
269 DBusWrapper iDBusWrapper;
270 #endif /*WITH_SOCKETHANDLER_LOOP*/
271 #endif /*WITH_DBUS_WRAPPER */
273 DatabaseHandler iDatabaseHandler(databasePath);
274 RoutingSender iRoutingSender(listRoutingPluginDirs);
275 CommandSender iCommandSender(listCommandPluginDirs);
276 ControlSender iControlSender(controllerPlugin);
277 Router iRouter(&iDatabaseHandler, &iControlSender);
279 #ifdef WITH_DBUS_WRAPPER
280 #ifdef WITH_SOCKETHANDLER_LOOP
281 CommandReceiver iCommandReceiver(&iDatabaseHandler, &iControlSender, &iSocketHandler, &iDBusWrapper);
282 RoutingReceiver iRoutingReceiver(&iDatabaseHandler, &iRoutingSender, &iControlSender, &iSocketHandler, &iDBusWrapper);
283 ControlReceiver iControlReceiver(&iDatabaseHandler, &iRoutingSender, &iCommandSender, &iSocketHandler, &iRouter);
285 TelnetServer iTelnetServer(&iSocketHandler, &iCommandSender, &iCommandReceiver, &iRoutingSender, &iRoutingReceiver, &iControlSender, &iControlReceiver, &iDatabaseHandler, &iRouter, telnetport, maxConnections);
287 #else /*WITH_SOCKETHANDLER_LOOP */
288 CommandReceiver iCommandReceiver(&iDatabaseHandler,&iControlSender,&iDBusWrapper);
289 RoutingReceiver iRoutingReceiver(&iDatabaseHandler,&iRoutingSender,&iControlSender,&iDBusWrapper);
290 ControlReceiver iControlReceiver(&iDatabaseHandler,&iRoutingSender,&iCommandSender, &iRouter);
291 #endif /*WITH_SOCKETHANDLER_LOOP*/
292 #else /*WITH_DBUS_WRAPPER*/
293 CommandReceiver iCommandReceiver(&iDatabaseHandler,&iControlSender,&iSocketHandler);
294 RoutingReceiver iRoutingReceiver(&iDatabaseHandler,&iRoutingSender,&iControlSender,&iSocketHandler);
295 ControlReceiver iControlReceiver(&iDatabaseHandler,&iRoutingSender,&iCommandSender,&iSocketHandler, &iRouter);
297 TelnetServer iTelnetServer(&iSocketHandler,telnetport,maxConnections);
299 #endif /*WITH_DBUS_WRAPPER*/
302 DatabaseObserver iObserver(&iCommandSender, &iRoutingSender, &iTelnetServer);
304 DatabaseObserver iObserver(&iCommandSender, &iRoutingSender);
307 iDatabaseHandler.registerObserver(&iObserver);
309 //startup all the Plugins and Interfaces
310 iControlSender.startupController(&iControlReceiver);
311 iCommandSender.startupInterface(&iCommandReceiver);
312 iRoutingSender.startupRoutingInterface(&iRoutingReceiver);
314 //when the routingInterface is done, all plugins are loaded:
315 iControlSender.hookAllPluginsLoaded();
317 #ifdef WITH_SOCKETHANDLER_LOOP
318 iSocketHandler.start_listenting();
319 #endif /*WITH_SOCKETHANDLER_LOOP*/
321 #ifdef WITH_DBUS_WRAPPER
322 #ifdef WITH_SIMPLEDBUS_LOOP
323 iDBusWrapper.dbusMainLoop();
324 #endif/*WITH_SIMPLEDBUS_LOOP*/
325 #endif /*WITH_DBUS_WRAPPER*/