Browse Source

read header and payload separately

pull/515/head
orignal 9 years ago
parent
commit
fb94d6ae2b
  1. 135
      I2CP.cpp
  2. 12
      I2CP.h

135
I2CP.cpp

@ -115,15 +115,14 @@ namespace client
} }
I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket): I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
m_Owner (owner), m_Socket (socket), m_Owner (owner), m_Socket (socket), m_Payload (nullptr),
m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0),
m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true) m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true)
{ {
} }
I2CPSession::~I2CPSession () I2CPSession::~I2CPSession ()
{ {
delete[] m_NextMessage; delete[] m_Payload;
} }
void I2CPSession::Start () void I2CPSession::Start ()
@ -141,117 +140,72 @@ namespace client
if (m_Socket) if (m_Socket)
{ {
auto s = shared_from_this (); 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) [s](const boost::system::error_code& ecode, std::size_t bytes_transferred)
{ {
if (!ecode && bytes_transferred > 0 && s->m_Buffer[0] == I2CP_PROTOCOL_BYTE) if (!ecode && bytes_transferred > 0 && s->m_Header[0] == I2CP_PROTOCOL_BYTE)
s->Receive (); s->ReceiveHeader ();
else else
s->Terminate (); s->Terminate ();
}); });
} }
} }
void I2CPSession::Receive () void I2CPSession::ReceiveHeader ()
{ {
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, I2CP_SESSION_BUFFER_SIZE), boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Header, I2CP_HEADER_SIZE),
std::bind (&I2CPSession::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 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) if (ecode)
Terminate (); Terminate ();
else else
{ {
size_t offset = 0; // from m_Buffer m_PayloadLen = bufbe32toh (m_Header + I2CP_HEADER_LENGTH_OFFSET);
if (m_NextMessage) if (m_PayloadLen > 0)
{ {
if (!m_NextMessageLen) // we didn't receive header yet m_Payload = new uint8_t[m_PayloadLen];
{ ReceivePayload ();
if (m_NextMessageOffset + bytes_transferred < I2CP_HEADER_SIZE) }
{ else // no following payload
// 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)
{ {
if (bytes_transferred - offset < I2CP_HEADER_SIZE) HandleMessage ();
{ ReceiveHeader (); // next message
// 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 void I2CPSession::ReceivePayload ()
break; {
} boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Payload, m_PayloadLen),
boost::asio::transfer_all (),
auto msgLen = bufbe32toh (m_Buffer + offset + I2CP_HEADER_LENGTH_OFFSET) + I2CP_HEADER_SIZE; std::bind (&I2CPSession::HandleReceivedPayload, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
if (msgLen > 0xFFFF) // 64K }
{
LogPrint (eLogError, "I2CP: message length ", msgLen, " exceeds 64K. Terminated"); void I2CPSession::HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred)
Terminate (); {
return; if (ecode)
} Terminate ();
if (msgLen <= bytes_transferred - offset) else
{ {
HandleNextMessage (m_Buffer + offset); HandleMessage ();
offset += msgLen; delete[] m_Payload;
} m_Payload = nullptr;
else m_PayloadLen = 0;
{ ReceiveHeader (); // next message
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) 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) if (handler)
(this->*handler)(buf + I2CP_HEADER_SIZE, bufbe32toh (buf + I2CP_HEADER_LENGTH_OFFSET)); (this->*handler)(m_Payload, m_PayloadLen);
else 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 () void I2CPSession::Terminate ()
@ -267,6 +221,7 @@ namespace client
m_Socket = nullptr; m_Socket = nullptr;
} }
m_Owner.RemoveSession (GetSessionID ()); m_Owner.RemoveSession (GetSessionID ());
LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " terminated");
} }
void I2CPSession::SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len) void I2CPSession::SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len)

12
I2CP.h

@ -126,9 +126,11 @@ namespace client
private: private:
void ReadProtocolByte (); void ReadProtocolByte ();
void Receive (); void ReceiveHeader ();
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleReceivedHeader (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleNextMessage (const uint8_t * buf); void ReceivePayload ();
void HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleMessage ();
void Terminate (); void Terminate ();
void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf); 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; I2CPServer& m_Owner;
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket; std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
uint8_t m_Buffer[I2CP_SESSION_BUFFER_SIZE], * m_NextMessage; uint8_t m_Header[I2CP_HEADER_SIZE], * m_Payload;
size_t m_NextMessageLen, m_NextMessageOffset; size_t m_PayloadLen;
std::shared_ptr<I2CPDestination> m_Destination; std::shared_ptr<I2CPDestination> m_Destination;
uint16_t m_SessionID; uint16_t m_SessionID;

Loading…
Cancel
Save