diff --git a/Daemon.cpp b/Daemon.cpp
index 00bfd817..7dec30a9 100644
--- a/Daemon.cpp
+++ b/Daemon.cpp
@@ -124,47 +124,16 @@ namespace i2p
ipv4 = false;
ipv6 = true;
#endif
-
- i2p::context.SetSupportsV6 (ipv6);
- i2p::context.SetSupportsV4 (ipv4);
-
- bool nat; i2p::config::GetOption("nat", nat);
- if (nat)
- {
- LogPrint(eLogInfo, "Daemon: assuming be are behind NAT");
- // we are behind nat, try setting via host
- std::string host; i2p::config::GetOption("host", host);
- if (!i2p::config::IsDefault("host"))
- {
- LogPrint(eLogInfo, "Daemon: setting address for incoming connections to ", host);
- i2p::context.UpdateAddress (boost::asio::ip::address::from_string (host));
- }
- }
- else
- {
- // we are not behind nat
- std::string ifname; i2p::config::GetOption("ifname", ifname);
- if (ifname.size())
- {
- // bind to interface, we have no NAT so set external address too
- auto addr = i2p::util::net::GetInterfaceAddress(ifname, ipv6);
- LogPrint(eLogInfo, "Daemon: bind to network interface ", ifname, " with public address ", addr);
- i2p::context.UpdateAddress(addr);
- }
- }
-
-
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);
- }
-
-
- bool transit; i2p::config::GetOption("notransit", transit);
+ }
i2p::context.SetSupportsV6 (ipv6);
i2p::context.SetSupportsV4 (ipv4);
+
+ bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
SetMaxNumTransitTunnels (transitTunnels);
@@ -252,14 +221,15 @@ namespace i2p
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
bool ssu; i2p::config::GetOption("ssu", ssu);
LogPrint(eLogInfo, "Daemon: starting Transports");
- if(!ssu) LogPrint(eLogDebug, "Daemon: ssu disabled");
- if(!ntcp) LogPrint(eLogDebug, "Daemon: ntcp disabled");
+ if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
+ if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
i2p::transport::transports.Start(ntcp, ssu);
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU()) {
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;
}
diff --git a/Destination.cpp b/Destination.cpp
index abfe3227..2df14a9f 100644
--- a/Destination.cpp
+++ b/Destination.cpp
@@ -470,7 +470,7 @@ namespace client
else
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", GetIdentHash().ToBase32());
// we have to publish again
- s->Publish ();
+ s->Publish ();
});
}
}
diff --git a/HTTPServer.cpp b/HTTPServer.cpp
index 2be70cec..566ad53e 100644
--- a/HTTPServer.cpp
+++ b/HTTPServer.cpp
@@ -72,6 +72,7 @@ namespace http {
const char HTTP_PAGE_SAM_SESSION[] = "sam_session";
const char HTTP_PAGE_I2P_TUNNELS[] = "i2p_tunnels";
const char HTTP_PAGE_COMMANDS[] = "commands";
+ const char HTTP_PAGE_LEASESETS[] = "leasesets";
const char HTTP_COMMAND_ENABLE_TRANSIT[] = "enable_transit";
const char HTTP_COMMAND_DISABLE_TRANSIT[] = "disable_transit";
const char HTTP_COMMAND_SHUTDOWN_START[] = "shutdown_start";
@@ -140,6 +141,7 @@ namespace http {
" Main page
\r\n
\r\n"
" Router commands
\r\n"
" Local destinations
\r\n"
+ " Lease Sets
\r\n"
" Tunnels
\r\n"
" Transit tunnels
\r\n"
" Transports
\r\n"
@@ -327,6 +329,57 @@ namespace http {
}
}
+ void ShowLeasesSets(std::stringstream& s)
+ {
+ s << "
LeaseSets
";
+ // for each lease set
+ i2p::data::netdb.VisitLeaseSets(
+ [&s](const i2p::data::IdentHash dest, std::shared_ptr leaseSet)
+ {
+ // create copy of lease set so we extract leases
+ i2p::data::LeaseSet ls(leaseSet->GetBuffer(), leaseSet->GetBufferLen());
+ // begin lease set entry
+ s << "";
+ // invalid ?
+ if (!ls.IsValid())
+ s << "
!! Invalid !!
";
+ // ident
+ s << "
" << dest.ToBase32() << "
";
+ // LeaseSet time
+ s << "
expires: " << ls.GetExpirationTime() << "
";
+ // get non expired leases
+ auto leases = ls.GetNonExpiredLeases();
+ // show non expired leases
+ s << "
Non Expired Leases: " << leases.size() << "
";
+ // for each lease
+ s << "
";
+ for ( auto & l : leases )
+ {
+ // begin lease
+ s << "
";
+ // gateway
+ s << "
Gateway: " << l->tunnelGateway.ToBase64() << "
";
+ // tunnel id
+ s << "
TunnelID: " << l->tunnelID << "
";
+ // end date
+ s << "
EndDate: " << l->endDate << "
";
+ // end lease
+ s << "
";
+ }
+ // end for each lease
+ s << "
";
+ // end lease set entry
+ s << "
";
+ // linebreak
+ s << "
";
+ }
+ );
+ // end for each lease set
+ }
+
void ShowTunnels (std::stringstream& s)
{
s << "Queue size: " << i2p::tunnel::tunnels.GetQueueSize () << "
\r\n";
@@ -639,6 +692,8 @@ namespace http {
ShowSAMSession (s, params["sam_id"]);
else if (page == HTTP_PAGE_I2P_TUNNELS)
ShowI2PTunnels (s);
+ else if (page == HTTP_PAGE_LEASESETS)
+ ShowLeasesSets(s);
else {
res.code = 400;
ShowError(s, "Unknown page: " + page);
diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp
index 1b2d0317..92ab8281 100644
--- a/I2NPProtocol.cpp
+++ b/I2NPProtocol.cpp
@@ -165,9 +165,10 @@ namespace i2p
buf += 32;
memcpy (buf, replyTunnel->GetNextIdentHash (), 32); // reply tunnel GW
buf += 32;
- *buf = DATABASE_LOOKUP_DELIVERY_FLAG | DATABASE_LOOKUP_ENCYPTION_FLAG | DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP; // flags
- htobe32buf (buf + 1, replyTunnel->GetNextTunnelID ()); // reply tunnel ID
- buf += 5;
+ *buf = DATABASE_LOOKUP_DELIVERY_FLAG | DATABASE_LOOKUP_ENCRYPTION_FLAG | DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP; // flags
+ buf ++;
+ htobe32buf (buf, replyTunnel->GetNextTunnelID ()); // reply tunnel ID
+ buf += 4;
// excluded
htobe16buf (buf, cnt);
@@ -182,7 +183,7 @@ namespace i2p
}
// encryption
memcpy (buf, replyKey, 32);
- buf[32] = 1; // 1 tag
+ buf[32] = uint8_t( 1 ); // 1 tag
memcpy (buf + 33, replyTag, 32);
buf += 65;
diff --git a/I2NPProtocol.h b/I2NPProtocol.h
index 1ade55ed..76871114 100644
--- a/I2NPProtocol.h
+++ b/I2NPProtocol.h
@@ -90,7 +90,7 @@ namespace i2p
// DatabaseLookup flags
const uint8_t DATABASE_LOOKUP_DELIVERY_FLAG = 0x01;
- const uint8_t DATABASE_LOOKUP_ENCYPTION_FLAG = 0x02;
+ const uint8_t DATABASE_LOOKUP_ENCRYPTION_FLAG = 0x02;
const uint8_t DATABASE_LOOKUP_TYPE_FLAGS_MASK = 0x0C;
const uint8_t DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP = 0;
const uint8_t DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP = 0x04; // 0100
diff --git a/Makefile b/Makefile
index 22f016ea..147bedd4 100644
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ else # win32 mingw
endif
ifeq ($(USE_MESHNET),yes)
- CXXFLAGS += -DMESHNET
+ NEEDED_CXXFLAGS += -DMESHNET
endif
all: mk_obj_dir $(ARLIB) $(ARLIB_CLIENT) $(I2PD)
diff --git a/NetDb.cpp b/NetDb.cpp
index f89617be..f5b51064 100644
--- a/NetDb.cpp
+++ b/NetDb.cpp
@@ -213,6 +213,7 @@ namespace data
bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len,
std::shared_ptr from)
{
+ std::unique_lock lock(m_LeaseSetsMutex);
bool updated = false;
if (!from) // unsolicited LS must be received directly
{
@@ -264,6 +265,7 @@ namespace data
std::shared_ptr NetDb::FindLeaseSet (const IdentHash& destination) const
{
+ std::unique_lock lock(m_LeaseSetsMutex);
auto it = m_LeaseSets.find (destination);
if (it != m_LeaseSets.end ())
return it->second;
@@ -318,6 +320,13 @@ namespace data
return true;
}
+ void NetDb::VisitLeaseSets(LeaseSetVisitor v)
+ {
+ std::unique_lock lock(m_LeaseSetsMutex);
+ for ( auto & entry : m_LeaseSets)
+ v(entry.first, entry.second);
+ }
+
void NetDb::Load ()
{
// make sure we cleanup netDb from previous attempts
@@ -623,17 +632,18 @@ namespace data
char key[48];
int l = i2p::data::ByteStreamToBase64 (buf, 32, key, 48);
key[l] = 0;
- uint8_t flag = buf[64];
IdentHash replyIdent(buf + 32);
-
+ uint8_t flag = buf[64];
+
+
LogPrint (eLogDebug, "NetDb: DatabaseLookup for ", key, " recieved flags=", (int)flag);
uint8_t lookupType = flag & DATABASE_LOOKUP_TYPE_FLAGS_MASK;
const uint8_t * excluded = buf + 65;
uint32_t replyTunnelID = 0;
if (flag & DATABASE_LOOKUP_DELIVERY_FLAG) //reply to tunnel
{
- replyTunnelID = bufbe32toh (buf + 65);
+ replyTunnelID = bufbe32toh (excluded);
excluded += 4;
}
uint16_t numExcluded = bufbe16toh (excluded);
@@ -641,7 +651,7 @@ namespace data
if (numExcluded > 512)
{
LogPrint (eLogWarning, "NetDb: number of excluded peers", numExcluded, " exceeds 512");
- numExcluded = 0; // TODO:
+ return;
}
std::shared_ptr replyMsg;
@@ -714,35 +724,39 @@ namespace data
}
if (!found)
{
- std::set excludedRouters;
+ std::set excludedRouters;
+ const uint8_t * exclude_ident = excluded;
for (int i = 0; i < numExcluded; i++)
{
- excludedRouters.insert (excluded);
- excluded += 32;
+ excludedRouters.insert (exclude_ident);
+ exclude_ident += 32;
}
closestFloodfills = GetClosestFloodfills (ident, 3, excludedRouters, true);
if (!numExcluded) // save if no excluded
m_LookupResponses[ident] = std::make_pair(closestFloodfills, i2p::util::GetSecondsSinceEpoch ());
}
replyMsg = CreateDatabaseSearchReply (ident, closestFloodfills);
- }
+ }
}
-
+ excluded += numExcluded * 32;
if (replyMsg)
{
if (replyTunnelID)
{
// encryption might be used though tunnel only
- if (flag & DATABASE_LOOKUP_ENCYPTION_FLAG) // encrypted reply requested
+ if (flag & DATABASE_LOOKUP_ENCRYPTION_FLAG) // encrypted reply requested
{
const uint8_t * sessionKey = excluded;
- uint8_t numTags = sessionKey[32];
- if (numTags > 0)
+ const uint8_t numTags = excluded[32];
+ if (numTags)
{
- const uint8_t * sessionTag = sessionKey + 33; // take first tag
+ const i2p::garlic::SessionTag sessionTag(excluded + 33); // take first tag
i2p::garlic::GarlicRoutingSession garlic (sessionKey, sessionTag);
replyMsg = garlic.WrapSingleMessage (replyMsg);
+ if(replyMsg == nullptr) LogPrint(eLogError, "NetDb: failed to wrap message");
}
+ else
+ LogPrint(eLogWarning, "NetDb: encrypted reply requested but no tags provided");
}
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
diff --git a/NetDb.h b/NetDb.h
index 3b54ae4c..43b069b9 100644
--- a/NetDb.h
+++ b/NetDb.h
@@ -31,12 +31,10 @@ namespace data
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60;
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90*60; // 1.5 hours
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27*60*60; // 27 hours
-
-#ifdef MESHNET
- const int NETDB_PUBLISH_INTERVAL = 60;
-#else
const int NETDB_PUBLISH_INTERVAL = 60*40;
-#endif
+
+ /** function for visiting a leaseset stored in a floodfill */
+ typedef std::function)> LeaseSetVisitor;
class NetDb
{
@@ -85,7 +83,10 @@ namespace data
int GetNumRouters () const { return m_RouterInfos.size (); };
int GetNumFloodfills () const { return m_Floodfills.size (); };
int GetNumLeaseSets () const { return m_LeaseSets.size (); };
-
+
+ /** visit all lease sets we currently store */
+ void VisitLeaseSets(LeaseSetVisitor v);
+
private:
void Load ();
@@ -103,6 +104,7 @@ namespace data
private:
+ mutable std::mutex m_LeaseSetsMutex;
std::map > m_LeaseSets;
mutable std::mutex m_RouterInfosMutex;
std::map > m_RouterInfos;
diff --git a/RouterContext.cpp b/RouterContext.cpp
index 02a344de..f61aaed8 100644
--- a/RouterContext.cpp
+++ b/RouterContext.cpp
@@ -49,10 +49,10 @@ namespace i2p
uint16_t port; i2p::config::GetOption("port", port);
if (!port)
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
- std::string host; i2p::config::GetOption("host", host);
- if (i2p::config::IsDefault("host"))
- host = "127.0.0.1"; // replace default address with safe value
- routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
+ bool ipv4; i2p::config::GetOption("ipv4", ipv4);
+ bool ipv6; i2p::config::GetOption("ipv6", ipv6);
+ std::string host = i2p::util::config::GetHost(ipv4, ipv6);
+ routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
routerInfo.AddNTCPAddress (host.c_str(), port);
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC
diff --git a/Transports.cpp b/Transports.cpp
index 2d572aef..a54455cc 100644
--- a/Transports.cpp
+++ b/Transports.cpp
@@ -114,7 +114,7 @@ namespace transport
auto& addresses = context.GetRouterInfo ().GetAddresses ();
for (auto address : addresses)
{
- if (!m_NTCPServer && enableNTCP)
+ if (m_NTCPServer == nullptr && enableNTCP)
{
m_NTCPServer = new NTCPServer ();
m_NTCPServer->Start ();
@@ -129,7 +129,7 @@ namespace transport
if (address->transportStyle == RouterInfo::eTransportSSU)
{
- if (!m_SSUServer && enableSSU)
+ if (m_SSUServer == nullptr && enableSSU)
{
if (address->host.is_v4())
m_SSUServer = new SSUServer (address->port);
diff --git a/util.cpp b/util.cpp
index 89bcda6c..5913d9a7 100644
--- a/util.cpp
+++ b/util.cpp
@@ -461,5 +461,30 @@ namespace net
}
}
+namespace config
+{
+ std::string GetHost(bool ipv4, bool ipv6)
+ {
+ std::string host;
+ if(ipv6)
+ host = "::";
+ else if(ipv4)
+ host = "127.0.0.1";
+ bool nat; i2p::config::GetOption("nat", nat);
+ if (nat)
+ {
+ if (!i2p::config::IsDefault("host"))
+ i2p::config::GetOption("host", host);
+ }
+ else
+ {
+ // we are not behind nat
+ std::string ifname; i2p::config::GetOption("ifname", ifname);
+ if (ifname.size())
+ host = i2p::util::net::GetInterfaceAddress(ifname, ipv6).to_string(); // bind to interface, we have no NAT so set external address too
+ }
+ return host;
+ }
+} // config
} // util
} // i2p
diff --git a/util.h b/util.h
index 7c393e02..8995f12b 100644
--- a/util.h
+++ b/util.h
@@ -68,6 +68,12 @@ namespace util
int GetMTU (const boost::asio::ip::address& localAddress);
const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6=false);
}
+
+ namespace config
+ {
+ /** get the host to use from out config, for use in RouterContext.cpp */
+ std::string GetHost(bool ipv4=true, bool ipv6=true);
+ }
}
}