diff --git a/I2CP.cpp b/I2CP.cpp index d3e25e99..d6ba4e42 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -1,3 +1,6 @@ +#include +#include "I2PEndian.h" +#include "Log.h" #include "I2CP.h" @@ -5,12 +8,18 @@ namespace i2p { namespace client { - I2CPSession::I2CPSession (std::shared_ptr socket): - m_Socket (socket) + I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): + m_Owner (owner), m_Socket (socket), + m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0) { ReadProtocolByte (); } + I2CPSession::~I2CPSession () + { + delete[] m_NextMessage; + } + void I2CPSession::ReadProtocolByte () { if (m_Socket) @@ -38,15 +47,65 @@ namespace client if (ecode) Terminate (); else + { + size_t offset = 0; + if (m_NextMessage) + { + if (m_NextMessageOffset + bytes_transferred <= m_NextMessageLen) + { + memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, bytes_transferred); + m_NextMessageOffset += bytes_transferred; + } + else + { + offset = m_NextMessageLen - m_NextMessageOffset; + memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, offset); + HandleNextMessage (m_NextMessage); + delete[] m_NextMessage; + } + } + while (offset < bytes_transferred) + { + auto msgLen = bufbe32toh (m_Buffer + offset + I2CP_HEADER_LENGTH_OFFSET) + I2CP_HEADER_SIZE; + 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 (); + } + } + + void I2CPSession::HandleNextMessage (const uint8_t * buf) + { + auto handler = m_Owner.GetMessagesHandlers ()[buf[I2CP_HEADER_TYPE_OFFSET]]; + if (handler) + (this->*handler)(buf + I2CP_HEADER_SIZE, bufbe32toh (buf + I2CP_HEADER_LENGTH_OFFSET)); + else + LogPrint (eLogError, "I2CP: Unknown I2CP messsage ", (int)buf[I2CP_HEADER_TYPE_OFFSET]); } void I2CPSession::Terminate () { } + void I2CPSession::GetDateMessageHandler (const uint8_t * buf, size_t len) + { + } + I2CPServer::I2CPServer (const std::string& interface, int port) { + memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers)); + m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler; } } } diff --git a/I2CP.h b/I2CP.h index e4b94870..cb17626d 100644 --- a/I2CP.h +++ b/I2CP.h @@ -11,32 +11,55 @@ namespace i2p namespace client { const uint8_t I2CP_PRTOCOL_BYTE = 0x2A; - const size_t I2CP_SESSION_BUFFER_SIZE = 8192; + const size_t I2CP_SESSION_BUFFER_SIZE = 4096; + const size_t I2CP_HEADER_LENGTH_OFFSET = 0; + const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4; + const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; + + const uint8_t I2CP_GET_DATE_MESSAGE = 32; + + class I2CPServer; class I2CPSession: public std::enable_shared_from_this { public: - I2CPSession (std::shared_ptr socket); + I2CPSession (I2CPServer& owner, std::shared_ptr socket); + ~I2CPSession (); + + // message handlers + void GetDateMessageHandler (const uint8_t * buf, size_t len); 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 Terminate (); private: + I2CPServer& m_Owner; std::shared_ptr m_Socket; - uint8_t m_Buffer[I2CP_SESSION_BUFFER_SIZE]; + uint8_t m_Buffer[I2CP_SESSION_BUFFER_SIZE], * m_NextMessage; + size_t m_NextMessageLen, m_NextMessageOffset; }; - + typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len); + class I2CPServer { public: I2CPServer (const std::string& interface, int port); + + private: + + I2CPMessageHandler m_MessagesHandlers[256]; + + public: + + const decltype(m_MessagesHandlers)& GetMessagesHandlers () const { return m_MessagesHandlers; }; }; } }