bool init(InitOptions options, int & retval) { init_options = new InitOptions(options); if (init_options->show_help()) return true; if ( options.daemonize() ) { fawkes::daemon::init(options.daemon_pid_file(), options.basename()); if (options.daemonize_kill()) { fawkes::daemon::kill(); retval = 0; return false; } else if (options.daemonize_status()) { retval = fawkes::daemon::running() ? 0 : 1; return false; } else { if (fawkes::daemon::start()) { retval = 0; return false; } } } // *** set user group if requested const char *user = NULL; const char *group = NULL; if (options.has_username()) { user = options.username(); } if (options.has_groupname()) { group = options.groupname(); } if (user != NULL) { struct passwd *pw; if (! (pw = getpwnam(user))) { printf("Failed to find user %s, check -u argument.\n", user); retval = 203; return false; } int r = 0; r = setreuid(pw->pw_uid, pw->pw_uid); if (r < 0) { perror("Failed to drop privileges (user)"); } } if (group != NULL) { struct group *gr; if (! (gr = getgrnam(group))) { printf("Failed to find group %s, check -g argument.\n", user); retval = 204; return false; } int r = 0; r = setregid(gr->gr_gid, gr->gr_gid); if (r < 0) { perror("Failed to drop privileges (group)"); } } // *** setup base thread and shm registry Thread::init_main(); shm_registry = NULL; struct passwd *uid_pw = getpwuid(getuid()); if (uid_pw == NULL) { shm_registry = new SharedMemoryRegistry(); } else { char *registry_name; if (asprintf(®istry_name, USER_SHM_NAME, uid_pw->pw_name) == -1) { shm_registry = new SharedMemoryRegistry(); } else { shm_registry = new SharedMemoryRegistry(registry_name); free(registry_name); } } if (! shm_registry) { throw Exception("Failed to create shared memory registry"); } // *** setup logging if (options.has_loggers()) { try { logger = LoggerFactory::multilogger_instance(options.loggers()); } catch (Exception &e) { e.append("Initializing multi logger failed"); throw; } } else { logger = new MultiLogger(new ConsoleLogger()); } logger->set_loglevel(options.log_level()); LibLogger::init(logger); // *** Prepare home dir directory, just in case const char *homedir = getenv("HOME"); if (homedir) { char *userdir; if (asprintf(&userdir, "%s/%s", homedir, USERDIR) != -1) { if (access(userdir, W_OK) != 0) { if (mkdir(userdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) { logger->log_warn("FawkesMainThread", "Failed to create .fawkes " "directory %s, trying without", userdir); } } free(userdir); } } // *** setup config SQLiteConfiguration *sqconfig = NULL; if (options.config_file() && fnmatch("*.sql", options.config_file(), FNM_PATHNAME) == 0) { sqconfig = new SQLiteConfiguration(CONFDIR); config = sqconfig; } else { config = new YamlConfiguration(CONFDIR); } config->load(options.config_file()); if (sqconfig) { try { SQLiteConfiguration::SQLiteValueIterator *i = sqconfig->modified_iterator(); while (i->next()) { std::string modtype = i->get_modtype(); if (modtype == "changed") { logger->log_warn("FawkesMainThread", "Default config value CHANGED: %s" "(was: %s now: %s)", i->path(), i->get_oldvalue().c_str(), i->get_as_string().c_str()); } else if (modtype == "erased") { logger->log_warn("FawkesMainThread", "Default config value ERASED: %s", i->path()); } else { logger->log_debug("FawkesMainThread", "Default config value ADDED: %s " "(value: %s)", i->path(), i->get_as_string().c_str()); } } delete i; } catch (Exception &e) { logger->log_warn("FawkesMainThread", "Failed to read modified default " "config values, no dump?"); } } if (! options.has_loggers()) { // Allow configuration override from config if (config->exists("/fawkes/mainapp/loggers")) { try { std::string loggers = config->get_string("/fawkes/mainapp/loggers"); MultiLogger *new_logger = LoggerFactory::multilogger_instance(loggers.c_str(), options.log_level()); logger = new_logger; LibLogger::finalize(); LibLogger::init(new_logger); } catch (Exception &e) { logger->log_warn("FawkesMainThread", "Loggers set in config file, " "but failed to read, exception follows."); logger->log_warn("FawkesMainThread", e); } } } if (config->exists("/fawkes/mainapp/log_stderr_as_warn")) { try { bool log_stderr_as_warn = config->get_bool("/fawkes/mainapp/log_stderr_as_warn"); if (log_stderr_as_warn) { #ifdef HAVE_LOGGING_FD_REDIRECT log_fd_redirect_stderr_ = new LogFileDescriptorToLog(STDERR_FILENO, logger, "stderr", Logger::LL_WARN); #else logger->log_warn("FawkesMainThread", "stderr log redirection enabled but not available at compile time"); #endif } } catch (Exception &e) {} // ignored } // *** Determine network parameters bool enable_ipv4 = true; bool enable_ipv6 = true; std::string listen_ipv4; std::string listen_ipv6; unsigned int net_tcp_port = 1910; std::string net_service_name = "Fawkes on %h"; if (options.has_net_tcp_port()) { net_tcp_port = options.net_tcp_port(); } else { try { net_tcp_port = config->get_uint("/network/fawkes/tcp_port"); } catch (Exception &e) {} // ignore, we stick with the default } if (options.has_net_service_name()) { net_service_name = options.net_service_name(); } else { try { net_service_name = config->get_string("/network/fawkes/service_name"); } catch (Exception &e) {} // ignore, we stick with the default } if (net_tcp_port > 65535) { logger->log_warn("FawkesMainThread", "Invalid port '%u', using 1910", net_tcp_port); net_tcp_port = 1910; } try { enable_ipv4 = config->get_bool("/network/ipv4/enable"); } catch (Exception &e) {} // ignore, we stick with the default try { enable_ipv6 = config->get_bool("/network/ipv6/enable"); } catch (Exception &e) {} // ignore, we stick with the default try { listen_ipv4 = config->get_string("/network/ipv4/listen"); } catch (Exception &e) {} // ignore, we stick with the default try { listen_ipv6 = config->get_string("/network/ipv6/listen"); } catch (Exception &e) {} // ignore, we stick with the default if (! enable_ipv4) { logger->log_warn("FawkesMainThread", "Disabling IPv4 support"); } if (! enable_ipv6) { logger->log_warn("FawkesMainThread", "Disabling IPv6 support"); } if (! listen_ipv4.empty()) { logger->log_info("FawkesMainThread", "Listening on IPv4 address %s", listen_ipv4.c_str()); } if (! listen_ipv6.empty()) { logger->log_info("FawkesMainThread", "Listening on IPv6 address %s", listen_ipv4.c_str()); } // *** Setup blackboard std::string bb_magic_token = ""; unsigned int bb_size = 2097152; try { bb_magic_token = config->get_string("/fawkes/mainapp/blackboard_magic_token"); logger->log_info("FawkesMainApp", "BlackBoard magic token defined. " "Using shared memory BlackBoard."); } catch (Exception &e) { // ignore } try { bb_size = config->get_uint("/fawkes/mainapp/blackboard_size"); } catch (Exception &e) { logger->log_warn("FawkesMainApp", "BlackBoard size not defined. " "Will use %u, saving to default DB", bb_size); config->set_default_uint("/fawkes/mainapp/blackboard_size", bb_size); } // Cleanup stale BlackBoard shared memory segments if requested if ( options.bb_cleanup()) { LocalBlackBoard::cleanup(bb_magic_token.c_str(), /* output with lister? */ true); SharedMemoryRegistry::cleanup(); } LocalBlackBoard *lbb = NULL; if ( bb_magic_token == "") { lbb = new LocalBlackBoard(bb_size); } else { lbb = new LocalBlackBoard(bb_size, bb_magic_token.c_str()); } blackboard = lbb; #ifdef HAVE_TF tf_transformer = new tf::Transformer(); tf_listener = new tf::TransformListener(blackboard, tf_transformer); #endif aspect_manager = new AspectManager(); thread_manager = new ThreadManager(aspect_manager, aspect_manager); plugin_manager = new PluginManager(thread_manager, config, "/fawkes/meta_plugins/", options.plugin_module_flags(), options.init_plugin_cache()); network_manager = new FawkesNetworkManager(thread_manager, enable_ipv4, enable_ipv6, listen_ipv4, listen_ipv6, net_tcp_port, net_service_name.c_str()); nethandler_config = new ConfigNetworkHandler(config, network_manager->hub()); nethandler_plugin = new PluginNetworkHandler(plugin_manager, network_manager->hub()); nethandler_plugin->start(); network_logger = new NetworkLogger(network_manager->hub(), logger->loglevel()); logger->add_logger(network_logger); clock = Clock::instance(); start_time = new Time(clock); lbb->start_nethandler(network_manager->hub()); // *** Create main thread, but do not start, yet main_thread = new fawkes::FawkesMainThread(config, logger, thread_manager, plugin_manager, options.load_plugin_list(), options.default_plugin()); aspect_manager->register_default_inifins(blackboard, thread_manager->aspect_collector(), config, logger, clock, network_manager->hub(), main_thread, logger, thread_manager, network_manager->nnresolver(), network_manager->service_publisher(), network_manager->service_browser(), plugin_manager, tf_transformer); retval = 0; return true; }
int main(int argc, char **argv) { signal(SIGINT, signal_handler); LocalBlackBoard *llbb = new LocalBlackBoard(BLACKBOARD_MEMSIZE); BlackBoard *lbb = llbb; FawkesNetworkServerThread *fns = new FawkesNetworkServerThread(1910); fns->start(); llbb->start_nethandler(fns); BlackBoard *rbb = new RemoteBlackBoard("localhost", 1910); InterfaceInfoList *infl = rbb->list_all(); for (InterfaceInfoList::iterator i = infl->begin(); i != infl->end(); ++i) { const unsigned char *hash = (*i).hash(); char phash[__INTERFACE_HASH_SIZE * 2 + 1]; memset(phash, 0, sizeof(phash)); for (unsigned int j = 0; j < __INTERFACE_HASH_SIZE; ++j) { sprintf(&phash[j * 2], "%02x", hash[j]); } printf("%s::%s (%s), w:%i r:%u s:%u\n", (*i).type(), (*i).id(), phash, (*i).has_writer(), (*i).num_readers(), (*i).serial()); } delete infl; //TestInterface *ti_writer; TestInterface *ti_reader; TestInterface *ti_writer; try { cout << "Opening interfaces.. " << flush; ti_writer = rbb->open_for_writing<TestInterface>("SomeID"); ti_reader = rbb->open_for_reading<TestInterface>("SomeID"); cout << "success, " << "writer hash=" << ti_writer->hash_printable() << " reader hash=" << ti_reader->hash_printable() << endl; } catch (Exception &e) { cout << "failed! Aborting" << endl; e.print_trace(); exit(1); } try { cout << "Trying to open second writer.. " << flush; TestInterface *ti_writer_two; ti_writer_two = rbb->open_for_writing<TestInterface>("SomeID"); cout << "BUG: Detection of second writer did NOT work!" << endl; exit(2); } catch (BlackBoardWriterActiveException &e) { cout << "exception caught as expected, detected and prevented second writer!" << endl; } try { cout << "Trying to open third writer.. " << flush; TestInterface *ti_writer_three; ti_writer_three = rbb->open_for_writing<TestInterface>("AnotherID"); cout << "No exception as expected, different ID ok!" << endl; rbb->close(ti_writer_three); } catch (BlackBoardWriterActiveException &e) { cout << "BUG: Third writer with different ID detected as another writer!" << endl; exit(3); } cout << endl << endl << "Running data tests ==================================================" << endl; cout << "Writing initial value (" << TestInterface::TEST_CONSTANT << ") into interface as TestInt" << endl; ti_writer->set_test_int( TestInterface::TEST_CONSTANT ); try { ti_writer->write(); } catch (InterfaceWriteDeniedException &e) { cout << "BUG: caught write denied exception" << endl; e.print_trace(); } cout << "Giving some time to have value processed" << endl; usleep(100000); cout << "Reading value from reader interface.. " << flush; ti_reader->read(); int val = ti_reader->test_int(); if ( val == TestInterface::TEST_CONSTANT ) { cout << " success, value is " << ti_reader->test_int() << " as expected" << endl; } else { cout << " failure, value is " << ti_reader->test_int() << ", expected " << TestInterface::TEST_CONSTANT << endl; } cout << "Closing interfaces.. " << flush; try { rbb->close(ti_reader); rbb->close(ti_writer); cout << "done" << endl; } catch (Exception &e) { cout << "failed" << endl; e.print_trace(); } cout << endl << endl << "Starting MESSAGING tests" << endl << "Press Ctrl-C to continue with next test" << endl << endl; ti_writer = lbb->open_for_writing<TestInterface>("Messaging"); ti_reader = rbb->open_for_reading<TestInterface>("Messaging"); printf("Writer serial: %u shifted: %u\n", ti_writer->serial(), ti_writer->serial() << 16); printf("Reader serial: %u shifted: %u\n", ti_reader->serial(), ti_reader->serial() << 16); test_messaging(ti_reader, ti_writer); rbb->close(ti_reader); lbb->close(ti_writer); cout << endl << endl << "Starting MESSAGING tests, doing repeater scenario" << endl << "Press Ctrl-C to continue with next test" << endl << endl; quit = false; delete rbb; LocalBlackBoard *repllbb = new LocalBlackBoard(BLACKBOARD_MEMSIZE); FawkesNetworkServerThread *repfns = new FawkesNetworkServerThread(1911); repfns->start(); repllbb->start_nethandler(repfns); BlackBoard *rep_rbb = new RemoteBlackBoard("localhost", 1911); rbb = new RemoteBlackBoard("localhost", 1911); TestInterface *rep_reader; TestInterface *rep_writer; ti_writer = rbb->open_for_writing<TestInterface>("Messaging"); ti_reader = lbb->open_for_reading<TestInterface>("Messaging"); rep_reader = rep_rbb->open_for_reading<TestInterface>("Messaging"); rep_writer = lbb->open_for_writing<TestInterface>("Messaging"); printf("Writer serial: %u shifted: %u\n", ti_writer->serial(), ti_writer->serial() << 16); printf("Reader serial: %u shifted: %u\n", ti_reader->serial(), ti_reader->serial() << 16); SyncInterfaceListener *sil = new SyncInterfaceListener(rep_reader, rep_writer, rep_rbb, lbb); test_messaging(ti_reader, ti_writer); delete sil; lbb->close(ti_reader); rbb->close(ti_writer); rep_rbb->close(rep_reader); lbb->close(rep_writer); delete repllbb; delete rep_rbb; cout << "Tests done" << endl; delete rbb; delete llbb; delete fns; }