IIsoTpChannel Interface¶
A single ISO 15765-2 (ISO-TP) channel bound to one IsoTpEndpoint (TX/RX CAN-ID pair, plus addressing mode). Threading model per SRS FR-TP-016 / FR-RAW-020..023: all protocol state is owned by a single IProtocolActor mailbox, so callers may invoke SendAsync(ReadOnlyMemory<byte>, CancellationToken) concurrently from arbitrary threads and receive frames from arbitrary threads; internal state is never mutated from more than one place at a time.
Implements IDisposable
Remarks¶
One channel = one PDU at a time on the wire: an outgoing multi-frame PDU (First-Frame + Consecutive-Frames) is completed (or aborted with an IsoTpException) before the next SendAsync(ReadOnlyMemory<byte>, CancellationToken) call is transmitted. This mirrors ISO 15765-2 §6.4's "one N-USData at a time" model; overlapping sends from different callers are serialized by the channel.
Received PDUs are delivered both as an event (DatagramReceived) and as an System.Collections.Generic.IAsyncEnumerable<> from ReceiveAllAsync(CancellationToken); a single ReceiveAsync(CancellationToken) call awaits the next one. Both surfaces share the same bounded buffer.
IDisposable.Dispose is thread-safe and idempotent (FR-RAW-021).
Properties¶
IIsoTpChannel.Endpoint Property¶
The endpoint this channel is bound to (TX/RX CAN-ID pair + addressing mode).
Property Value¶
IIsoTpChannel.Options Property¶
The channel options used at construction (immutable).
Property Value¶
Methods¶
IIsoTpChannel.DiscardPendingPdus() Method¶
Drains every buffered inbox item — both completed PDUs and pending reassembly-abort
faults enqueued by AbortRx — and returns how many were dropped. Also silently
aborts any in-flight multi-frame reassembly on the actor so leftover consecutive frames
cannot finish and enqueue a stale PDU after a higher-layer timeout/cancel
Higher layers (e.g. UDS) call this after a cancelled/timed-out wait
so a late peer PDU or a leftover abort fault cannot be consumed as the answer to a later
request. A receive on another thread meanwhile reads the inbox before the discard or after
it, never in between, so it neither takes an item the discard drops nor misses one it keeps.
Returns¶
IIsoTpChannel.DiscardPendingPdus(long) Method¶
As DiscardPendingPdus(), dropping what arrived before arrivedBefore (a GetTimestamp reading) rather than before now, and keeping what arrived since. For a caller that inspects the inbox before discarding — routing an NRC 0x78 to its window — the stamp taken before the inspection makes the two one step: everything the discard drops was inspected, and a frame arriving between the inspection and the discard is kept for the caller's next read instead of vanishing.
Parameters¶
arrivedBefore Int64
Returns¶
IIsoTpChannel.GetReceptionsInProgress() Method¶
The multi-frame receptions in progress — First Frames read off the bus whose PDUs have not been delivered — oldest first, each as its First Frame: arrival, announced length and leading data bytes. For a caller whose own deadline ends with the first frame of a response and not with its last (ISO 14229-2 P2, #28): a response that began in time is then waited for beyond that deadline, bounded by the transport's N_Cr instead — after checking from the leading bytes that it is the response being waited for. More than one is possible when the channel's actor is behind the bus; a record is withdrawn only once its outcome — the PDU, or the error of an aborted reassembly — is in the inbox, or the frame was refused. A snapshot: a reception can begin, complete or be refused the moment after, so a caller waiting on one re-checks rather than waiting unboundedly.
System.Collections.Generic.IReadOnlyList<CanKit.Pro.IsoTp.IsoTpReceptionInProgress> GetReceptionsInProgress();
Returns¶
IReadOnlyList<IsoTpReceptionInProgress>
IIsoTpChannel.ReceiveAllAsync(CancellationToken) Method¶
Enumerates every fully reassembled inbound PDU as it becomes available. The enumeration
ends when the channel is disposed. A reassembly abort (N_Cr / CF sequence mismatch /
SF·FF supersede) faults the enumerator with the same exception
ReceiveAsync(CancellationToken) would throw.
Cancel by passing a token via WithCancellation or by disposing the channel.
System.Collections.Generic.IAsyncEnumerable<byte[]> ReceiveAllAsync(System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
cancellationToken CancellationToken
Returns¶
IIsoTpChannel.ReceiveAsync(CancellationToken) Method¶
Awaits the next fully reassembled inbound PDU. Cancels via cancellationToken. Faults with IsoTpTimeoutException (NCr) or IsoTpException when an in-progress multi-frame reassembly is aborted (N_Cr, CF sequence mismatch, or a superseding SF/FF — including when the new FF is refused with FC(OVFLW); FR-TP-010), so a caller waiting for that PDU does not hang indefinitely. A PDU queued before either end below is still delivered; only an empty inbox meets the end. Faults with InvalidOperationException once the channel is disposed, and with ObjectDisposedException -- or the failure itself -- once the bus service under the channel was disposed or its subscription failed: nothing will arrive again, and every waiting and later receive gets that same exception. The failure is also raised once through BackgroundExceptionOccurred.
System.Threading.Tasks.Task<byte[]> ReceiveAsync(System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
cancellationToken CancellationToken
Returns¶
IIsoTpChannel.ReceiveWithArrivalAsync(CancellationToken) Method¶
As ReceiveAsync(CancellationToken), with the same ends and faults, but also reports the monotonic instant the PDU was queued.
System.Threading.Tasks.Task<CanKit.Pro.IsoTp.IsoTpReceivedPdu> ReceiveWithArrivalAsync(System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
cancellationToken CancellationToken
Returns¶
Remarks¶
For callers that enforce a response deadline. ReceiveAsync(CancellationToken) can only tell them when they observed the PDU, and a caller descheduled past its own deadline cannot tell a punctual response from a late one on that basis — it would either accept a response it had already given up on, or reject a timely one for arriving while it was not looking. The arrival timestamp removes the ambiguity, so the deadline holds regardless of scheduling.
IIsoTpChannel.SendAsync(ReadOnlyMemory<byte>, CancellationToken) Method¶
Sends pdu as one ISO-TP N-USData PDU. The returned task completes when the last frame of the PDU is TX-confirmed by the driver (SF) or when the peer has FC-cleared the entire multi-frame PDU and the last CF is confirmed (FF+CFs). It faults with an IsoTpException on protocol timeouts (FR-TP-010), an Overflow FC (FR-TP-012), exceeding WFTmax (FR-TP-011), or a driver rejection; with ObjectDisposedException when the channel is disposed before or during the send, including while the call is queued behind another send; with OperationCanceledException when cancellationToken is cancelled; and with whatever the bus layer threw from the driver call, unwrapped. An empty or over-long pdu is refused before anything is queued, with ArgumentException / ArgumentOutOfRangeException.
System.Threading.Tasks.Task SendAsync(System.ReadOnlyMemory<byte> pdu, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
User data, 1..4095 bytes for classic CAN, or up to MaxFdFirstFrameLength for CAN-FD. Must not be empty.
cancellationToken CancellationToken
Cancels the returned task (standard .NET convention); a canceled send aborts the in-flight PDU. The channel keeps the one-PDU-at-a-time send gate until any already-submitted bus TX from that PDU completes, so the next call cannot interleave frames on the wire with the aborted transfer.
Returns¶
IIsoTpChannel.SendWithTransmitStampAsync(ReadOnlyMemory<byte>, CancellationToken) Method¶
As SendAsync(ReadOnlyMemory<byte>, CancellationToken), but returns the two monotonic (GetTimestamp) instants bracketing the driver call for the PDU's last frame: just before it was handed over, and no later than the driver accepted it (see IsoTpTransmitStamps). Zero for an instant not reported.
System.Threading.Tasks.Task<CanKit.Pro.IsoTp.IsoTpTransmitStamps> SendWithTransmitStampAsync(System.ReadOnlyMemory<byte> pdu, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
cancellationToken CancellationToken
Returns¶
Remarks¶
The send-side counterpart of ReceiveWithArrivalAsync(CancellationToken), and needed for the same reason. A caller whose response deadline starts when its request went out cannot read that instant off its own clock: awaiting this method returns behind the bus TX confirmation, an actor hop and the caller's own scheduling, all of which happen after the peer already has the request. Timing the deadline from the returned stamp makes its start as independent of scheduling as the arrival stamp makes its end -- pinning only one of the two leaves the deadline movable from the other side.
IIsoTpChannel.SettleAsync(CancellationToken) Method¶
Completes once every frame the bus had delivered before the call has been taken through
the channel: a PDU it completed is in the inbox, a reception it began is in
GetReceptionsInProgress(). For a decision taken at a deadline — is a
response there, was there a 0x78 — what the inbox does not hold after this did not
arrive before the call; without it, a frame stamped in time can still be on its way
through the channel's actor when the deadline fires. Called on the
channel's own actor — from a BackgroundExceptionOccurred handler — it returns at
once and the frames on their way are handled after the current work item: they queue
behind frames already in the mailbox, and handling them inline would reorder the two.
cancellationToken ends the wait, not the settling: what the demux had buffered has been handed to the actor by then and is handled as usual. A token cancelled before the call, or while the wait is still queued behind the actor's other work, cancels the returned task; once the actor has reached the wait it completes normally.
System.Threading.Tasks.Task SettleAsync(System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
cancellationToken CancellationToken
Ends the wait for the actor to catch up.
Returns¶
IIsoTpChannel.TryReceiveWithArrival(IsoTpReceivedPdu) Method¶
Takes the next inbound PDU if one is already queued, without waiting for one to arrive. Returns false — leaving pdu at its default — when the inbox is empty; a PDU queued before the channel was disposed, or before its bus service was lost, is still returned afterwards. Throws the recorded reassembly-abort exception when the queued item is a fault, exactly as ReceiveWithArrivalAsync(CancellationToken) would; neither end of the inbox is reported here. A DiscardPendingPdus(long) running concurrently is waited for: the read is made either before the discard or after it, never while it has the inbox, so a PDU the discard retains is not reported absent, and one it drops is not returned (#383). Every receive of this channel reads the inbox the same way.
Parameters¶
pdu IsoTpReceivedPdu
Returns¶
Remarks¶
The companion to ReceiveWithArrivalAsync(CancellationToken) for a caller whose deadline has already passed. Awaiting with an expired token is not the same thing: an already-cancelled token wins against a queued item, so the wait would report a timeout while the answer sat unread in the inbox. Separating <em>how long to wait</em> from <em>was it in time</em> leaves the second question to the arrival stamp, which is the only reading of it that does not depend on when the caller was scheduled.
Events¶
IIsoTpChannel.BackgroundExceptionOccurred Event¶
Raised when a background failure (reassembly abort, event-handler exception, subscription failure, actor loop exception) needs to be surfaced to the application. This is the documented channel for out-of-band errors (FR-RAW-023). Failures tied to a specific SendAsync(ReadOnlyMemory<byte>, CancellationToken) call are reported via that call's returned task; reassembly aborts are reported both here and by faulting a pending ReceiveAsync(CancellationToken) (FailTx analogue on the receive side).
Raised on a thread-pool thread, never on the channel's actor loop, and only once what the report announces is in place: a reassembly abort has already faulted the inbox, so a handler that answers it with ReceiveAsync(CancellationToken), DiscardPendingPdus() or a send -- or disposes the channel -- does not deadlock the actor (#356). Reports are delivered one at a time, in the order they were made; a handler that blocks holds up the reports behind it, not the channel. Each handler is called on its own, so one that throws does not keep the report from the handlers after it; its exception is dropped. A report may reach its handlers after IDisposable.Dispose has returned.
Event Type¶
IIsoTpChannel.DatagramReceived Event¶
Raised (on a thread-pool thread) every time a full PDU is reassembled. The same PDU is enqueued for ReceiveAsync(CancellationToken)/ReceiveAllAsync(CancellationToken) before the event fires, so a handler that synchronously waits on those APIs — or on DiscardPendingPdus() — cannot deadlock the protocol actor. Handlers must be non-throwing; a throwing handler is caught and surfaced via BackgroundExceptionOccurred.
Each PDU gets its own thread-pool work item, so handlers for successive PDUs may run
concurrently and not necessarily in the order the PDUs completed;
ReceiveAsync(CancellationToken)/ReceiveAllAsync(CancellationToken) keep that order. No new
PDU is raised for a frame handled after IDisposable.Dispose has begun, but a
handler already queued, or starting at that moment, may still run: Dispose does not
wait for handlers, and a handler may itself call it.