diff options
| author | Martin Ridgers <[email protected]> | 2021-11-25 11:07:49 +0100 |
|---|---|---|
| committer | Martin Ridgers <[email protected]> | 2021-11-25 11:07:49 +0100 |
| commit | 594501a96a4b64d3832d844909172a33fa14e7e2 (patch) | |
| tree | 4e48156c975064f5edf32202e02e18b720f503b9 | |
| parent | Tests for building ArgV for a fork-exec (diff) | |
| parent | Merge branch 'main' of https://github.com/EpicGames/zen (diff) | |
| download | zen-594501a96a4b64d3832d844909172a33fa14e7e2.tar.xz zen-594501a96a4b64d3832d844909172a33fa14e7e2.zip | |
Merged main
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | scripts/deploybuild.py | 22 | ||||
| -rw-r--r-- | xmake.lua | 50 | ||||
| -rw-r--r-- | zenhttp/httpasio.cpp | 122 | ||||
| -rw-r--r-- | zenserver-test/zenserver-test.cpp | 4 | ||||
| -rw-r--r-- | zenserver/upstream/jupiter.cpp | 4 |
6 files changed, 130 insertions, 73 deletions
diff --git a/.gitignore b/.gitignore index 103d3bd3f..204a2c274 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ x64/ x86/ bld/ +build/ [Bb]in/ [Oo]bj/ [Ll]og/ diff --git a/scripts/deploybuild.py b/scripts/deploybuild.py index c81235a8c..d137c3da1 100644 --- a/scripts/deploybuild.py +++ b/scripts/deploybuild.py @@ -50,20 +50,20 @@ while not os.path.exists(os.path.join(zenroot, "zen.sln")): zenroot = os.path.dirname(zenroot) jazz_print("Zen root:", zenroot) - # Build fresh binaries -if use_xmake: - build_cmd = ["xmake", "-b", "zenserver"] - build_output_dir = r'build\windows\x64\release' -else: - vs_path = vswhere.get_latest_path() # can also specify prerelease=True - jazz_print("BUILDING CODE", f"using VS root: {vs_path}") - devenv_path = os.path.join(vs_path, "Common7\\IDE\\devenv.com") - build_cmd = [devenv_path, "/build", "Release", "zen.sln"] - build_output_dir = r'x64\Release' - try: + if use_xmake: + subprocess.run(["xmake.exe", "config", "-p", "windows", "-a", "x64", "-m", "release"], check=True) + build_cmd = ["xmake.exe", "build", "--rebuild", "zenserver"] + build_output_dir = r'build\windows\x64\release' + else: + vs_path = vswhere.get_latest_path() # can also specify prerelease=True + jazz_print("BUILDING CODE", f"using VS root: {vs_path}") + devenv_path = os.path.join(vs_path, "Common7\\IDE\\devenv.com") + build_cmd = [devenv_path, "/build", "Release", "zen.sln"] + build_output_dir = r'x64\Release' + subprocess.run(build_cmd, check=True) except: jazz_fail("Build failed!") @@ -136,3 +136,53 @@ includes("zenstore", "zenstore-test") includes("zenutil") includes("zenserver", "zenserver-test") includes("zen") + +task("bundle") + on_run(function() + import("detect.tools.find_zip") + import("detect.tools.find_7z") + + -- copy files + local dirs = { + binaries = "./build/windows/x64/release", + bundles = "./build/bundles", + bundle = "./build/bundles/zenzerver-win64" + } + + local files = { + dirs.binaries .. "/zenserver.exe", + dirs.binaries .. "/zenserver.pdb", + "./vcpkg_installed/x64-windows-static/tools/sentry-native/crashpad_handler.exe" + } + + os.mkdir(dirs.bundles) + os.mkdir(dirs.bundle) + + for _,file in ipairs(files) do + printf("copy '%s' -> '%s'\n", file, dirs.bundle) + os.cp(file, dirs.bundle) + end + + -- create archive + local bundle_name = "zenserver-win64.zip" + + local zip_cmd = find_7z() + assert(zip_cmd) + + local zip_args = {} + table.insert(zip_args, "a") + table.insert(zip_args, dirs.bundles .. "/" .. bundle_name) + table.insert(zip_args, dirs.bundle .. "/*.*") + + printf("creating bundle '%s'...", dirs.bundles .. "/" .. bundle_name) + os.runv(zip_cmd, zip_args) + os.rm(dirs.bundle) + + printf(" Ok!") + end) + + set_menu { + usage = "xmake bundle", + description = "Create zip bundle from binaries", + options = {} + } diff --git a/zenhttp/httpasio.cpp b/zenhttp/httpasio.cpp index d94f6af2e..0ed5e78cf 100644 --- a/zenhttp/httpasio.cpp +++ b/zenhttp/httpasio.cpp @@ -6,6 +6,7 @@ #include <zenhttp/httpserver.h> #include <deque> +#include <memory> #include <memory_resource> ZEN_THIRD_PARTY_INCLUDES_START @@ -171,7 +172,7 @@ private: IoBuffer m_BodyBuffer; uint64_t m_BodyPosition = 0; http_parser m_Parser; - char m_HeaderBuffer[512]; + char m_HeaderBuffer[1024]; void AppendInputBytes(const char* Data, size_t Bytes); void AppendCurrentHeader(); @@ -283,7 +284,7 @@ private: ////////////////////////////////////////////////////////////////////////// -struct HttpServerConnection +struct HttpServerConnection : std::enable_shared_from_this<HttpServerConnection> { HttpServerConnection(HttpAsioServerImpl& Server, std::unique_ptr<asio::ip::tcp::socket>&& Socket); ~HttpServerConnection(); @@ -292,6 +293,8 @@ struct HttpServerConnection void TerminateConnection(); void HandleRequest(); + std::shared_ptr<HttpServerConnection> AsSharedPtr() { return shared_from_this(); } + private: enum class RequestState { @@ -371,50 +374,32 @@ HttpServerConnection::EnqueueRead() asio::async_read(*m_Socket.get(), m_RequestBuffer, asio::transfer_at_least(16), - [this](const asio::error_code& Ec, std::size_t ByteCount) { - if (Ec) - { - if (m_RequestState == RequestState::kDone || m_RequestState == RequestState::kInitialRead) - { - // Expected, just silently handle the condition - // - // if we get an I/O error on the boundary between two messages - // it should be fine to just not say anything - - ZEN_TRACE("(expected) socket read error: conn#{} '{}'", m_ConnectionId, Ec.message()); - } - else - { - ZEN_WARN("unexpected socket read error: conn#{} {}", m_ConnectionId, Ec.message()); - } - - delete this; - } - else - { - ZEN_TRACE("read: conn#:{} seq#:{} t:{} bytes:{}", - m_ConnectionId, - m_RequestCounter.load(std::memory_order_relaxed), - zen::GetCurrentThreadId(), - ByteCount); - - OnDataReceived(Ec, ByteCount); - } - }); + [Conn = AsSharedPtr()](const asio::error_code& Ec, std::size_t ByteCount) { Conn->OnDataReceived(Ec, ByteCount); }); } void HttpServerConnection::OnDataReceived(const asio::error_code& Ec, std::size_t ByteCount) { - ZEN_UNUSED(ByteCount); - if (Ec) { - ZEN_ERROR("OnDataReceived Error: {}", Ec.message()); - - return OnError(); + if (m_RequestState == RequestState::kDone || m_RequestState == RequestState::kInitialRead) + { + ZEN_TRACE("on data received ERROR (EXPECTED), connection '{}' reason '{}'", m_ConnectionId, Ec.message()); + return; + } + else + { + ZEN_ERROR("on data received ERROR, connection '{}' reason '{}'", m_ConnectionId, Ec.message()); + return OnError(); + } } + ZEN_TRACE("on data received, connection '{}', request '{}', thread '{}', bytes '{}'", + m_ConnectionId, + m_RequestCounter.load(std::memory_order_relaxed), + zen::GetCurrentThreadId(), + NiceBytes(ByteCount)); + while (m_RequestBuffer.size()) { const asio::const_buffer& InputBuffer = m_RequestBuffer.data(); @@ -440,24 +425,34 @@ HttpServerConnection::OnDataReceived(const asio::error_code& Ec, std::size_t Byt void HttpServerConnection::OnResponseDataSent(const asio::error_code& Ec, std::size_t ByteCount, bool Pop) { - ZEN_UNUSED(ByteCount); if (Ec) { - ZEN_ERROR("OnResponseDataSent Error: {}", Ec.message()); - return OnError(); + ZEN_ERROR("on data sent ERROR, connection '{}' reason '{}'", m_ConnectionId, Ec.message()); + OnError(); } else { + ZEN_TRACE("on data sent, connection '{}', request '{}', thread '{}', bytes '{}'", + m_ConnectionId, + m_RequestCounter.load(std::memory_order_relaxed), + zen::GetCurrentThreadId(), + NiceBytes(ByteCount)); + if (!m_RequestData.IsKeepAlive()) { m_RequestState = RequestState::kDone; m_Socket->close(); } - else if (Pop) + else { - RwLock::ExclusiveLockScope _(m_ResponsesLock); - m_Responses.pop_front(); + if (Pop) + { + RwLock::ExclusiveLockScope _(m_ResponsesLock); + m_Responses.pop_front(); + } + + m_RequestCounter.fetch_add(1); } } } @@ -480,7 +475,7 @@ HttpServerConnection::HandleRequest() if (Ec) { - ZEN_WARN("socket shutdown reported error: {}", Ec.message()); + ZEN_WARN("socket shutdown ERROR, reason '{}'", Ec.message()); } } else @@ -488,14 +483,11 @@ HttpServerConnection::HandleRequest() m_RequestState = RequestState::kWriting; } - const uint32_t RequestNum = m_RequestCounter.load(std::memory_order_relaxed); - m_RequestCounter.fetch_add(1); - if (HttpService* Service = m_Server.RouteRequest(m_RequestData.Url())) { HttpAsioServerRequest Request(m_RequestData, *Service, m_RequestData.Body()); - ZEN_TRACE("Handling request: Conn#{} Req#{}", m_ConnectionId, RequestNum); + ZEN_TRACE("handle request, connection '{}' request '{}'", m_ConnectionId, m_RequestCounter.load(std::memory_order_relaxed)); Service->HandleRequest(Request); @@ -527,9 +519,8 @@ HttpServerConnection::HandleRequest() asio::async_write(*m_Socket.get(), ResponseBuffers, asio::transfer_exactly(ResponseLength), - [this, RequestNum](const asio::error_code& Ec, std::size_t ByteCount) { - ZEN_TRACE("Response sent: Conn#{} Req#{} ({})", m_ConnectionId, RequestNum, NiceBytes(ByteCount)); - OnResponseDataSent(Ec, ByteCount, true); + [Conn = AsSharedPtr()](const asio::error_code& Ec, std::size_t ByteCount) { + Conn->OnResponseDataSent(Ec, ByteCount, true); }); return; @@ -550,9 +541,10 @@ HttpServerConnection::HandleRequest() "\r\n"sv; } - asio::async_write(*m_Socket.get(), asio::buffer(Response), [this](const asio::error_code& Ec, std::size_t ByteCount) { - OnResponseDataSent(Ec, ByteCount); - }); + asio::async_write( + *m_Socket.get(), + asio::buffer(Response), + [Conn = AsSharedPtr()](const asio::error_code& Ec, std::size_t ByteCount) { Conn->OnResponseDataSent(Ec, ByteCount); }); } else { @@ -574,9 +566,10 @@ HttpServerConnection::HandleRequest() "No suitable route found"sv; } - asio::async_write(*m_Socket.get(), asio::buffer(Response), [this](const asio::error_code& Ec, std::size_t ByteCount) { - OnResponseDataSent(Ec, ByteCount); - }); + asio::async_write( + *m_Socket.get(), + asio::buffer(Response), + [Conn = AsSharedPtr()](const asio::error_code& Ec, std::size_t ByteCount) { Conn->OnResponseDataSent(Ec, ByteCount); }); } } @@ -877,8 +870,13 @@ struct HttpAcceptor HttpAcceptor(HttpAsioServerImpl& Server, asio::io_service& IoService, uint16_t Port) : m_Server(Server) , m_IoService(IoService) - , m_Acceptor(m_IoService, asio::ip::tcp::endpoint(asio::ip::address_v4::any(), Port)) + , m_Acceptor(m_IoService, asio::ip::tcp::v6()) { + m_Acceptor.set_option(asio::ip::v6_only(false)); + m_Acceptor.set_option(asio::socket_base::reuse_address(true)); + m_Acceptor.set_option(asio::ip::tcp::no_delay(true)); + m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), Port)); + m_Acceptor.listen(); } void Start() @@ -902,14 +900,14 @@ struct HttpAcceptor else { // New connection established, pass socket ownership into connection object - // and initiate request handling loop + // and initiate request handling loop. The connection lifetime is + // managed by the async read/write loop by passing the shared + // reference to the callbacks. Socket->set_option(asio::ip::tcp::no_delay(true)); - HttpServerConnection* Conn = new HttpServerConnection(m_Server, std::move(Socket)); + auto Conn = std::make_shared<HttpServerConnection>(m_Server, std::move(Socket)); Conn->HandleNewRequest(); - - // note: the connection object is responsible for deleting itself } if (!m_IsStopped.load()) diff --git a/zenserver-test/zenserver-test.cpp b/zenserver-test/zenserver-test.cpp index c83278fe7..a92273486 100644 --- a/zenserver-test/zenserver-test.cpp +++ b/zenserver-test/zenserver-test.cpp @@ -1753,6 +1753,7 @@ TEST_CASE("zcache.policy") zen::IoBuffer Body(zen::IoBuffer::Wrap, Result.text.data(), Result.text.size()); zen::CbPackage Package; const bool Ok = Package.TryLoad(Body); + CHECK(Ok); CHECK(Ok); @@ -1774,6 +1775,7 @@ TEST_CASE("zcache.policy") zen::IoBuffer Body(zen::IoBuffer::Wrap, Result.text.data(), Result.text.size()); zen::CbPackage Package; const bool Ok = Package.TryLoad(Body); + CHECK(Ok); CHECK(Ok); CHECK(Package.GetAttachments().size() != 0); @@ -1814,6 +1816,7 @@ TEST_CASE("zcache.policy") zen::IoBuffer Body(zen::IoBuffer::Wrap, Result.text.data(), Result.text.size()); zen::CbPackage Package; const bool Ok = Package.TryLoad(Body); + CHECK(Ok); CHECK(Ok); @@ -1835,6 +1838,7 @@ TEST_CASE("zcache.policy") zen::IoBuffer Body(zen::IoBuffer::Wrap, Result.text.data(), Result.text.size()); zen::CbPackage Package; const bool Ok = Package.TryLoad(Body); + CHECK(Ok); CHECK(Ok); CHECK(Package.GetAttachments().size() != 0); diff --git a/zenserver/upstream/jupiter.cpp b/zenserver/upstream/jupiter.cpp index a9f6e4036..177184591 100644 --- a/zenserver/upstream/jupiter.cpp +++ b/zenserver/upstream/jupiter.cpp @@ -672,6 +672,7 @@ CloudCacheSession::GetComputeUpdates(std::string_view ChannelId, const uint32_t Session.SetOption(cpr::Url{Uri.c_str()}); Session.SetOption(cpr::Header{{"Authorization", AccessToken.Value}, {"Accept", "application/x-ue-cb"}}); + Session.SetOption(cpr::Body{}); cpr::Response Response = Session.Post(); ZEN_DEBUG("POST {}", Response); @@ -707,6 +708,7 @@ CloudCacheSession::GetObjectTree(const IoHash& Key) Session.SetOption(cpr::Url{Uri.c_str()}); Session.SetOption(cpr::Header{{"Authorization", AccessToken.Value}, {"Accept", "application/octet-stream"}}); + Session.SetOption(cpr::Body{}); cpr::Response Response = Session.Get(); ZEN_DEBUG("GET {}", Response); @@ -771,6 +773,7 @@ CloudCacheSession::CacheTypeExists(std::string_view TypeId, const IoHash& Key) Session.SetOption(cpr::Url{Uri.c_str()}); Session.SetOption(cpr::Header{{"Authorization", AccessToken.Value}}); + Session.SetOption(cpr::Body{}); cpr::Response Response = Session.Head(); ZEN_DEBUG("HEAD {}", Response); @@ -809,6 +812,7 @@ CloudCacheSession::CacheTypeExists(std::string_view TypeId, const std::set<IoHas Session.SetOption(cpr::Url{Uri.c_str()}); Session.SetOption(cpr::Header{{"Authorization", AccessToken.Value}, {"Accept", "application/x-ue-cb"}}); + Session.SetOption(cpr::Body{}); cpr::Response Response = Session.Post(); ZEN_DEBUG("POST {}", Response); |