canadensis_udp/
lib.rs

1//!
2//! # Cyphal/UDP transport
3//!
4//! The current version of the transport is documented in [a forum post from 2022-12-02](https://forum.opencyphal.org/t/cyphal-udp-architectural-issues-caused-by-the-dependency-between-the-nodes-ip-address-and-its-identity/1765/60).
5//!
6//! If the `std` feature is enabled, this implementation requires the `std` library for sockets.
7//!
8//! ## How sockets work
9//!
10//! ### Sending
11//!
12//! A transport can use one socket to send all outgoing message and service transfers.
13//! This socket binds to and an ephemeral UDP port on one network interface.
14//!
15//! Outgoing transfers get sent to a multicast address based on the port ID and a fixed
16//! UDP port.
17//!
18//! ### Receiving transfers
19//!
20//! All transfers are received through one socket, which joins any multicast groups required to
21//! receive the correct frames.
22//!
23
24#![cfg_attr(not(feature = "std"), no_std)]
25
26extern crate alloc;
27extern crate canadensis_core;
28extern crate canadensis_header;
29extern crate heapless;
30extern crate log;
31extern crate nb;
32#[cfg(feature = "std")]
33extern crate socket2;
34extern crate zerocopy;
35
36use canadensis_core::transport::Transport;
37use canadensis_core::{OutOfMemoryError, Priority};
38use canadensis_header::{NodeId16, TransferId64};
39use core::fmt::Debug;
40
41pub use crate::rx::{UdpReceiver, UdpSessionData};
42pub use crate::tx::UdpTransmitter;
43
44mod address;
45pub mod driver;
46mod rx;
47mod tx;
48
49/// Size of the transfer CRC in bytes
50///
51/// This is added to the end of every frame
52const TRANSFER_CRC_SIZE: usize = 4;
53
54/// The minimum size of a Cyphal/UDP packet
55///
56/// This is also the minimum MTU. It includes the Cyphal/UDP header and the transfer CRC.
57pub const MIN_PACKET_SIZE: usize = canadensis_header::SIZE + TRANSFER_CRC_SIZE;
58
59/// The default UDP port used for communication
60pub const DEFAULT_PORT: u16 = 9382;
61
62/// The Cyphal/UDP transport
63///
64/// This matches [the standard described on the forum on 2022-12-02](https://forum.opencyphal.org/t/cyphal-udp-architectural-issues-caused-by-the-dependency-between-the-nodes-ip-address-and-its-identity/1765/60).
65pub struct UdpTransport(());
66
67impl Transport for UdpTransport {
68    type NodeId = UdpNodeId;
69    type TransferId = UdpTransferId;
70    type Priority = Priority;
71}
72
73/// A UDP node ID
74pub type UdpNodeId = NodeId16;
75
76pub struct UdpTransferIds([UdpTransferId; u16::MAX as usize + 1]);
77
78impl Default for UdpTransferIds {
79    fn default() -> Self {
80        UdpTransferIds([UdpTransferId::default(); u16::MAX as usize + 1])
81    }
82}
83
84impl AsMut<[UdpTransferId]> for UdpTransferIds {
85    fn as_mut(&mut self) -> &mut [UdpTransferId] {
86        &mut self.0
87    }
88}
89
90/// A UDP transfer identifier
91///
92/// This is just a `u64`.
93pub type UdpTransferId = TransferId64;
94
95#[derive(Debug)]
96pub enum Error<S> {
97    Memory(OutOfMemoryError),
98    Socket(S),
99}
100
101impl<S> From<OutOfMemoryError> for Error<S> {
102    fn from(oom: OutOfMemoryError) -> Self {
103        Error::Memory(oom)
104    }
105}