Table of Contents

Class CompanionProtocol

Namespace
AppleTvControlLibrary.Protocol
Assembly
AppleTvControlLibrary.dll

Protocol logic related to Companion: frame dispatch, XID/frame-type based response correlation, and OPACK-level send/receive plumbing built on top of CompanionConnection.

public sealed class CompanionProtocol : IDisposable, IAsyncDisposable
Inheritance
CompanionProtocol
Implements
Inherited Members

Remarks

Unlike pyatv, which relies on asyncio futures (SharedData) to await a response, this port uses synchronous callback-based correlation: sending a frame is expected to synchronously (or, for a real transport, eventually) result in CompanionConnection.FrameReceived being invoked with the matching response, at which point the originally registered continuation is invoked. This keeps the type usable both by an in-memory test harness (as used for WP5/WP6 validation) and by a future asynchronous socket transport without changing the correlation logic itself.

Constructors

CompanionProtocol(CompanionConnection, SrpAuthHandler)

Initializes a new instance of the CompanionProtocol class.

public CompanionProtocol(CompanionConnection connection, SrpAuthHandler srp)

Parameters

connection CompanionConnection

The underlying framed connection.

srp SrpAuthHandler

The SRP handler used for pair-verify.

Fields

SRP_INPUT_INFO

SRP HKDF info string for the client's inbound encryption key.

public const string SRP_INPUT_INFO = "ServerEncrypt-main"

Field Value

string

SRP_OUTPUT_INFO

SRP HKDF info string for the client's outbound encryption key.

public const string SRP_OUTPUT_INFO = "ClientEncrypt-main"

Field Value

string

SRP_SALT

SRP HKDF salt used when deriving Companion encryption keys.

public const string SRP_SALT = ""

Field Value

string

Properties

AsyncSender

Gets or sets the asynchronous callback that transmits fully-built frames.

public Func<byte[], Task>? AsyncSender { get; set; }

Property Value

Func<byte[], Task>

Listener

Gets or sets the listener notified when an event frame is received.

public ICompanionProtocolListener? Listener { get; set; }

Property Value

ICompanionProtocolListener

ResponseTimeout

public TimeSpan ResponseTimeout { get; set; }

Property Value

TimeSpan

Remarks

Unlike the in-memory fake device used for WP5/WP6 validation (where CompanionConnection.FrameReceived fires synchronously, inline with the send call), a real socket transport delivers the response from a separate read thread/task, asynchronously with respect to the caller of ExchangeAuth(FrameType, Dictionary<string, object?>)/ ExchangeOpack(FrameType, Dictionary<string, object?>). This wait handle lets both usages share the same correlation logic without changing it: the fake device signals it before the wait ever blocks, while a real transport signals it once the background read loop processes the matching frame.

Sender

Gets a callback invoked whenever a fully-built frame needs to be transmitted.

[Obsolete("Use AsyncSender instead.")]
public Action<byte[]>? Sender { get; set; }

Property Value

Action<byte[]>

Remarks

This decouples CompanionProtocol from any specific transport; a caller (production socket code, or a test harness driving a fake device in-memory) is responsible for actually delivering the bytes and, eventually, feeding any response back in via CompanionConnection.ReceiveData.

Methods

Dispose()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

public void Dispose()

DisposeAsync()

Asynchronously faults pending exchanges and disposes this protocol instance.

public ValueTask DisposeAsync()

Returns

ValueTask

ExchangeAuth(FrameType, Dictionary<string, object?>)

Exchange an auth frame (PS_ or PV_).

[Obsolete("Use ExchangeAuthAsync instead.")]
public Dictionary<object, object?> ExchangeAuth(FrameType frameType, Dictionary<string, object?> data)

Parameters

frameType FrameType

The frame type to send.

data Dictionary<string, object>

The message content.

Returns

Dictionary<object, object>

The decoded OPACK response.

ExchangeAuthAsync(FrameType, Dictionary<string, object?>, CancellationToken)

Asynchronously exchanges an auth frame (PS_ or PV_).

public Task<Dictionary<object, object?>> ExchangeAuthAsync(FrameType frameType, Dictionary<string, object?> data, CancellationToken cancellationToken = default)

Parameters

frameType FrameType
data Dictionary<string, object>
cancellationToken CancellationToken

Returns

Task<Dictionary<object, object>>

ExchangeOpack(FrameType, Dictionary<string, object?>)

Send data as OPACK and decode the result as OPACK.

[Obsolete("Use ExchangeOpackAsync instead.")]
public Dictionary<object, object?> ExchangeOpack(FrameType frameType, Dictionary<string, object?> data)

Parameters

frameType FrameType

The frame type to send.

data Dictionary<string, object>

The message content.

Returns

Dictionary<object, object>

The decoded OPACK response.

ExchangeOpackAsync(FrameType, Dictionary<string, object?>, CancellationToken)

Asynchronously sends OPACK data and decodes the OPACK response.

public Task<Dictionary<object, object?>> ExchangeOpackAsync(FrameType frameType, Dictionary<string, object?> data, CancellationToken cancellationToken = default)

Parameters

frameType FrameType
data Dictionary<string, object>
cancellationToken CancellationToken

Returns

Task<Dictionary<object, object>>

SendOpack(FrameType, Dictionary<string, object?>)

Send data encoded with OPACK, adding an XID if not already present.

[Obsolete("Use SendOpackAsync instead.")]
public void SendOpack(FrameType frameType, Dictionary<string, object?> data)

Parameters

frameType FrameType

The frame type to send.

data Dictionary<string, object>

The message content.

SendOpackAsync(FrameType, Dictionary<string, object?>, CancellationToken)

Asynchronously sends data encoded with OPACK, adding an XID if not already present.

public Task SendOpackAsync(FrameType frameType, Dictionary<string, object?> data, CancellationToken cancellationToken = default)

Parameters

frameType FrameType

The frame type to send.

data Dictionary<string, object>

The message content.

cancellationToken CancellationToken

A token that cancels waiting to send or receive a response.

Returns

Task

A task that completes after the transport accepts the frame.

Events

ConnectionFaulted

Raised when the underlying CompanionConnection enters its terminal faulted state, whether due to an unexpected transport/decrypt/dispatch failure, a clean remote close, or disposal. See Exception to distinguish an unexpected loss from an expected close.

public event EventHandler<ConnectionClosedEventArgs>? ConnectionFaulted

Event Type

EventHandler<ConnectionClosedEventArgs>