Files
Beyhan Oğur d5f52cc3d3 first commit
2026-09-03 04:45:36 +03:00

26 KiB
Raw Permalink Blame History

Packet Processing Pipeline

**Referenced Files in This Document** - [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs) - [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs) - [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs) - [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs) - [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs) - [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs) - [ActionPacketQueueItem.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueueItem.cs) - [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs) - [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs) - [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs) - [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs) - [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs) - [MobileMoving.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileMoving.cs) - [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs) - [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs) - [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs) - [Engine.cs](file://ClassicAssist.Shared/Engine.cs)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion
  10. Appendices

Introduction

This document explains the packet processing pipeline in ClassicAssist.Avalonia, focusing on how raw network I/O is transformed into protocol objects and then applied to entities. It covers:

  • The PacketHandler architecture for incoming/outgoing routing
  • Compression handling and protocol version detection
  • Event-driven message bus pattern for packet distribution
  • Concrete examples of registration, invocation, and error propagation
  • Performance considerations for high-frequency packets and memory optimization
  • How to implement custom packet handlers and integrate with the existing pipeline

Project Structure

The networking stack resides primarily under ClassicAssist.Shared/UO/Network and related data/object layers. Key areas include:

  • Network core: PacketHandler, Incoming/Outgoing handlers and filters, queues
  • Data serialization: PacketReader/Writer, BasePacket
  • Protocol packets: concrete packet types (e.g., MobileUpdate, MobileMoving)
  • Game objects: Entity, Mobile, PlayerMobile updated by packets
  • Engine integration: initialization and lifecycle hooks
graph TB
subgraph "Networking Core"
PH["PacketHandler"]
INH["IncomingPacketHandlers"]
OUTH["OutgoingPacketHandlers"]
INF["IncomingPacketFilters"]
OUTF["OutgoingPacketFilters"]
APQ["ActionPacketQueue"]
end
subgraph "Serialization"
PR["PacketReader"]
PW["PacketWriter"]
BP["BasePacket"]
end
subgraph "Packets"
MU["MobileUpdate"]
MM["MobileMoving"]
end
subgraph "Game Objects"
ENT["Entity"]
MOB["Mobile"]
PMOB["PlayerMobile"]
end
subgraph "Engine"
ENG["Engine"]
end
ENG --> PH
PH --> INF
PH --> INH
PH --> APQ
PH --> OUTF
PH --> OUTH
INH --> PR
OUTH --> PW
INH --> MU
INH --> MM
MU --> MOB
MM --> MOB
MOB --> ENT
PMOB --> MOB

Diagram sources

Section sources

Core Components

  • PacketHandler: Central orchestrator for incoming and outgoing packets; manages filters, compression, dispatching, and queuing.
  • IncomingPacketHandlers: Registry and dispatcher for inbound packet types to their specific handlers.
  • OutgoingPacketHandlers: Registry and dispatcher for outbound packet types to their writers.
  • IncomingPacketFilters / OutgoingPacketFilters: Pluggable filter chain that can inspect, modify, or drop packets.
  • ActionPacketQueue: Ordered queue for deferring actions across frames or threads.
  • PacketReader / PacketWriter: Binary readers/writers used by packet implementations.
  • BasePacket: Common base for all packet types providing shared behavior and metadata.
  • Protocol Packets: Concrete classes like MobileUpdate and MobileMoving that parse wire format and update game state.
  • Game Objects: Entity, Mobile, PlayerMobile are mutated by packet handlers to reflect server state.
  • Engine: Initializes networking components and wires up lifecycle events.

Section sources

Architecture Overview

The pipeline follows a layered approach:

  • Raw bytes arrive from the network socket
  • Compression is handled before parsing
  • PacketReader deserializes into typed packet instances
  • IncomingPacketFilters run first, then IncomingPacketHandlers route to specific logic
  • Handlers update game objects (e.g., Mobile, PlayerMobile)
  • Outgoing packets are serialized via PacketWriter, pass through OutgoingPacketFilters, and are sent
sequenceDiagram
participant Net as "Network I/O"
participant Comp as "Compression"
participant PH as "PacketHandler"
participant IF as "IncomingPacketFilters"
participant IH as "IncomingPacketHandlers"
participant PR as "PacketReader"
participant Obj as "Game Objects"
participant OF as "OutgoingPacketFilters"
participant OH as "OutgoingPacketHandlers"
participant PW as "PacketWriter"
Net->>Comp : "Raw bytes"
Comp-->>PH : "Decompressed stream"
PH->>PR : "Read next packet"
PR-->>PH : "Typed packet instance"
PH->>IF : "Run incoming filters"
IF-->>PH : "Allow/Drop/Modify"
PH->>IH : "Dispatch to handler"
IH->>Obj : "Apply updates (e.g., Mobile)"
Note over IH,Obj : "Event-driven updates propagate"
PH->>OF : "Run outgoing filters"
OF-->>PH : "Allow/Drop/Modify"
PH->>PW : "Serialize outgoing packet"
PW-->>Net : "Compressed bytes"

Diagram sources

Detailed Component Analysis

PacketHandler Architecture

Responsibilities:

  • Lifecycle management and initialization
  • Version negotiation and protocol detection
  • Compression setup and teardown
  • Routing incoming packets through filters and handlers
  • Queuing actions for later execution
  • Serializing outgoing packets through filters and writers

Key behaviors:

  • Incoming path: read -> decompress -> parse -> filter -> dispatch -> apply
  • Outgoing path: create packet -> serialize -> filter -> compress -> send
  • Error propagation: exceptions during parsing/handling are captured and surfaced to the engine for logging and recovery
classDiagram
class PacketHandler {
+Initialize()
+ProcessIncoming(bytes)
+Send(packet)
-RunIncomingFilters(packet)
-DispatchIncoming(packet)
-RunOutgoingFilters(packet)
-SerializeOutgoing(packet)
}
class IncomingPacketHandlers {
+Register(type, handler)
+Invoke(packet)
}
class OutgoingPacketHandlers {
+Register(type, writer)
+Write(packet)
}
class IncomingPacketFilters {
+Add(filter)
+Execute(packet) bool
}
class OutgoingPacketFilters {
+Add(filter)
+Execute(packet) bool
}
class ActionPacketQueue {
+Enqueue(item)
+Drain()
}
class Compression {
+Decompress(input) byte[]
+Compress(data) byte[]
}
PacketHandler --> IncomingPacketHandlers : "dispatches"
PacketHandler --> OutgoingPacketHandlers : "serializes"
PacketHandler --> IncomingPacketFilters : "filters in"
PacketHandler --> OutgoingPacketFilters : "filters out"
PacketHandler --> ActionPacketQueue : "queues work"
PacketHandler --> Compression : "uses"

Diagram sources

Section sources

Incoming Packet Flow and Event Bus Pattern

Flow highlights:

  • PacketReader reads fields according to the packet’s wire format
  • IncomingPacketHandlers maps packet type to a handler method
  • Handlers mutate game objects (e.g., Mobile, PlayerMobile)
  • Updates may trigger event notifications consumed by UI or subsystems
sequenceDiagram
participant PH as "PacketHandler"
participant PR as "PacketReader"
participant IH as "IncomingPacketHandlers"
participant MU as "MobileUpdate"
participant MOB as "Mobile"
participant PMOB as "PlayerMobile"
PH->>PR : "Read packet header/type"
PR-->>PH : "Instance of MobileUpdate"
PH->>IH : "Invoke handler for MobileUpdate"
IH->>MU : "Parse fields"
MU->>MOB : "Update position/status"
MOB->>PMOB : "Notify player-specific changes"
Note over PH,IH : "Event-driven updates propagate to subscribers"

Diagram sources

Section sources

Outgoing Packet Flow

Flow highlights:

  • Create a typed packet object
  • OutgoingPacketHandlers serializes it using PacketWriter
  • OutgoingPacketFilters can inspect/modify/drop
  • Compression is applied before sending
sequenceDiagram
participant App as "Application Code"
participant OH as "OutgoingPacketHandlers"
participant PW as "PacketWriter"
participant OF as "OutgoingPacketFilters"
participant PH as "PacketHandler"
participant Net as "Network I/O"
App->>OH : "Create and enqueue packet"
OH->>PW : "Serialize packet"
PW-->>OH : "Byte buffer"
OH->>OF : "Run outgoing filters"
OF-->>OH : "Allow/Drop/Modify"
OH->>PH : "Return processed buffer"
PH->>Net : "Send compressed bytes"

Diagram sources

Section sources

Compression Handling and Protocol Version Detection

  • Compression: Decompression occurs before parsing; compression is applied after filtering and before transmission.
  • Protocol version detection: Handled during initialization and handshake; influences which packet formats and handlers are active.
flowchart TD
Start(["Start"]) --> Detect["Detect protocol version"]
Detect --> InitComp["Initialize compression context"]
InitComp --> ReadLoop["Read loop"]
ReadLoop --> InFilter{"Incoming filters allow?"}
InFilter --> |No| DropIn["Drop packet"]
InFilter --> |Yes| Parse["Parse packet"]
Parse --> Dispatch["Dispatch to handler"]
Dispatch --> Update["Update game objects"]
Update --> ReadLoop
DropIn --> ReadLoop
ReadLoop --> End(["Stop"])

Diagram sources

Section sources

Error Propagation and Recovery

  • Parsing errors: Invalid headers or truncated packets raise exceptions; these are caught by the handler layer and logged.
  • Handler errors: Exceptions thrown inside handlers are wrapped and propagated to the engine for centralized handling.
  • Filter errors: Filters must not throw; they should return a decision (allow/drop) and log issues internally.
flowchart TD
Entry(["Incoming packet"]) --> TryParse["Try parse"]
TryParse --> Ok{"Parsed OK?"}
Ok --> |No| LogErr["Log parse error"]
LogErr --> Next["Next packet"]
Ok --> RunFilters["Run incoming filters"]
RunFilters --> Allow{"Allowed?"}
Allow --> |No| Drop["Drop packet"]
Allow --> |Yes| InvokeHandler["Invoke handler"]
InvokeHandler --> HOk{"Handler OK?"}
HOk --> |No| WrapErr["Wrap and propagate error"]
HOk --> |Yes| Apply["Apply updates"]
Apply --> Next
Drop --> Next
Next --> Exit(["Exit"])

Diagram sources

Section sources

Concrete Examples

Registering an Incoming Packet Handler

  • Use the incoming registry to map a packet type to a handler method.
  • Ensure the handler accepts the correct packet type and updates game objects safely.

Section sources

Invoking a Handler and Updating Entities

  • A MobileUpdate packet parses fields and applies changes to Mobile/PlayerMobile.
  • Subscribers receive updates via events or property change notifications.

Section sources

Sending an Outgoing Packet

  • Construct a typed packet, enqueue it, and let OutgoingPacketHandlers serialize it.
  • Filters can intercept to log or modify content before compression and send.

Section sources

Implementing a Custom Packet Handler

Steps:

  1. Define a new packet class derived from BasePacket if needed.
  2. Register an incoming handler mapping your packet type to a method.
  3. In the handler, use PacketReader to parse fields and update relevant objects.
  4. If you need to defer work, enqueue items via ActionPacketQueue.

Section sources

Dependency Analysis

High-level dependencies between networking components and game objects:

graph LR
PH["PacketHandler"] --> INH["IncomingPacketHandlers"]
PH --> OUTH["OutgoingPacketHandlers"]
PH --> INF["IncomingPacketFilters"]
PH --> OUTF["OutgoingPacketFilters"]
PH --> APQ["ActionPacketQueue"]
INH --> PR["PacketReader"]
OUTH --> PW["PacketWriter"]
INH --> MU["MobileUpdate"]
INH --> MM["MobileMoving"]
MU --> MOB["Mobile"]
MM --> MOB
MOB --> ENT["Entity"]

Diagram sources

Section sources

Performance Considerations

  • Minimize allocations in hot paths:
    • Reuse buffers where possible in PacketReader/Writer.
    • Avoid per-packet object creation when simple primitives suffice.
  • Keep handlers fast:
    • Do heavy work off the main thread; enqueue via ActionPacketQueue.
    • Batch updates to reduce UI churn.
  • Filtering efficiency:
    • Place cheap checks early in filter chains.
    • Avoid expensive string operations in tight loops.
  • Compression overhead:
    • Tune compression settings based on bandwidth vs CPU trade-offs.
  • Threading model:
    • Ensure thread-safe access to shared game objects.
    • Use queues to decouple network I/O from game logic.

[No sources needed since this section provides general guidance]

Troubleshooting Guide

Common issues and remedies:

  • Parse failures: Check packet length and version compatibility; verify PacketReader usage matches wire format.
  • Missing handlers: Confirm registration of incoming handlers for expected packet types.
  • Dropped packets: Inspect incoming/outgoing filters to ensure they are not inadvertently dropping traffic.
  • High CPU usage: Profile handlers and filters; move heavy work to background queues.
  • Memory pressure: Monitor allocations in hot paths; consider pooling strategies.

Section sources

Conclusion

The ClassicAssist.Avalonia packet pipeline cleanly separates concerns across parsing, filtering, dispatch, and application updates. By leveraging typed packets, a central PacketHandler, and pluggable filters, the system remains extensible and maintainable. Following the performance and troubleshooting recommendations ensures robust operation under high-frequency network loads.

[No sources needed since this section summarizes without analyzing specific files]

Appendices

Quick Reference: Typical Registration and Usage Paths

  • Incoming registration: Map packet type to handler in IncomingPacketHandlers.
  • Outgoing usage: Create packet, enqueue, and rely on OutgoingPacketHandlers to serialize.
  • Custom filters: Add to IncomingPacketFilters or OutgoingPacketFilters for inspection/modification.
  • Deferring work: Enqueue tasks via ActionPacketQueue for later processing.

Section sources