Gauntlet RPC message-bus listener never receives game-to-Gauntlet pushes on default Windows (fix proposed in GitHub PR #15073)

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]

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]

We are going to integrate this change as it fixes a problem that is frequently encounter by users.

Thanks to have taken the time to propose this fix.

[Attachment Removed]