diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 209d3352..f99c67b6 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -148,7 +148,7 @@ namespace transport void SSU2Server::Receive (boost::asio::ip::udp::socket& socket) { Packet * packet = m_PacketsPool.AcquireMt (); - socket.async_receive_from (boost::asio::buffer (packet->buf, SSU2_MTU), packet->from, + socket.async_receive_from (boost::asio::buffer (packet->buf, SSU2_MAX_PACKET_SIZE), packet->from, std::bind (&SSU2Server::HandleReceivedFrom, this, std::placeholders::_1, std::placeholders::_2, packet, std::ref (socket))); } @@ -388,7 +388,7 @@ namespace transport m_LastSession->ProcessPeerTest (buf, len); break; case eSSU2SessionStateClosing: - m_LastSession->RequestTermination (); // send termination again + m_LastSession->RequestTermination (eSSU2TerminationReasonIdleTimeout); // send termination again break; case eSSU2SessionStateTerminated: m_LastSession = nullptr; @@ -630,7 +630,7 @@ namespace transport else if (it.second->IsTerminationTimeoutExpired (ts)) { if (it.second->IsEstablished ()) - it.second->RequestTermination (); + it.second->RequestTermination (eSSU2TerminationReasonIdleTimeout); else GetService ().post (std::bind (&SSU2Session::Terminate, it.second)); } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 429cfdb7..99862947 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -25,7 +25,7 @@ namespace transport { struct Packet { - uint8_t buf[SSU2_MTU]; + uint8_t buf[SSU2_MAX_PACKET_SIZE]; size_t len; boost::asio::ip::udp::endpoint from; }; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index d3fc2555..4e1d63ca 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -25,7 +25,7 @@ namespace transport m_DestConnID (0), m_SourceConnID (0), m_State (eSSU2SessionStateUnknown), m_SendPacketNum (0), m_ReceivePacketNum (0), m_IsDataReceived (false), m_WindowSize (SSU2_MAX_WINDOW_SIZE), m_RelayTag (0), - m_ConnectTimer (server.GetService ()) + m_ConnectTimer (server.GetService ()), m_TerminationReason (eSSU2TerminationReasonNormalClose) { m_NoiseState.reset (new i2p::crypto::NoiseSymmetricState); if (in_RemoteRouter && m_Address) @@ -168,11 +168,12 @@ namespace transport } } - void SSU2Session::RequestTermination () + void SSU2Session::RequestTermination (SSU2TerminationReason reason) { if (m_State == eSSU2SessionStateEstablished || m_State == eSSU2SessionStateClosing) { m_State = eSSU2SessionStateClosing; + m_TerminationReason = reason; SendTermination (); } } @@ -329,7 +330,7 @@ namespace transport LogPrint (eLogInfo, "SSU2: Packet was not Acked after ", it->second->numResends, " attempts. Terminate session"); m_SentPackets.clear (); m_SendQueue.clear (); - RequestTermination (); + RequestTermination (eSSU2TerminationReasonTimeout); return; } else @@ -2097,6 +2098,15 @@ namespace transport return CreatePeerTestBlock (buf, len, 1, eSSU2PeerTestCodeAccept, nullptr, signedData, 10 + asz + i2p::context.GetIdentity ()->GetSignatureLen ()); } + + size_t SSU2Session::CreateTerminationBlock (uint8_t * buf, size_t len) + { + buf[0] = eSSU2BlkTermination; + htobe16buf (buf + 1, 9); + htobe64buf (buf + 3, m_ReceivePacketNum); + buf[11] = (uint8_t)m_TerminationReason; + return 12; + } std::shared_ptr SSU2Session::ExtractRouterInfo (const uint8_t * buf, size_t size) { @@ -2157,10 +2167,7 @@ namespace transport void SSU2Session::SendTermination () { uint8_t payload[32]; - size_t payloadSize = 12; - payload[0] = eSSU2BlkTermination; - htobe16buf (payload + 1, 9); - memset (payload + 3, 0, 9); + size_t payloadSize = CreateTerminationBlock (payload, 32); payloadSize += CreatePaddingBlock (payload + payloadSize, 32 - payloadSize); SendData (payload, payloadSize); } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 348cff56..a287a6de 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -31,6 +31,7 @@ namespace transport const int SSU2_TOKEN_EXPIRATION_THRESHOLD = 2; // in seconds const int SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT = 10; // in seconds const int SSU2_PEER_TEST_EXPIRATION_TIMEOUT = 60; // 60 seconds + const size_t SSU2_MAX_PACKET_SIZE = 1500; const size_t SSU2_MTU = 1440; // TODO: should be 1456 for ipv4 const size_t SSU2_MAX_PAYLOAD_SIZE = SSU2_MTU - 32; const int SSU2_HANDSHAKE_RESEND_INTERVAL = 1; // in seconds @@ -119,6 +120,32 @@ namespace transport eSSU2RelayResponseCodeCharlieSignatureFailure = 67, eSSU2RelayResponseCodeCharlieAliceIsUnknown = 70 }; + + enum SSU2TerminationReason + { + eSSU2TerminationReasonNormalClose = 0, + eSSU2TerminationReasonTerminationReceived = 1, + eSSU2TerminationReasonIdleTimeout = 2, + eSSU2TerminationReasonRouterShutdown = 3, + eSSU2TerminationReasonDataPhaseAEADFailure= 4, + eSSU2TerminationReasonIncompatibleOptions = 5, + eSSU2TerminationReasonTncompatibleSignatureType = 6, + eSSU2TerminationReasonClockSkew = 7, + eSSU2TerminationPaddingViolation = 8, + eSSU2TerminationReasonAEADFramingError = 9, + eSSU2TerminationReasonPayloadFormatError = 10, + eSSU2TerminationReasonSessionRequestError = 11, + eSSU2TerminationReasonSessionCreatedError = 12, + eSSU2TerminationReasonSessionConfirmedError = 13, + eSSU2TerminationReasonTimeout = 14, + eSSU2TerminationReasonRouterInfoSignatureVerificationFail = 15, + eSSU2TerminationReasonInvalidS = 16, + eSSU2TerminationReasonBanned = 17, + eSSU2TerminationReasonBadToken = 18, + eSSU2TerminationReasonConnectionLimits = 19, + eSSU2TerminationReasonIncompatibleVersion = 20, + eSSU2TerminationReasonWrongNetID = 21 + }; struct SSU2IncompleteMessage { @@ -189,7 +216,7 @@ namespace transport void WaitForIntroduction (); void SendPeerTest (); // Alice, Data message void Terminate (); - void RequestTermination (); + void RequestTermination (SSU2TerminationReason reason); void CleanUp (uint64_t ts); void FlushData (); void Done () override; @@ -264,6 +291,7 @@ namespace transport size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, SSU2RelayResponseCode code, uint32_t nonce, bool endpoint, uint64_t token); // add endpoint for Chralie and no endpoint for Bob size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen); size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint32_t nonce); // Alice + size_t CreateTerminationBlock (uint8_t * buf, size_t len); private: @@ -291,6 +319,7 @@ namespace transport uint32_t m_RelayTag; // between Bob and Charlie OnEstablished m_OnEstablished; // callback from Established boost::asio::deadline_timer m_ConnectTimer; + SSU2TerminationReason m_TerminationReason; }; inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce)