LizardByte / LizardByte/Sunshine
WSASendMsg() failed: 10022 (WSAEINVAL) on every WAN / port-forwarded UDP send — IP_PKTINFO source address rejected. Minimal single-NIC repro
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 41.3k
- Forks
- 2.1k
- Avg merge
- 23h 47m
- Merged PRs (30d)
- 124
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Is your issue described in the documentation?
- [x] I have read the documentation
### Is your issue present in the latest beta/pre-release?
This issue is present in the latest pre-release
### Describe the Bug
Over a port-forwarded WAN connection, every outbound video/ping UDP packet fails with `WSASendMsg() failed: 10022` (WSAEINVAL). The stream reaches CLIENT CONNECTED and the encoder is created fine, but not a single UDP packet leaves the host, so the client hits Initial Ping Timeout after ~10s.
LAN streaming is 100% fine — including dialing the host's own public IP and letting it NAT-loopback. Only genuine external clients arriving through the router's port-forward fail. The first 10022 appears ~17ms after the encoder is created, on the initial small ping reply (single packet via send(), no USO cmsg), so this is not USO/offload related.
I reduced it to a minimal repro and it still fails identically on both Sunshine and Apollo (shared Windows send path).
Ruled out with single-variable A/B tests (each with logs):
| Hypothesis | Test | Result |
|---|---|---|
| Encoder/GPU | — | ruled out; the YUV444 / NvEncUnregisterAsyncEvent lines are normal encoder-probe noise between the "// Testing for available encoders //" banners; all NVENC encoders create fine |
| Video encryption | wan_encryption_mode=0 | still 10022 |
| IPv4-mapped / dual-stack | address_family=ipv4 (client logged as bare IPv4, no ::ffff:) | still 10022 |
| Multiple NICs / IP forwarding / virtual adapters | reduced to a single Ethernet adapter, forwarding disabled | still 10022 |
| Routing | single default route, in/out interface identical | not the cause |
| Implementation | Sunshine -> Apollo | identical 10022 |
### Expected Behavior
A client connecting over WAN through a router port-forward should stream normally (outbound UDP packets are sent), exactly as it does on LAN.
### Additional Context
Root cause: in src/platform/windows/misc.cpp, both send() and send_batch() unconditionally attach an IP_PKTINFO control message pinning the source address:
IN_PKTINFO pktInfo;
SOCKADDR_IN saddr_v4 = to_sockaddr(send_info.source_address.to_v4(), 0);
pktInfo.ipi_addr = saddr_v4.sin_addr;
pktInfo.ipi_ifindex = 0;
cm->cmsg_level = IPPROTO_IP;
cm->cmsg_type = IP_PKTINFO;
With ipi_ifindex=0, Windows derives the outgoing interface from routing to the destination and then requires ipi_addr to be a unicast address assigned to that interface, else WSASendMsg returns WSAEINVAL. For a port-forwarded WAN client, send_info.source_address is not a locally-assigned address on the interface that routes to the client's public IP, so every packet is rejected. This is why LAN / native-IPv6 / mesh-VPN paths work (the dialed address is a real local interface address) but NAT port-forward does not. send() also has no fallback — on failure it just logs and returns false.
Suggested fix: on WSAEINVAL, retry without the IP_PKTINFO cmsg (plain send with no source pinning). A single-homed host doesn't need forced source selection — which is exactly why LAN already works. Small, low-risk change.
Adding a one-line debug log of send_info.source_address right before the WSASendMsg call would confirm the exact address being pinned on the WAN path. Happy to build a patched binary and test any fallback patch — the repro is deterministic.
Related: #3043 (closed as stale), #2120, ClassicOldSong/Apollo#1041 (open).
### Host Operating System
Windows
### Operating System Version
Windows 11, 10.0.26200
### Architecture
amd64/x86_64
### Package
Windows - msi installer (recommended)
### GPU Type
NVIDIA
### GPU Model
NVIDIA GeForce RTX 4060 Laptop GPU
### GPU Driver/Mesa Version
610.62
### Capture Method
Desktop Duplication API (Windows)
### Apps
```json
```
### Log output
```shell
```
### Online logs
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/platform/windows/misc.cpp, focusing on the send() and send_batch() paths that construct the IP_PKTINFO control message. Reproduce the failure with a single-NIC Windows host and a port-forwarded WAN client, then verify that outbound UDP packets are sent successfully while LAN streaming remains working.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100