diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index fbec0a5b..d33592c1 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -853,6 +853,8 @@ namespace transport } break; case eSSU2BlkRelayTag: + LogPrint (eLogDebug, "SSU2: RelayTag"); + m_RelayTag = bufbe32toh (buf + offset); break; case eSSU2BlkNewToken: { @@ -1026,8 +1028,8 @@ namespace transport s.Insert (session->GetRemoteIdentity ()->GetIdentHash (), 32); // chash s.Insert (buf + 1, 14); // nonce, relay tag, timestamp, ver, asz uint8_t asz = buf[14]; - s.Insert (buf + 15, asz + 2); // Alice IP, Alice Port - if (!s.Verify (GetRemoteIdentity (), buf + 17 + asz)) + s.Insert (buf + 15, asz); // Alice Port, Alice IP + if (!s.Verify (GetRemoteIdentity (), buf + 15 + asz)) { LogPrint (eLogWarning, "SSU2: RelayRequest signature verification failed"); return; // TODO: send relay response @@ -1039,6 +1041,29 @@ namespace transport payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MTU - payloadSize); session->SendData (payload, payloadSize); } + + void SSU2Session::HandleRelayIntro (const uint8_t * buf, size_t len) + { + // we are Charlie + SignedData s; + s.Insert ((const uint8_t *)"RelayRequestData", 16); // prologue + s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash + s.Insert (i2p::context.GetIdentHash (), 32); // chash + s.Insert (buf + 33, 14); // nonce, relay tag, timestamp, ver, asz + uint8_t asz = buf[46]; + s.Insert (buf + 47, asz); // Alice Port, Alice IP + if (!s.Verify (GetRemoteIdentity (), buf + 47 + asz)) + { + LogPrint (eLogWarning, "SSU2: RelayIntro signature verification failed"); + return; // TODO: send relay response + } + + // TODO: send RelayResponse to Bob + + boost::asio::ip::udp::endpoint ep; + if (ExtractEndpoint (buf + 47, asz, ep)) + m_Server.SendHolePunch (ep); + } bool SSU2Session::ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep) { @@ -1580,7 +1605,10 @@ namespace transport m_SocketV6.send_to (bufs, to, 0, ec); else m_SocketV4.send_to (bufs, to, 0, ec); - i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen); + if (!ec) + i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen); + else + LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to); } void SSU2Server::Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen, @@ -1597,9 +1625,25 @@ namespace transport m_SocketV6.send_to (bufs, to, 0, ec); else m_SocketV4.send_to (bufs, to, 0, ec); - i2p::transport::transports.UpdateSentBytes (headerLen + headerXLen + payloadLen); + + if (!ec) + i2p::transport::transports.UpdateSentBytes (headerLen + headerXLen + payloadLen); + else + LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to); } + void SSU2Server::SendHolePunch (const boost::asio::ip::udp::endpoint& to) + { + boost::system::error_code ec; + if (to.address ().is_v6 ()) + m_SocketV6.send_to (boost::asio::buffer ((uint8_t *)nullptr, 0), to, 0, ec); + else + m_SocketV4.send_to (boost::asio::buffer ((uint8_t *)nullptr, 0), to, 0, ec); + + if (ec) + LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to); + } + bool SSU2Server::CreateSession (std::shared_ptr router, std::shared_ptr address) { diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index b70b1ebe..1bd930f6 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -186,6 +186,7 @@ namespace transport void HandleFollowOnFragment (const uint8_t * buf, size_t len); bool ConcatOutOfSequenceFragments (std::shared_ptr m); // true if message complete void HandleRelayRequest (const uint8_t * buf, size_t len); + void HandleRelayIntro (const uint8_t * buf, size_t len); size_t CreateAddressBlock (const boost::asio::ip::udp::endpoint& ep, uint8_t * buf, size_t len); size_t CreateAckBlock (uint8_t * buf, size_t len); @@ -257,7 +258,8 @@ namespace transport const boost::asio::ip::udp::endpoint& to); void Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen, const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to); - + void SendHolePunch (const boost::asio::ip::udp::endpoint& to); + bool CreateSession (std::shared_ptr router, std::shared_ptr address);