diff options
| author | Stefan Boberg <[email protected]> | 2026-03-12 15:03:03 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-03-12 15:03:03 +0100 |
| commit | 81bc43aa96f0059cecb28d1bd88338b7d84667f9 (patch) | |
| tree | a3428cb7fddceae0b284d33562af5bf3e64a367e /src/zenserver/proxy/httptrafficinspector.h | |
| parent | update fmt 12.0.0 -> 12.1.0 (#828) (diff) | |
| download | zen-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.h | 85 |
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 |