Browse Source

full implementation of peer test

pull/163/head
orignal 10 years ago
parent
commit
51aea367c3
  1. 22
      SSU.cpp
  2. 14
      SSU.h
  3. 84
      SSUSession.cpp
  4. 10
      SSUSession.h

22
SSU.cpp

@ -463,12 +463,28 @@ namespace transport
} }
} }
void SSUServer::NewPeerTest (uint32_t nonce) void SSUServer::NewPeerTest (uint32_t nonce, PeerTestParticipant role)
{ {
m_PeerTests[nonce] = i2p::util::GetMillisecondsSinceEpoch (); m_PeerTests[nonce] = { i2p::util::GetMillisecondsSinceEpoch (), role };
} }
void SSUServer::PeerTestComplete (uint32_t nonce) PeerTestParticipant SSUServer::GetPeerTestParticipant (uint32_t nonce)
{
auto it = m_PeerTests.find (nonce);
if (it != m_PeerTests.end ())
return it->second.role;
else
return ePeerTestParticipantUnknown;
}
void SSUServer::UpdatePeerTest (uint32_t nonce, PeerTestParticipant role)
{
auto it = m_PeerTests.find (nonce);
if (it != m_PeerTests.end ())
it->second.role = role;
}
void SSUServer::RemovePeerTest (uint32_t nonce)
{ {
m_PeerTests.erase (nonce); m_PeerTests.erase (nonce);
} }

14
SSU.h

@ -53,8 +53,10 @@ namespace transport
void AddRelay (uint32_t tag, const boost::asio::ip::udp::endpoint& relay); void AddRelay (uint32_t tag, const boost::asio::ip::udp::endpoint& relay);
std::shared_ptr<SSUSession> FindRelaySession (uint32_t tag); std::shared_ptr<SSUSession> FindRelaySession (uint32_t tag);
void NewPeerTest (uint32_t nonce); void NewPeerTest (uint32_t nonce, PeerTestParticipant role);
void PeerTestComplete (uint32_t nonce); PeerTestParticipant GetPeerTestParticipant (uint32_t nonce);
void UpdatePeerTest (uint32_t nonce, PeerTestParticipant role);
void RemovePeerTest (uint32_t nonce);
private: private:
@ -76,6 +78,12 @@ namespace transport
private: private:
struct PeerTest
{
uint64_t creationTime;
PeerTestParticipant role;
};
bool m_IsRunning; bool m_IsRunning;
std::thread * m_Thread, * m_ThreadV6, * m_ReceiversThread; std::thread * m_Thread, * m_ThreadV6, * m_ReceiversThread;
boost::asio::io_service m_Service, m_ServiceV6, m_ReceiversService; boost::asio::io_service m_Service, m_ServiceV6, m_ReceiversService;
@ -87,7 +95,7 @@ namespace transport
std::mutex m_SessionsMutex; std::mutex m_SessionsMutex;
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSUSession> > m_Sessions; std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSUSession> > m_Sessions;
std::map<uint32_t, boost::asio::ip::udp::endpoint> m_Relays; // we are introducer std::map<uint32_t, boost::asio::ip::udp::endpoint> m_Relays; // we are introducer
std::map<uint32_t, uint64_t> m_PeerTests; // nonce -> creation time in milliseconds std::map<uint32_t, PeerTest> m_PeerTests; // nonce -> creation time in milliseconds
public: public:
// for HTTP only // for HTTP only

84
SSUSession.cpp

@ -896,62 +896,80 @@ namespace transport
LogPrint (eLogWarning, "Address of ", size, " bytes not supported"); LogPrint (eLogWarning, "Address of ", size, " bytes not supported");
return; return;
} }
if (m_PeerTestNonces.count (nonce) > 0) switch (m_Server.GetPeerTestParticipant (nonce))
{ {
// existing test // existing test
if (m_PeerTest) // Alice case ePeerTestParticipantAlice1:
{ {
if (m_State == eSessionStateEstablished) if (m_State == eSessionStateEstablished)
LogPrint (eLogDebug, "SSU peer test from Bob. We are Alice"); LogPrint (eLogDebug, "SSU peer test from Bob. We are Alice");
else else
{ {
LogPrint (eLogDebug, "SSU first peer test from Charlie. We are Alice"); LogPrint (eLogDebug, "SSU first peer test from Charlie. We are Alice");
m_PeerTest = false; m_Server.UpdatePeerTest (nonce, ePeerTestParticipantAlice2);
m_PeerTestNonces.erase (nonce);
m_Server.PeerTestComplete (nonce);
SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (), SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (),
senderEndpoint.port (), introKey, true, false); // to Charlie senderEndpoint.port (), introKey, true, false); // to Charlie
} }
} break;
else if (port) // Bob }
case ePeerTestParticipantAlice2:
{
if (m_State == eSessionStateEstablished)
LogPrint (eLogDebug, "SSU peer test from Bob. We are Alice");
else
{
// peer test successive
LogPrint (eLogDebug, "SSU second peer test from Charlie. We are Alice");
m_Server.RemovePeerTest (nonce);
}
break;
}
case ePeerTestParticipantBob:
{ {
LogPrint (eLogDebug, "SSU peer test from Charlie. We are Bob"); LogPrint (eLogDebug, "SSU peer test from Charlie. We are Bob");
m_PeerTestNonces.erase (nonce); // nonce has been used m_Server.RemovePeerTest (nonce); // nonce has been used
boost::asio::ip::udp::endpoint ep (boost::asio::ip::address_v4 (be32toh (address)), be16toh (port)); // Alice's address/port boost::asio::ip::udp::endpoint ep (boost::asio::ip::address_v4 (be32toh (address)), be16toh (port)); // Alice's address/port
auto session = m_Server.FindSession (ep); // find session with Alice auto session = m_Server.FindSession (ep); // find session with Alice
if (session) if (session)
session->Send (PAYLOAD_TYPE_PEER_TEST, buf1, len); // back to Alice session->Send (PAYLOAD_TYPE_PEER_TEST, buf1, len); // back to Alice
break;
} }
else // Charlie case ePeerTestParticipantCharlie:
{ {
LogPrint (eLogDebug, "SSU peer test from Alice. We are Charlie"); LogPrint (eLogDebug, "SSU peer test from Alice. We are Charlie");
m_Server.RemovePeerTest (nonce); // nonce has been used
SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (), SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (),
senderEndpoint.port (), introKey); // to Alice with her actual address senderEndpoint.port (), introKey); // to Alice with her actual address
break;
} }
} // test not found
else case ePeerTestParticipantUnknown:
{
if (m_State == eSessionStateEstablished)
{ {
// new test if (m_State == eSessionStateEstablished)
m_PeerTestNonces.insert (nonce);
if (port)
{ {
LogPrint (eLogDebug, "SSU peer test from Bob. We are Charlie"); // new test
Send (PAYLOAD_TYPE_PEER_TEST, buf1, len); // back to Bob if (port)
SendPeerTest (nonce, be32toh (address), be16toh (port), introKey); // to Alice with her address received from Bob {
LogPrint (eLogDebug, "SSU peer test from Bob. We are Charlie");
m_Server.NewPeerTest (nonce, ePeerTestParticipantCharlie);
Send (PAYLOAD_TYPE_PEER_TEST, buf1, len); // back to Bob
SendPeerTest (nonce, be32toh (address), be16toh (port), introKey); // to Alice with her address received from Bob
}
else
{
LogPrint (eLogDebug, "SSU peer test from Alice. We are Bob");
auto session = m_Server.GetRandomEstablishedSession (shared_from_this ()); // Charlie
if (session)
{
m_Server.NewPeerTest (nonce, ePeerTestParticipantBob);
session->SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (),
senderEndpoint.port (), introKey, false); // to Charlie with Alice's actual address
}
}
} }
else else
{ LogPrint (eLogError, "SSU unexpected peer test");
LogPrint (eLogDebug, "SSU peer test from Alice. We are Bob");
auto session = m_Server.GetRandomEstablishedSession (shared_from_this ()); // Charlie
if (session)
session->SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (),
senderEndpoint.port (), introKey, false); // to Charlie with Alice's actual address
}
} }
else
LogPrint (eLogDebug, "SSU second peer test from Charlie. We are Alice");
} }
} }
@ -1023,8 +1041,8 @@ namespace transport
} }
uint32_t nonce = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (); uint32_t nonce = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
if (!nonce) nonce = 1; if (!nonce) nonce = 1;
m_PeerTestNonces.insert (nonce); m_PeerTest = false;
m_Server.NewPeerTest (nonce); m_Server.NewPeerTest (nonce, ePeerTestParticipantAlice1);
SendPeerTest (nonce, 0, 0, address->key, false, false); // address and port always zero for Alice SendPeerTest (nonce, 0, 0, address->key, false, false); // address and port always zero for Alice
} }

10
SSUSession.h

@ -49,6 +49,15 @@ namespace transport
eSessionStateFailed eSessionStateFailed
}; };
enum PeerTestParticipant
{
ePeerTestParticipantUnknown = 0,
ePeerTestParticipantAlice1,
ePeerTestParticipantAlice2,
ePeerTestParticipantBob,
ePeerTestParticipantCharlie
};
class SSUServer; class SSUServer;
class SSUSession: public TransportSession, public std::enable_shared_from_this<SSUSession> class SSUSession: public TransportSession, public std::enable_shared_from_this<SSUSession>
{ {
@ -133,7 +142,6 @@ namespace transport
SessionState m_State; SessionState m_State;
bool m_IsSessionKey; bool m_IsSessionKey;
uint32_t m_RelayTag; uint32_t m_RelayTag;
std::set<uint32_t> m_PeerTestNonces;
i2p::crypto::CBCEncryption m_SessionKeyEncryption; i2p::crypto::CBCEncryption m_SessionKeyEncryption;
i2p::crypto::CBCDecryption m_SessionKeyDecryption; i2p::crypto::CBCDecryption m_SessionKeyDecryption;
i2p::crypto::AESKey m_SessionKey; i2p::crypto::AESKey m_SessionKey;

Loading…
Cancel
Save