diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 13801076..0c2ec5bc 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -192,8 +192,8 @@ verify = true [addressbook] ## AddressBook subscription URL for initial setup -## Default: inr.i2p at "mainline" I2P Network -# defaulturl = http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt +## Default: reg.i2p at "mainline" I2P Network +# defaulturl = http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt ## Optional subscriptions URLs, separated by comma # subscriptions = http://inr.i2p/export/alive-hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 80d56651..ccbfbb1d 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -35,403 +35,406 @@ namespace i2p { - namespace util +namespace util +{ + class Daemon_Singleton::Daemon_Singleton_Private { - class Daemon_Singleton::Daemon_Singleton_Private - { - public: - Daemon_Singleton_Private() {}; - ~Daemon_Singleton_Private() {}; - - std::unique_ptr httpServer; - std::unique_ptr m_I2PControlService; - std::unique_ptr UPnP; - std::unique_ptr m_NTPSync; - }; - - Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {} - Daemon_Singleton::~Daemon_Singleton() { - delete &d; - } - - bool Daemon_Singleton::IsService () const - { - bool service = false; + public: + Daemon_Singleton_Private() {}; + ~Daemon_Singleton_Private() {}; + + std::unique_ptr httpServer; + std::unique_ptr m_I2PControlService; + std::unique_ptr UPnP; + std::unique_ptr m_NTPSync; + }; + + Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {} + Daemon_Singleton::~Daemon_Singleton() { + delete &d; + } + + bool Daemon_Singleton::IsService () const + { + bool service = false; #ifndef _WIN32 - i2p::config::GetOption("service", service); + i2p::config::GetOption("service", service); #endif - return service; - } + return service; + } - bool Daemon_Singleton::init(int argc, char* argv[]) { - return init(argc, argv, nullptr); - } + bool Daemon_Singleton::init(int argc, char* argv[]) { + return init(argc, argv, nullptr); + } - bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr logstream) - { - i2p::config::Init(); - i2p::config::ParseCmdline(argc, argv); + bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr logstream) + { + i2p::config::Init(); + i2p::config::ParseCmdline(argc, argv); - std::string config; i2p::config::GetOption("conf", config); - std::string datadir; i2p::config::GetOption("datadir", datadir); - i2p::fs::DetectDataDir(datadir, IsService()); - i2p::fs::Init(); + std::string config; i2p::config::GetOption("conf", config); + std::string datadir; i2p::config::GetOption("datadir", datadir); + i2p::fs::DetectDataDir(datadir, IsService()); + i2p::fs::Init(); - datadir = i2p::fs::GetDataDir(); + datadir = i2p::fs::GetDataDir(); - if (config == "") - { - config = i2p::fs::DataDirPath("i2pd.conf"); - if (!i2p::fs::Exists (config)) { - // use i2pd.conf only if exists - config = ""; /* reset */ - } + if (config == "") + { + config = i2p::fs::DataDirPath("i2pd.conf"); + if (!i2p::fs::Exists (config)) { + // use i2pd.conf only if exists + config = ""; /* reset */ } + } - i2p::config::ParseConfig(config); - i2p::config::Finalize(); + i2p::config::ParseConfig(config); + i2p::config::Finalize(); - i2p::config::GetOption("daemon", isDaemon); + i2p::config::GetOption("daemon", isDaemon); - std::string logs = ""; i2p::config::GetOption("log", logs); - std::string logfile = ""; i2p::config::GetOption("logfile", logfile); - std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel); - bool logclftime; i2p::config::GetOption("logclftime", logclftime); + std::string logs = ""; i2p::config::GetOption("log", logs); + std::string logfile = ""; i2p::config::GetOption("logfile", logfile); + std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel); + bool logclftime; i2p::config::GetOption("logclftime", logclftime); - /* setup logging */ - if (logclftime) - i2p::log::Logger().SetTimeFormat ("[%d/%b/%Y:%H:%M:%S %z]"); + /* setup logging */ + if (logclftime) + i2p::log::Logger().SetTimeFormat ("[%d/%b/%Y:%H:%M:%S %z]"); - if (isDaemon && (logs == "" || logs == "stdout")) - logs = "file"; + if (isDaemon && (logs == "" || logs == "stdout")) + logs = "file"; - i2p::log::Logger().SetLogLevel(loglevel); - if (logstream) { - LogPrint(eLogInfo, "Log: will send messages to std::ostream"); - i2p::log::Logger().SendTo (logstream); - } else if (logs == "file") { - if (logfile == "") - logfile = i2p::fs::DataDirPath("i2pd.log"); - LogPrint(eLogInfo, "Log: will send messages to ", logfile); - i2p::log::Logger().SendTo (logfile); + i2p::log::Logger().SetLogLevel(loglevel); + if (logstream) { + LogPrint(eLogInfo, "Log: will send messages to std::ostream"); + i2p::log::Logger().SendTo (logstream); + } else if (logs == "file") { + if (logfile == "") + logfile = i2p::fs::DataDirPath("i2pd.log"); + LogPrint(eLogInfo, "Log: will send messages to ", logfile); + i2p::log::Logger().SendTo (logfile); #ifndef _WIN32 - } else if (logs == "syslog") { - LogPrint(eLogInfo, "Log: will send messages to syslog"); - i2p::log::Logger().SendTo("i2pd", LOG_DAEMON); + } else if (logs == "syslog") { + LogPrint(eLogInfo, "Log: will send messages to syslog"); + i2p::log::Logger().SendTo("i2pd", LOG_DAEMON); #endif - } else { - // use stdout -- default - } + } else { + // use stdout -- default + } - LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); - LogPrint(eLogDebug, "FS: main config file: ", config); - LogPrint(eLogDebug, "FS: data directory: ", datadir); + LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); + LogPrint(eLogDebug, "FS: main config file: ", config); + LogPrint(eLogDebug, "FS: data directory: ", datadir); - bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); - bool aesni; i2p::config::GetOption("cpuext.aesni", aesni); - bool avx; i2p::config::GetOption("cpuext.avx", avx); - bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt); - i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt); + bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); + bool aesni; i2p::config::GetOption("cpuext.aesni", aesni); + bool avx; i2p::config::GetOption("cpuext.avx", avx); + bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt); + i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt); - int netID; i2p::config::GetOption("netid", netID); - i2p::context.SetNetID (netID); - i2p::context.Init (); + int netID; i2p::config::GetOption("netid", netID); + i2p::context.SetNetID (netID); + i2p::context.Init (); - bool ipv6; i2p::config::GetOption("ipv6", ipv6); - bool ipv4; i2p::config::GetOption("ipv4", ipv4); + bool ipv6; i2p::config::GetOption("ipv6", ipv6); + bool ipv4; i2p::config::GetOption("ipv4", ipv4); #ifdef MESHNET - // manual override for meshnet - ipv4 = false; - ipv6 = true; + // manual override for meshnet + ipv4 = false; + ipv6 = true; #endif - bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); - boost::asio::ip::address_v6 yggaddr; - if (ygg) + bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); + boost::asio::ip::address_v6 yggaddr; + if (ygg) + { + std::string yggaddress; i2p::config::GetOption ("meshnets.yggaddress", yggaddress); + if (!yggaddress.empty ()) { - std::string yggaddress; i2p::config::GetOption ("meshnets.yggaddress", yggaddress); - if (!yggaddress.empty ()) + yggaddr = boost::asio::ip::address_v6::from_string (yggaddress); + if (yggaddr.is_unspecified () || !i2p::util::net::IsYggdrasilAddress (yggaddr) || + !i2p::util::net::IsLocalAddress (yggaddr)) { - yggaddr = boost::asio::ip::address_v6::from_string (yggaddress); - if (yggaddr.is_unspecified () || !i2p::util::net::IsYggdrasilAddress (yggaddr) || - !i2p::util::net::IsLocalAddress (yggaddr)) - { - LogPrint(eLogWarning, "Daemon: Can't find Yggdrasil address ", yggaddress); - ygg = false; - } + LogPrint(eLogWarning, "Daemon: Can't find Yggdrasil address ", yggaddress); + ygg = false; } - else - { - yggaddr = i2p::util::net::GetYggdrasilAddress (); - if (yggaddr.is_unspecified ()) - { - LogPrint(eLogWarning, "Daemon: Yggdrasil is not running. Disabled"); - ygg = false; - } - } - } - - uint16_t port; i2p::config::GetOption("port", port); - if (!i2p::config::IsDefault("port")) - { - LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port); - i2p::context.UpdatePort (port); } - i2p::context.SetSupportsV6 (ipv6); - i2p::context.SetSupportsV4 (ipv4); - i2p::context.SetSupportsMesh (ygg, yggaddr); - - i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later - bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); - if (ntcp2) + else { - bool published; i2p::config::GetOption("ntcp2.published", published); - if (published) + yggaddr = i2p::util::net::GetYggdrasilAddress (); + if (yggaddr.is_unspecified ()) { - uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port); - if (!ntcp2port) ntcp2port = port; // use standard port - i2p::context.PublishNTCP2Address (ntcp2port, true); // publish - if (ipv6) - { - std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr); - auto addr = boost::asio::ip::address_v6::from_string (ipv6Addr); - if (!addr.is_unspecified () && addr != boost::asio::ip::address_v6::any ()) - i2p::context.UpdateNTCP2V6Address (addr); // set ipv6 address if configured - } - if (ygg) - i2p::context.UpdateNTCP2V6Address (yggaddr); + LogPrint(eLogWarning, "Daemon: Yggdrasil is not running. Disabled"); + ygg = false; } - else - i2p::context.PublishNTCP2Address (port, false); // unpublish } + } - bool transit; i2p::config::GetOption("notransit", transit); - i2p::context.SetAcceptsTunnels (!transit); - uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); - SetMaxNumTransitTunnels (transitTunnels); - - bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); - if (isFloodfill) { - LogPrint(eLogInfo, "Daemon: router will be floodfill"); - i2p::context.SetFloodfill (true); - } else { - i2p::context.SetFloodfill (false); - } + uint16_t port; i2p::config::GetOption("port", port); + if (!i2p::config::IsDefault("port")) + { + LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port); + i2p::context.UpdatePort (port); + } + i2p::context.SetSupportsV6 (ipv6); + i2p::context.SetSupportsV4 (ipv4); + i2p::context.SetSupportsMesh (ygg, yggaddr); - /* this section also honors 'floodfill' flag, if set above */ - std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth); - if (bandwidth.length () > 0) + i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later + bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); + if (ntcp2) + { + bool published; i2p::config::GetOption("ntcp2.published", published); + if (published) { - if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X') + uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port); + if (!ntcp2port) ntcp2port = port; // use standard port + i2p::context.PublishNTCP2Address (ntcp2port, true); // publish + if (ipv6) { - i2p::context.SetBandwidth (bandwidth[0]); - LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps"); + std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr); + auto addr = boost::asio::ip::address_v6::from_string (ipv6Addr); + if (!addr.is_unspecified () && addr != boost::asio::ip::address_v6::any ()) + i2p::context.UpdateNTCP2V6Address (addr); // set ipv6 address if configured } - else - { - auto value = std::atoi(bandwidth.c_str()); - if (value > 0) - { - i2p::context.SetBandwidth (value); - LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps"); - } - else - { - LogPrint(eLogInfo, "Daemon: unexpected bandwidth ", bandwidth, ". Set to 'low'"); - i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2); - } + if (ygg) + i2p::context.UpdateNTCP2V6Address (yggaddr); } } - else if (isFloodfill) - { - LogPrint(eLogInfo, "Daemon: floodfill bandwidth set to 'extra'"); - i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1); - } else - { - LogPrint(eLogInfo, "Daemon: bandwidth set to 'low'"); - i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2); - } - - int shareRatio; i2p::config::GetOption("share", shareRatio); - i2p::context.SetShareRatio (shareRatio); + i2p::context.PublishNTCP2Address (port, false); // unpublish + } - std::string family; i2p::config::GetOption("family", family); - i2p::context.SetFamily (family); - if (family.length () > 0) - LogPrint(eLogInfo, "Daemon: family set to ", family); + bool transit; i2p::config::GetOption("notransit", transit); + i2p::context.SetAcceptsTunnels (!transit); + uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); + SetMaxNumTransitTunnels (transitTunnels); - bool trust; i2p::config::GetOption("trust.enabled", trust); - if (trust) - { - LogPrint(eLogInfo, "Daemon: explicit trust enabled"); - std::string fam; i2p::config::GetOption("trust.family", fam); - std::string routers; i2p::config::GetOption("trust.routers", routers); - bool restricted = false; - if (fam.length() > 0) - { - std::set fams; - size_t pos = 0, comma; - do - { - comma = fam.find (',', pos); - fams.insert (fam.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos)); - pos = comma + 1; - } - while (comma != std::string::npos); - i2p::transport::transports.RestrictRoutesToFamilies(fams); - restricted = fams.size() > 0; - } - if (routers.length() > 0) { - std::set idents; - size_t pos = 0, comma; - do - { - comma = routers.find (',', pos); - i2p::data::IdentHash ident; - ident.FromBase64 (routers.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos)); - idents.insert (ident); - pos = comma + 1; - } - while (comma != std::string::npos); - LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routers"); - i2p::transport::transports.RestrictRoutesToRouters(idents); - restricted = idents.size() > 0; - } - if(!restricted) - LogPrint(eLogError, "Daemon: no trusted routers of families specified"); - } - - bool hidden; i2p::config::GetOption("trust.hidden", hidden); - if (hidden) - { - LogPrint(eLogInfo, "Daemon: using hidden mode"); - i2p::data::netdb.SetHidden(true); - } - return true; + bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); + if (isFloodfill) { + LogPrint(eLogInfo, "Daemon: router will be floodfill"); + i2p::context.SetFloodfill (true); } - - bool Daemon_Singleton::start() + else { - i2p::log::Logger().Start(); - LogPrint(eLogInfo, "Daemon: starting NetDB"); - i2p::data::netdb.Start(); - - bool upnp; i2p::config::GetOption("upnp.enabled", upnp); - if (upnp) { - d.UPnP = std::unique_ptr(new i2p::transport::UPnP); - d.UPnP->Start (); - } + i2p::context.SetFloodfill (false); + } - bool nettime; i2p::config::GetOption("nettime.enabled", nettime); - if (nettime) + /* this section also honors 'floodfill' flag, if set above */ + std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth); + if (bandwidth.length () > 0) + { + if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X') { - d.m_NTPSync = std::unique_ptr(new i2p::util::NTPTimeSync); - d.m_NTPSync->Start (); + i2p::context.SetBandwidth (bandwidth[0]); + LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps"); } - - bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); - bool ssu; i2p::config::GetOption("ssu", ssu); - bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved); - LogPrint(eLogInfo, "Daemon: starting Transports"); - if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled"); - if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled"); - - i2p::transport::transports.SetCheckReserved(checkInReserved); - i2p::transport::transports.Start(ntcp2, ssu); - if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2()) - LogPrint(eLogInfo, "Daemon: Transports started"); else { - LogPrint(eLogError, "Daemon: failed to start Transports"); - /** shut down netdb right away */ - i2p::transport::transports.Stop(); - i2p::data::netdb.Stop(); - return false; - } - - bool http; i2p::config::GetOption("http.enabled", http); - if (http) { - std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); - uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); - LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort); - try + auto value = std::atoi(bandwidth.c_str()); + if (value > 0) { - d.httpServer = std::unique_ptr(new i2p::http::HTTPServer(httpAddr, httpPort)); - d.httpServer->Start(); - } - catch (std::exception& ex) + i2p::context.SetBandwidth (value); + LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps"); + } + else { - LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ()); - ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ()); + LogPrint(eLogInfo, "Daemon: unexpected bandwidth ", bandwidth, ". Set to 'low'"); + i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2); } } + } + else if (isFloodfill) + { + LogPrint(eLogInfo, "Daemon: floodfill bandwidth set to 'extra'"); + i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1); + } + else + { + LogPrint(eLogInfo, "Daemon: bandwidth set to 'low'"); + i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2); + } + int shareRatio; i2p::config::GetOption("share", shareRatio); + i2p::context.SetShareRatio (shareRatio); - LogPrint(eLogInfo, "Daemon: starting Tunnels"); - i2p::tunnel::tunnels.Start(); - - LogPrint(eLogInfo, "Daemon: starting Client"); - i2p::client::context.Start (); + std::string family; i2p::config::GetOption("family", family); + i2p::context.SetFamily (family); + if (family.length () > 0) + LogPrint(eLogInfo, "Daemon: family set to ", family); - // I2P Control Protocol - bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol); - if (i2pcontrol) { - std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr); - uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort); - LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort); - try + bool trust; i2p::config::GetOption("trust.enabled", trust); + if (trust) + { + LogPrint(eLogInfo, "Daemon: explicit trust enabled"); + std::string fam; i2p::config::GetOption("trust.family", fam); + std::string routers; i2p::config::GetOption("trust.routers", routers); + bool restricted = false; + if (fam.length() > 0) + { + std::set fams; + size_t pos = 0, comma; + do { - d.m_I2PControlService = std::unique_ptr(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort)); - d.m_I2PControlService->Start (); - } - catch (std::exception& ex) + comma = fam.find (',', pos); + fams.insert (fam.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos)); + pos = comma + 1; + } + while (comma != std::string::npos); + i2p::transport::transports.RestrictRoutesToFamilies(fams); + restricted = fams.size() > 0; + } + if (routers.length() > 0) { + std::set idents; + size_t pos = 0, comma; + do { - LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ()); - ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ()); + comma = routers.find (',', pos); + i2p::data::IdentHash ident; + ident.FromBase64 (routers.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos)); + idents.insert (ident); + pos = comma + 1; } + while (comma != std::string::npos); + LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routers"); + i2p::transport::transports.RestrictRoutesToRouters(idents); + restricted = idents.size() > 0; } - return true; + if(!restricted) + LogPrint(eLogError, "Daemon: no trusted routers of families specified"); + } + + bool hidden; i2p::config::GetOption("trust.hidden", hidden); + if (hidden) + { + LogPrint(eLogInfo, "Daemon: using hidden mode"); + i2p::data::netdb.SetHidden(true); + } + return true; + } + + bool Daemon_Singleton::start() + { + i2p::log::Logger().Start(); + LogPrint(eLogInfo, "Daemon: starting NetDB"); + i2p::data::netdb.Start(); + + bool upnp; i2p::config::GetOption("upnp.enabled", upnp); + if (upnp) { + d.UPnP = std::unique_ptr(new i2p::transport::UPnP); + d.UPnP->Start (); + } + + bool nettime; i2p::config::GetOption("nettime.enabled", nettime); + if (nettime) + { + d.m_NTPSync = std::unique_ptr(new i2p::util::NTPTimeSync); + d.m_NTPSync->Start (); } - bool Daemon_Singleton::stop() + bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); + bool ssu; i2p::config::GetOption("ssu", ssu); + bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved); + LogPrint(eLogInfo, "Daemon: starting Transports"); + if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled"); + if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled"); + + i2p::transport::transports.SetCheckReserved(checkInReserved); + i2p::transport::transports.Start(ntcp2, ssu); + if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2()) + LogPrint(eLogInfo, "Daemon: Transports started"); + else { - LogPrint(eLogInfo, "Daemon: shutting down"); - LogPrint(eLogInfo, "Daemon: stopping Client"); - i2p::client::context.Stop(); - LogPrint(eLogInfo, "Daemon: stopping Tunnels"); - i2p::tunnel::tunnels.Stop(); + LogPrint(eLogError, "Daemon: failed to start Transports"); + /** shut down netdb right away */ + i2p::transport::transports.Stop(); + i2p::data::netdb.Stop(); + return false; + } - if (d.UPnP) + bool http; i2p::config::GetOption("http.enabled", http); + if (http) { + std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); + uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); + LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort); + try { - d.UPnP->Stop (); - d.UPnP = nullptr; + d.httpServer = std::unique_ptr(new i2p::http::HTTPServer(httpAddr, httpPort)); + d.httpServer->Start(); } - - if (d.m_NTPSync) + catch (std::exception& ex) { - d.m_NTPSync->Stop (); - d.m_NTPSync = nullptr; + LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ()); + ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ()); } + } - LogPrint(eLogInfo, "Daemon: stopping Transports"); - i2p::transport::transports.Stop(); - LogPrint(eLogInfo, "Daemon: stopping NetDB"); - i2p::data::netdb.Stop(); - if (d.httpServer) { - LogPrint(eLogInfo, "Daemon: stopping HTTP Server"); - d.httpServer->Stop(); - d.httpServer = nullptr; + + LogPrint(eLogInfo, "Daemon: starting Tunnels"); + i2p::tunnel::tunnels.Start(); + + LogPrint(eLogInfo, "Daemon: starting Client"); + i2p::client::context.Start (); + + // I2P Control Protocol + bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol); + if (i2pcontrol) { + std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr); + uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort); + LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort); + try + { + d.m_I2PControlService = std::unique_ptr(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort)); + d.m_I2PControlService->Start (); } - if (d.m_I2PControlService) + catch (std::exception& ex) { - LogPrint(eLogInfo, "Daemon: stopping I2PControl"); - d.m_I2PControlService->Stop (); - d.m_I2PControlService = nullptr; + LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ()); + ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ()); } - i2p::crypto::TerminateCrypto (); - i2p::log::Logger().Stop(); + } + return true; + } - return true; + bool Daemon_Singleton::stop() + { + LogPrint(eLogInfo, "Daemon: shutting down"); + LogPrint(eLogInfo, "Daemon: stopping Client"); + i2p::client::context.Stop(); + LogPrint(eLogInfo, "Daemon: stopping Tunnels"); + i2p::tunnel::tunnels.Stop(); + + if (d.UPnP) + { + d.UPnP->Stop (); + d.UPnP = nullptr; + } + + if (d.m_NTPSync) + { + d.m_NTPSync->Stop (); + d.m_NTPSync = nullptr; } + + LogPrint(eLogInfo, "Daemon: stopping Transports"); + i2p::transport::transports.Stop(); + LogPrint(eLogInfo, "Daemon: stopping NetDB"); + i2p::data::netdb.Stop(); + if (d.httpServer) { + LogPrint(eLogInfo, "Daemon: stopping HTTP Server"); + d.httpServer->Stop(); + d.httpServer = nullptr; + } + if (d.m_I2PControlService) + { + LogPrint(eLogInfo, "Daemon: stopping I2PControl"); + d.m_I2PControlService->Stop (); + d.m_I2PControlService = nullptr; + } + i2p::crypto::TerminateCrypto (); + i2p::log::Logger().Stop(); + + return true; + } } } diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 32db8ff1..d000a9e0 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -49,8 +49,8 @@ namespace datagram std::shared_ptr DatagramDestination::GetSession(const i2p::data::IdentHash & ident) { return ObtainSession(ident); - } - + } + void DatagramDestination::SendDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort) { if (session) @@ -67,21 +67,21 @@ namespace datagram auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, fromPort, toPort, false, !session->IsRatchets ()); // datagram session->SendMsg(msg); - } - } + } + } void DatagramDestination::SendRawDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort) { if (session) session->SendMsg(CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ())); // raw } - + void DatagramDestination::FlushSendQueue (std::shared_ptr session) { if (session) session->FlushSendQueue (); - } - + } + void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len) { i2p::data::IdentityEx identity; @@ -242,7 +242,7 @@ namespace datagram if (msg || m_SendQueue.empty ()) m_SendQueue.push_back(msg); // flush queue right away if full - if (!msg || m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) + if (!msg || m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) FlushSendQueue(); } @@ -286,14 +286,14 @@ namespace datagram m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); if (!m_RemoteLeaseSet) { - if(!m_RequestingLS) + if(!m_RequestingLS) { m_RequestingLS = true; m_LocalDestination->RequestDestination(m_RemoteIdent, std::bind(&DatagramSession::HandleLeaseSetUpdated, this, std::placeholders::_1)); } return nullptr; - } - } + } + } if (!m_RoutingSession || m_RoutingSession->IsTerminated () || !m_RoutingSession->IsReadyToSend ()) { @@ -305,81 +305,81 @@ namespace datagram m_PendingRoutingSessions.clear (); found = true; break; - } + } if (!found) - { + { m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); if (!m_RoutingSession->GetOwner () || !m_RoutingSession->IsReadyToSend ()) m_PendingRoutingSessions.push_back (m_RoutingSession); - } - } - + } + } + auto path = m_RoutingSession->GetSharedRoutingPath(); if (path && m_RoutingSession->IsRatchets () && m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT) - { + { m_RoutingSession->SetSharedRoutingPath (nullptr); path = nullptr; } - - if (path) + + if (path) { if (path->outboundTunnel && !path->outboundTunnel->IsEstablished ()) - { + { // bad outbound tunnel, switch outbound tunnel path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(path->outboundTunnel); if (!path->outboundTunnel) m_RoutingSession->SetSharedRoutingPath (nullptr); - } - - if (path->remoteLease && path->remoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) + } + + if (path->remoteLease && path->remoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) { // bad lease, switch to next one - if (m_RemoteLeaseSet) + if (m_RemoteLeaseSet) { auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( - [&](const i2p::data::Lease& l) -> bool + [&](const i2p::data::Lease& l) -> bool { return l.tunnelID == path->remoteLease->tunnelID; }); auto sz = ls.size(); - if (sz) + if (sz) { auto idx = rand() % sz; path->remoteLease = ls[idx]; } else m_RoutingSession->SetSharedRoutingPath (nullptr); - } - else - { + } + else + { // no remote lease set? LogPrint(eLogWarning, "DatagramSession: no cached remote lease set for ", m_RemoteIdent.ToBase32()); m_RoutingSession->SetSharedRoutingPath (nullptr); - } + } } - } - else + } + else { // no current path, make one path = std::make_shared(); path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(); if (!path->outboundTunnel) return nullptr; - - if (m_RemoteLeaseSet) + + if (m_RemoteLeaseSet) { // pick random next good lease auto ls = m_RemoteLeaseSet->GetNonExpiredLeases(); auto sz = ls.size(); - if (sz) + if (sz) { auto idx = rand() % sz; path->remoteLease = ls[idx]; } else return nullptr; - } - else + } + else { // no remote lease set currently, bail LogPrint(eLogWarning, "DatagramSession: no remote lease set found for ", m_RemoteIdent.ToBase32());