diff options
Diffstat (limited to 'src/zenserver-test/projectclient.cpp')
| -rw-r--r-- | src/zenserver-test/projectclient.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/src/zenserver-test/projectclient.cpp b/src/zenserver-test/projectclient.cpp new file mode 100644 index 000000000..597838e0d --- /dev/null +++ b/src/zenserver-test/projectclient.cpp @@ -0,0 +1,164 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "projectclient.h" + +#if 0 + +# include <zencore/compactbinary.h> +# include <zencore/logging.h> +# include <zencore/sharedbuffer.h> +# include <zencore/string.h> +# include <zencore/zencore.h> + +# include <asio.hpp> +# include <gsl/gsl-lite.hpp> + +# if ZEN_PLATFORM_WINDOWS +# include <atlbase.h> +# endif + +namespace zen { + +struct ProjectClientConnection +{ + ProjectClientConnection(int BasePort) { Connect(BasePort); } + + void Connect(int BasePort) + { + ZEN_UNUSED(BasePort); + + WideStringBuilder<64> PipeName; + PipeName << "\\\\.\\pipe\\zenprj"; // TODO: this should use an instance-specific identifier! + + HANDLE hPipe = CreateFileW(PipeName.c_str(), + GENERIC_READ | GENERIC_WRITE, + 0, // Sharing doesn't make any sense + nullptr, // No security attributes + OPEN_EXISTING, // Open existing pipe + 0, // Attributes + nullptr // Template file + ); + + if (hPipe == INVALID_HANDLE_VALUE) + { + ZEN_WARN("failed while creating named pipe {}", WideToUtf8(PipeName)); + + throw std::system_error(GetLastError(), std::system_category(), fmt::format("Failed to open named pipe '{}'", WideToUtf8(PipeName))); + } + + // Change to message mode + DWORD dwMode = PIPE_READMODE_MESSAGE; + BOOL Success = SetNamedPipeHandleState(hPipe, &dwMode, nullptr, nullptr); + + if (!Success) + { + throw std::system_error(GetLastError(), + std::system_category(), + fmt::format("Failed to change named pipe '{}' to message mode", WideToUtf8(PipeName))); + } + + m_hPipe.Attach(hPipe); // This now owns the handle and will close it + } + + ~ProjectClientConnection() {} + + CbObject MessageTransaction(CbObject Request) + { + DWORD dwWrittenBytes = 0; + + MemoryView View = Request.GetView(); + + BOOL Success = ::WriteFile(m_hPipe, View.GetData(), gsl::narrow_cast<DWORD>(View.GetSize()), &dwWrittenBytes, nullptr); + + if (!Success) + { + throw std::system_error(GetLastError(), std::system_category(), "Failed to write pipe message"); + } + + ZEN_ASSERT(dwWrittenBytes == View.GetSize()); + + DWORD dwReadBytes = 0; + + Success = ReadFile(m_hPipe, m_Buffer, sizeof m_Buffer, &dwReadBytes, nullptr); + + if (!Success) + { + DWORD ErrorCode = GetLastError(); + + if (ERROR_MORE_DATA == ErrorCode) + { + // Response message is larger than our buffer - handle it by allocating a larger + // buffer on the heap and read the remainder into that buffer + + DWORD dwBytesAvail = 0, dwLeftThisMessage = 0; + + Success = PeekNamedPipe(m_hPipe, nullptr, 0, nullptr, &dwBytesAvail, &dwLeftThisMessage); + + if (Success) + { + UniqueBuffer MessageBuffer = UniqueBuffer::Alloc(dwReadBytes + dwLeftThisMessage); + + memcpy(MessageBuffer.GetData(), m_Buffer, dwReadBytes); + + Success = ReadFile(m_hPipe, + reinterpret_cast<uint8_t*>(MessageBuffer.GetData()) + dwReadBytes, + dwLeftThisMessage, + &dwReadBytes, + nullptr); + + if (Success) + { + return CbObject(SharedBuffer(std::move(MessageBuffer))); + } + } + } + + throw std::system_error(GetLastError(), std::system_category(), "Failed to read pipe message"); + } + + return CbObject(SharedBuffer::MakeView(MakeMemoryView(m_Buffer))); + } + +private: + static const int kEmbeddedBufferSize = 512 - 16; + + CHandle m_hPipe; + uint8_t m_Buffer[kEmbeddedBufferSize]; +}; + +struct LocalProjectClient::ClientImpl +{ + ClientImpl(int BasePort) : m_BasePort(BasePort) {} + ~ClientImpl() {} + + void Start() {} + void Stop() {} + + inline int BasePort() const { return m_BasePort; } + +private: + int m_BasePort = 0; +}; + +LocalProjectClient::LocalProjectClient(int BasePort) +{ + m_Impl = std::make_unique<ClientImpl>(BasePort); + m_Impl->Start(); +} + +LocalProjectClient::~LocalProjectClient() +{ + m_Impl->Stop(); +} + +CbObject +LocalProjectClient::MessageTransaction(CbObject Request) +{ + ProjectClientConnection Cx(m_Impl->BasePort()); + + return Cx.MessageTransaction(Request); +} + +} // namespace zen + +#endif // 0 |