diff --git a/libi2pd/SSU2OutOfSession.cpp b/libi2pd/SSU2OutOfSession.cpp index 46809217..a2e0941e 100644 --- a/libi2pd/SSU2OutOfSession.cpp +++ b/libi2pd/SSU2OutOfSession.cpp @@ -229,7 +229,7 @@ namespace transport const boost::asio::ip::udp::endpoint& remoteEndpoint, std::shared_ptr addr): SSU2Session (server), // we create full incoming session - m_Nonce (nonce) + m_Nonce (nonce), m_NumResends (0), m_HolePunchResendTimer (server.GetService ()) { // we are Charlie uint64_t destConnID = htobe64 (((uint64_t)nonce << 32) | nonce); // dest id @@ -295,6 +295,36 @@ namespace transport memcpy (m_RelayResponseBlock.data (), relayResponseBlock, relayResponseBlockLen); #endif SendHolePunch (); + ScheduleResend (); + } + + void SSU2HolePunchSession::ScheduleResend () + { + if (m_NumResends < SSU2_HOLE_PUNCH_MAX_NUM_RESENDS) + { + m_HolePunchResendTimer.expires_from_now (boost::posix_time::milliseconds( + SSU2_HOLE_PUNCH_RESEND_INTERVAL + GetServer ().GetRng ()() % SSU2_HOLE_PUNCH_RESEND_INTERVAL_VARIANCE)); + std::weak_ptr s(std::static_pointer_cast(shared_from_this ())); + m_HolePunchResendTimer.async_wait ([s](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto s1 = s.lock (); + if (s1 && s1->GetState () == eSSU2SessionStateHolePunch) + { + s1->SendHolePunch (); + s1->ScheduleResend (); + } + } + }); + m_NumResends++; + } + } + + bool SSU2HolePunchSession::ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len) + { + m_HolePunchResendTimer.cancel (); + return SSU2Session::ProcessFirstIncomingMessage (connID, buf, len); } } } diff --git a/libi2pd/SSU2OutOfSession.h b/libi2pd/SSU2OutOfSession.h index 1069ab40..176a30f9 100644 --- a/libi2pd/SSU2OutOfSession.h +++ b/libi2pd/SSU2OutOfSession.h @@ -52,6 +52,10 @@ namespace transport boost::asio::deadline_timer m_PeerTestResendTimer; }; + const int SSU2_HOLE_PUNCH_RESEND_INTERVAL = 1000; // in milliseconds + const int SSU2_HOLE_PUNCH_RESEND_INTERVAL_VARIANCE = 500; // in milliseconds + const int SSU2_HOLE_PUNCH_MAX_NUM_RESENDS = 3; + class SSU2HolePunchSession: public SSU2Session // Charlie { public: @@ -60,15 +64,20 @@ namespace transport std::shared_ptr addr); void SendHolePunch (const uint8_t * relayResponseBlock, size_t relayResponseBlockLen); + + bool ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len) override; // SessionRequest private: void SendHolePunch (); + void ScheduleResend (); private: uint32_t m_Nonce; + int m_NumResends; std::vector m_RelayResponseBlock; + boost::asio::deadline_timer m_HolePunchResendTimer; }; } }