aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-09-13 12:24:59 +0200
committerStefan Boberg <[email protected]>2021-09-13 12:24:59 +0200
commit4e2649977d034b913413d2cb35d4a88afc30393f (patch)
tree9258d4329a2217d581aaedfb251a655692987d4d
parentAdded Ref<>::Get to work around issue casting a pointer to a derived type to ... (diff)
downloadzen-4e2649977d034b913413d2cb35d4a88afc30393f.tar.xz
zen-4e2649977d034b913413d2cb35d4a88afc30393f.zip
Changed interface for httpServerRequest::SessionId()/RequestId() so they share storage and lazy eval logic
They now call into ParseSessionId()/ParseRequestId() when required Eliminates redundant logic in derived implementations Also moved package transport code into httpshared.(cpp|h) for easier sharing with client code Added some I/O error reporting in http.sys related code Changed IHttpPackageHandler interface to support partially updated handling flow
-rw-r--r--zenhttp/httpserver.cpp136
-rw-r--r--zenhttp/httpshared.cpp116
-rw-r--r--zenhttp/httpshared.h32
-rw-r--r--zenhttp/httpsys.cpp139
-rw-r--r--zenhttp/include/zenhttp/httpserver.h13
-rw-r--r--zenhttp/zenhttp.vcxproj2
-rw-r--r--zenhttp/zenhttp.vcxproj.filters2
-rw-r--r--zenserver/testing/httptest.cpp38
-rw-r--r--zenserver/testing/httptest.h17
9 files changed, 307 insertions, 188 deletions
diff --git a/zenhttp/httpserver.cpp b/zenhttp/httpserver.cpp
index 39bec435d..50141167d 100644
--- a/zenhttp/httpserver.cpp
+++ b/zenhttp/httpserver.cpp
@@ -3,6 +3,7 @@
#include <zenhttp/httpserver.h>
#include "httpnull.h"
+#include "httpshared.h"
#include "httpsys.h"
#include "httpuws.h"
@@ -262,72 +263,10 @@ HttpServerRequest::~HttpServerRequest()
{
}
-struct CbPackageHeader
-{
- uint32_t HeaderMagic;
- uint32_t AttachmentCount;
- uint32_t Reserved1;
- uint32_t Reserved2;
-};
-
-static constinit uint32_t kCbPkgMagic = 0xaa77aacc;
-
-struct CbAttachmentEntry
-{
- uint64_t AttachmentSize;
- uint32_t Reserved1;
- IoHash AttachmentHash;
-};
-
void
HttpServerRequest::WriteResponse(HttpResponseCode ResponseCode, CbPackage Data)
{
- const std::span<const CbAttachment>& Attachments = Data.GetAttachments();
-
- std::vector<IoBuffer> ResponseBuffers;
- ResponseBuffers.reserve(3 + Attachments.size()); // TODO: may want to use an additional fudge factor here to avoid growing since each
- // attachment is likely to consist of several buffers
-
- uint64_t TotalAttachmentsSize = 0;
-
- // Fixed size header
-
- CbPackageHeader Hdr{.HeaderMagic = kCbPkgMagic, .AttachmentCount = gsl::narrow<uint32_t>(Attachments.size())};
-
- ResponseBuffers.push_back(IoBufferBuilder::MakeCloneFromMemory(&Hdr, sizeof Hdr));
-
- // Attachment metadata array
-
- IoBuffer AttachmentMetadataBuffer = IoBuffer{sizeof(CbAttachmentEntry) * (Attachments.size() + /* root */ 1)};
-
- CbAttachmentEntry* AttachmentInfo = reinterpret_cast<CbAttachmentEntry*>(AttachmentMetadataBuffer.MutableData());
-
- ResponseBuffers.push_back(AttachmentMetadataBuffer); // Attachment metadata
-
- // Root object
-
- IoBuffer RootIoBuffer = Data.GetObject().GetBuffer().AsIoBuffer();
- ResponseBuffers.push_back(RootIoBuffer); // Root object
-
- *AttachmentInfo++ = {.AttachmentSize = RootIoBuffer.Size(), .AttachmentHash = Data.GetObjectHash()};
-
- // Attachment payloads
-
- for (const CbAttachment& Attachment : Attachments)
- {
- CompressedBuffer AttachmentBuffer = Attachment.AsCompressedBinary();
- CompositeBuffer Compressed = AttachmentBuffer.GetCompressed();
-
- *AttachmentInfo++ = {.AttachmentSize = AttachmentBuffer.GetCompressedSize(),
- .AttachmentHash = IoHash::FromBLAKE3(AttachmentBuffer.GetRawHash())};
-
- for (const SharedBuffer& Segment : Compressed.GetSegments())
- {
- ResponseBuffers.push_back(Segment.AsIoBuffer());
- TotalAttachmentsSize += Segment.GetSize();
- }
- }
-
+ std::vector<IoBuffer> ResponseBuffers = FormatPackageMessage(Data);
return WriteResponse(ResponseCode, HttpContentType::kCbPackage, ResponseBuffers);
}
@@ -400,13 +339,27 @@ HttpServerRequest::GetQueryParams()
Oid
HttpServerRequest::SessionId() const
{
- return {};
+ if (m_Flags & kHaveSessionId)
+ {
+ return m_SessionId;
+ }
+
+ m_SessionId = ParseSessionId();
+ m_Flags |= kHaveSessionId;
+ return m_SessionId;
}
uint32_t
HttpServerRequest::RequestId() const
{
- return {};
+ if (m_Flags & kHaveRequestId)
+ {
+ return m_RequestId;
+ }
+
+ m_RequestId = ParseRequestId();
+ m_Flags |= kHaveRequestId;
+ return m_RequestId;
}
CbObject
@@ -418,62 +371,19 @@ HttpServerRequest::ReadPayloadObject()
{
return LoadCompactBinaryObject(std::move(Payload));
}
- else
- {
- return {};
- }
+
+ return {};
}
CbPackage
HttpServerRequest::ReadPayloadPackage()
{
- // TODO: this should not read into a contiguous buffer!
-
- IoBuffer Payload = ReadPayload();
- MemoryInStream InStream(Payload);
- BinaryReader Reader(InStream);
-
- if (!Payload)
- {
- return {};
- }
-
- CbPackage Package;
-
- CbPackageHeader Hdr;
- Reader.Read(&Hdr, sizeof Hdr);
-
- if (Hdr.HeaderMagic != kCbPkgMagic)
- {
- // report error
- return {};
- }
-
- uint32_t ChunkCount = Hdr.AttachmentCount + 1;
-
- std::unique_ptr<CbAttachmentEntry[]> AttachmentEntries{new CbAttachmentEntry[ChunkCount]};
-
- Reader.Read(AttachmentEntries.get(), sizeof(CbAttachmentEntry) * ChunkCount);
-
- for (uint32_t i = 0; i < ChunkCount; ++i)
+ if (IoBuffer Payload = ReadPayload())
{
- const uint64_t AttachmentSize = AttachmentEntries[i].AttachmentSize;
- IoBuffer AttachmentBuffer{AttachmentSize};
- Reader.Read(AttachmentBuffer.MutableData(), AttachmentSize);
- CompressedBuffer CompBuf(CompressedBuffer::FromCompressed(SharedBuffer(AttachmentBuffer)));
-
- if (i == 0)
- {
- Package.SetObject(LoadCompactBinaryObject(CompBuf));
- }
- else
- {
- CbAttachment Attachment(CompBuf);
- Package.AddAttachment(Attachment);
- }
+ return ParsePackageMessage(Payload);
}
- return Package;
+ return {};
}
//////////////////////////////////////////////////////////////////////////
diff --git a/zenhttp/httpshared.cpp b/zenhttp/httpshared.cpp
new file mode 100644
index 000000000..f11f91fae
--- /dev/null
+++ b/zenhttp/httpshared.cpp
@@ -0,0 +1,116 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include "httpshared.h"
+
+#include <zencore/compactbinarypackage.h>
+#include <zencore/iobuffer.h>
+#include <zencore/iohash.h>
+#include <zencore/stream.h>
+
+#include <span>
+#include <vector>
+
+namespace zen {
+
+std::vector<IoBuffer>
+FormatPackageMessage(const CbPackage& Data)
+{
+ const std::span<const CbAttachment>& Attachments = Data.GetAttachments();
+
+ std::vector<IoBuffer> ResponseBuffers;
+ ResponseBuffers.reserve(3 + Attachments.size()); // TODO: may want to use an additional fudge factor here to avoid growing since each
+ // attachment is likely to consist of several buffers
+
+ uint64_t TotalAttachmentsSize = 0;
+
+ // Fixed size header
+
+ CbPackageHeader Hdr{.HeaderMagic = kCbPkgMagic, .AttachmentCount = gsl::narrow<uint32_t>(Attachments.size())};
+
+ ResponseBuffers.push_back(IoBufferBuilder::MakeCloneFromMemory(&Hdr, sizeof Hdr));
+
+ // Attachment metadata array
+
+ IoBuffer AttachmentMetadataBuffer = IoBuffer{sizeof(CbAttachmentEntry) * (Attachments.size() + /* root */ 1)};
+
+ CbAttachmentEntry* AttachmentInfo = reinterpret_cast<CbAttachmentEntry*>(AttachmentMetadataBuffer.MutableData());
+
+ ResponseBuffers.push_back(AttachmentMetadataBuffer); // Attachment metadata
+
+ // Root object
+
+ IoBuffer RootIoBuffer = Data.GetObject().GetBuffer().AsIoBuffer();
+ ResponseBuffers.push_back(RootIoBuffer); // Root object
+
+ *AttachmentInfo++ = {.AttachmentSize = RootIoBuffer.Size(), .AttachmentHash = Data.GetObjectHash()};
+
+ // Attachment payloads
+
+ for (const CbAttachment& Attachment : Attachments)
+ {
+ CompressedBuffer AttachmentBuffer = Attachment.AsCompressedBinary();
+ CompositeBuffer Compressed = AttachmentBuffer.GetCompressed();
+
+ *AttachmentInfo++ = {.AttachmentSize = AttachmentBuffer.GetCompressedSize(),
+ .AttachmentHash = IoHash::FromBLAKE3(AttachmentBuffer.GetRawHash())};
+
+ for (const SharedBuffer& Segment : Compressed.GetSegments())
+ {
+ ResponseBuffers.push_back(Segment.AsIoBuffer());
+ TotalAttachmentsSize += Segment.GetSize();
+ }
+ }
+
+ return std::move(ResponseBuffers);
+}
+
+CbPackage
+ParsePackageMessage(IoBuffer Payload)
+{
+ MemoryInStream InStream(Payload);
+ BinaryReader Reader(InStream);
+
+ if (!Payload)
+ {
+ return {};
+ }
+
+ CbPackage Package;
+
+ CbPackageHeader Hdr;
+ Reader.Read(&Hdr, sizeof Hdr);
+
+ if (Hdr.HeaderMagic != kCbPkgMagic)
+ {
+ // report error
+ return {};
+ }
+
+ uint32_t ChunkCount = Hdr.AttachmentCount + 1;
+
+ std::unique_ptr<CbAttachmentEntry[]> AttachmentEntries{new CbAttachmentEntry[ChunkCount]};
+
+ Reader.Read(AttachmentEntries.get(), sizeof(CbAttachmentEntry) * ChunkCount);
+
+ for (uint32_t i = 0; i < ChunkCount; ++i)
+ {
+ const uint64_t AttachmentSize = AttachmentEntries[i].AttachmentSize;
+ IoBuffer AttachmentBuffer{AttachmentSize};
+ Reader.Read(AttachmentBuffer.MutableData(), AttachmentSize);
+ CompressedBuffer CompBuf(CompressedBuffer::FromCompressed(SharedBuffer(AttachmentBuffer)));
+
+ if (i == 0)
+ {
+ Package.SetObject(LoadCompactBinaryObject(CompBuf));
+ }
+ else
+ {
+ CbAttachment Attachment(CompBuf);
+ Package.AddAttachment(Attachment);
+ }
+ }
+
+ return Package;
+}
+
+} // namespace zen \ No newline at end of file
diff --git a/zenhttp/httpshared.h b/zenhttp/httpshared.h
new file mode 100644
index 000000000..dbbebb348
--- /dev/null
+++ b/zenhttp/httpshared.h
@@ -0,0 +1,32 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/iohash.h>
+
+namespace zen {
+
+class IoBuffer;
+class CbPackage;
+
+struct CbPackageHeader
+{
+ uint32_t HeaderMagic;
+ uint32_t AttachmentCount;
+ uint32_t Reserved1;
+ uint32_t Reserved2;
+};
+
+static constinit uint32_t kCbPkgMagic = 0xaa77aacc;
+
+struct CbAttachmentEntry
+{
+ uint64_t AttachmentSize;
+ uint32_t Reserved1;
+ IoHash AttachmentHash;
+};
+
+std::vector<IoBuffer> FormatPackageMessage(const CbPackage& Data);
+CbPackage ParsePackageMessage(IoBuffer Payload);
+
+} // namespace zen
diff --git a/zenhttp/httpsys.cpp b/zenhttp/httpsys.cpp
index f5f9d4249..cde371f2f 100644
--- a/zenhttp/httpsys.cpp
+++ b/zenhttp/httpsys.cpp
@@ -4,6 +4,7 @@
#include <zencore/compactbinary.h>
#include <zencore/compactbinarybuilder.h>
+#include <zencore/compactbinarypackage.h>
#include <zencore/except.h>
#include <zencore/logging.h>
#include <zencore/scopeguard.h>
@@ -145,7 +146,10 @@ private:
/**
* This is the handler for the initial HTTP I/O request which will receive the headers
- * and however much of the remaining payload might fit in the embedded request buffer
+ * and however much of the remaining payload might fit in the embedded request buffer.
+ *
+ * It is also used to receive any entity body data relating to the request
+ *
*/
struct InitialRequestHandler : public HttpSysRequestHandler
{
@@ -176,8 +180,8 @@ public:
HttpSysServerRequest(HttpSysTransaction& Tx, HttpService& Service, IoBuffer PayloadBuffer);
~HttpSysServerRequest() = default;
- virtual Oid SessionId() const override;
- virtual uint32_t RequestId() const override;
+ virtual Oid ParseSessionId() const override;
+ virtual uint32_t ParseRequestId() const override;
virtual IoBuffer ReadPayload() override;
virtual void WriteResponse(HttpResponseCode ResponseCode) override;
@@ -409,7 +413,14 @@ HttpSysRequestHandler*
HttpMessageResponseRequest::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred)
{
ZEN_UNUSED(NumberOfBytesTransferred);
- ZEN_UNUSED(IoResult);
+
+ if (IoResult)
+ {
+ spdlog::warn("response aborted due to error: '{}'", GetWindowsErrorAsString(IoResult));
+
+ // if one transmit failed there's really no need to go on
+ return nullptr;
+ }
if (m_RemainingChunkCount == 0)
{
@@ -438,6 +449,21 @@ HttpMessageResponseRequest::IssueRequest(std::error_code& ErrorCode)
m_RemainingChunkCount -= ThisRequestChunkCount;
m_NextDataChunkOffset += ThisRequestChunkCount;
+ /* Should this code also use HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA?
+
+ From the docs:
+
+ This flag enables buffering of data in the kernel on a per-response basis. It should
+ be used by an application doing synchronous I/O, or by a an application doing
+ asynchronous I/O with no more than one send outstanding at a time.
+
+ Applications using asynchronous I/O which may have more than one send outstanding at
+ a time should not use this flag.
+
+ When this flag is set, it should be used consistently in calls to the
+ HttpSendHttpResponse function as well.
+ */
+
ULONG SendFlags = 0;
if (m_RemainingChunkCount)
@@ -526,10 +552,14 @@ HttpMessageResponseRequest::IssueRequest(std::error_code& ErrorCode)
CancelThreadpoolIo(Iocp);
- spdlog::error("failed to send HTTP response (error: {}) URL: {}"sv, SendResult, HttpReq->pRawUrl);
+ spdlog::error("failed to send HTTP response (error: '{}'), request URL: {}"sv, SendResult, HttpReq->pRawUrl);
ErrorCode = MakeWin32ErrorCode(SendResult);
}
+ else
+ {
+ ErrorCode = {};
+ }
}
/**
@@ -926,53 +956,66 @@ HttpSysTransaction::InvokeRequestHandler(HttpService& Service, IoBuffer Payload)
{
HttpSysServerRequest& ThisRequest = m_HandlerRequest.emplace(*this, Service, Payload);
- if ((ThisRequest.RequestContentType() == HttpContentType::kCbPackageOffer) && (ThisRequest.RequestVerb() == HttpVerb::kPost))
+ if (ThisRequest.RequestVerb() == HttpVerb::kPost)
{
- // The client is presenting us with a package attachments offer, we need
- // to filter it down to the list of attachments we need them to send in
- // the follow-up request
-
- m_PackageHandler = Service.HandlePackageRequest(ThisRequest);
-
- if (m_PackageHandler)
+ if (ThisRequest.RequestContentType() == HttpContentType::kCbPackageOffer)
{
- CbObject OfferMessage = LoadCompactBinaryObject(Payload);
+ // The client is presenting us with a package attachments offer, we need
+ // to filter it down to the list of attachments we need them to send in
+ // the follow-up request
- std::vector<IoHash> OfferCids;
+ m_PackageHandler = Service.HandlePackageRequest(ThisRequest);
- for (auto& CidEntry : OfferMessage["offer"])
+ if (m_PackageHandler)
{
- if (!CidEntry.IsHash())
+ CbObject OfferMessage = LoadCompactBinaryObject(Payload);
+
+ std::vector<IoHash> OfferCids;
+
+ for (auto& CidEntry : OfferMessage["offer"])
{
- // Should yield bad request response?
+ if (!CidEntry.IsHash())
+ {
+ // Should yield bad request response?
+
+ continue;
+ }
- continue;
+ OfferCids.push_back(CidEntry.AsHash(IoHash::Zero));
}
- OfferCids.push_back(CidEntry.AsHash(IoHash::Zero));
- }
+ m_PackageHandler->FilterOffer(OfferCids);
- m_PackageHandler->FilterOffer(OfferCids);
+ CbObjectWriter ResponseWriter;
+ ResponseWriter.BeginArray("need");
- CbObjectWriter ResponseWriter;
- ResponseWriter.BeginArray("need");
+ for (const IoHash& Cid : OfferCids)
+ {
+ ResponseWriter.AddHash(Cid);
+ }
- for (const IoHash& Cid : OfferCids)
- {
- ResponseWriter.AddHash(Cid);
+ ResponseWriter.EndArray();
+
+ // Emit filter response
+ ThisRequest.WriteResponse(HttpResponseCode::OK, ResponseWriter.Save());
+
+ return ThisRequest;
}
+ }
+ else if (ThisRequest.RequestContentType() == HttpContentType::kCbPackage)
+ {
+ // Process chunks in package request
- ResponseWriter.EndArray();
+ m_PackageHandler = Service.HandlePackageRequest(ThisRequest);
- // Emit filter response
- ThisRequest.WriteResponse(HttpResponseCode::OK, ResponseWriter.Save());
+ if (m_PackageHandler)
+ {
+ CbPackage Package;
- return ThisRequest;
+ Package.TryLoad(ThisRequest.ReadPayload());
+ }
}
}
- else if ((ThisRequest.RequestContentType() == HttpContentType::kCbPackage) && (ThisRequest.RequestVerb() == HttpVerb::kPost))
- {
- }
// Default request handling
@@ -1024,13 +1067,8 @@ HttpSysServerRequest::HttpSysServerRequest(HttpSysTransaction& Tx, HttpService&
}
Oid
-HttpSysServerRequest::SessionId() const
+HttpSysServerRequest::ParseSessionId() const
{
- if (m_Flags & kHaveSessionId)
- {
- return m_SessionId;
- }
-
const HTTP_REQUEST* HttpRequestPtr = m_HttpTx.HttpRequest();
for (int i = 0; i < HttpRequestPtr->Headers.UnknownHeaderCount; ++i)
@@ -1042,24 +1080,17 @@ HttpSysServerRequest::SessionId() const
{
if (Header.RawValueLength == Oid::StringLength)
{
- m_SessionId = Oid::FromHexString({Header.pRawValue, Header.RawValueLength});
+ return Oid::FromHexString({Header.pRawValue, Header.RawValueLength});
}
}
}
- m_Flags |= kHaveSessionId;
-
- return m_SessionId;
+ return {};
}
uint32_t
-HttpSysServerRequest::RequestId() const
+HttpSysServerRequest::ParseRequestId() const
{
- if (m_Flags & kHaveRequestId)
- {
- return m_RequestId;
- }
-
const HTTP_REQUEST* HttpRequestPtr = m_HttpTx.HttpRequest();
for (int i = 0; i < HttpRequestPtr->Headers.UnknownHeaderCount; ++i)
@@ -1070,13 +1101,13 @@ HttpSysServerRequest::RequestId() const
if (HeaderName == "UE-Request"sv)
{
std::string_view RequestValue{Header.pRawValue, Header.RawValueLength};
- std::from_chars(RequestValue.data(), RequestValue.data() + RequestValue.size(), m_RequestId);
+ uint32_t RequestId = 0;
+ std::from_chars(RequestValue.data(), RequestValue.data() + RequestValue.size(), RequestId);
+ return RequestId;
}
}
- m_Flags |= kHaveRequestId;
-
- return m_RequestId;
+ return 0;
}
IoBuffer
diff --git a/zenhttp/include/zenhttp/httpserver.h b/zenhttp/include/zenhttp/httpserver.h
index f859eb038..44559db53 100644
--- a/zenhttp/include/zenhttp/httpserver.h
+++ b/zenhttp/include/zenhttp/httpserver.h
@@ -213,9 +213,9 @@ public:
inline HttpContentType RequestContentType() { return m_ContentType; }
inline HttpContentType AcceptContentType() { return m_AcceptType; }
- inline uint64_t ContentLength() const { return m_ContentLength; }
- virtual Oid SessionId() const;
- virtual uint32_t RequestId() const;
+ inline uint64_t ContentLength() const { return m_ContentLength; }
+ Oid SessionId() const;
+ uint32_t RequestId() const;
inline bool IsHandled() const { return !!(m_Flags & kIsHandled); }
inline bool SuppressBody() const { return !!(m_Flags & kSuppressBody); }
@@ -265,15 +265,18 @@ protected:
mutable Oid m_SessionId = Oid::Zero;
inline void SetIsHandled() { m_Flags |= kIsHandled; }
+
+ virtual Oid ParseSessionId() const = 0;
+ virtual uint32_t ParseRequestId() const = 0;
};
class IHttpPackageHandler : public RefCounted
{
public:
virtual void FilterOffer(std::vector<IoHash>& OfferCids) = 0;
- virtual void OnBeginChunks() = 0;
+ virtual void OnRequestBegin() = 0;
virtual IoBuffer CreateTarget(const IoHash& Cid, uint64_t StorageSize) = 0;
- virtual void OnEndChunks() = 0;
+ virtual void OnRequestComplete() = 0;
};
/**
diff --git a/zenhttp/zenhttp.vcxproj b/zenhttp/zenhttp.vcxproj
index 34c83326e..722944b21 100644
--- a/zenhttp/zenhttp.vcxproj
+++ b/zenhttp/zenhttp.vcxproj
@@ -96,12 +96,14 @@
<ClCompile Include="httpclient.cpp" />
<ClCompile Include="httpnull.cpp" />
<ClCompile Include="httpserver.cpp" />
+ <ClCompile Include="httpshared.cpp" />
<ClCompile Include="httpsys.cpp" />
<ClCompile Include="httpuws.cpp" />
<ClCompile Include="iothreadpool.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="httpnull.h" />
+ <ClInclude Include="httpshared.h" />
<ClInclude Include="httpsys.h" />
<ClInclude Include="httpuws.h" />
<ClInclude Include="include\zenhttp\httpclient.h" />
diff --git a/zenhttp/zenhttp.vcxproj.filters b/zenhttp/zenhttp.vcxproj.filters
index 9c2d05cd5..c05a8304e 100644
--- a/zenhttp/zenhttp.vcxproj.filters
+++ b/zenhttp/zenhttp.vcxproj.filters
@@ -7,6 +7,7 @@
<ClCompile Include="iothreadpool.cpp" />
<ClCompile Include="httpnull.cpp" />
<ClCompile Include="httpuws.cpp" />
+ <ClCompile Include="httpshared.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\zenhttp\httpclient.h" />
@@ -16,6 +17,7 @@
<ClInclude Include="include\zenhttp\zenhttp.h" />
<ClInclude Include="httpnull.h" />
<ClInclude Include="httpuws.h" />
+ <ClInclude Include="httpshared.h" />
</ItemGroup>
<ItemGroup>
<None Include="xmake.lua" />
diff --git a/zenserver/testing/httptest.cpp b/zenserver/testing/httptest.cpp
index d1955ca27..2d469c936 100644
--- a/zenserver/testing/httptest.cpp
+++ b/zenserver/testing/httptest.cpp
@@ -36,17 +36,33 @@ HttpTestingService::HandleRequest(HttpServerRequest& Request)
m_Router.HandleRequest(Request);
}
-//////////////////////////////////////////////////////////////////////////
-
Ref<IHttpPackageHandler>
HttpTestingService::HandlePackageRequest(HttpServerRequest& HttpServiceRequest)
{
- return new PackageHandler(HttpServiceRequest);
+ RwLock::ExclusiveLockScope _(m_RwLock);
+
+ const uint32_t RequestId = HttpServiceRequest.RequestId();
+
+ if (auto It = m_HandlerMap.find(RequestId); It != m_HandlerMap.end())
+ {
+ Ref<HttpTestingService::PackageHandler> Handler = std::move(It->second);
+
+ m_HandlerMap.erase(It);
+
+ return Handler.Get();
+ }
+
+ auto InsertResult = m_HandlerMap.insert({RequestId, nullptr});
+
+ _.ReleaseNow();
+
+ return (InsertResult.first->second = new PackageHandler(*this, RequestId)).Get();
}
-HttpTestingService::PackageHandler::PackageHandler(const HttpServerRequest& Request)
+//////////////////////////////////////////////////////////////////////////
+
+HttpTestingService::PackageHandler::PackageHandler(HttpTestingService& Svc, uint32_t RequestId) : m_Svc(Svc), m_RequestId(RequestId)
{
- ZEN_UNUSED(Request);
}
HttpTestingService::PackageHandler::~PackageHandler()
@@ -61,7 +77,12 @@ HttpTestingService::PackageHandler::FilterOffer(std::vector<IoHash>& OfferCids)
return;
}
void
-HttpTestingService::PackageHandler::OnBeginChunks()
+HttpTestingService::PackageHandler::OnRequestBegin()
+{
+}
+
+void
+HttpTestingService::PackageHandler::OnRequestComplete()
{
}
@@ -73,9 +94,4 @@ HttpTestingService::PackageHandler::CreateTarget(const IoHash& Cid, uint64_t Sto
return {};
}
-void
-HttpTestingService::PackageHandler::OnEndChunks()
-{
-}
-
} // namespace zen
diff --git a/zenserver/testing/httptest.h b/zenserver/testing/httptest.h
index 2f3482abc..5809d4e2e 100644
--- a/zenserver/testing/httptest.h
+++ b/zenserver/testing/httptest.h
@@ -24,17 +24,24 @@ public:
class PackageHandler : public IHttpPackageHandler
{
public:
- PackageHandler(const HttpServerRequest& Request);
+ PackageHandler(HttpTestingService& Svc, uint32_t RequestId);
~PackageHandler();
- void FilterOffer(std::vector<IoHash>& OfferCids) override;
- void OnBeginChunks() override;
- IoBuffer CreateTarget(const IoHash& Cid, uint64_t StorageSize) override;
- void OnEndChunks() override;
+ virtual void FilterOffer(std::vector<IoHash>& OfferCids) override;
+ virtual void OnRequestBegin() override;
+ virtual IoBuffer CreateTarget(const IoHash& Cid, uint64_t StorageSize) override;
+ virtual void OnRequestComplete() override;
+
+ private:
+ HttpTestingService& m_Svc;
+ uint32_t m_RequestId;
};
private:
HttpRequestRouter m_Router;
+
+ RwLock m_RwLock;
+ std::unordered_map<uint32_t, Ref<PackageHandler>> m_HandlerMap;
};
} // namespace zen