Add the packet capture service and the connection sources - #901
Open
sven-n wants to merge 1 commit into
Open
Conversation
The service collects the connections of all servers which run in this process and captures their traffic on request. It's the layer between the capture hook of the connections and the admin panel page. * A server which can provide the connections of its clients implements IConnectionSource. That's the game server, the connect server and the chat server; the proxies of a distributed deployment don't, so their connections are simply not listed. * Each connection is described by an ICapturedConnectionInfo, which is implemented by the servers themselves. That way the network connection stays inside the server which owns it: the info exposes the account and character name, the endpoint, the client version, the packet definition set which applies - and it attaches or detaches a capture sink on request. * The PacketCaptureService finds those servers over the already registered IServerProvider, so no additional registration is needed when servers are created or removed at runtime. * A capture is shared by all interested parties and stops when the last one is gone. Its packets are kept in a capped buffer, so a busy connection can't fill the memory. Registered in the all-in-one startup only, like the live map page. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Pb82LmoaUVdZtBtQs7xrtA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 2 of #895. Targets the phase 1 branch of #897, so it can be merged after that one — please review/merge #897 first, this PR then rebases onto master automatically.
The service is the layer between the capture hook of phase 1 and the admin panel page of phase 3: it collects the connections of all servers which run in this process and captures their traffic on request. Nothing uses it yet.
How the servers provide their connections
A server which can provide the connections of its clients implements
IConnectionSource— the game server, the connect server and the chat server do. The proxies of a distributed deployment don't, so their connections are simply not listed, which is exactly the graceful degradation we want.Each connection is described by an
ICapturedConnectionInfo, implemented by the servers themselves. That keeps theIConnectioninside the server which owns it — the info exposes what the UI needs (account name, character name, endpoint, client version, the packet definition set which applies) and attaches or detaches a capture sink on request.IGameContext.GetPlayersAsync(),RemotePlayerwith a connectionAccount.LoginName,SelectedCharacter.Name— read live, so a login or character selection shows up right awayRemotePlayer.ClientVersionClientListener.ClientsConnectServer.ClientVersionfrom its settingsChatClient.NicknameThe
PacketCaptureServicefinds those servers through the already registeredIServerProvider. That means no extra registration plumbing, and it covers game servers which are created or removed at runtime by theGameServerContainerfor free. It's registered in the all-in-one startup only, like the live map page.Capturing
StartCaptureAsync(connectionId)returns aLiveCapturedConnectionand registers it as a sink. A second caller for the same connection gets the same capture; the capture is only detached when the last interested party calledStopCapture— so two admins watching the same player don't disturb each other.The captured packets go into a capped buffer (default 5,000, oldest dropped), so a busy connection can't fill the memory.
LiveCapturedConnectionimplements the existingICapturedConnection, which means an admin panel page and the WinForms tool can consume the same model — and a capture can be saved as.mucapwith the extensions we already have.Direction: a packet sent on a server connection goes to the client, a received one goes to the server. The existing
Packet.ToServeris set accordingly.Deviations from the plan in #895
PlayerAdded/PlayerRemovedevents onGameContext. The plan wanted them so the connection list could update push-based. With the servers being queried on demand, they aren't needed, and adding unused public events felt speculative. If phase 3 wants push updates instead of refreshing on demand, they're easy to add then.SetObservationAsyncandIsObservedare not in the service yet. They belong to the account flag, which arrives with the migration in phase 5.MUnique.OpenMU.Interfaces(forServerType).Interfacesitself stays free of project references. If you'd rather have the capture abstractions in a separate small project instead of the analyzer library, that's a straightforward move.Tests
8 new tests in
PacketCaptureServiceTest: connections collected from several sources (and a server which isn't a source being skipped), lookup by id, lookup by account or character name (case insensitive, server scoped), a capture being attached and detached, a capture being shared by two parties and only stopped by the last one, an unknown connection returning null, the direction of captured packets, and the oldest packets being dropped when the buffer is full.Verification
dotnet build MUnique.OpenMU.sln -p:ci=true→ 0 errors; no warning originates in a file this PR adds or changes.MUnique.OpenMU.Network.Testsis at 59 passed, 4 skipped).🤖 Generated with Claude Code
https://claude.ai/code/session_01Pb82LmoaUVdZtBtQs7xrtA
Generated by Claude Code