Commit Graph

5 Commits

Author SHA1 Message Date
gamer147
7d4da69f22 refactor(battlenode): low-churn §B/§D/§E/§F quality cleanups
Behavior-preserving; 231 BattleNode tests green.

- §D: MsgEnvelope.Try -> RetryAttempt (drops keyword-escape; wire key stays "try");
  SocketIoFrame.AckResponse arg -> pubSeqEcho.
- §B: Gungnir.EmitInterval -> BattleNodeOptions.AliveEmitInterval (unused literal
  moved to its config home); deck-idx 4L -> InitialHand.Length + 1.
- §E: shared Wire.WireJsonOptions.CamelCase replaces the duplicated camelCase
  JsonSerializerOptions in EngineIoHandshake and MsgEnvelope.
- §F: do-NOT-consistency-fix polarity notes on TurnEndFinalHandler (From wins)
  and RetireKillHandler (From loses).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 23:06:44 -04:00
gamer147
99129c786c fix(battle-node): harden SIO parse + narrow Matched OppoId/Seed to int
#3: SocketIoFrame.Parse now range-checks the packet type char (was
unchecked cast — any char outside 0-6 produced an undefined enum
value) and uses int.TryParse for ack-id (was int.Parse — a >10-digit
ack-id threw OverflowException, tearing down the WS mid-game). Both
now throw ArgumentException consistently. The read loop in
RealParticipant wraps both EIO and SIO parse calls with try-catch so
a malformed frame is logged and skipped instead of killing the battle.

#4: MatchedSelfInfo/MatchedOppoInfo OppoId and Seed narrowed from
long to int. The client reads both with Convert.ToInt32 inside a
swallowing try/catch — any value > int.MaxValue silently dropped the
Matched event, preventing the battle from starting. Seed was already
int-range (BattleSeeds.Stable returns int); OppoId (viewer ID) is
~847M in captures, well under int.MaxValue. The narrowing cast now
happens explicitly in ServerBattleFrames.BuildMatched at the wire
boundary.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-04 21:57:29 -04:00
gamer147
133346e3e8 refactor(battle-node): SocketIoFrame throws on namespace; typed JSON construction 2026-06-01 11:48:17 -04:00
gamer147
6ff4f70f1a fix(battle-node): SocketIoFrame disposal safety + escaping + empty-args encoding
- Wrap all JsonDocument.Parse calls in using blocks and Clone() each
  retained JsonElement to eliminate UAF hazard after GC.
- Use JsonSerializer.Serialize with UnsafeRelaxedJsonEscaping so event
  names with " or \ produce \" / \ rather than " / plain \;
  avoids malformed JSON on Encode().
- Guard the [ ] block in Encode() behind EventName-or-args check so
  Connect/Disconnect packets round-trip as bare "0"/"1" not "0[]".
- Add three regression tests: Connect no-bracket, Event round-trip,
  special-char event name escaping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 21:46:02 -04:00
gamer147
8b1f613407 feat(battle-node): SocketIoFrame parse/encode for SIO2 incl. binary attachments 2026-05-31 21:39:53 -04:00