aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver/proxy/httptrafficinspector.h
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2026-03-12 15:03:03 +0100
committerGitHub Enterprise <[email protected]>2026-03-12 15:03:03 +0100
commit81bc43aa96f0059cecb28d1bd88338b7d84667f9 (patch)
treea3428cb7fddceae0b284d33562af5bf3e64a367e /src/zenserver/proxy/httptrafficinspector.h
parentupdate fmt 12.0.0 -> 12.1.0 (#828) (diff)
downloadzen-81bc43aa96f0059cecb28d1bd88338b7d84667f9.tar.xz
zen-81bc43aa96f0059cecb28d1bd88338b7d84667f9.zip
Transparent proxy mode (#823)
Adds a **transparent TCP proxy mode** to zenserver (activated via `zenserver proxy`), allowing it to sit between clients and upstream Zen servers to inspect and monitor HTTP/1.x traffic in real time. Primarily useful during development, to be able to observe multi-server/client interactions in one place. - **Dedicated proxy port** -- Proxy mode defaults to port 8118 with its own data directory to avoid collisions with a normal zenserver instance. - **TCP proxy core** (`src/zenserver/proxy/`) -- A new transparent TCP proxy that forwards connections to upstream targets, with support for both TCP/IP and Unix socket listeners. Multi-threaded I/O for connection handling. Supports Unix domain sockets for both upstream/downstream. - **HTTP traffic inspection** -- Parses HTTP/1.x request/response streams inline to extract method, path, status, content length, and WebSocket upgrades without breaking the proxied data. - **Proxy dashboard** -- A web UI showing live connection stats, per-target request counts, active connections, bytes transferred, and client IP/session ID rollups. - **Server mode display** -- Dashboard banner now shows the running server mode (Zen Proxy, Zen Compute, etc.). Supporting changes included in this branch: - **Wildcard log level matching** -- Log levels can now be set per-category using wildcard patterns (e.g. `proxy.*=debug`). - **`zen down --all`** -- New flag to shut down all running zenserver instances; also used by the new `xmake kill` task. - Minor test stability fixes (flaky hash collisions, per-thread RNG seeds). - Support ZEN_MALLOC environment variable for default allocator selection and switch default to rpmalloc - Fixed sentry-native build to allow LTO on Windows
Diffstat (limited to 'src/zenserver/proxy/httptrafficinspector.h')
-rw-r--r--src/zenserver/proxy/httptrafficinspector.h85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/zenserver/proxy/httptrafficinspector.h b/src/zenserver/proxy/httptrafficinspector.h
new file mode 100644
index 000000000..f4af0e77e
--- /dev/null
+++ b/src/zenserver/proxy/httptrafficinspector.h
@@ -0,0 +1,85 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/logging.h>
+#include <zencore/uid.h>
+
+ZEN_THIRD_PARTY_INCLUDES_START
+#include <http_parser.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+
+#include <atomic>
+#include <cstdint>
+#include <string>
+#include <string_view>
+
+namespace zen {
+
+class HttpTrafficInspector
+{
+public:
+ enum class Direction
+ {
+ Request,
+ Response
+ };
+
+ HttpTrafficInspector(Direction Dir, std::string_view SessionLabel);
+
+ void Inspect(const char* Data, size_t Length);
+
+ uint64_t GetMessageCount() const { return m_MessageCount.load(std::memory_order_relaxed); }
+ bool IsUpgraded() const { return m_Upgraded.load(std::memory_order_relaxed); }
+ Oid GetSessionId() const;
+ bool HasSessionId() const;
+
+ void SetObserver(class IHttpTrafficObserver* Observer) { m_Observer = Observer; }
+
+private:
+ int OnUrl(const char* Data, size_t Length);
+ int OnHeaderField(const char* Data, size_t Length);
+ int OnHeaderValue(const char* Data, size_t Length);
+ int OnHeadersComplete();
+ int OnMessageComplete();
+
+ void ResetMessageState();
+
+ static HttpTrafficInspector* GetThis(http_parser* Parser) { return static_cast<HttpTrafficInspector*>(Parser->data); }
+
+ static http_parser_settings s_RequestSettings;
+ static http_parser_settings s_ResponseSettings;
+
+ LoggerRef Log() { return m_Log; }
+
+ LoggerRef m_Log;
+ http_parser m_Parser;
+ Direction m_Direction;
+ std::string m_SessionLabel;
+ bool m_Disabled = false;
+
+ // Per-message state
+ std::string m_Url;
+ std::string m_Method;
+ uint16_t m_StatusCode = 0;
+ int64_t m_ContentLength = -1;
+ std::string m_CurrentHeaderField;
+ std::atomic<uint64_t> m_MessageCount{0};
+ std::atomic<bool> m_Upgraded{false};
+ Oid m_SessionId = Oid::Zero;
+ bool m_SessionIdCaptured = false;
+ IHttpTrafficObserver* m_Observer = nullptr;
+};
+
+class IHttpTrafficObserver
+{
+public:
+ virtual ~IHttpTrafficObserver() = default;
+ virtual void OnMessageComplete(HttpTrafficInspector::Direction Dir,
+ std::string_view Method,
+ std::string_view Url,
+ uint16_t StatusCode,
+ int64_t ContentLength) = 0;
+};
+
+} // namespace zen