diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index a78b24b0..4cce355d 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1023,6 +1023,41 @@ namespace transport void NTCP2Session::SendQueue () { if (!m_SendQueue.empty ()) + { + auto buf = m_Server.NewNTCP2FrameBuffer (); + uint8_t * payload = buf->data (); + size_t s = 0; + // add I2NP blocks + while (!m_SendQueue.empty ()) + { + auto msg = m_SendQueue.front (); + size_t len = msg->GetNTCP2Length (); + if (s + len + 3 <= NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) // 3 bytes block header + { + payload[s] = eNTCP2BlkI2NPMessage; // blk + htobe16buf (payload + s + 1, len); // size + s += 3; + msg->ToNTCP2 (); + memcpy (payload + s, msg->GetNTCP2Header (), len); + s += len; + m_SendQueue.pop_front (); + } + else if (len + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) + { + LogPrint (eLogError, "NTCP2: I2NP message of size ", len, " can't be sent. Dropped"); + m_SendQueue.pop_front (); + } + else + break; + } + // add padding block + s += CreatePaddingBlock (s, payload + s, NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - s); + // send + SendNextFrame (payload, s); + m_Server.DeleteNTCP2FrameBuffer (buf); + } + +/* if (!m_SendQueue.empty ()) { std::vector > msgs; size_t s = 0; @@ -1045,7 +1080,7 @@ namespace transport break; } SendI2NPMsgs (msgs); - } + } */ } size_t NTCP2Session::CreatePaddingBlock (size_t msgLen, uint8_t * buf, size_t len) diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index ee7ce892..c0aed286 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -217,6 +217,7 @@ namespace transport std::list > m_SendQueue; }; + typedef std::array NTCP2FrameBuffer; // TODO: remove class NTCP2Server { public: @@ -235,6 +236,9 @@ namespace transport void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr conn); + NTCP2FrameBuffer * NewNTCP2FrameBuffer () { return m_NTCP2FrameBuffersPool.Acquire(); } + void DeleteNTCP2FrameBuffer (NTCP2FrameBuffer * buf) { return m_NTCP2FrameBuffersPool.Release(buf); } + private: void Run (); @@ -258,6 +262,8 @@ namespace transport std::map > m_NTCP2Sessions; std::list > m_PendingIncomingSessions; + i2p::util::MemoryPool m_NTCP2FrameBuffersPool; // TODO: remove + public: // for HTTP/I2PControl