1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
//! Transport layer traits
use crate::error::{OutOfMemoryError, ServiceSubscribeError};
use crate::time::{Clock, Instant};
use crate::transfer::Transfer;
use crate::{ServiceId, SubjectId};
use alloc::vec::Vec;
use core::convert::TryFrom;
use core::fmt::Debug;
use hash32::Hash;
/// Basic requirements for a transport that can be used to send and receive transfers
///
/// The [`Transmitter`](Transmitter) and [`Receiver`](Receiver) sub-traits add additional functions.
pub trait Transport {
/// A node ID type that can hold the node ID values that this transport allows
type NodeId: Debug + Clone + PartialEq + Eq + Hash + Into<usize> + TryFrom<u16>;
/// A transfer ID type that can hold all supported transfer ID values
type TransferId: TransferId;
/// A priority type that can hold all supported priority values
type Priority: Clone + Debug + From<crate::Priority>;
}
/// A transmitter that can send outgoing transfers
pub trait Transmitter<I>
where
I: Instant,
{
/// The transport that this transmitter works with
type Transport: Transport;
/// The driver type that this transmitter uses to send frames
type Driver;
/// An error type
///
/// This type must have an out-of-memory variant that can hold an `OutOfMemoryError`.
type Error: Debug + From<OutOfMemoryError>;
/// Starts the process of sending an outgoing transfer
///
/// The transport implementation may block until the entire transfer is sent, or put frames in
/// a queue to be sent separately.
fn push<A, C>(
&mut self,
transfer: Transfer<A, I, Self::Transport>,
clock: &mut C,
driver: &mut Self::Driver,
) -> nb::Result<(), Self::Error>
where
A: AsRef<[u8]>,
C: Clock<Instant = I>;
/// Attempts to send all queued outgoing frames
///
/// If ths transport's `push` implementation blocks until all frames have been sent,
/// this function may be empty.
///
/// The transport implementation may block until all frames have been sent, or return
/// `Err(nb::Error::WouldBlock)` if not all frames can be sent.
///
/// Return values:
/// * `Ok(())`: All frames were sent
/// * `Err(nb::Error::WouldBlock)`: At least one frame could not be sent yet
/// * `Err(nb::Error::Other(e))`: Some other error occurred
fn flush<C>(&mut self, clock: &mut C, driver: &mut Self::Driver) -> nb::Result<(), Self::Error>
where
C: Clock<Instant = I>;
/// Returns the maximum transmission unit of this transport, in bytes
///
/// A message larger than this will need to be split into multiple frames.
///
/// For example, UAVCAN/CAN over classic CAN can transfer up to 7 bytes per frame (the eighth
/// byte is used up by the tail byte), so it would return 7.
fn mtu(&self) -> usize;
}
/// A receiver that can assemble incoming frames into transfers
pub trait Receiver<I>
where
I: Instant,
{
/// The transport that this transmitter works with
type Transport: Transport;
/// The driver type that this transmitter uses to receive frames
type Driver;
/// An error type
///
/// This type must have an out-of-memory variant that can hold an `OutOfMemoryError`.
type Error: Debug + From<OutOfMemoryError>;
/// Checks for incoming frames and processes them, possibly returning a transfer
///
/// If the frame completes a transfer and the transfer matches an active subscription, the
/// transfer is returned.
///
/// This function must not block. If no frame can immediately be read, it should return `Ok(None)`.
///
/// If the transport reads a frame and processes it, but the frame does not complete a transfer,
/// this function must try again to read and process a frame. It must not return `Ok(None)`
/// if there are incoming frames that remain to be processed.
///
/// This function must not return any transfers for which the transport is not currently
/// subscribed. It also must not return any service transfers not addressed to this node.
///
/// The argument `now` should be the current time. This may be used to assign timestamps to
/// incoming frames and delete sessions that have timed out.
fn receive(
&mut self,
now: I,
driver: &mut Self::Driver,
) -> Result<Option<Transfer<Vec<u8>, I, Self::Transport>>, Self::Error>;
/// Subscribes to messages on a subject
///
/// This will enable incoming transfers from all nodes on the specified subject ID.
///
/// subject: The subject ID to subscribe to
///
/// payload_size_max: The maximum number of payload bytes expected on this subject
/// (longer transfers will be dropped)
///
/// timeout: The maximum time between the first and last frames in a transfer (transfers that
/// do not finish within this time will be dropped)
///
/// If all transfers fit into one frame, the timeout has no meaning and may be zero.
///
fn subscribe_message(
&mut self,
subject: SubjectId,
payload_size_max: usize,
timeout: I::Duration,
driver: &mut Self::Driver,
) -> Result<(), Self::Error>;
/// Unsubscribes from messages on a subject
fn unsubscribe_message(&mut self, subject: SubjectId, driver: &mut Self::Driver);
/// Subscribes to requests for a service
///
/// This will enable incoming service request transfers from all nodes on the specified service
/// ID.
///
/// service: The service ID to subscribe to
///
/// payload_size_max: The maximum number of payload bytes expected on this subject
/// (longer transfers will be dropped)
///
/// timeout: The maximum time between the first and last frames in a transfer (transfers that
/// do not finish within this time will be dropped)
///
/// If all transfers fit into one frame, the timeout has no meaning and may be zero.
///
/// This function returns an error if this node is anonymous or some other transport error
/// occurs.
///
fn subscribe_request(
&mut self,
service: ServiceId,
payload_size_max: usize,
timeout: I::Duration,
driver: &mut Self::Driver,
) -> Result<(), ServiceSubscribeError<Self::Error>>;
/// Unsubscribes from requests for a service
fn unsubscribe_request(&mut self, service: ServiceId, driver: &mut Self::Driver);
/// Subscribes to responses for a service
///
/// This will enable incoming service response transfers from all nodes on the specified service
/// ID.
///
/// service: The service ID to subscribe to
///
/// payload_size_max: The maximum number of payload bytes expected on this subject
/// (longer transfers will be dropped)
///
/// timeout: The maximum time between the first and last frames in a transfer (transfers that
/// do not finish within this time will be dropped)
///
/// If all transfers fit into one frame, the timeout has no meaning and may be zero.
///
/// This function returns an error if this node is anonymous or some other transport error
/// occurs.
///
fn subscribe_response(
&mut self,
service: ServiceId,
payload_size_max: usize,
timeout: I::Duration,
driver: &mut Self::Driver,
) -> Result<(), ServiceSubscribeError<Self::Error>>;
/// Unsubscribes from responses for a service
fn unsubscribe_response(&mut self, service: ServiceId, driver: &mut Self::Driver);
}
/// Required operations for a transfer ID
pub trait TransferId: Default + Debug + Clone {
/// Increments the value of this transfer ID by 1
///
/// If this transfer ID is the maximum allowed value, this function must wrap around to the
/// minimum allowed value.
fn increment(self) -> Self;
}