|
|
@ -193,65 +193,82 @@ namespace transport |
|
|
|
i2p::HandleI2NPMessage (msg); |
|
|
|
i2p::HandleI2NPMessage (msg); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
std::shared_ptr<TransportSession> session = m_NTCPServer->FindNTCPSession (ident); |
|
|
|
|
|
|
|
if (!session) |
|
|
|
auto it = m_Peers.find (ident); |
|
|
|
|
|
|
|
if (it == m_Peers.end ()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto r = netdb.FindRouter (ident); |
|
|
|
auto r = netdb.FindRouter (ident); |
|
|
|
if (r) |
|
|
|
it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, nullptr})).first; |
|
|
|
{ |
|
|
|
if (!ConnectToPeer (ident, it->second)) |
|
|
|
if (m_SSUServer) |
|
|
|
{ |
|
|
|
session = m_SSUServer->FindSession (r); |
|
|
|
DeleteI2NPMessage (msg); |
|
|
|
if (!session) |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (it->second.session) |
|
|
|
|
|
|
|
it->second.session->SendI2NPMessage (msg); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
it->second.delayedMessages.push_back (msg); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, Peer& peer) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (peer.router) // we have RI already
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!peer.numAttempts) // NTCP
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
peer.numAttempts++; |
|
|
|
|
|
|
|
auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ()); |
|
|
|
|
|
|
|
if (address && !peer.router->UsesIntroducer () && !peer.router->IsUnreachable ()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// existing session not found. create new
|
|
|
|
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router); |
|
|
|
// try NTCP first if message size < 16K
|
|
|
|
m_NTCPServer->Connect (address->host, address->port, s); |
|
|
|
auto address = r->GetNTCPAddress (!context.SupportsV6 ()); |
|
|
|
return true; |
|
|
|
if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < NTCP_MAX_MESSAGE_SIZE) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, r); |
|
|
|
|
|
|
|
session = s; |
|
|
|
|
|
|
|
m_NTCPServer->Connect (address->host, address->port, s); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// then SSU
|
|
|
|
|
|
|
|
if (m_SSUServer) |
|
|
|
|
|
|
|
session = m_SSUServer->GetSession (r); |
|
|
|
|
|
|
|
if (!session) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LogPrint ("No NTCP and SSU addresses available"); |
|
|
|
|
|
|
|
DeleteI2NPMessage (msg); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else if (peer.numAttempts == 1)// SSU
|
|
|
|
{ |
|
|
|
{ |
|
|
|
LogPrint ("Router not found. Requested"); |
|
|
|
peer.numAttempts++; |
|
|
|
i2p::data::netdb.RequestDestination (ident); |
|
|
|
if (m_SSUServer) |
|
|
|
auto resendTimer = new boost::asio::deadline_timer (m_Service); |
|
|
|
{ |
|
|
|
resendTimer->expires_from_now (boost::posix_time::seconds(5)); // 5 seconds
|
|
|
|
if (m_SSUServer->GetSession (peer.router)) |
|
|
|
resendTimer->async_wait (boost::bind (&Transports::HandleResendTimer, |
|
|
|
return true; |
|
|
|
this, boost::asio::placeholders::error, resendTimer, ident, msg)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
LogPrint (eLogError, "No NTCP and SSU addresses available"); |
|
|
|
|
|
|
|
m_Peers.erase (ident); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else // otherwise request RI
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LogPrint ("Router not found. Requested"); |
|
|
|
|
|
|
|
i2p::data::netdb.RequestDestination (ident); |
|
|
|
|
|
|
|
auto resendTimer = new boost::asio::deadline_timer (m_Service); |
|
|
|
|
|
|
|
resendTimer->expires_from_now (boost::posix_time::seconds(5)); // 5 seconds
|
|
|
|
|
|
|
|
resendTimer->async_wait (boost::bind (&Transports::HandleResendTimer, |
|
|
|
|
|
|
|
this, boost::asio::placeholders::error, resendTimer, ident)); |
|
|
|
} |
|
|
|
} |
|
|
|
if (session) |
|
|
|
return true; |
|
|
|
session->SendI2NPMessage (msg); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Transports::HandleResendTimer (const boost::system::error_code& ecode, |
|
|
|
void Transports::HandleResendTimer (const boost::system::error_code& ecode, |
|
|
|
boost::asio::deadline_timer * timer, const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg) |
|
|
|
boost::asio::deadline_timer * timer, const i2p::data::IdentHash& ident) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto r = netdb.FindRouter (ident); |
|
|
|
auto it = m_Peers.find (ident); |
|
|
|
if (r) |
|
|
|
if (it != m_Peers.end ()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LogPrint ("Router found. Sending message"); |
|
|
|
auto r = netdb.FindRouter (ident); |
|
|
|
PostMessage (ident, msg); |
|
|
|
if (r) |
|
|
|
} |
|
|
|
{ |
|
|
|
else |
|
|
|
LogPrint ("Router found. Trying to connect"); |
|
|
|
{ |
|
|
|
it->second.router = r; |
|
|
|
LogPrint ("Router not found. Failed to send message"); |
|
|
|
ConnectToPeer (ident, it->second); |
|
|
|
DeleteI2NPMessage (msg); |
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LogPrint ("Router not found. Failed to send messages"); |
|
|
|
|
|
|
|
m_Peers.erase (it); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
delete timer; |
|
|
|
delete timer; |
|
|
|
} |
|
|
|
} |
|
|
@ -304,9 +321,10 @@ namespace transport |
|
|
|
it->second.session = session; |
|
|
|
it->second.session = session; |
|
|
|
for (auto it1: it->second.delayedMessages) |
|
|
|
for (auto it1: it->second.delayedMessages) |
|
|
|
session->SendI2NPMessage (it1); |
|
|
|
session->SendI2NPMessage (it1); |
|
|
|
|
|
|
|
it->second.delayedMessages.clear (); |
|
|
|
} |
|
|
|
} |
|
|
|
/* else // incoming connection
|
|
|
|
else // incoming connection
|
|
|
|
m_Peers[ident] = { nullptr, session };*/ |
|
|
|
m_Peers[ident] = { 0, nullptr, session }; |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -317,8 +335,12 @@ namespace transport |
|
|
|
auto ident = session->GetRemoteIdentity ().GetIdentHash (); |
|
|
|
auto ident = session->GetRemoteIdentity ().GetIdentHash (); |
|
|
|
auto it = m_Peers.find (ident); |
|
|
|
auto it = m_Peers.find (ident); |
|
|
|
if (it != m_Peers.end ()) |
|
|
|
if (it != m_Peers.end ()) |
|
|
|
m_Peers.erase (it); |
|
|
|
{ |
|
|
|
// TODO:: check for delayed messages
|
|
|
|
if (it->second.delayedMessages.size () > 0) |
|
|
|
|
|
|
|
ConnectToPeer (ident, it->second); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
m_Peers.erase (it); |
|
|
|
|
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|