diff options
| author | Stefan Boberg <[email protected]> | 2023-09-20 15:22:03 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-09-20 15:22:03 +0200 |
| commit | 14d7568f9c7d970b7bbf7b6463a0a8530f98bb6f (patch) | |
| tree | bf24ac15759385cea339f7e1cf5380f984f5699a /src/zenserver/vfs/vfsservice.cpp | |
| parent | changelog version bump (diff) | |
| download | zen-14d7568f9c7d970b7bbf7b6463a0a8530f98bb6f.tar.xz zen-14d7568f9c7d970b7bbf7b6463a0a8530f98bb6f.zip | |
VFS implementation for local storage service (#396)
currently, only Windows (using Projected File System) is supported
Diffstat (limited to 'src/zenserver/vfs/vfsservice.cpp')
| -rw-r--r-- | src/zenserver/vfs/vfsservice.cpp | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/zenserver/vfs/vfsservice.cpp b/src/zenserver/vfs/vfsservice.cpp new file mode 100644 index 000000000..c53682d93 --- /dev/null +++ b/src/zenserver/vfs/vfsservice.cpp @@ -0,0 +1,217 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "vfsservice.h" +#include "vfsimpl.h" + +#include <zencore/compactbinarybuilder.h> + +namespace zen { + +using namespace std::literals; + +#if ZEN_WITH_VFS + +////////////////////////////////////////////////////////////////////////// + +bool +GetContentAsCbObject(HttpServerRequest& HttpReq, CbObject& Cb) +{ + IoBuffer Payload = HttpReq.ReadPayload(); + HttpContentType PayloadContentType = HttpReq.RequestContentType(); + + switch (PayloadContentType) + { + case HttpContentType::kJSON: + case HttpContentType::kUnknownContentType: + case HttpContentType::kText: + { + std::string JsonText(reinterpret_cast<const char*>(Payload.GetData()), Payload.GetSize()); + Cb = LoadCompactBinaryFromJson(JsonText).AsObject(); + if (!Cb) + { + HttpReq.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + "Content format not supported, expected JSON format"); + return false; + } + } + break; + case HttpContentType::kCbObject: + Cb = LoadCompactBinaryObject(Payload); + if (!Cb) + { + HttpReq.WriteResponse(HttpResponseCode::BadRequest, + HttpContentType::kText, + "Content format not supported, expected compact binary format"); + return false; + } + break; + default: + HttpReq.WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "Invalid request content type"); + return false; + } + + return true; +} + +////////////////////////////////////////////////////////////////////////// +// +// to test: +// +// echo {"method": "mount", "params": {"path": "d:\\VFS_ROOT"}} | curl.exe http://localhost:1337/vfs --data-binary @- +// echo {"method": "unmount"} | curl.exe http://localhost:1337/vfs --data-binary @- + +VfsService::VfsService() +{ + m_Impl = new Impl; + + m_Router.RegisterRoute( + "info", + [&](HttpRouterRequest& Request) { + CbObjectWriter Cbo; + Cbo << "running" << m_Impl->IsVfsRunning(); + Cbo << "rootpath" << m_Impl->GetMountpointPath(); + + Request.ServerRequest().WriteResponse(HttpResponseCode::OK, Cbo.Save()); + }, + HttpVerb::kGet | HttpVerb::kHead); + + m_Router.RegisterRoute( + "", + [&](HttpRouterRequest& Req) { + CbObject Payload; + + if (!GetContentAsCbObject(Req.ServerRequest(), Payload)) + return; + + std::string_view RpcName = Payload["method"sv].AsString(); + + if (RpcName == "mount"sv) + { + CbObjectView Params = Payload["params"sv].AsObjectView(); + std::string_view Mountpath = Params["path"sv].AsString(); + + if (Mountpath.empty()) + { + return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "no path specified"); + } + + if (m_Impl->IsVfsRunning()) + { + return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "VFS already mounted"); + } + + try + { + m_Impl->Mount(Mountpath); + } + catch (std::exception& Ex) + { + return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, Ex.what()); + } + + Req.ServerRequest().WriteResponse(HttpResponseCode::OK); + } + else if (RpcName == "unmount"sv) + { + if (!m_Impl->IsVfsRunning()) + { + return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "VFS not active"); + } + + try + { + m_Impl->Unmount(); + } + catch (std::exception& Ex) + { + return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, Ex.what()); + } + + Req.ServerRequest().WriteResponse(HttpResponseCode::OK); + } + else + { + Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "unknown RPC"sv); + } + }, + HttpVerb::kPost); +} + +VfsService::~VfsService() +{ + delete m_Impl; +} + +void +VfsService::Mount(std::string_view MountPoint) +{ + m_Impl->Mount(MountPoint); +} + +void +VfsService::Unmount() +{ + m_Impl->Unmount(); +} + +void +VfsService::AddService(Ref<ProjectStore>&& Ps) +{ + m_Impl->AddService(std::move(Ps)); +} + +void +VfsService::AddService(Ref<ZenCacheStore>&& Z$) +{ + m_Impl->AddService(std::move(Z$)); +} + +#else + +VfsService::VfsService() +{ +} + +VfsService::~VfsService() +{ +} + +void +VfsService::Mount(std::string_view MountPoint) +{ + ZEN_UNUSED(MountPoint); +} + +void +VfsService::Unmount() +{ +} + +void +VfsService::AddService(Ref<ProjectStore>&& Ps) +{ + ZEN_UNUSED(Ps); +} + +void +VfsService::AddService(Ref<ZenCacheStore>&& Z$) +{ + ZEN_UNUSED(Z$); +} + +#endif + +const char* +VfsService::BaseUri() const +{ + return "/vfs/"; +} + +void +VfsService::HandleRequest(HttpServerRequest& HttpServiceRequest) +{ + m_Router.HandleRequest(HttpServiceRequest); +} + +} // namespace zen |