Skip to content

C# - Message Types ​

Nnrp.Core exposes the transport-neutral NNRP wire model. Application code normally uses the role APIs in Nnrp.Client and Nnrp.Server; these message types are for transport providers, diagnostics, conformance targets, and protocol tooling.

csharp
using Nnrp.Core;

Common Message Shape ​

Every concrete message is a readonly struct composed from an NnrpHeader, zero or one fixed-width metadata value, and any body regions defined by that message. For example, TransportProbeAckMessage exposes this exact shape:

csharp
public NnrpHeader Header { get; }
public TransportProbeAckMetadata Metadata { get; }

public NnrpFramedMessage ToFramedMessage();
public byte[] ToArray();

public static bool TryParse(
    ReadOnlyMemory<byte> source,
    out TransportProbeAckMessage message,
    out NnrpParseError error);

Messages such as PingMessage, PongMessage, and ResultDropMessage are header-only; CloseMessage has a body and no metadata. Metadata types expose ToArray() and TryParse(ReadOnlySpan<byte>, ...). Strict overloads reject reserved values and non-zero reserved fields. Message parsing validates the header type, fixed metadata length, body-region lengths, and trailing data before returning a value.

This ToArray() / TryParse(...) contract is frozen for the complete Preview 4 baseline set: ClientHelloMetadata, SessionPatchAckMetadata, FlowUpdateMetadata, ResultHintMetadata, FrameSubmitMetadata, ResultPushMetadata, CachePutMetadata, CacheAckMetadata, CacheInvalidateMetadata, TransportProbeMetadata, TransportProbeAckMetadata, and ObjectReferenceBlock. The public Conformance target calls these codecs instead of carrying an independent parser.

Connection Handshake ​

ClientHelloMessage ​

PropertyTypeMeaning
HeaderNnrpHeaderClientHello frame header
MetadataClientHelloMetadataVersion, profile, payload, codec, cache, lane, and budget capabilities
AuthBlockReadOnlyMemory<byte>Application authentication bytes
ExtensionsReadOnlyMemory<ControlExtensionBlock>Aligned control-extension blocks

Typed accessors decode the client transport policy, loss tolerance, and payload capabilities:

csharp
bool TryGetClientTransportPolicyExtension(
    out ClientTransportPolicyExtension extension,
    out NnrpParseError error);
bool TryGetClientLossToleranceExtension(
    out ClientLossToleranceExtension extension,
    out NnrpParseError error);
bool TryGetClientPayloadCapabilitiesExtension(
    out ClientPayloadCapabilitiesExtension extension,
    out NnrpParseError error);

ServerHelloAckMessage ​

PropertyTypeMeaning
HeaderNnrpHeaderServerHelloAck frame header
MetadataServerHelloAckMetadataSelected capabilities, limits, retry policy, and server flags
ExtensionsReadOnlyMemory<ControlExtensionBlock>Accepted control-extension blocks

Typed accessors decode the accepted transport policy, loss tolerance, and payload capabilities:

csharp
bool TryGetServerTransportPolicyAckExtension(
    out ServerTransportPolicyAckExtension extension,
    out NnrpParseError error);
bool TryGetServerLossToleranceAckExtension(
    out ServerLossToleranceAckExtension extension,
    out NnrpParseError error);
bool TryGetServerPayloadCapabilitiesAckExtension(
    out ServerPayloadCapabilitiesAckExtension extension,
    out NnrpParseError error);

PingMessage, PongMessage, CloseMessage, and ErrorMessage complete the connection-control surface. ErrorMessage carries ErrorMetadata plus optional diagnostic bytes.

Session Lifecycle ​

MessageMetadata/body
SessionOpenMessageSessionOpenMetadata plus auth, resume-token, and extension bytes
SessionOpenAckMessageSessionOpenAckMetadata plus resume-token and extension bytes
SessionPatchMessageSessionPatchMetadata plus optional TensorProfilePatchBlock
SessionPatchAckMessageSessionPatchAckMetadata plus optional TensorProfilePatchAckBlock
SessionCloseMessageSessionCloseMetadata
SessionCloseAckMessageSessionCloseAckMetadata
SessionMigrateMessageSessionMigrateMetadata
SessionMigrateAckMessageSessionMigrateAckMetadata

Role APIs own lifecycle ordering. Low-level callers must enforce the same state transitions through NnrpSessionStateMachine.

For the Preview4 application-facing lifecycle model, use NnrpConnectionLifecycle and NnrpSessionLifecycle. The model preserves whether a session was opened or resumed when a close request is rejected.

Submission And Results ​

FrameSubmitMessage ​

FrameSubmitMessage contains:

  • FrameSubmitMetadata
  • one TensorSubmitBlock
  • an optional camera block
  • tile IDs
  • tensor section blocks

FrameSubmitMetadata carries dimensions, frame/input profile, latency budget, cadence, submit and budget policy, object-reference mask, dependency frame, payload-kind bitmap, and payload-frame count. The wire operation_id is managed by the Preview4 runtime-control tail and role APIs; it is not aliased to FrameId.

ResultPushMessage ​

ResultPushMessage contains:

  • ResultPushMetadata
  • one TensorResultBlock
  • tile IDs and tensor sections
  • typed payload descriptors
  • typed payload frame bytes and validated frame views
  • typed profile-coverage records

Parsing validates typed-payload ranges and profile coverage before exposing views. Use the role API snapshot types when data must outlive the decoded frame.

Other data messages ​

MessageMeaning
FrameCancelMessageCancels the frame identified by its header
ResultDropMessageTerminates a result without a payload
ResultHintMessageCarries applied budget policy, congestion state, reason, and retry delay
SubmitOutcomeDiscriminated result containing either ResultPushMessage or ResultDropMessage

Cache Messages ​

Preview4 uses the full cache identity: namespace, high and low key words, and object kind.

MessagePublic payload
CachePutMessageCachePutMetadata plus ObjectBytes
CacheAckMessageCacheAckMetadata
CacheInvalidateMessageCacheInvalidateMetadata

Role-facing cache operations use NnrpCacheObjectId. They do not expose a second narrow key type.

Flow And Transport Probe Messages ​

FlowUpdateMessage wraps FlowUpdateMetadata, including scope, reason, backpressure level, connection/session/operation credits, the 64-bit operation ID, retry delay, credit epoch, and flags.

TransportProbeMessage carries TransportProbeMetadata plus the probe payload. TransportProbeAckMessage carries TransportProbeAckMetadata. Provider selection consumes the probe result through the typed provider API; applications do not parse probe packets themselves.

ControlExtensionBlock ​

ControlExtensionBlock is the public aligned TLV value used by handshake messages.

csharp
public readonly struct ControlExtensionBlock
{
    public ushort ExtensionType { get; }
    public ReadOnlyMemory<byte> Value { get; }
    public uint Length { get; }
    public int TotalLength { get; }
    public int PaddingLength { get; }
    public bool IsCritical { get; }
    public ushort TypeCode { get; }
    public ControlExtensionType TypedType { get; }

    public void WriteTo(Span<byte> destination);
    public byte[] ToArray();
    public static bool TryParse(
        ReadOnlySpan<byte> source,
        out ControlExtensionBlock block,
        out int bytesConsumed,
        out NnrpParseError error);
}

Unknown critical extensions fail negotiation. Unknown non-critical extensions may be ignored while their aligned wire length is still consumed.

Lifetime Rules ​

WARNING

ReadOnlyMemory<byte> and typed frame views may reference the input packet or a native-owned buffer. Do not retain them beyond the documented owner lifetime. Role APIs return copied snapshots where lifetime must be independent.

NNRP Documentation