diff --git a/Garlic.cpp b/Garlic.cpp
index 3e336092..c003b9a7 100644
--- a/Garlic.cpp
+++ b/Garlic.cpp
@@ -5,6 +5,7 @@
#include "RouterContext.h"
#include "I2NPProtocol.h"
#include "Tunnel.h"
+#include "TunnelPool.h"
#include "Timestamp.h"
#include "Streaming.h"
#include "Garlic.h"
@@ -288,9 +289,12 @@ namespace garlic
else
{
// new session
+ i2p::tunnel::TunnelPool * pool = nullptr;
+ if (msg->from)
+ pool = msg->from->GetTunnelPool ();
ElGamalBlock elGamal;
if (i2p::crypto::ElGamalDecrypt (
- msg->from ? i2p::context.GetLeaseSetPrivateKey () : i2p::context.GetPrivateKey (),
+ pool ? pool->GetEncryptionPrivateKey () : i2p::context.GetPrivateKey (),
buf, (uint8_t *)&elGamal, true))
{
uint8_t iv[32]; // IV is first 16 bytes
diff --git a/HTTPServer.cpp b/HTTPServer.cpp
index c7d1fcaf..f914fefd 100644
--- a/HTTPServer.cpp
+++ b/HTTPServer.cpp
@@ -139,6 +139,8 @@ namespace util
for (auto it: i2p::tunnel::tunnels.GetOutboundTunnels ())
{
it->GetTunnelConfig ()->Print (s);
+ if (it->GetTunnelPool ())
+ s << " " << "Pool";
s << " " << (int)it->GetNumSentBytes () << "
";
}
@@ -195,14 +197,31 @@ namespace util
s << "
Flibusta
";
}
- void HTTPConnection::HandleDestinationRequest (const std::string& b32, const std::string& uri)
+ void HTTPConnection::HandleDestinationRequest (const std::string& address, const std::string& uri)
{
- uint8_t destination[32];
- if (i2p::data::Base32ToByteStream (b32.c_str (), b32.length (), destination, 32) != 32)
- {
- LogPrint ("Invalid Base32 address ", b32);
- return;
+ i2p::data::IdentHash destination;
+ std::string fullAddress;
+ if (address.find (".i2p") != std::string::npos)
+ {
+ auto addr = i2p::data::netdb.FindAddress(address);
+ if (!addr)
+ {
+ LogPrint ("Unknown address ", address);
+ return;
+ }
+ destination = *addr;
+ fullAddress = address;
+ }
+ else
+ {
+ if (i2p::data::Base32ToByteStream (address.c_str (), address.length (), (uint8_t *)destination, 32) != 32)
+ {
+ LogPrint ("Invalid Base32 address ", address);
+ return;
+ }
+ fullAddress = address + ".b32.i2p";
}
+
auto leaseSet = i2p::data::netdb.FindLeaseSet (destination);
if (!leaseSet || !leaseSet->HasNonExpiredLeases ())
{
@@ -223,7 +242,7 @@ namespace util
auto s = i2p::stream::CreateStream (*leaseSet);
if (s)
{
- std::string request = "GET " + uri + " HTTP/1.1\n Host:" + b32 + ".b32.i2p\n";
+ std::string request = "GET " + uri + " HTTP/1.1\n Host:" + fullAddress + "\n";
s->Send ((uint8_t *)request.c_str (), request.length (), 10);
std::stringstream ss;
uint8_t buf[8192];
diff --git a/HTTPServer.h b/HTTPServer.h
index a62a2074..546f5bc2 100644
--- a/HTTPServer.h
+++ b/HTTPServer.h
@@ -48,7 +48,7 @@ namespace util
void HandleWrite(const boost::system::error_code& ecode);
void HandleRequest ();
- void HandleDestinationRequest (const std::string& b32, const std::string& uri);
+ void HandleDestinationRequest (const std::string& address, const std::string& uri);
void FillContent (std::stringstream& s);
std::string ExtractAddress ();
diff --git a/NetDb.cpp b/NetDb.cpp
index 951f9623..2b3598fc 100644
--- a/NetDb.cpp
+++ b/NetDb.cpp
@@ -550,11 +550,15 @@ namespace data
void NetDb::Publish ()
{
std::set excluded; // TODO: fill up later
- auto floodfill = GetClosestFloodfill (i2p::context.GetRouterInfo ().GetIdentHash (), excluded);
- if (floodfill)
- {
- LogPrint ("Publishing our RouterInfo to ", floodfill->GetIdentHashAbbreviation ());
- transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg ());
+ for (int i = 0; i < 3; i++)
+ {
+ auto floodfill = GetClosestFloodfill (i2p::context.GetRouterInfo ().GetIdentHash (), excluded);
+ if (floodfill)
+ {
+ LogPrint ("Publishing our RouterInfo to ", floodfill->GetIdentHashAbbreviation ());
+ transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg ());
+ excluded.insert (floodfill->GetIdentHash ());
+ }
}
}
diff --git a/RouterContext.cpp b/RouterContext.cpp
index cb8eb355..bde075ad 100644
--- a/RouterContext.cpp
+++ b/RouterContext.cpp
@@ -14,10 +14,6 @@ namespace i2p
if (!Load ())
CreateNewRouter ();
Save ();
-
- // we generate LeaseSet at every start-up
- CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
- dh.GenerateKeyPair(m_Rnd, m_LeaseSetPrivateKey, m_LeaseSetPublicKey);
}
void RouterContext::CreateNewRouter ()
diff --git a/RouterContext.h b/RouterContext.h
index 092c50b5..abbc3775 100644
--- a/RouterContext.h
+++ b/RouterContext.h
@@ -20,8 +20,6 @@ namespace i2p
i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; };
const uint8_t * GetPrivateKey () const { return m_Keys.privateKey; };
const uint8_t * GetSigningPrivateKey () const { return m_Keys.signingPrivateKey; };
- const uint8_t * GetLeaseSetPrivateKey () const { return m_LeaseSetPrivateKey; };
- const uint8_t * GetLeaseSetPublicKey () const { return m_LeaseSetPublicKey; };
const i2p::data::Identity& GetRouterIdentity () const { return m_RouterInfo.GetRouterIdentity (); };
CryptoPP::RandomNumberGenerator& GetRandomNumberGenerator () { return m_Rnd; };
@@ -42,7 +40,6 @@ namespace i2p
i2p::data::RouterInfo m_RouterInfo;
i2p::data::Keys m_Keys;
CryptoPP::DSA::PrivateKey m_SigningPrivateKey;
- uint8_t m_LeaseSetPublicKey[256], m_LeaseSetPrivateKey[256];
CryptoPP::AutoSeededRandomPool m_Rnd;
};
diff --git a/SSU.cpp b/SSU.cpp
index 196c0a72..64886e90 100644
--- a/SSU.cpp
+++ b/SSU.cpp
@@ -418,7 +418,10 @@ namespace ssu
LogPrint ("Unexpected payload type ", (int)(header->flag >> 4));
}
else
+ {
LogPrint ("MAC verification failed");
+ Failed ();
+ }
}
else
LogPrint ("SSU is not supported");
@@ -511,6 +514,14 @@ namespace ssu
m_DelayedMessages.clear ();
}
}
+
+ void SSUSession::Failed ()
+ {
+ m_State = eSessionStateFailed;
+ Close ();
+ if (m_Server)
+ m_Server->DeleteSession (this); // delete this
+ }
const uint8_t * SSUSession::GetIntroKey () const
{
diff --git a/SSU.h b/SSU.h
index c61d09bb..c0c82e3e 100644
--- a/SSU.h
+++ b/SSU.h
@@ -58,7 +58,8 @@ namespace ssu
eSessionRelayRequestSent,
eSessionRelayRequestReceived,
eSessionRelayResponseReceived,
- eSessionStateEstablished
+ eSessionStateEstablished,
+ eSessionStateFailed
};
class SSUServer;
@@ -91,6 +92,7 @@ namespace ssu
void SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress, uint32_t relayTag);
void ProcessRelayResponse (uint8_t * buf, size_t len);
void Established ();
+ void Failed ();
void ProcessData (uint8_t * buf, size_t len);
void SendMsgAck (uint32_t msgID);
void SendSesionDestroyed ();
diff --git a/Streaming.cpp b/Streaming.cpp
index b7282145..d365e57c 100644
--- a/Streaming.cpp
+++ b/Streaming.cpp
@@ -171,7 +171,7 @@ namespace stream
CreateDataMessage (this, packet, size), m_LocalDestination->GetLeaseSet ());
if (!m_OutboundTunnel)
- m_OutboundTunnel = i2p::tunnel::tunnels.GetNextOutboundTunnel ();
+ m_OutboundTunnel = m_LocalDestination->GetTunnelPool ()->GetNextOutboundTunnel ();
auto leases = m_RemoteLeaseSet.GetNonExpiredLeases ();
if (m_OutboundTunnel && !leases.empty ())
{
@@ -377,7 +377,7 @@ namespace stream
size_t size = 0;
memcpy (buf + size, &m_Identity, sizeof (m_Identity));
size += sizeof (m_Identity); // destination
- memcpy (buf + size, i2p::context.GetLeaseSetPublicKey (), 256);
+ memcpy (buf + size, m_Pool->GetEncryptionPublicKey (), 256);
size += 256; // encryption key
memset (buf + size, 0, 128);
size += 128; // signing key
diff --git a/Streaming.h b/Streaming.h
index 8f0f289a..b0f7fda9 100644
--- a/Streaming.h
+++ b/Streaming.h
@@ -108,6 +108,7 @@ namespace stream
const i2p::data::Keys& GetKeys () const { return m_Keys; };
const i2p::data::Identity& GetIdentity () const { return m_Identity; };
I2NPMessage * GetLeaseSet ();
+ i2p::tunnel::TunnelPool * GetTunnelPool () const { return m_Pool; };
void Sign (uint8_t * buf, int len, uint8_t * signature) const;
Stream * CreateNewStream (const i2p::data::LeaseSet& remote);
diff --git a/Tunnel.cpp b/Tunnel.cpp
index e9e59b86..5d93c50a 100644
--- a/Tunnel.cpp
+++ b/Tunnel.cpp
@@ -390,13 +390,16 @@ namespace tunnel
if (ts > (*it)->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
{
LogPrint ("Tunnel ", (*it)->GetTunnelID (), " expired");
+ auto pool = (*it)->GetTunnelPool ();
+ if (pool)
+ pool->TunnelExpired (*it);
it = m_OutboundTunnels.erase (it);
}
else
it++;
}
- if (m_OutboundTunnels.size () < 10)
+ if (m_OutboundTunnels.size () < 15) // TODO: store exploratory tunnels explicitly
{
// trying to create one more oubound tunnel
if (m_InboundTunnels.empty ()) return;
@@ -520,6 +523,9 @@ namespace tunnel
void Tunnels::AddOutboundTunnel (OutboundTunnel * newTunnel)
{
m_OutboundTunnels.push_back (newTunnel);
+ auto pool = newTunnel->GetTunnelPool ();
+ if (pool)
+ pool->TunnelCreated (newTunnel);
}
void Tunnels::AddInboundTunnel (InboundTunnel * newTunnel)
diff --git a/TunnelPool.cpp b/TunnelPool.cpp
index d9d38354..6d6516ec 100644
--- a/TunnelPool.cpp
+++ b/TunnelPool.cpp
@@ -1,36 +1,54 @@
+#include
+#include "CryptoConst.h"
#include "Tunnel.h"
#include "NetDb.h"
#include "Timestamp.h"
+#include "RouterContext.h"
#include "TunnelPool.h"
namespace i2p
{
namespace tunnel
{
- TunnelPool::TunnelPool (i2p::data::LocalDestination * owner, int numTunnels):
- m_Owner (owner), m_NumTunnels (numTunnels)
+ TunnelPool::TunnelPool (i2p::data::LocalDestination * localDestination, int numTunnels):
+ m_LocalDestination (localDestination), m_NumTunnels (numTunnels), m_LastOutboundTunnel (nullptr)
{
+ CryptoPP::AutoSeededRandomPool rnd;
+ CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
+ dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
}
TunnelPool::~TunnelPool ()
{
for (auto it: m_InboundTunnels)
it->SetTunnelPool (nullptr);
+ for (auto it: m_OutboundTunnels)
+ it->SetTunnelPool (nullptr);
}
void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel)
{
m_InboundTunnels.insert (createdTunnel);
- if (m_Owner)
- m_Owner->UpdateLeaseSet ();
+ if (m_LocalDestination)
+ m_LocalDestination->UpdateLeaseSet ();
}
void TunnelPool::TunnelExpired (InboundTunnel * expiredTunnel)
{
m_InboundTunnels.erase (expiredTunnel);
- if (m_Owner)
- m_Owner->UpdateLeaseSet ();
+ if (m_LocalDestination)
+ m_LocalDestination->UpdateLeaseSet ();
}
+
+ void TunnelPool::TunnelCreated (OutboundTunnel * createdTunnel)
+ {
+ m_OutboundTunnels.insert (createdTunnel);
+ }
+
+ void TunnelPool::TunnelExpired (OutboundTunnel * expiredTunnel)
+ {
+ m_OutboundTunnels.erase (expiredTunnel);
+ }
std::vector TunnelPool::GetInboundTunnels (int num) const
{
@@ -45,16 +63,37 @@ namespace tunnel
return v;
}
+ OutboundTunnel * TunnelPool::GetNextOutboundTunnel ()
+ {
+ if (m_OutboundTunnels.empty ()) return nullptr;
+ auto tunnel = *m_OutboundTunnels.begin ();
+ if (m_LastOutboundTunnel && tunnel == m_LastOutboundTunnel)
+ {
+ for (auto it: m_OutboundTunnels)
+ if (it != m_LastOutboundTunnel)
+ {
+ tunnel = it;
+ break;
+ }
+ }
+ m_LastOutboundTunnel = tunnel;
+ return tunnel;
+ }
+
void TunnelPool::CreateTunnels ()
{
int num = m_InboundTunnels.size ();
for (int i = num; i < m_NumTunnels; i++)
CreateInboundTunnel ();
+ num = m_OutboundTunnels.size ();
+ for (int i = num; i < m_NumTunnels; i++)
+ CreateOutboundTunnel ();
}
void TunnelPool::CreateInboundTunnel ()
{
- OutboundTunnel * outboundTunnel = tunnels.GetNextOutboundTunnel ();
+ OutboundTunnel * outboundTunnel = m_OutboundTunnels.size () > 0 ?
+ *m_OutboundTunnels.begin () : tunnels.GetNextOutboundTunnel ();
LogPrint ("Creating destination inbound tunnel...");
auto firstHop = i2p::data::netdb.GetRandomRouter (outboundTunnel ? outboundTunnel->GetEndpointRouter () : nullptr);
auto secondHop = i2p::data::netdb.GetRandomRouter (firstHop);
@@ -63,11 +102,31 @@ namespace tunnel
{
firstHop,
secondHop
- // TODO: swithc to 3-hops later
+ // TODO: switch to 3-hops later
/*i2p::data::netdb.GetRandomRouter (secondHop) */
}),
outboundTunnel);
tunnel->SetTunnelPool (this);
}
+
+ void TunnelPool::CreateOutboundTunnel ()
+ {
+ InboundTunnel * inboundTunnel = m_InboundTunnels.size () > 0 ?
+ *m_InboundTunnels.begin () : tunnels.GetNextInboundTunnel ();
+ if (inboundTunnel)
+ {
+ LogPrint ("Creating destination outbound tunnel...");
+ auto firstHop = i2p::data::netdb.GetRandomRouter (&i2p::context.GetRouterInfo ());
+ auto secondHop = i2p::data::netdb.GetRandomRouter (firstHop);
+ auto * tunnel = tunnels.CreateTunnel (
+ new TunnelConfig (std::vector
+ {
+ firstHop,
+ secondHop
+ },
+ inboundTunnel->GetTunnelConfig ()));
+ tunnel->SetTunnelPool (this);
+ }
+ }
}
}
diff --git a/TunnelPool.h b/TunnelPool.h
index 988e83c0..f8b6aab5 100644
--- a/TunnelPool.h
+++ b/TunnelPool.h
@@ -20,24 +20,33 @@ namespace tunnel
{
public:
- TunnelPool (i2p::data::LocalDestination * owner, int numTunnels = 5);
+ TunnelPool (i2p::data::LocalDestination * localDestination, int numTunnels = 5);
~TunnelPool ();
+ const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
+ const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; };
+
void CreateTunnels ();
void TunnelCreated (InboundTunnel * createdTunnel);
void TunnelExpired (InboundTunnel * expiredTunnel);
+ void TunnelCreated (OutboundTunnel * createdTunnel);
+ void TunnelExpired (OutboundTunnel * expiredTunnel);
std::vector GetInboundTunnels (int num) const;
-
+ OutboundTunnel * GetNextOutboundTunnel ();
+
private:
void CreateInboundTunnel ();
-
+ void CreateOutboundTunnel ();
+
private:
- i2p::data::LocalDestination * m_Owner;
+ uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
+ i2p::data::LocalDestination * m_LocalDestination;
int m_NumTunnels;
std::set m_InboundTunnels; // recent tunnel appears first
-
+ std::set m_OutboundTunnels;
+ OutboundTunnel * m_LastOutboundTunnel;
};
}
}