Browse Source

introducer session

pull/64/head
orignal 11 years ago
parent
commit
31f906240e
  1. 97
      SSU.cpp
  2. 8
      SSU.h

97
SSU.cpp

@ -75,18 +75,14 @@ namespace ssu
case eSessionRelayRequestSent: case eSessionRelayRequestSent:
// relay response // relay response
ProcessRelayResponse (buf,len); ProcessRelayResponse (buf,len);
m_Server.DeleteSession (this);
break; break;
case eSessionRelayResponseReceived: case eSessionIntroduced:
// HolePunch received // HolePunch received
LogPrint ("SSU HolePuch of ", len, " bytes received"); LogPrint ("SSU HolePuch of ", len, " bytes received");
m_State = eSessionStateEstablished;
Established ();
break;
case eSessionRelayRequestReceived:
// HolePunch
m_State = eSessionStateUnknown; m_State = eSessionStateUnknown;
Connect (); Connect ();
break; break;
default: default:
LogPrint ("SSU state not implemented yet"); LogPrint ("SSU state not implemented yet");
} }
@ -151,7 +147,7 @@ namespace ssu
if (!Validate (buf, len, introKey)) if (!Validate (buf, len, introKey))
{ {
LogPrint ("MAC verification intro key failed"); LogPrint ("MAC verification intro key failed");
Failed (); m_Server.DeleteSession (this);
return; return;
} }
@ -273,7 +269,7 @@ namespace ssu
m_Server.Send (buf, 304, m_RemoteEndpoint); m_Server.Send (buf, 304, m_RemoteEndpoint);
} }
void SSUSession::SendRelayRequest (const i2p::data::RouterInfo::Introducer& introducer) void SSUSession::SendRelayRequest (uint32_t iTag, const uint8_t * iKey)
{ {
auto address = i2p::context.GetRouterInfo ().GetSSUAddress (); auto address = i2p::context.GetRouterInfo ().GetSSUAddress ();
if (!address) if (!address)
@ -284,7 +280,7 @@ namespace ssu
uint8_t buf[96 + 18]; uint8_t buf[96 + 18];
uint8_t * payload = buf + sizeof (SSUHeader); uint8_t * payload = buf + sizeof (SSUHeader);
*(uint32_t *)payload = htobe32 (introducer.iTag); *(uint32_t *)payload = htobe32 (iTag);
payload += 4; payload += 4;
*payload = 0; // no address *payload = 0; // no address
payload++; payload++;
@ -299,7 +295,7 @@ namespace ssu
uint8_t iv[16]; uint8_t iv[16];
rnd.GenerateBlock (iv, 16); // random iv rnd.GenerateBlock (iv, 16); // random iv
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, introducer.iKey, iv, introducer.iKey); FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, iKey, iv, iKey);
m_State = eSessionRelayRequestSent; m_State = eSessionRelayRequestSent;
m_Server.Send (buf, 96, m_RemoteEndpoint); m_Server.Send (buf, 96, m_RemoteEndpoint);
} }
@ -404,27 +400,22 @@ namespace ssu
{ {
Decrypt (buf, len, address->key); Decrypt (buf, len, address->key);
SSUHeader * header = (SSUHeader *)buf; SSUHeader * header = (SSUHeader *)buf;
if ((header->flag >> 4) == PAYLOAD_TYPE_RELAY_RESPONSE) if (header->GetPayloadType () == PAYLOAD_TYPE_RELAY_RESPONSE)
{ {
LogPrint ("Relay response received"); LogPrint ("Relay response received");
m_State = eSessionRelayRequestReceived;
uint8_t * payload = buf + sizeof (SSUHeader); uint8_t * payload = buf + sizeof (SSUHeader);
payload++; payload++; // remote size
boost::asio::ip::address_v4 remoteIP (be32toh (*(uint32_t* )(payload))); //boost::asio::ip::address_v4 remoteIP (be32toh (*(uint32_t* )(payload)));
payload += 4; payload += 4; // remote address
uint16_t remotePort = be16toh (*(uint16_t *)(payload)); //uint16_t remotePort = be16toh (*(uint16_t *)(payload));
payload += 2; payload += 2; // remote port
boost::asio::ip::udp::endpoint newRemoteEndpoint(remoteIP, remotePort); payload++; // our size
m_Server.ReassignSession (m_RemoteEndpoint, newRemoteEndpoint);
m_RemoteEndpoint = newRemoteEndpoint;
payload++;
boost::asio::ip::address_v4 ourIP (be32toh (*(uint32_t* )(payload))); boost::asio::ip::address_v4 ourIP (be32toh (*(uint32_t* )(payload)));
payload += 4; payload += 4; // our address
uint16_t ourPort = be16toh (*(uint16_t *)(payload)); uint16_t ourPort = be16toh (*(uint16_t *)(payload));
payload += 2; payload += 2; // our port
LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort); LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort);
i2p::context.UpdateAddress (ourIP.to_string ().c_str ()); i2p::context.UpdateAddress (ourIP.to_string ().c_str ());
m_State= eSessionRelayResponseReceived;
} }
else else
LogPrint ("Unexpected payload type ", (int)(header->flag >> 4)); LogPrint ("Unexpected payload type ", (int)(header->flag >> 4));
@ -524,7 +515,7 @@ namespace ssu
} }
} }
void SSUSession::ConnectThroughIntroducer (const i2p::data::RouterInfo::Introducer& introducer) void SSUSession::Introduce (uint32_t iTag, const uint8_t * iKey)
{ {
if (m_State == eSessionStateUnknown) if (m_State == eSessionStateUnknown)
{ {
@ -532,10 +523,19 @@ namespace ssu
m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT));
m_Timer.async_wait (boost::bind (&SSUSession::HandleConnectTimer, m_Timer.async_wait (boost::bind (&SSUSession::HandleConnectTimer,
this, boost::asio::placeholders::error)); this, boost::asio::placeholders::error));
SendRelayRequest (introducer); SendRelayRequest (iTag, iKey);
} }
} }
void SSUSession::WaitForIntroduction ()
{
m_State = eSessionIntroduced;
// set connect timer
m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT));
m_Timer.async_wait (boost::bind (&SSUSession::HandleConnectTimer,
this, boost::asio::placeholders::error));
}
void SSUSession::Close () void SSUSession::Close ()
{ {
SendSesionDestroyed (); SendSesionDestroyed ();
@ -977,11 +977,12 @@ namespace ssu
else else
{ {
// otherwise create new session // otherwise create new session
session = new SSUSession (*this, remoteEndpoint, router, peerTest);
m_Sessions[remoteEndpoint] = session;
if (!router->UsesIntroducer ()) if (!router->UsesIntroducer ())
{ {
// connect directly // connect directly
session = new SSUSession (*this, remoteEndpoint, router, peerTest);
m_Sessions[remoteEndpoint] = session;
LogPrint ("Creating new SSU session to [", router->GetIdentHashAbbreviation (), "] ", LogPrint ("Creating new SSU session to [", router->GetIdentHashAbbreviation (), "] ",
remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ()); remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ());
session->Connect (); session->Connect ();
@ -989,24 +990,27 @@ namespace ssu
else else
{ {
// connect through introducer // connect through introducer
session->WaitForIntroduction ();
if (address->introducers.size () > 0) if (address->introducers.size () > 0)
{ {
auto& introducer = address->introducers[0]; // TODO: auto& introducer = address->introducers[0]; // TODO:
boost::asio::ip::udp::endpoint introducerEndpoint (introducer.iHost, introducer.iPort); boost::asio::ip::udp::endpoint introducerEndpoint (introducer.iHost, introducer.iPort);
it = m_Sessions.find (introducerEndpoint); LogPrint ("Creating new SSU session to [", router->GetIdentHashAbbreviation (),
if (it == m_Sessions.end ())
{
session = new SSUSession (*this, introducerEndpoint, router);
m_Sessions[introducerEndpoint] = session;
LogPrint ("Creating new SSU session to [", router->GetIdentHashAbbreviation (),
"] through introducer ", introducerEndpoint.address ().to_string (), ":", introducerEndpoint.port ()); "] through introducer ", introducerEndpoint.address ().to_string (), ":", introducerEndpoint.port ());
session->ConnectThroughIntroducer (introducer); it = m_Sessions.find (introducerEndpoint);
} SSUSession * introducerSession = nullptr;
else if (it != m_Sessions.end ())
{ {
LogPrint ("Session to introducer already exists"); LogPrint ("Session to introducer already exists");
// TODO: introducerSession = it->second;
} }
else
{
LogPrint ("New session to introducer created");
introducerSession = new SSUSession (*this, introducerEndpoint, router);
m_Sessions[introducerEndpoint] = introducerSession;
}
introducerSession->Introduce (introducer.iTag, introducer.iKey);
} }
else else
LogPrint ("Router is unreachable, but not introducers presentd. Ignored"); LogPrint ("Router is unreachable, but not introducers presentd. Ignored");
@ -1038,19 +1042,6 @@ namespace ssu
} }
m_Sessions.clear (); m_Sessions.clear ();
} }
void SSUServer::ReassignSession (const boost::asio::ip::udp::endpoint& oldEndpoint, const boost::asio::ip::udp::endpoint& newEndpoint)
{
auto it = m_Sessions.find (oldEndpoint);
if (it != m_Sessions.end ())
{
auto session = it->second;
m_Sessions.erase (it);
m_Sessions[newEndpoint] = session;
LogPrint ("SSU session reassigned from ", oldEndpoint.address ().to_string (), ":", oldEndpoint.port (),
" to ", newEndpoint.address ().to_string (), ":", newEndpoint.port ());
}
}
} }
} }

8
SSU.h

@ -62,7 +62,7 @@ namespace ssu
eSessionStateConfirmedReceived, eSessionStateConfirmedReceived,
eSessionRelayRequestSent, eSessionRelayRequestSent,
eSessionRelayRequestReceived, eSessionRelayRequestReceived,
eSessionRelayResponseReceived, eSessionIntroduced,
eSessionStateEstablished, eSessionStateEstablished,
eSessionStateFailed eSessionStateFailed
}; };
@ -78,7 +78,8 @@ namespace ssu
~SSUSession (); ~SSUSession ();
void Connect (); void Connect ();
void ConnectThroughIntroducer (const i2p::data::RouterInfo::Introducer& introducer); void Introduce (uint32_t iTag, const uint8_t * iKey);
void WaitForIntroduction ();
void Close (); void Close ();
boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
const i2p::data::RouterInfo * GetRemoteRouter () const { return m_RemoteRouter; }; const i2p::data::RouterInfo * GetRemoteRouter () const { return m_RemoteRouter; };
@ -94,7 +95,7 @@ namespace ssu
void ProcessSessionRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); void ProcessSessionRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
void SendSessionRequest (); void SendSessionRequest ();
void SendRelayRequest (const i2p::data::RouterInfo::Introducer& introducer); void SendRelayRequest (uint32_t iTag, const uint8_t * iKey);
void ProcessSessionCreated (uint8_t * buf, size_t len); void ProcessSessionCreated (uint8_t * buf, size_t len);
void SendSessionCreated (const uint8_t * x); void SendSessionCreated (const uint8_t * x);
void ProcessSessionConfirmed (uint8_t * buf, size_t len); void ProcessSessionConfirmed (uint8_t * buf, size_t len);
@ -153,7 +154,6 @@ namespace ssu
boost::asio::io_service& GetService () { return m_Socket.get_io_service(); }; boost::asio::io_service& GetService () { return m_Socket.get_io_service(); };
const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; }; const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; };
void Send (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); void Send (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to);
void ReassignSession (const boost::asio::ip::udp::endpoint& oldEndpoint, const boost::asio::ip::udp::endpoint& newEndpoint);
private: private:

Loading…
Cancel
Save