00001 #include "config.h"
00002 #include "Configuration.h"
00003 #include "ibrdtn/utils/Utils.h"
00004 #include "core/Node.h"
00005 #include "ibrcommon/net/NetInterface.h"
00006 #include <ibrcommon/Logger.h>
00007 #include "net/DiscoveryAnnouncement.h"
00008
00009 using namespace dtn::net;
00010 using namespace dtn::core;
00011 using namespace dtn::utils;
00012 using namespace ibrcommon;
00013
00014 namespace dtn
00015 {
00016 namespace daemon
00017 {
00018 Configuration::NetConfig::NetConfig(std::string n, NetType t, const ibrcommon::NetInterface &i, int p, bool d)
00019 : name(n), type(t), interface(i), port(p), discovery(d)
00020 {
00021 }
00022
00023 Configuration::NetConfig::NetConfig(std::string n, NetType t, const std::string &a, int p, bool d)
00024 : name(n), type(t), interface("lo"), address(a), port(p), discovery(d)
00025 {
00026 }
00027
00028 Configuration::NetConfig::~NetConfig()
00029 {
00030 }
00031
00032 std::string Configuration::version()
00033 {
00034 std::stringstream ss;
00035 ss << PACKAGE_VERSION;
00036 #ifdef SVN_REVISION
00037 ss << " (build " << SVN_REVISION << ")";
00038 #endif
00039
00040 return ss.str();
00041 }
00042
00043 Configuration::Configuration()
00044 : _filename("config.ini"), _doapi(true)
00045 {
00046 }
00047
00048 Configuration::~Configuration()
00049 {}
00050
00051 Configuration::Discovery::Discovery()
00052 : _enabled(true), _timeout(5) {};
00053
00054 Configuration::Statistic::Statistic() {};
00055
00056 Configuration::Debug::Debug()
00057 : _enabled(false), _quiet(false), _level(0) {};
00058
00059 Configuration::Logger::Logger()
00060 : _quiet(false), _options(0) {};
00061
00062 Configuration::Network::Network()
00063 : _routing("default"), _forwarding(true), _tcp_nodelay(true), _tcp_chunksize(1024), _default_net("lo"), _use_default_net(false) {};
00064
00065 Configuration::Discovery::~Discovery() {};
00066 Configuration::Statistic::~Statistic() {};
00067 Configuration::Debug::~Debug() {};
00068 Configuration::Logger::~Logger() {};
00069 Configuration::Network::~Network() {};
00070
00071 const Configuration::Discovery& Configuration::getDiscovery() const
00072 {
00073 return _disco;
00074 }
00075
00076 const Configuration::Statistic& Configuration::getStatistic() const
00077 {
00078 return _stats;
00079 }
00080
00081 const Configuration::Debug& Configuration::getDebug() const
00082 {
00083 return _debug;
00084 }
00085
00086 const Configuration::Logger& Configuration::getLogger() const
00087 {
00088 return _logger;
00089 }
00090
00091 const Configuration::Network& Configuration::getNetwork() const
00092 {
00093 return _network;
00094 }
00095
00096 Configuration& Configuration::getInstance()
00097 {
00098 static Configuration conf;
00099 return conf;
00100 }
00101
00102 void Configuration::params(int argc, char *argv[])
00103 {
00104 for (int i = 0; i < argc; i++)
00105 {
00106 std::string arg = argv[i];
00107
00108 if (arg == "-c" && argc > i)
00109 {
00110 _filename = argv[i + 1];
00111 }
00112
00113 if (arg == "-i" && argc > i)
00114 {
00115 _network._default_net = ibrcommon::NetInterface(argv[i + 1]);
00116 _network._use_default_net = true;
00117 }
00118
00119 if (arg == "--noapi")
00120 {
00121 _doapi = false;
00122 }
00123
00124 if ((arg == "--version") || (arg == "-v"))
00125 {
00126 std::cout << "IBR-DTN version: " << version() << std::endl;
00127 exit(0);
00128 }
00129
00130 if (arg == "--nodiscovery")
00131 {
00132 _disco._enabled = false;
00133 }
00134
00135 if (arg == "-d")
00136 {
00137 _debug._enabled = true;
00138 _debug._level = atoi(argv[i + 1]);
00139 }
00140
00141 if (arg == "-q")
00142 {
00143 _debug._quiet = true;
00144 }
00145
00146 if ((arg == "--help") || (arg == "-h"))
00147 {
00148 std::cout << "IBR-DTN version: " << version() << std::endl;
00149 std::cout << "Syntax: dtnd [options]" << std::endl;
00150 std::cout << " -h|--help display this text" << std::endl;
00151 std::cout << " -c <file> set a configuration file" << std::endl;
00152 std::cout << " -i <interface> interface to bind on (e.g. eth0)" << std::endl;
00153 std::cout << " -d <level> enable debugging and set a verbose level" << std::endl;
00154 std::cout << " -q enables the quiet mode (no logging to the console)" << std::endl;
00155 std::cout << " --noapi disable API module" << std::endl;
00156 std::cout << " --nodiscovery disable discovery module" << std::endl;
00157 exit(0);
00158 }
00159 }
00160 }
00161
00162 void Configuration::load()
00163 {
00164 load(_filename);
00165 }
00166
00167 void Configuration::load(string filename)
00168 {
00169 try {
00170
00171 _conf = ibrcommon::ConfigFile(filename);
00172
00173 IBRCOMMON_LOGGER(info) << "Configuration: " << filename << IBRCOMMON_LOGGER_ENDL;
00174 } catch (ibrcommon::ConfigFile::file_not_found ex) {
00175 IBRCOMMON_LOGGER(info) << "Using default settings. Call with --help for options." << IBRCOMMON_LOGGER_ENDL;
00176 _conf = ConfigFile();
00177 }
00178
00179
00180 _disco.load(_conf);
00181 _stats.load(_conf);
00182 _debug.load(_conf);
00183 _logger.load(_conf);
00184 _network.load(_conf);
00185 }
00186
00187 void Configuration::Discovery::load(const ibrcommon::ConfigFile &conf)
00188 {
00189 _timeout = conf.read<unsigned int>("discovery_timeout", 5);
00190 }
00191
00192 void Configuration::Statistic::load(const ibrcommon::ConfigFile&)
00193 {
00194 }
00195
00196 void Configuration::Logger::load(const ibrcommon::ConfigFile&)
00197 {
00198 }
00199
00200 void Configuration::Debug::load(const ibrcommon::ConfigFile&)
00201 {
00202 }
00203
00204 bool Configuration::Debug::quiet() const
00205 {
00206 return _quiet;
00207 }
00208
00209 bool Configuration::Debug::enabled() const
00210 {
00211 return _enabled;
00212 }
00213
00214 int Configuration::Debug::level() const
00215 {
00216 return _level;
00217 }
00218
00219 string Configuration::getNodename()
00220 {
00221 try {
00222 return _conf.read<string>("local_uri");
00223 } catch (ibrcommon::ConfigFile::key_not_found ex) {
00224 char *hostname_array = new char[64];
00225 if ( gethostname(hostname_array, 64) != 0 )
00226 {
00227
00228 delete[] hostname_array;
00229 return "local";
00230 }
00231
00232 string hostname(hostname_array);
00233 delete[] hostname_array;
00234
00235 stringstream ss;
00236 ss << "dtn://" << hostname;
00237 ss >> hostname;
00238
00239 return hostname;
00240 }
00241 }
00242
00243 const std::list<Configuration::NetConfig>& Configuration::Network::getInterfaces() const
00244 {
00245 return _interfaces;
00246 }
00247
00248 std::string Configuration::Discovery::address() const throw (ParameterNotFoundException)
00249 {
00250 try {
00251 return Configuration::getInstance()._conf.read<string>("discovery_address");
00252 } catch (ConfigFile::key_not_found ex) {
00253 throw ParameterNotFoundException();
00254 }
00255 }
00256
00257 int Configuration::Discovery::port() const
00258 {
00259 return Configuration::getInstance()._conf.read<int>("discovery_port", 4551);
00260 }
00261
00262 unsigned int Configuration::Discovery::timeout() const
00263 {
00264 return _timeout;
00265 }
00266
00267 Configuration::NetConfig Configuration::getAPIInterface()
00268 {
00269
00270 return Configuration::NetConfig("local", Configuration::NetConfig::NETWORK_TCP, ibrcommon::NetInterface("lo"), 4550);
00271
00272
00273
00274 }
00275
00276 ibrcommon::File Configuration::getAPISocket()
00277 {
00278 try {
00279 return ibrcommon::File(_conf.read<std::string>("api_socket"));
00280 } catch (const ConfigFile::key_not_found&) {
00281 throw ParameterNotSetException();
00282 }
00283 }
00284
00285 std::string Configuration::getStorage() const
00286 {
00287 return _conf.read<std::string>("storage", "default");
00288 }
00289
00290 void Configuration::Network::load(const ibrcommon::ConfigFile &conf)
00291 {
00295 _static_routes.clear();
00296
00297 string key = "route1";
00298 unsigned int keynumber = 1;
00299
00300 while (conf.keyExists( key ))
00301 {
00302 vector<string> route = dtn::utils::Utils::tokenize(" ", conf.read<string>(key, "dtn:none dtn:none"));
00303 _static_routes.push_back( dtn::routing::StaticRoutingExtension::StaticRoute( route.front(), route.back() ) );
00304
00305 keynumber++;
00306 stringstream ss; ss << "route" << keynumber; ss >> key;
00307 }
00308
00312
00313 int count = 1;
00314
00315
00316 std::string prefix = "static1_";
00317
00318 while ( conf.keyExists(prefix + "uri") )
00319 {
00320 Node n(Node::NODE_PERMANENT);
00321
00322 n.setAddress( conf.read<std::string>(prefix + "address", "127.0.0.1") );
00323 n.setPort( conf.read<unsigned int>(prefix + "port", 4556) );
00324 n.setURI( conf.read<std::string>(prefix + "uri", "dtn:none") );
00325
00326 std::string protocol = conf.read<std::string>(prefix + "proto", "tcp");
00327 if (protocol == "tcp") n.setProtocol(Node::CONN_TCPIP);
00328 if (protocol == "udp") n.setProtocol(Node::CONN_UDPIP);
00329 if (protocol == "zigbee") n.setProtocol(Node::CONN_ZIGBEE);
00330 if (protocol == "bluetooth") n.setProtocol(Node::CONN_BLUETOOTH);
00331 if (protocol == "http") n.setProtocol(Node::CONN_HTTP);
00332
00333 count++;
00334
00335 std::stringstream prefix_stream;
00336 prefix_stream << "static" << count << "_";
00337 prefix = prefix_stream.str();
00338
00339 _nodes.push_back(n);
00340 }
00341
00345 _routing = conf.read<string>("routing", "default");
00346
00350 _forwarding = (conf.read<std::string>("routing_forwarding", "yes") == "yes");
00351
00355 _interfaces.clear();
00356
00357 if (_use_default_net)
00358 {
00359 _interfaces.push_back( Configuration::NetConfig("default", Configuration::NetConfig::NETWORK_TCP, _default_net, 4556) );
00360 }
00361 else try
00362 {
00363 vector<string> nets = dtn::utils::Utils::tokenize(" ", conf.read<string>("net_interfaces") );
00364 for (vector<string>::const_iterator iter = nets.begin(); iter != nets.end(); iter++)
00365 {
00366 std::string netname = (*iter);
00367
00368 std::string key_type = "net_" + netname + "_type";
00369 std::string key_port = "net_" + netname + "_port";
00370 std::string key_interface = "net_" + netname + "_interface";
00371 std::string key_address = "net_" + netname + "_address";
00372 std::string key_discovery = "net_" + netname + "_discovery";
00373
00374 std::string type_name = conf.read<string>(key_type, "tcp");
00375 Configuration::NetConfig::NetType type = Configuration::NetConfig::NETWORK_UNKNOWN;
00376
00377 if (type_name == "tcp") type = Configuration::NetConfig::NETWORK_TCP;
00378 if (type_name == "udp") type = Configuration::NetConfig::NETWORK_UDP;
00379 if (type_name == "http") type = Configuration::NetConfig::NETWORK_HTTP;
00380 if (type_name == "lowpan") type = Configuration::NetConfig::NETWORK_LOWPAN;
00381
00382 switch (type)
00383 {
00384 case Configuration::NetConfig::NETWORK_HTTP:
00385 {
00386 Configuration::NetConfig::NetConfig nc(netname, type,
00387 conf.read<std::string>(key_address, "http://localhost/"), 0,
00388 conf.read<std::string>(key_discovery, "yes") == "no");
00389
00390 _interfaces.push_back(nc);
00391 break;
00392 }
00393
00394 default:
00395 {
00396 Configuration::NetConfig::NetConfig nc(netname, type,
00397 ibrcommon::NetInterface(conf.read<std::string>(key_interface, "lo")),
00398 conf.read<unsigned int>(key_port, 4556),
00399 conf.read<std::string>(key_discovery, "yes") == "yes");
00400
00401 _interfaces.push_back(nc);
00402 break;
00403 }
00404 }
00405 }
00406 } catch (ConfigFile::key_not_found ex) {
00407
00408 }
00409
00413 _tcp_nodelay = (conf.read<std::string>("tcp_nodelay", "yes") == "yes");
00414 _tcp_chunksize = conf.read<unsigned int>("tcp_chunksize", 1024);
00415 }
00416
00417 const list<dtn::routing::StaticRoutingExtension::StaticRoute>& Configuration::Network::getStaticRoutes() const
00418 {
00419 return _static_routes;
00420 }
00421
00422 const std::list<Node>& Configuration::Network::getStaticNodes() const
00423 {
00424 return _nodes;
00425 }
00426
00427 int Configuration::getTimezone()
00428 {
00429 return _conf.read<int>( "timezone", 0 );
00430 }
00431
00432 ibrcommon::File Configuration::getPath(string name)
00433 {
00434 stringstream ss;
00435 ss << name << "_path";
00436 string key; ss >> key;
00437
00438 try {
00439 return ibrcommon::File(_conf.read<string>(key));
00440 } catch (ConfigFile::key_not_found ex) {
00441 throw ParameterNotSetException();
00442 }
00443 }
00444
00445 unsigned int Configuration::getUID()
00446 {
00447 try {
00448 return _conf.read<unsigned int>("user");
00449 } catch (ConfigFile::key_not_found ex) {
00450 throw ParameterNotSetException();
00451 }
00452 }
00453
00454 unsigned int Configuration::getGID()
00455 {
00456 try {
00457 return _conf.read<unsigned int>("group");
00458 } catch (ConfigFile::key_not_found ex) {
00459 throw ParameterNotSetException();
00460 }
00461 }
00462
00463
00464 bool Configuration::Discovery::enabled() const
00465 {
00466 return _enabled;
00467 }
00468
00469 bool Configuration::Discovery::announce() const
00470 {
00471 return (Configuration::getInstance()._conf.read<int>("discovery_announce", 1) == 1);
00472 }
00473
00474 bool Configuration::Discovery::shortbeacon() const
00475 {
00476 return (Configuration::getInstance()._conf.read<int>("discovery_short", 0) == 1);
00477 }
00478
00479 char Configuration::Discovery::version() const
00480 {
00481 return Configuration::getInstance()._conf.read<int>("discovery_version", 2);
00482 }
00483
00484 bool Configuration::doAPI()
00485 {
00486 return _doapi;
00487 }
00488
00489 string Configuration::getNotifyCommand()
00490 {
00491 try {
00492 return _conf.read<string>("notify_cmd");
00493 } catch (ConfigFile::key_not_found ex) {
00494 throw ParameterNotSetException();
00495 }
00496 }
00497
00498 Configuration::RoutingExtension Configuration::Network::getRoutingExtension() const
00499 {
00500 if ( _routing == "epidemic" ) return EPIDEMIC_ROUTING;
00501 if ( _routing == "flooding" ) return FLOOD_ROUTING;
00502 return DEFAULT_ROUTING;
00503 }
00504
00505
00506 bool Configuration::Network::doForwarding() const
00507 {
00508 return _forwarding;
00509 }
00510
00511 bool Configuration::Network::getTCPOptionNoDelay() const
00512 {
00513 return _tcp_nodelay;
00514 }
00515
00516 size_t Configuration::Network::getTCPChunkSize() const
00517 {
00518 return _tcp_chunksize;
00519 }
00520
00521 bool Configuration::Statistic::enabled() const
00522 {
00523 return Configuration::getInstance()._conf.keyExists("statistic_type");
00524 }
00525
00526 ibrcommon::File Configuration::Statistic::logfile() const throw (ParameterNotSetException)
00527 {
00528 try {
00529 return ibrcommon::File(Configuration::getInstance()._conf.read<std::string>("statistic_file"));
00530 } catch (ConfigFile::key_not_found ex) {
00531 throw ParameterNotSetException();
00532 }
00533 }
00534
00535 std::string Configuration::Statistic::type() const
00536 {
00537 return Configuration::getInstance()._conf.read<std::string>("statistic_type", "stdout");
00538 }
00539
00540 unsigned int Configuration::Statistic::interval() const
00541 {
00542 return Configuration::getInstance()._conf.read<unsigned int>("statistic_interval", 300);
00543 }
00544
00545 std::string Configuration::Statistic::address() const
00546 {
00547 return Configuration::getInstance()._conf.read<std::string>("statistic_address", "127.0.0.1");
00548 }
00549
00550 unsigned int Configuration::Statistic::port() const
00551 {
00552 return Configuration::getInstance()._conf.read<unsigned int>("statistic_port", 1234);
00553 }
00554
00555 size_t Configuration::getLimit(std::string suffix)
00556 {
00557 std::string unparsed = _conf.read<std::string>("limit_" + suffix, "0");
00558
00559 std::stringstream ss(unparsed);
00560
00561 float value; ss >> value;
00562 char multiplier = 0; ss >> multiplier;
00563
00564 switch (multiplier)
00565 {
00566 default:
00567 return (size_t)value;
00568 break;
00569
00570 case 'G':
00571 return (size_t)(value * 1000000000);
00572 break;
00573
00574 case 'M':
00575 return (size_t)(value * 1000000);
00576 break;
00577
00578 case 'K':
00579 return (size_t)(value * 1000);
00580 break;
00581 }
00582
00583 return 0;
00584 }
00585
00586 bool Configuration::Logger::quiet() const
00587 {
00588 return _quiet;
00589 }
00590
00591 unsigned int Configuration::Logger::options() const
00592 {
00593 return _options;
00594 }
00595
00596 std::ostream& Configuration::Logger::output() const
00597 {
00598 return std::cout;
00599 }
00600 }
00601 }