Browse Source

[gzip] do not initialize deflator if gzip is not enabled for tunnel

Signed-off-by: R4SAS <r4sas@i2pmail.org>
pull/1696/head
R4SAS 3 years ago
parent
commit
d2faec70be
Signed by: r4sas
GPG Key ID: 66F6C87B98EBCFE2
  1. 14
      libi2pd/Datagram.cpp
  2. 4
      libi2pd/Datagram.h
  3. 72
      libi2pd/I2NPProtocol.cpp
  4. 14
      libi2pd/Streaming.cpp
  5. 2
      libi2pd/Streaming.h

14
libi2pd/Datagram.cpp

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2020, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -21,6 +21,9 @@ namespace datagram
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip): DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip):
m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip) m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip)
{ {
if (m_Gzip)
m_Deflator.reset (new i2p::data::GzipDeflator);
auto identityLen = m_Owner->GetIdentity ()->GetFullLen (); auto identityLen = m_Owner->GetIdentity ()->GetFullLen ();
m_From.resize (identityLen); m_From.resize (identityLen);
m_Owner->GetIdentity ()->ToBuffer (m_From.data (), identityLen); m_Owner->GetIdentity ()->ToBuffer (m_From.data (), identityLen);
@ -152,11 +155,16 @@ namespace datagram
const std::vector<std::pair<const uint8_t *, size_t> >& payloads, const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum) uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum)
{ {
size_t size;
auto msg = m_I2NPMsgsPool.AcquireShared (); auto msg = m_I2NPMsgsPool.AcquireShared ();
uint8_t * buf = msg->GetPayload (); uint8_t * buf = msg->GetPayload ();
buf += 4; // reserve for length buf += 4; // reserve for length
size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) :
i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len); if (m_Gzip && m_Deflator)
size = m_Deflator->Deflate (payloads, buf, msg->maxLen - msg->len);
else
size = i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len);
if (size) if (size)
{ {
htobe32buf (msg->GetPayload (), size); // length htobe32buf (msg->GetPayload (), size); // length

4
libi2pd/Datagram.h

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2020, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -164,7 +164,7 @@ namespace datagram
std::map<uint16_t, Receiver> m_ReceiversByPorts; std::map<uint16_t, Receiver> m_ReceiversByPorts;
i2p::data::GzipInflator m_Inflator; i2p::data::GzipInflator m_Inflator;
i2p::data::GzipDeflator m_Deflator; std::unique_ptr<i2p::data::GzipDeflator> m_Deflator;
std::vector<uint8_t> m_From, m_Signature; std::vector<uint8_t> m_From, m_Signature;
i2p::util::MemoryPool<I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE> > m_I2NPMsgsPool; i2p::util::MemoryPool<I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE> > m_I2NPMsgsPool;
}; };

72
libi2pd/I2NPProtocol.cpp

@ -40,7 +40,7 @@ namespace i2p
{ {
I2NPMessage * msg = nullptr; I2NPMessage * msg = nullptr;
if (endpoint) if (endpoint)
{ {
// should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet // should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet
msg = new I2NPMessageBuffer<2*i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28>(); // reserved for alignment and NTCP 16 + 6 + 6 msg = new I2NPMessageBuffer<2*i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28>(); // reserved for alignment and NTCP 16 + 6 + 6
msg->Align (6); msg->Align (6);
@ -50,7 +50,7 @@ namespace i2p
{ {
msg = new I2NPMessageBuffer<i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34>(); // reserved for alignment and NTCP 16 + 6 + 12 msg = new I2NPMessageBuffer<i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34>(); // reserved for alignment and NTCP 16 + 6 + 12
msg->Align (12); msg->Align (12);
} }
return std::shared_ptr<I2NPMessage>(msg); return std::shared_ptr<I2NPMessage>(msg);
} }
@ -222,12 +222,12 @@ namespace i2p
{ {
memcpy (buf + 33, replyTag, 8); // 8 bytes tag memcpy (buf + 33, replyTag, 8); // 8 bytes tag
buf += 41; buf += 41;
} }
else else
{ {
memcpy (buf + 33, replyTag, 32); // 32 bytes tag memcpy (buf + 33, replyTag, 32); // 32 bytes tag
buf += 65; buf += 65;
} }
m->len += (buf - m->GetPayload ()); m->len += (buf - m->GetPayload ());
m->FillI2NPMessageHeader (eI2NPDatabaseLookup); m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
@ -267,7 +267,7 @@ namespace i2p
LogPrint (eLogError, "I2NP: Invalid RouterInfo buffer for DatabaseStore"); LogPrint (eLogError, "I2NP: Invalid RouterInfo buffer for DatabaseStore");
return nullptr; return nullptr;
} }
auto m = NewI2NPShortMessage (); auto m = NewI2NPShortMessage ();
uint8_t * payload = m->GetPayload (); uint8_t * payload = m->GetPayload ();
@ -285,12 +285,12 @@ namespace i2p
buf += 32; // reply tunnel gateway buf += 32; // reply tunnel gateway
} }
else else
{ {
memset (buf, 0, 4); // zero tunnelID means direct reply memset (buf, 0, 4); // zero tunnelID means direct reply
buf += 4; buf += 4;
memcpy (buf, context.GetIdentHash (), 32); memcpy (buf, context.GetIdentHash (), 32);
buf += 32; buf += 32;
} }
} }
uint8_t * sizePtr = buf; uint8_t * sizePtr = buf;
@ -303,7 +303,7 @@ namespace i2p
{ {
i2p::data::GzipDeflator deflator; i2p::data::GzipDeflator deflator;
size = deflator.Deflate (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len); size = deflator.Deflate (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len);
} }
if (size) if (size)
{ {
htobe16buf (sizePtr, size); // size htobe16buf (sizePtr, size); // size
@ -427,14 +427,14 @@ namespace i2p
{ {
LogPrint (eLogWarning, "I2NP: Reply AEAD encryption failed"); LogPrint (eLogWarning, "I2NP: Reply AEAD encryption failed");
return false; return false;
} }
} }
else else
{ {
encryption.SetKey (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET); encryption.SetKey (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET);
encryption.SetIV (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET); encryption.SetIV (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET);
encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply); encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply);
} }
} }
return true; return true;
} }
@ -561,7 +561,7 @@ namespace i2p
LogPrint (eLogDebug, "I2NP: Short request record ", i, " is ours"); LogPrint (eLogDebug, "I2NP: Short request record ", i, " is ours");
uint8_t clearText[SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE]; uint8_t clearText[SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE];
if (!i2p::context.DecryptTunnelShortRequestRecord (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) if (!i2p::context.DecryptTunnelShortRequestRecord (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText))
{ {
LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i); LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i);
return; return;
} }
@ -569,7 +569,7 @@ namespace i2p
{ {
LogPrint (eLogWarning, "I2NP: Unknown layer encryption type ", clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE], " in short request record"); LogPrint (eLogWarning, "I2NP: Unknown layer encryption type ", clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE], " in short request record");
return; return;
} }
auto& noiseState = i2p::context.GetCurrentNoiseState (); auto& noiseState = i2p::context.GetCurrentNoiseState ();
uint8_t replyKey[32], layerKey[32], ivKey[32]; uint8_t replyKey[32], layerKey[32], ivKey[32];
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK);
@ -581,7 +581,7 @@ namespace i2p
{ {
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "TunnelLayerIVKey", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "TunnelLayerIVKey", noiseState.m_CK);
memcpy (ivKey, noiseState.m_CK + 32, 32); memcpy (ivKey, noiseState.m_CK + 32, 32);
} }
else else
memcpy (ivKey, noiseState.m_CK , 32); memcpy (ivKey, noiseState.m_CK , 32);
@ -593,7 +593,7 @@ namespace i2p
i2p::transport::transports.IsTransitBandwidthExceeded ()) i2p::transport::transports.IsTransitBandwidthExceeded ())
retCode = 30; retCode = 30;
if (!retCode) if (!retCode)
{ {
// create new transit tunnel // create new transit tunnel
auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
@ -604,13 +604,13 @@ namespace i2p
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG); clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
} }
// encrypt reply // encrypt reply
uint8_t nonce[12]; uint8_t nonce[12];
memset (nonce, 0, 12); memset (nonce, 0, 12);
uint8_t * reply = buf + 1; uint8_t * reply = buf + 1;
for (int j = 0; j < num; j++) for (int j = 0; j < num; j++)
{ {
nonce[4] = j; // nonce is record # nonce[4] = j; // nonce is record #
if (j == i) if (j == i)
{ {
@ -621,29 +621,29 @@ namespace i2p
{ {
LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed"); LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed");
return; return;
} }
} }
else else
i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, reply); i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, reply);
reply += SHORT_TUNNEL_BUILD_RECORD_SIZE; reply += SHORT_TUNNEL_BUILD_RECORD_SIZE;
} }
// send reply // send reply
if (isEndpoint) if (isEndpoint)
{ {
auto replyMsg = NewI2NPShortMessage (); auto replyMsg = NewI2NPShortMessage ();
replyMsg->Concat (buf, len); replyMsg->Concat (buf, len);
replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local? clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local?
{ {
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "RGarlicKeyAndTag", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "RGarlicKeyAndTag", noiseState.m_CK);
uint64_t tag; uint64_t tag;
memcpy (&tag, noiseState.m_CK, 8); memcpy (&tag, noiseState.m_CK, 8);
// we send it to reply tunnel // we send it to reply tunnel
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag))); i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag)));
} }
else else
{ {
// IBGW is local // IBGW is local
@ -653,18 +653,18 @@ namespace i2p
tunnel->SendTunnelDataMsg (replyMsg); tunnel->SendTunnelDataMsg (replyMsg);
else else
LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply"); LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply");
} }
} }
else else
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len, CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len,
bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
return; return;
} }
record += SHORT_TUNNEL_BUILD_RECORD_SIZE; record += SHORT_TUNNEL_BUILD_RECORD_SIZE;
} }
} }
std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (const uint8_t * buf) std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (const uint8_t * buf)
{ {
auto msg = NewI2NPTunnelMessage (false); auto msg = NewI2NPTunnelMessage (false);
@ -781,13 +781,13 @@ namespace i2p
break; break;
case eI2NPShortTunnelBuild: case eI2NPShortTunnelBuild:
HandleShortTunnelBuildMsg (msgID, buf, size); HandleShortTunnelBuildMsg (msgID, buf, size);
break; break;
case eI2NPVariableTunnelBuildReply: case eI2NPVariableTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, false); HandleTunnelBuildReplyMsg (msgID, buf, size, false);
break; break;
case eI2NPShortTunnelBuildReply: case eI2NPShortTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, true); HandleTunnelBuildReplyMsg (msgID, buf, size, true);
break; break;
case eI2NPTunnelBuild: case eI2NPTunnelBuild:
HandleTunnelBuildMsg (buf, size); HandleTunnelBuildMsg (buf, size);
break; break;
@ -844,8 +844,8 @@ namespace i2p
case eI2NPVariableTunnelBuildReply: case eI2NPVariableTunnelBuildReply:
case eI2NPTunnelBuild: case eI2NPTunnelBuild:
case eI2NPTunnelBuildReply: case eI2NPTunnelBuildReply:
case eI2NPShortTunnelBuild: case eI2NPShortTunnelBuild:
case eI2NPShortTunnelBuildReply: case eI2NPShortTunnelBuildReply:
// forward to tunnel thread // forward to tunnel thread
i2p::tunnel::tunnels.PostTunnelData (msg); i2p::tunnel::tunnels.PostTunnelData (msg);
break; break;

14
libi2pd/Streaming.cpp

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2020, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -1040,6 +1040,8 @@ namespace stream
m_Owner (owner), m_LocalPort (localPort), m_Gzip (gzip), m_Owner (owner), m_LocalPort (localPort), m_Gzip (gzip),
m_PendingIncomingTimer (m_Owner->GetService ()) m_PendingIncomingTimer (m_Owner->GetService ())
{ {
if (m_Gzip)
m_Deflator.reset (new i2p::data::GzipDeflator);
} }
StreamingDestination::~StreamingDestination () StreamingDestination::~StreamingDestination ()
@ -1296,13 +1298,17 @@ namespace stream
std::shared_ptr<I2NPMessage> StreamingDestination::CreateDataMessage ( std::shared_ptr<I2NPMessage> StreamingDestination::CreateDataMessage (
const uint8_t * payload, size_t len, uint16_t toPort, bool checksum) const uint8_t * payload, size_t len, uint16_t toPort, bool checksum)
{ {
size_t size;
auto msg = m_I2NPMsgsPool.AcquireShared (); auto msg = m_I2NPMsgsPool.AcquireShared ();
uint8_t * buf = msg->GetPayload (); uint8_t * buf = msg->GetPayload ();
buf += 4; // reserve for lengthlength buf += 4; // reserve for lengthlength
msg->len += 4; msg->len += 4;
size_t size = (!m_Gzip || len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE)?
i2p::data::GzipNoCompression (payload, len, buf, msg->maxLen - msg->len): if (m_Gzip && m_Deflator)
m_Deflator.Deflate (payload, len, buf, msg->maxLen - msg->len); size = m_Deflator->Deflate (payload, len, buf, msg->maxLen - msg->len);
else
size = i2p::data::GzipNoCompression (payload, len, buf, msg->maxLen - msg->len);
if (size) if (size)
{ {
htobe32buf (msg->GetPayload (), size); // length htobe32buf (msg->GetPayload (), size); // length

2
libi2pd/Streaming.h

@ -312,7 +312,7 @@ namespace stream
public: public:
i2p::data::GzipInflator m_Inflator; i2p::data::GzipInflator m_Inflator;
i2p::data::GzipDeflator m_Deflator; std::unique_ptr<i2p::data::GzipDeflator> m_Deflator;
// for HTTP only // for HTTP only
const decltype(m_Streams)& GetStreams () const { return m_Streams; }; const decltype(m_Streams)& GetStreams () const { return m_Streams; };

Loading…
Cancel
Save