diff options
Diffstat (limited to 'zenserver/cidstore.cpp')
| -rw-r--r-- | zenserver/cidstore.cpp | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/zenserver/cidstore.cpp b/zenserver/cidstore.cpp new file mode 100644 index 000000000..5de347a17 --- /dev/null +++ b/zenserver/cidstore.cpp @@ -0,0 +1,126 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "cidstore.h" + +#include <zencore/compress.h> +#include <zencore/fmtutils.h> +#include <zencore/logging.h> +#include <zenstore/cidstore.h> + +#include <gsl/gsl-lite.hpp> + +namespace zen { + +HttpCidService::HttpCidService(CidStore& Store) : m_CidStore(Store) +{ + m_Router.AddPattern("cid", "([0-9A-Fa-f]{40})"); + + m_Router.RegisterRoute( + "{cid}", + [this](HttpRouterRequest& Req) { + IoHash Hash = IoHash::FromHexString(Req.GetCapture(1)); + ZEN_DEBUG("CID request for {}", Hash); + + HttpServerRequest& ServerRequest = Req.ServerRequest(); + + switch (ServerRequest.RequestVerb()) + { + case HttpVerb::kGet: + case HttpVerb::kHead: + { + if (IoBuffer Value = m_CidStore.FindChunkByCid(Hash)) + { + return ServerRequest.WriteResponse(HttpResponseCode::OK, HttpContentType::kBinary, Value); + } + + return ServerRequest.WriteResponse(HttpResponseCode::NotFound); + } + break; + + case HttpVerb::kPut: + { + IoBuffer Payload = ServerRequest.ReadPayload(); + CompressedBuffer Compressed = CompressedBuffer::FromCompressed(SharedBuffer(Payload)); + if (!Compressed) + { + return ServerRequest.WriteResponse(HttpResponseCode::UnsupportedMediaType); + } + + IoHash PayloadHash = IoHash::FromBLAKE3(Compressed.GetRawHash()); + + // URI hash must match content hash + if (PayloadHash != Hash) + { + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest); + } + + m_CidStore.AddChunk(Compressed); + + return ServerRequest.WriteResponse(HttpResponseCode::OK); + } + break; + + default: + break; + } + }, + HttpVerb::kGet | HttpVerb::kPut | HttpVerb::kHead); +} + +const char* +HttpCidService::BaseUri() const +{ + return "/cid/"; +} + +void +HttpCidService::HandleRequest(zen::HttpServerRequest& Request) +{ + if (Request.RelativeUri().empty()) + { + // Root URI request + + switch (Request.RequestVerb()) + { + case HttpVerb::kPut: + case HttpVerb::kPost: + { + IoBuffer Payload = Request.ReadPayload(); + CompressedBuffer Compressed = CompressedBuffer::FromCompressed(SharedBuffer(Payload)); + if (!Compressed) + { + return Request.WriteResponse(HttpResponseCode::UnsupportedMediaType); + } + + IoHash PayloadHash = IoHash::FromBLAKE3(Compressed.GetRawHash()); + + ZEN_DEBUG("CID POST request for {} ({} bytes)", PayloadHash, Payload.Size()); + + auto InsertResult = m_CidStore.AddChunk(Compressed); + + if (InsertResult.New) + { + return Request.WriteResponse(HttpResponseCode::Created); + } + else + { + return Request.WriteResponse(HttpResponseCode::OK); + } + } + break; + + case HttpVerb::kGet: + case HttpVerb::kHead: + break; + + default: + break; + } + } + else + { + m_Router.HandleRequest(Request); + } +} + +} // namespace zen |