diff --git a/SSU.cpp b/SSU.cpp index a137f1a8..7a58692f 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -325,7 +325,7 @@ namespace ssu // encrypt message with intro key FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, 368, introKey, iv, introKey); - m_Server.Send (buf, 368, m_RemoteEndpoint); + Send (buf, 368); } void SSUSession::SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress) @@ -363,7 +363,7 @@ namespace ssu rnd.GenerateBlock (iv, 16); // random iv // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CONFIRMED, buf, 480, m_SessionKey, iv, m_MacKey); - m_Server.Send (buf, 480, m_RemoteEndpoint); + Send (buf, 480); } void SSUSession::ProcessRelayRequest (uint8_t * buf, size_t len) @@ -633,7 +633,7 @@ namespace ssu if (!m_DelayedMessages.empty ()) { for (auto it :m_DelayedMessages) - Send (it); + m_Data.Send (it); m_DelayedMessages.clear (); } if (m_PeerTest && (m_RemoteRouter && m_RemoteRouter->IsPeerTesting ())) @@ -689,7 +689,7 @@ namespace ssu if (msg) { if (m_State == eSessionStateEstablished) - Send (msg); + m_Data.Send (msg); else m_DelayedMessages.push_back (msg); } @@ -804,7 +804,7 @@ namespace ssu memcpy (payload, introKey, 32); // intro key // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_PEER_TEST, buf, 80); - m_Server.Send (buf, 80, m_RemoteEndpoint); + Send (buf, 80); } void SSUSession::SendMsgAck (uint32_t msgID) @@ -821,7 +821,7 @@ namespace ssu // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); - m_Server.Send (buf, 48, m_RemoteEndpoint); + Send (buf, 48); } void SSUSession::SendSesionDestroyed () @@ -831,59 +831,10 @@ namespace ssu uint8_t buf[48 + 18]; // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_DESTROYED, buf, 48); - m_Server.Send (buf, 48, m_RemoteEndpoint); + Send (buf, 48); } } - void SSUSession::Send (i2p::I2NPMessage * msg) - { - uint32_t msgID = htobe32 (msg->ToSSU ()); - size_t payloadSize = SSU_MTU - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3) - size_t len = msg->GetLength (); - uint8_t * msgBuf = msg->GetSSUHeader (); - - uint32_t fragmentNum = 0; - while (len > 0) - { - uint8_t buf[SSU_MTU + 18], * payload = buf + sizeof (SSUHeader); - *payload = DATA_FLAG_WANT_REPLY; // for compatibility - payload++; - *payload = 1; // always 1 message fragment per message - payload++; - *(uint32_t *)payload = msgID; - payload += 4; - bool isLast = (len <= payloadSize); - size_t size = isLast ? len : payloadSize; - uint32_t fragmentInfo = (fragmentNum << 17); - if (isLast) - fragmentInfo |= 0x010000; - - fragmentInfo |= size; - fragmentInfo = htobe32 (fragmentInfo); - memcpy (payload, (uint8_t *)(&fragmentInfo) + 1, 3); - payload += 3; - memcpy (payload, msgBuf, size); - - size += payload - buf; - if (size & 0x0F) // make sure 16 bytes boundary - size = ((size >> 4) + 1) << 4; // (/16 + 1)*16 - - // encrypt message with session key - FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size); - m_Server.Send (buf, size, m_RemoteEndpoint); - - if (!isLast) - { - len -= payloadSize; - msgBuf += payloadSize; - } - else - len = 0; - fragmentNum++; - } - DeleteI2NPMessage (msg); - } - void SSUSession::Send (uint8_t type, const uint8_t * payload, size_t len) { uint8_t buf[SSU_MTU + 18]; @@ -896,9 +847,14 @@ namespace ssu memcpy (buf + sizeof (SSUHeader), payload, len); // encrypt message with session key FillHeaderAndEncrypt (type, buf, msgSize); - m_Server.Send (buf, msgSize, m_RemoteEndpoint); + Send (buf, msgSize); } + void SSUSession::Send (const uint8_t * buf, size_t size) + { + m_Server.Send (buf, size, m_RemoteEndpoint); + } + SSUServer::SSUServer (int port): m_Thread (nullptr), m_Work (m_Service), m_Endpoint (boost::asio::ip::udp::v4 (), port), m_Socket (m_Service, m_Endpoint) { @@ -961,7 +917,7 @@ namespace ssu return nullptr; } - void SSUServer::Send (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to) + void SSUServer::Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to) { m_Socket.send_to (boost::asio::buffer (buf, len), to); LogPrint ("SSU sent ", len, " bytes"); diff --git a/SSU.h b/SSU.h index 9a29a3e1..80260d99 100644 --- a/SSU.h +++ b/SSU.h @@ -99,8 +99,8 @@ namespace ssu void ProcessData (uint8_t * buf, size_t len); void SendMsgAck (uint32_t msgID); void SendSesionDestroyed (); - void Send (i2p::I2NPMessage * msg); void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key + void Send (const uint8_t * buf, size_t size); void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const uint8_t * aesKey, const uint8_t * iv, const uint8_t * macKey); void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key @@ -148,7 +148,7 @@ namespace ssu boost::asio::io_service& GetService () { return m_Socket.get_io_service(); }; const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; }; - void Send (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); + void Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); void AddRelay (uint32_t tag, const boost::asio::ip::udp::endpoint& relay); SSUSession * FindRelaySession (uint32_t tag); diff --git a/SSUData.cpp b/SSUData.cpp index 6a7f4dc3..2683fb79 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -135,6 +135,54 @@ namespace ssu } } + void SSUData::Send (i2p::I2NPMessage * msg) + { + uint32_t msgID = htobe32 (msg->ToSSU ()); + size_t payloadSize = SSU_MTU - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3) + size_t len = msg->GetLength (); + uint8_t * msgBuf = msg->GetSSUHeader (); + + uint32_t fragmentNum = 0; + while (len > 0) + { + uint8_t buf[SSU_MTU + 18], * payload = buf + sizeof (SSUHeader); + *payload = DATA_FLAG_WANT_REPLY; // for compatibility + payload++; + *payload = 1; // always 1 message fragment per message + payload++; + *(uint32_t *)payload = msgID; + payload += 4; + bool isLast = (len <= payloadSize); + size_t size = isLast ? len : payloadSize; + uint32_t fragmentInfo = (fragmentNum << 17); + if (isLast) + fragmentInfo |= 0x010000; + + fragmentInfo |= size; + fragmentInfo = htobe32 (fragmentInfo); + memcpy (payload, (uint8_t *)(&fragmentInfo) + 1, 3); + payload += 3; + memcpy (payload, msgBuf, size); + + size += payload - buf; + if (size & 0x0F) // make sure 16 bytes boundary + size = ((size >> 4) + 1) << 4; // (/16 + 1)*16 + + // encrypt message with session key + m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size); + m_Session.Send (buf, size); + + if (!isLast) + { + len -= payloadSize; + msgBuf += payloadSize; + } + else + len = 0; + fragmentNum++; + } + DeleteI2NPMessage (msg); + } } } diff --git a/SSUData.h b/SSUData.h index 6f6c398d..188ff07b 100644 --- a/SSUData.h +++ b/SSUData.h @@ -27,6 +27,7 @@ namespace ssu ~SSUData (); void ProcessMessage (uint8_t * buf, size_t len); + void Send (i2p::I2NPMessage * msg); private: