|
|
@ -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 (0), m_MessageID (0), m_IsSendAccepted (true) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
I2CPSession::~I2CPSession () |
|
|
|
I2CPSession::~I2CPSession () |
|
|
|
{ |
|
|
|
{ |
|
|
|
delete[] m_NextMessage; |
|
|
|
delete[] m_Payload; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void I2CPSession::Start () |
|
|
|
void I2CPSession::Start () |
|
|
@ -141,82 +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_NextMessageOffset + bytes_transferred < m_NextMessageLen) |
|
|
|
m_Payload = new uint8_t[m_PayloadLen]; |
|
|
|
{ |
|
|
|
ReceivePayload (); |
|
|
|
memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, bytes_transferred); |
|
|
|
|
|
|
|
m_NextMessageOffset += bytes_transferred; |
|
|
|
|
|
|
|
offset = bytes_transferred; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// m_NextMessage complete
|
|
|
|
|
|
|
|
offset = m_NextMessageLen - m_NextMessageOffset; |
|
|
|
|
|
|
|
memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, offset); |
|
|
|
|
|
|
|
HandleNextMessage (m_NextMessage); |
|
|
|
|
|
|
|
delete[] m_NextMessage; |
|
|
|
|
|
|
|
m_NextMessage = nullptr; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
while (offset < bytes_transferred) |
|
|
|
else // no following payload
|
|
|
|
{ |
|
|
|
{ |
|
|
|
auto msgLen = bufbe32toh (m_Buffer + offset + I2CP_HEADER_LENGTH_OFFSET) + I2CP_HEADER_SIZE; |
|
|
|
HandleMessage (); |
|
|
|
if (msgLen > 0xFFFF) // 64K
|
|
|
|
ReceiveHeader (); // next message
|
|
|
|
{ |
|
|
|
|
|
|
|
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 (); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void I2CPSession::HandleNextMessage (const uint8_t * buf) |
|
|
|
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::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 () |
|
|
@ -232,18 +221,25 @@ 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) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto l = len + I2CP_HEADER_SIZE; |
|
|
|
auto socket = m_Socket; |
|
|
|
uint8_t * buf = new uint8_t[l]; |
|
|
|
if (socket) |
|
|
|
htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len); |
|
|
|
{ |
|
|
|
buf[I2CP_HEADER_TYPE_OFFSET] = type; |
|
|
|
auto l = len + I2CP_HEADER_SIZE; |
|
|
|
memcpy (buf + I2CP_HEADER_SIZE, payload, len); |
|
|
|
uint8_t * buf = new uint8_t[l]; |
|
|
|
boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), |
|
|
|
htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len); |
|
|
|
std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), |
|
|
|
buf[I2CP_HEADER_TYPE_OFFSET] = type; |
|
|
|
std::placeholders::_1, std::placeholders::_2, buf)); |
|
|
|
memcpy (buf + I2CP_HEADER_SIZE, payload, len); |
|
|
|
|
|
|
|
boost::asio::async_write (*socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), |
|
|
|
|
|
|
|
std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), |
|
|
|
|
|
|
|
std::placeholders::_1, std::placeholders::_2, buf)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
LogPrint (eLogError, "I2CP: Can't write to the socket"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void I2CPSession::HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf) |
|
|
|
void I2CPSession::HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf) |
|
|
@ -277,7 +273,7 @@ namespace client |
|
|
|
while (offset < len) |
|
|
|
while (offset < len) |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::string param = ExtractString (buf + offset, len - offset); |
|
|
|
std::string param = ExtractString (buf + offset, len - offset); |
|
|
|
offset += param.length (); |
|
|
|
offset += param.length () + 1; |
|
|
|
if (buf[offset] != '=') |
|
|
|
if (buf[offset] != '=') |
|
|
|
{ |
|
|
|
{ |
|
|
|
LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead '=' after ", param); |
|
|
|
LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead '=' after ", param); |
|
|
@ -286,7 +282,7 @@ namespace client |
|
|
|
offset++; |
|
|
|
offset++; |
|
|
|
|
|
|
|
|
|
|
|
std::string value = ExtractString (buf + offset, len - offset); |
|
|
|
std::string value = ExtractString (buf + offset, len - offset); |
|
|
|
offset += value.length (); |
|
|
|
offset += value.length () + 1; |
|
|
|
if (buf[offset] != ';') |
|
|
|
if (buf[offset] != ';') |
|
|
|
{ |
|
|
|
{ |
|
|
|
LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead ';' after ", value); |
|
|
|
LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead ';' after ", value); |
|
|
@ -449,7 +445,7 @@ namespace client |
|
|
|
void I2CPSession::HostLookupMessageHandler (const uint8_t * buf, size_t len) |
|
|
|
void I2CPSession::HostLookupMessageHandler (const uint8_t * buf, size_t len) |
|
|
|
{ |
|
|
|
{ |
|
|
|
uint16_t sessionID = bufbe16toh (buf); |
|
|
|
uint16_t sessionID = bufbe16toh (buf); |
|
|
|
if (sessionID == m_SessionID) |
|
|
|
if (sessionID == m_SessionID || sessionID == 0xFFFF) // -1 means without session
|
|
|
|
{ |
|
|
|
{ |
|
|
|
uint32_t requestID = bufbe32toh (buf + 2); |
|
|
|
uint32_t requestID = bufbe32toh (buf + 2); |
|
|
|
//uint32_t timeout = bufbe32toh (buf + 6);
|
|
|
|
//uint32_t timeout = bufbe32toh (buf + 6);
|
|
|
@ -476,15 +472,17 @@ namespace client |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (m_Destination) |
|
|
|
std::shared_ptr<LeaseSetDestination> destination = m_Destination; |
|
|
|
|
|
|
|
if(!destination) destination = i2p::client::context.GetSharedLocalDestination (); |
|
|
|
|
|
|
|
if (destination) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto ls = m_Destination->FindLeaseSet (ident); |
|
|
|
auto ls = destination->FindLeaseSet (ident); |
|
|
|
if (ls) |
|
|
|
if (ls) |
|
|
|
SendHostReplyMessage (requestID, ls->GetIdentity ()); |
|
|
|
SendHostReplyMessage (requestID, ls->GetIdentity ()); |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto s = shared_from_this (); |
|
|
|
auto s = shared_from_this (); |
|
|
|
m_Destination->RequestDestination (ident, |
|
|
|
destination->RequestDestination (ident, |
|
|
|
[s, requestID](std::shared_ptr<i2p::data::LeaseSet> leaseSet) |
|
|
|
[s, requestID](std::shared_ptr<i2p::data::LeaseSet> leaseSet) |
|
|
|
{ |
|
|
|
{ |
|
|
|
s->SendHostReplyMessage (requestID, leaseSet ? leaseSet->GetIdentity () : nullptr); |
|
|
|
s->SendHostReplyMessage (requestID, leaseSet ? leaseSet->GetIdentity () : nullptr); |
|
|
|