While adopting the Gauntlet RPC Testing Framework (we have been working with Ben Salem’s team in our shared Slack channel), we found that the harness-side message-bus listener - RpcExecutor’s HttpListener on port 23232, which receives game-to-Gauntlet pushes at /sendmessage - binds a literal first-enumerated IP address, and on a default Windows setup that fails in two independent ways (both measured):
1. BIND: http.sys matches URL ACL reservations against the exact prefix string, so the standard non-admin reservation (netsh http add urlacl url=http://+:23232/) never covers a literal-IP bind. HttpListener.Start() fails with Access Denied unless UAT runs elevated.
2. DELIVERY: even when bound (e.g. running elevated), an IP-literal-host prefix is never matched when http.sys routes incoming requests - http.sys accepts the connection and answers 503 itself; the listener’s handler never sees the request. This holds even on loopback with the Host header string-equal to the prefix. Hostname prefixes (“localhost”) and the wildcard both deliver. See Steps to Reproduce for a ~10-line repro with no Unreal code involved.
Because the game-side sender logs “Successfully sent message” on ProcessRequest() == true (which reports dispatch, not delivery), the failure is silent: event-driven tests using RegisterMessageDelegate fail with healthy-looking logs, elevated or not. Additionally, on multi-adapter machines GetListenAddressAndPort() picks whichever adapter enumerates first, so the chosen IP is unpredictable per launch. Your team confirmed Epic runs UAT elevated on dev machines and farm agents - which masks defect 1 but not defect 2, so we suspect this affects Epic’s own event-driven Gauntlet runs as well.
Proposed fix (one line): bind the strong wildcard prefix (http://+:<port>/). Games still receive the specific routable address via -externalrpclistenaddress; the wildcard only broadens what the listener accepts. Verified on our side with an event-driven Gauntlet test going red -> green across elevated/non-elevated, with/without reservations, and on our build farm (agents run as LocalSystem).
Pull request: https://github.com/EpicGames/UnrealEngine/pull/15073
Questions:
1. Would you accept this PR (or an equivalent fix) upstream?
2. Are event-driven (push-based) Gauntlet tests currently passing in Epic’s own CI? If so, we would like to understand what differs from a stock Windows setup, since our measurements suggest the current bind cannot receive on one.
-------------------------------------------------------------
Steps to Reproduce:
Minimal repro of the delivery defect, no Unreal involved (run elevated so the bind succeeds):
1. In an elevated PowerShell: $l = New-Object System.Net.HttpListener; $l.Prefixes.Add(‘http://127.0.0.1:23232/’); $l.Start(); $l.GetContext()
2. From another shell: Invoke-WebRequest -Uri ‘http://127.0.0.1:23232/x’ -Method POST -Body ‘{}’
3. Observe: the sender receives HTTP 503 (answered by http.sys itself) and GetContext() never returns. Replace the prefix with ‘http://+:23232/’ and the identical request is delivered.
In-engine repro: any Gauntlet test that registers a message delegate (RpcExecutor.RegisterMessageDelegate) and has the game push to /sendmessage. Non-elevated, the listener fails to bind (Access Denied, logged as a Warning and swallowed). Elevated, it binds and every push is silently dropped while the game-side sender logs “Successfully sent message”.
[Attachment Removed]