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: make real daemon out of it- systemd conform
30 //todo: versioning of PluginInterfaces on linux level (.symver stuff)
31 //todo: all communication like all plugins loaded etc...
32 //todo: seperate documentation of test from normal project
33 //todo: check the startup sequence. Dbus shall be activated last...
34 //todo: there is a bug in the visible flags of sinks and sources. fix it.
35 //todo: make sure that iterators have a fixed end to prevent crashed while adding vectors while iterating on critical vectors
36 //todo: make sure all configurations are tested
38 #include <SocketHandler.h>
39 #ifdef WITH_DBUS_WRAPPER
40 #include <dbus/DBusWrapper.h>
42 #include "DatabaseHandler.h"
43 #include "ControlSender.h"
44 #include "CommandSender.h"
45 #include "RoutingSender.h"
46 #include "RoutingReceiver.h"
47 #include "CommandReceiver.h"
48 #include "ControlReceiver.h"
49 #include "DatabaseObserver.h"
50 #include "TelnetServer.h"
51 #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;
93 std::string dir = "/";
96 if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
98 DLT_LOG(AudioManager, DLT_LOG_ERROR, DLT_STRING("can't get file limit "));
102 if ((pid = fork()) < 0)
104 DLT_LOG(AudioManager, DLT_LOG_ERROR, DLT_STRING("cannot fork!"));
113 if (!dir.empty() && chdir(dir.c_str()) < 0)
115 DLT_LOG(AudioManager, DLT_LOG_ERROR, DLT_STRING("couldn't chdir to the new directory"));
118 if (rl.rlim_max == RLIM_INFINITY)
123 for (unsigned int i = 0; i < rl.rlim_max; i++)
128 int fd0 = open("/dev/null", O_RDONLY);
129 int fd1 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
130 int fd2 = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
132 if (fd0 != STDIN_FILENO || fd1 != STDOUT_FILENO || fd2 != STDERR_FILENO)
134 DLT_LOG(AudioManager, DLT_LOG_ERROR, DLT_STRING("new standard file descriptors were not opened"));
138 void parseCommandLine(int argc, char **argv)
140 while (optind < argc)
142 int option = getopt(argc, argv, "h::v::c::l::r::L::R::d::t::m::i::p::");
147 printf("Current settings:\n");
148 printf("\tAudioManagerDaemon Version:\t\t%s\n", DAEMONVERSION);
149 printf("\tTelnet portNumber:\t\t\t%i\n", telnetport);
150 printf("\tTelnet maxConnections:\t\t\t%i\n", maxConnections);
151 printf("\tSqlite Database path:\t\t\t%s\n", databasePath.c_str());
152 printf("\tControllerPlugin: \t\t\t%s\n", controllerPlugin.c_str());
153 printf("\tDirectory of CommandPlugins: \t\t%s\n", listCommandPluginDirs.front().c_str());
154 printf("\tDirectory of RoutingPlugins: \t\t%s\n", listRoutingPluginDirs.front().c_str());
158 assert(atoi(optarg)!=0);
159 telnetport = atoi(optarg);
162 assert(atoi(optarg)!=0);
163 maxConnections = atoi(optarg);
166 assert(!controllerPlugin.empty());
167 databasePath = std::string(optarg);
173 listCommandPluginDirs.clear();
174 listCommandPluginDirs.push_back(std::string(optarg));
177 listRoutingPluginDirs.clear();
178 listRoutingPluginDirs.push_back(std::string(optarg));
181 listCommandPluginDirs.push_back(std::string(optarg));
184 listRoutingPluginDirs.push_back(std::string(optarg));
187 controllerPlugin = std::string(optarg);
188 assert(!controllerPlugin.empty());
189 assert(controllerPlugin.find(".so")!=std::string::npos);
192 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
197 printf("AudioManagerDaemon Version: %s\n", DAEMONVERSION);
198 puts(USAGE_DESCRIPTION);
204 static void signalHandler(int sig, siginfo_t *siginfo, void *context)
209 DLT_LOG(AudioManager, DLT_LOG_ERROR, DLT_STRING("signal handler was called, exit now..."));
211 //todo: maually fire the mainloop
212 //todo: ifdef no sockethandler
216 int main(int argc, char *argv[])
218 DLT_REGISTER_APP("AudioManagerDeamon", "AudioManagerDeamon");
219 DLT_REGISTER_CONTEXT(AudioManager, "Main", "Main Context");
220 DLT_LOG(AudioManager, DLT_LOG_INFO, DLT_STRING("The AudioManager is started, "), DLT_STRING(DAEMONVERSION));
222 listCommandPluginDirs.push_back(std::string(DEFAULT_PLUGIN_COMMAND_DIR));
223 listRoutingPluginDirs.push_back(std::string(DEFAULT_PLUGIN_ROUTING_DIR));
225 //parse the commandline options
226 parseCommandLine(argc, (char**) argv);
228 //now the signal handler:
229 struct sigaction signalAction;
230 memset(&signalAction, '\0', sizeof(signalAction));
231 signalAction.sa_sigaction = &signalHandler;
232 signalAction.sa_flags = SA_SIGINFO;
233 sigaction(SIGINT, &signalAction, NULL);
234 sigaction(SIGQUIT, &signalAction, NULL);
235 sigaction(SIGTERM, &signalAction, NULL);
236 sigaction(SIGHUP, &signalAction, NULL);
237 sigaction(SIGQUIT, &signalAction, NULL);
239 struct sigaction signalChildAction;
240 memset(&signalChildAction, '\0', sizeof(signalChildAction));
241 signalChildAction.sa_flags = SA_NOCLDWAIT;
242 sigaction(SIGCHLD, &signalChildAction, NULL);
244 //Instantiate all classes. Keep in same order !
245 #ifdef WITH_SOCKETHANDLER_LOOP
246 SocketHandler iSocketHandler;
249 #ifdef WITH_DBUS_WRAPPER
250 #ifdef WITH_SOCKETHANDLER_LOOP
251 DBusWrapper iDBusWrapper(&iSocketHandler);
252 #else /*WITH_SOCKETHANDLER_LOOP*/
253 DBusWrapper iDBusWrapper;
254 #endif /*WITH_SOCKETHANDLER_LOOP*/
255 #endif /*WITH_DBUS_WRAPPER */
257 DatabaseHandler iDatabaseHandler(databasePath);
258 RoutingSender iRoutingSender(listRoutingPluginDirs);
259 CommandSender iCommandSender(listCommandPluginDirs);
260 ControlSender iControlSender(controllerPlugin);
262 #ifdef WITH_DBUS_WRAPPER
263 #ifdef WITH_SOCKETHANDLER_LOOP
264 CommandReceiver iCommandReceiver(&iDatabaseHandler, &iControlSender, &iSocketHandler, &iDBusWrapper);
265 RoutingReceiver iRoutingReceiver(&iDatabaseHandler, &iRoutingSender, &iControlSender, &iSocketHandler, &iDBusWrapper);
266 ControlReceiver iControlReceiver(&iDatabaseHandler, &iRoutingSender, &iCommandSender, &iSocketHandler);
268 TelnetServer iTelnetServer(&iSocketHandler,&iCommandSender,&iCommandReceiver,&iRoutingSender,&iRoutingReceiver,&iControlSender,&iControlReceiver,&iDatabaseHandler,telnetport,maxConnections);
270 #else /*WITH_SOCKETHANDLER_LOOP */
271 CommandReceiver iCommandReceiver(&iDatabaseHandler,&iControlSender,&iDBusWrapper);
272 RoutingReceiver iRoutingReceiver(&iDatabaseHandler,&iRoutingSender,&iControlSender,&iDBusWrapper);
273 ControlReceiver iControlReceiver(&iDatabaseHandler,&iRoutingSender,&iCommandSender);
274 #endif /*WITH_SOCKETHANDLER_LOOP*/
275 #else /*WITH_DBUS_WRAPPER*/
276 CommandReceiver iCommandReceiver(&iDatabaseHandler,&iControlSender,&iSocketHandler);
277 RoutingReceiver iRoutingReceiver(&iDatabaseHandler,&iRoutingSender,&iControlSender,&iSocketHandler);
278 ControlReceiver iControlReceiver(&iDatabaseHandler,&iRoutingSender,&iCommandSender,&iSocketHandler);
280 TelnetServer iTelnetServer(&iSocketHandler,telnetport,maxConnections);
282 #endif /*WITH_DBUS_WRAPPER*/
285 DatabaseObserver iObserver(&iCommandSender, &iRoutingSender,&iTelnetServer);
287 DatabaseObserver iObserver(&iCommandSender, &iRoutingSender);
290 //since the plugins have been loaded by the *Senders before, we can tell the Controller this:
291 iControlSender.hookAllPluginsLoaded();
293 //the controller should startup the interfaces - this is just for testing
294 iCommandSender.startupInterface(&iCommandReceiver);
295 iRoutingSender.startupRoutingInterface(&iRoutingReceiver);
296 iRoutingSender.routingInterfacesReady();
298 #ifdef WITH_SOCKETHANDLER_LOOP
299 iSocketHandler.start_listenting();
300 #endif /*WITH_SOCKETHANDLER_LOOP*/
302 #ifdef WITH_DBUS_WRAPPER
303 #ifdef WITH_SIMPLEDBUS_LOOP
304 iDBusWrapper.dbusMainLoop();
305 #endif/*WITH_SIMPLEDBUS_LOOP*/
306 #endif /*WITH_DBUS_WRAPPER*/