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
connectionCompanionConnectionThe underlying framed connection.
srpSrpAuthHandlerThe 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
SRP_OUTPUT_INFO
SRP HKDF info string for the client's outbound encryption key.
public const string SRP_OUTPUT_INFO = "ClientEncrypt-main"
Field Value
SRP_SALT
SRP HKDF salt used when deriving Companion encryption keys.
public const string SRP_SALT = ""
Field Value
Properties
AsyncSender
Gets or sets the asynchronous callback that transmits fully-built frames.
public Func<byte[], Task>? AsyncSender { get; set; }
Property Value
Listener
Gets or sets the listener notified when an event frame is received.
public ICompanionProtocolListener? Listener { get; set; }
Property Value
ResponseTimeout
Gets or sets how long to wait for a response before ExchangeAuth(FrameType, Dictionary<string, object?>) or ExchangeOpack(FrameType, Dictionary<string, object?>) throws a ProtocolException.
public TimeSpan ResponseTimeout { get; set; }
Property Value
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
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
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
frameTypeFrameTypeThe frame type to send.
dataDictionary<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
frameTypeFrameTypedataDictionary<string, object>cancellationTokenCancellationToken
Returns
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
frameTypeFrameTypeThe frame type to send.
dataDictionary<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
frameTypeFrameTypedataDictionary<string, object>cancellationTokenCancellationToken
Returns
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
frameTypeFrameTypeThe frame type to send.
dataDictionary<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
frameTypeFrameTypeThe frame type to send.
dataDictionary<string, object>The message content.
cancellationTokenCancellationTokenA 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