diff --git a/I2CP.cpp b/I2CP.cpp index dab7f9b0..f506a312 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -115,15 +115,14 @@ namespace client } I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): - m_Owner (owner), m_Socket (socket), - m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0), + m_Owner (owner), m_Socket (socket), m_Payload (nullptr), m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true) { } I2CPSession::~I2CPSession () { - delete[] m_NextMessage; + delete[] m_Payload; } void I2CPSession::Start () @@ -141,117 +140,72 @@ namespace client if (m_Socket) { auto s = shared_from_this (); - m_Socket->async_read_some (boost::asio::buffer (m_Buffer, 1), + m_Socket->async_read_some (boost::asio::buffer (m_Header, 1), [s](const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (!ecode && bytes_transferred > 0 && s->m_Buffer[0] == I2CP_PROTOCOL_BYTE) - s->Receive (); + if (!ecode && bytes_transferred > 0 && s->m_Header[0] == I2CP_PROTOCOL_BYTE) + s->ReceiveHeader (); else s->Terminate (); }); } } - void I2CPSession::Receive () + void I2CPSession::ReceiveHeader () { - m_Socket->async_read_some (boost::asio::buffer (m_Buffer, I2CP_SESSION_BUFFER_SIZE), - std::bind (&I2CPSession::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Header, I2CP_HEADER_SIZE), + boost::asio::transfer_all (), + std::bind (&I2CPSession::HandleReceivedHeader, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } - void I2CPSession::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) + void I2CPSession::HandleReceivedHeader (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) Terminate (); else { - size_t offset = 0; // from m_Buffer - if (m_NextMessage) + m_PayloadLen = bufbe32toh (m_Header + I2CP_HEADER_LENGTH_OFFSET); + if (m_PayloadLen > 0) { - if (!m_NextMessageLen) // we didn't receive header yet - { - if (m_NextMessageOffset + bytes_transferred < I2CP_HEADER_SIZE) - { - // still no complete header - memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, bytes_transferred); - m_NextMessageOffset += bytes_transferred; - offset = bytes_transferred; - } - else - { - // we know message length now - offset = I2CP_HEADER_SIZE - m_NextMessageOffset; - memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, offset); - m_NextMessageLen = bufbe32toh (m_NextMessage + I2CP_HEADER_LENGTH_OFFSET) + I2CP_HEADER_SIZE; - m_NextMessageOffset = I2CP_HEADER_SIZE; - } - } - - if (offset < bytes_transferred) - { - auto msgRemainingLen = m_NextMessageLen - m_NextMessageOffset; - auto bufRemainingLen = bytes_transferred - offset; - if (bufRemainingLen < msgRemainingLen) - { - memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer + offset, bufRemainingLen); - m_NextMessageOffset += bufRemainingLen; - offset += bufRemainingLen; - } - else - { - // m_NextMessage complete - offset += msgRemainingLen; - memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer + offset, msgRemainingLen); - HandleNextMessage (m_NextMessage); - delete[] m_NextMessage; - m_NextMessage = nullptr; - } - } - } - // process the rest - while (offset < bytes_transferred) + m_Payload = new uint8_t[m_PayloadLen]; + ReceivePayload (); + } + else // no following payload { - if (bytes_transferred - offset < I2CP_HEADER_SIZE) - { - // we don't have message header yet - m_NextMessage = new uint8_t[0xFFFF]; // allocate 64K - m_NextMessageLen = 0; // we must set message length later - m_NextMessageOffset = bytes_transferred - offset; - memcpy (m_NextMessage, m_Buffer + offset, m_NextMessageOffset); // just copy it - break; - } - - auto msgLen = bufbe32toh (m_Buffer + offset + I2CP_HEADER_LENGTH_OFFSET) + I2CP_HEADER_SIZE; - if (msgLen > 0xFFFF) // 64K - { - LogPrint (eLogError, "I2CP: message length ", msgLen, " exceeds 64K. Terminated"); - Terminate (); - return; - } - if (msgLen <= bytes_transferred - offset) - { - HandleNextMessage (m_Buffer + offset); - offset += msgLen; - } - else - { - m_NextMessageLen = msgLen; - m_NextMessageOffset = bytes_transferred - offset; - m_NextMessage = new uint8_t[m_NextMessageLen]; - memcpy (m_NextMessage, m_Buffer + offset, m_NextMessageOffset); - offset = bytes_transferred; - } - } - Receive (); + HandleMessage (); + ReceiveHeader (); // next message + } + } + } + + void I2CPSession::ReceivePayload () + { + boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Payload, m_PayloadLen), + boost::asio::transfer_all (), + std::bind (&I2CPSession::HandleReceivedPayload, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + } + + void I2CPSession::HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred) + { + if (ecode) + Terminate (); + else + { + HandleMessage (); + delete[] m_Payload; + m_Payload = nullptr; + m_PayloadLen = 0; + ReceiveHeader (); // next message } } - void I2CPSession::HandleNextMessage (const uint8_t * buf) + void I2CPSession::HandleMessage () { - auto handler = m_Owner.GetMessagesHandlers ()[buf[I2CP_HEADER_TYPE_OFFSET]]; + auto handler = m_Owner.GetMessagesHandlers ()[m_Header[I2CP_HEADER_TYPE_OFFSET]]; if (handler) - (this->*handler)(buf + I2CP_HEADER_SIZE, bufbe32toh (buf + I2CP_HEADER_LENGTH_OFFSET)); + (this->*handler)(m_Payload, m_PayloadLen); else - LogPrint (eLogError, "I2CP: Unknown I2CP messsage ", (int)buf[I2CP_HEADER_TYPE_OFFSET]); + LogPrint (eLogError, "I2CP: Unknown I2CP messsage ", (int)m_Header[I2CP_HEADER_TYPE_OFFSET]); } void I2CPSession::Terminate () @@ -267,6 +221,7 @@ namespace client m_Socket = nullptr; } m_Owner.RemoveSession (GetSessionID ()); + LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " terminated"); } void I2CPSession::SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len) diff --git a/I2CP.h b/I2CP.h index f77607ba..6fc0e846 100644 --- a/I2CP.h +++ b/I2CP.h @@ -126,9 +126,11 @@ namespace client private: void ReadProtocolByte (); - void Receive (); - void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); - void HandleNextMessage (const uint8_t * buf); + void ReceiveHeader (); + void HandleReceivedHeader (const boost::system::error_code& ecode, std::size_t bytes_transferred); + void ReceivePayload (); + void HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred); + void HandleMessage (); void Terminate (); void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf); @@ -143,8 +145,8 @@ namespace client I2CPServer& m_Owner; std::shared_ptr m_Socket; - uint8_t m_Buffer[I2CP_SESSION_BUFFER_SIZE], * m_NextMessage; - size_t m_NextMessageLen, m_NextMessageOffset; + uint8_t m_Header[I2CP_HEADER_SIZE], * m_Payload; + size_t m_PayloadLen; std::shared_ptr m_Destination; uint16_t m_SessionID;