Asv.Common 3.7.4 Help

Protocols

The protocol layer constructs connections, decoders, and outbound encoders from an explicit configuration. Protocol.Create(...) produces an IProtocolFactory; that factory can create routers, standalone parsers, and virtual connections.

Core Contracts

Protocol.Create(configure)

IProtocolBuilder

Protocols: parser and encoder factories

PortTypes: transport factories

Features: message processing

Formatters: text representation

IProtocolFactory

CreateRouter(id)

CreateParser(protocolId)

CreateVirtualConnection()

Contract

Responsibility

IProtocolBuilder

Registers protocol parsers, optional encoders, port types, features, formatters, logging, metrics, and time services.

IProtocolFactory

Exposes available registrations and creates configured protocol objects.

IProtocolContext

Supplies shared configuration to connection and parser implementations.

IProtocolParser

Consumes bytes through Push, publishes decoded messages and parsing errors, and supports Reset.

IProtocolEncoder

Encodes messages for one outbound stream, reporting a capacity bound and the actual number of bytes written.

IProtocolEncoderBuilder

Adds optional encoder registration to a protocol parser builder.

IProtocolEncoderContext

Exposes optional encoder factories keyed by protocol ID.

ProtocolInfo

Carries a protocol ID and display name.

The current builder registers the standard transport types and simple formatter by default. It does not select an application protocol automatically. ClearAll() clears the registrations and resets logging, metrics, and time configuration; register everything needed after calling it.

Configuration

using Asv.IO; var factory = Protocol.Create(builder => { builder.Protocols.RegisterExampleProtocol(); builder.Formatters.RegisterJsonFormatter(); builder.Features.RegisterEndpointIdTagFeature(); }); await using var router = factory.CreateRouter("application"); foreach (var protocol in router.AvailableProtocols) { Console.WriteLine($"{protocol.Id}: {protocol.Name}"); }

Production protocol packages provide their own registration extensions. The application selects those packages; the shared transport and inspection code can continue to use IProtocolMessage.

Outbound Encoders

Existing protocols need no new registration. DefaultProtocolEncoder delegates to the message's GetByteSize() and Serialize(ref Span<byte>), then reports the consumed span length. It serializes the message once and preserves the message's existing format, including serializers that consume fewer bytes than their reserved capacity.

A protocol that needs outbound stream state can register an encoder alongside its parser. For example, given the package's ProtocolInfo and encoder implementation:

builder.Protocols.RegisterEncoder(info, context => new MyProtocolEncoder());

The factory must return a fresh stateful encoder on each call. Each endpoint creates a registered encoder on its first send for that protocol and retains it for subsequent sends. Protocols without a custom registration use the shared stateless DefaultProtocolEncoder.Instance. Receive parsers have separate state. Registering an encoder does not register a parser or add a protocol to AvailableProtocols; the usual parser registration remains necessary. builder.Protocols.Clear() clears both parser and encoder registrations. ClearAll() also performs this reset.

IProtocolMessage, IProtocolBuilder, and IProtocolContext keep their existing members. Encoder registration is an optional capability: RegisterEncoder requires a builder implementing IProtocolEncoderBuilder and throws NotSupportedException otherwise. A context without IProtocolEncoderContext, or without a factory for the requested protocol ID, uses DefaultProtocolEncoder. Existing custom builders and contexts therefore continue to support their existing protocols without implementing the new interfaces.

For a manually owned stream, context.CreateEncoder(protocolId) creates the appropriate encoder. Retain that instance for the stream lifetime; calling it for every message would lose stream state. See Serialization for the encoder contract and explicit encoding helpers.

Parsing

A parser receives individual bytes. OnMessage publishes a decoded message. The ProtocolParser<TMessage, TMessageId> base class reports parsing failures through the OnError observable's R3 error-resume channel, so subscribe with an onErrorResume callback to observe them. Push returns a boolean recognition result rather than the decoded object. A true result does not guarantee that OnMessage was raised: for example, ExampleParser can recognize a complete frame whose message ID or payload is rejected by the base parser.

SubscriberParserEndpointTransportSubscriberParserEndpointTransportloop[For each byte]Received bytesPush(byte)OnMessage(message)OnRxMessage(message), after processing

An endpoint can run several registered parsers over incoming data. In the current endpoint read loop, a true parser result resets the parser set and stops dispatching that byte to the remaining parsers. Do not assume that every parser sees one independently framed stream or that every input byte produces a message.

Ownership And Diagnostics

Dispose standalone parsers, routers, and virtual connections when their owner finishes. A router owns its ports; ports own their endpoints. Keep subscriber lifetimes explicit as well.

VirtualConnection.Dispose() and DisposeAsync() disconnect the byte-forwarding and logging subscriptions before disposing either port. This prevents stream completion from being forwarded to an already disposed subject. Each port still completes its own public message observables. Dispose the virtual connection as the owner of both sides.

Use the configured TimeProvider, logger factory, and meter factory when implementing protocol components. This keeps timing and diagnostics consistent and permits deterministic tests.

Source Files

  • src/Asv.IO/Protocol/Protocol.cs and IProtocolBuilder.cs.

  • src/Asv.IO/Protocol/Parser/IProtocolParser.cs and ProtocolParser.cs.

  • src/Asv.IO/Protocol/Encoder/IProtocolEncoder.cs, ProtocolEncoderHelper.cs, and DefaultProtocolEncoder.cs.

  • src/Asv.IO/Example/Protocol/ExampleProtocol.cs.

See Connections for transport composition and Features and formatters for message processing.

26 October 2026