Example #1
0
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(&registry_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;
}
Example #2
0
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;
}