CNA-BUG-267: A join beyond MaxGamers is not refused: the host sends ServerWelcome, AddRemoteGamer throws Session is full!, and the receive path's catch-all drops it, so SessionFull is never raised

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

HandleClientHello sends ServerWelcome and registers wire ids before AddRemoteGamer checks capacity; the receive path swallows the exception, so an over-capacity client stays connected and NetworkSessionJoinError::SessionFull is never produced.

Identifier
CNA-BUG-267
Category
Bug
Subsystem
Networking & gamer services
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Medium (a triage suggestion, not a project priority)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
Microsoft::Xna::Framework::Net::NetworkSession::Join on a full host (ENetBackend HandleClientHello, NetworkSession::AddRemoteGamer, NetworkSessionJoinError::SessionFull)

Expected behaviour

A client that joins a session already holding MaxGamers gamers should be refused with a NetworkSessionJoinException carrying NetworkSessionJoinError::SessionFull, the value the XNA API defines for exactly this case, and the host's roster and the other peers should be left alone.

Actual behaviour at TARGET

HandleClientHello rejects only a duplicate handshake and a join in progress that the host forbids. It then creates the joining client's NetworkGamer objects, assigns and registers their wire ids, sends ServerWelcome, and only afterwards calls NetworkSession::AddRemoteGamer, which throws InvalidOperationException(“Session is full!”) once allGamers_ has reached maxGamers_. The receive path wraps the whole message switch in a catch-all that drops the exception, so a bad packet cannot take down Update(). The over-capacity client therefore has been welcomed and stays connected with its wire ids registered, the gamers beyond the limit are never added to the host's roster or announced to the other peers, and SessionFull is produced nowhere in the module (it appears only in the enum header).

Source locations

Evidence

Read at 009d40f5; nothing was executed. Found by the C10 conservation reviewer (unit ch51) and re-verified by the orchestrator against HandleClientHello, AddRemoteGamer and the receive path's exception handling. XNA's behaviour is taken from the API it defines (NetworkSessionJoinError::SessionFull), not from a decompiled join path.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

The capacity check in AddRemoteGamer is tested at the session level; no test connects an extra client to a full host and observes what the joiner sees.

Regression test

Start a host with maxGamers 2, connect a third client and expect its join to fail with SessionFull (or the host to disconnect the peer) instead of a welcomed client that the host never rosters.

Blast radius

SystemLink games with a fixed player limit whose lobby can be joined by more clients than the limit: the extra client believes it is in the session while the host ignores it. Sessions that never exceed their limit are unaffected.

Workaround

None in the library; a game can avoid it by checking the discovered session's open public slots before calling Join.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Known issues
Bug index