From 329439d0ae472c9d700a38ff6f6c1494ae429f51 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 17 May 2020 16:49:31 -0400 Subject: [PATCH] don't copy datagram payload --- libi2pd/Datagram.cpp | 32 ++++++++++++++++---------------- libi2pd/Datagram.h | 5 ++++- libi2pd/Gzip.cpp | 30 ++++++++++++++++++++++++++++++ libi2pd/Gzip.h | 2 ++ 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index a69c86b0..04e01796 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -24,34 +24,32 @@ namespace datagram void DatagramDestination::SendDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort) { auto owner = m_Owner; - std::vector v(MAX_DATAGRAM_SIZE); - uint8_t * buf = v.data(); - auto localIdentity = m_Owner->GetIdentity (); - auto identityLen = localIdentity->ToBuffer (buf, MAX_DATAGRAM_SIZE); - uint8_t * signature = buf + identityLen; + auto localIdentity = m_Owner->GetIdentity (); + auto identityLen = localIdentity->GetFullLen (); auto signatureLen = localIdentity->GetSignatureLen (); - uint8_t * buf1 = signature + signatureLen; size_t headerLen = identityLen + signatureLen; - - memcpy (buf1, payload, len); + + std::vector header(headerLen); + localIdentity->ToBuffer (header.data (), identityLen); + uint8_t * signature = header.data () + identityLen; if (localIdentity->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) { uint8_t hash[32]; - SHA256(buf1, len, hash); + SHA256(payload, len, hash); owner->Sign (hash, 32, signature); } else - owner->Sign (buf1, len, signature); + owner->Sign (payload, len, signature); - auto msg = CreateDataMessage (buf, len + headerLen, fromPort, toPort); auto session = ObtainSession(identity); + auto msg = CreateDataMessage ({{header.data (), headerLen}, {payload, len}}, fromPort, toPort, false, !session->IsRatchets ()); // datagram session->SendMsg(msg); } void DatagramDestination::SendRawDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort) { - auto msg = CreateDataMessage (payload, len, fromPort, toPort, true); // raw auto session = ObtainSession(identity); + auto msg = CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ()); // raw session->SendMsg(msg); } @@ -122,12 +120,14 @@ namespace datagram } - std::shared_ptr DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort, bool isRaw) + std::shared_ptr DatagramDestination::CreateDataMessage ( + const std::vector >& payloads, + uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum) { auto msg = NewI2NPMessage (); uint8_t * buf = msg->GetPayload (); buf += 4; // reserve for length - size_t size = m_Deflator.Deflate (payload, len, buf, msg->maxLen - msg->len); + size_t size = m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len); if (size) { htobe32buf (msg->GetPayload (), size); // length @@ -135,7 +135,7 @@ namespace datagram htobe16buf (buf + 6, toPort); // destination port buf[9] = isRaw ? i2p::client::PROTOCOL_TYPE_RAW : i2p::client::PROTOCOL_TYPE_DATAGRAM; // raw or datagram protocol msg->len += size + 4; - msg->FillI2NPMessageHeader (eI2NPData); + msg->FillI2NPMessageHeader (eI2NPData, 0, checksum); } else msg = nullptr; @@ -247,7 +247,7 @@ namespace datagram auto path = GetSharedRoutingPath(); if(path) path->updateTime = i2p::util::GetSecondsSinceEpoch (); - if (m_RoutingSession && m_RoutingSession->IsRatchets ()) + if (IsRatchets ()) SendMsg (nullptr); // send empty message in case if we have some data to send } diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index 0cfec838..87f3a7a8 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -51,6 +51,8 @@ namespace datagram /** get the last time in milliseconds for when we used this datagram session */ uint64_t LastActivity() const { return m_LastUse; } + bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); } + struct Info { std::shared_ptr IBGW; @@ -130,7 +132,8 @@ namespace datagram std::shared_ptr ObtainSession(const i2p::data::IdentHash & ident); - std::shared_ptr CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort, bool isRaw = false); + std::shared_ptr CreateDataMessage (const std::vector >& payloads, + uint16_t fromPort, uint16_t toPort, bool isRaw = false, bool checksum = true); void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); diff --git a/libi2pd/Gzip.cpp b/libi2pd/Gzip.cpp index 2ca711b0..cb6a79af 100644 --- a/libi2pd/Gzip.cpp +++ b/libi2pd/Gzip.cpp @@ -116,6 +116,36 @@ namespace data return 0; } + size_t GzipDeflator::Deflate (const std::vector >& bufs, uint8_t * out, size_t outLen) + { + if (m_IsDirty) deflateReset (&m_Deflator); + m_IsDirty = true; + size_t offset = 0; + int err; + for (const auto& it: bufs) + { + m_Deflator.next_in = const_cast(it.first); + m_Deflator.avail_in = it.second; + m_Deflator.next_out = out + offset; + m_Deflator.avail_out = outLen - offset; + auto flush = (it == bufs.back ()) ? Z_FINISH : Z_NO_FLUSH; + err = deflate (&m_Deflator, flush); + if (err) + { + if (flush && err == Z_STREAM_END) + { + out[9] = 0xff; // OS is always unknown + return outLen - m_Deflator.avail_out; + } + break; + } + offset = outLen - m_Deflator.avail_out; + } + // else + LogPrint (eLogError, "Gzip: Deflate error ", err); + return 0; + } + size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen) { static const uint8_t gzipHeader[11] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xff, 0x01 }; diff --git a/libi2pd/Gzip.h b/libi2pd/Gzip.h index cf08d920..e5b8775e 100644 --- a/libi2pd/Gzip.h +++ b/libi2pd/Gzip.h @@ -2,6 +2,7 @@ #define GZIP_H__ #include +#include namespace i2p { @@ -34,6 +35,7 @@ namespace data void SetCompressionLevel (int level); size_t Deflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen); + size_t Deflate (const std::vector >& bufs, uint8_t * out, size_t outLen); private: