aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Ridgers <[email protected]>2021-11-25 11:07:49 +0100
committerMartin Ridgers <[email protected]>2021-11-25 11:07:49 +0100
commit594501a96a4b64d3832d844909172a33fa14e7e2 (patch)
tree4e48156c975064f5edf32202e02e18b720f503b9
parentTests for building ArgV for a fork-exec (diff)
parentMerge branch 'main' of https://github.com/EpicGames/zen (diff)
downloadzen-594501a96a4b64d3832d844909172a33fa14e7e2.tar.xz
zen-594501a96a4b64d3832d844909172a33fa14e7e2.zip
Merged main
-rw-r--r--.gitignore1
-rw-r--r--scripts/deploybuild.py22
-rw-r--r--xmake.lua50
-rw-r--r--zenhttp/httpasio.cpp122
-rw-r--r--zenserver-test/zenserver-test.cpp4
-rw-r--r--zenserver/upstream/jupiter.cpp4
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!")
diff --git a/xmake.lua b/xmake.lua
index d8d8fddf6..c1aef5f85 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -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);