Skip to main content

statime_wire/messages/
mod.rs

1//! Ptp network messages
2
3use super::{Error, common::TlvSet};
4
5mod announce;
6mod delay_req;
7mod delay_resp;
8mod follow_up;
9mod header;
10mod management;
11mod p_delay_req;
12mod p_delay_resp;
13mod p_delay_resp_follow_up;
14mod signalling;
15mod sync;
16
17pub use announce::*;
18pub use delay_req::*;
19pub use delay_resp::*;
20pub use follow_up::*;
21pub use header::*;
22pub use management::*;
23pub use p_delay_req::*;
24pub use p_delay_resp::*;
25pub use p_delay_resp_follow_up::*;
26pub use signalling::*;
27pub use sync::*;
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30#[repr(u8)]
31pub(crate) enum MessageType {
32    Sync = 0x0,
33    DelayReq = 0x1,
34    PDelayReq = 0x2,
35    PDelayResp = 0x3,
36    FollowUp = 0x8,
37    DelayResp = 0x9,
38    PDelayRespFollowUp = 0xa,
39    Announce = 0xb,
40    Signaling = 0xc,
41    Management = 0xd,
42}
43
44impl TryFrom<u8> for MessageType {
45    type Error = Error;
46
47    fn try_from(value: u8) -> Result<Self, Self::Error> {
48        use MessageType::{
49            Announce, DelayReq, DelayResp, FollowUp, Management, PDelayReq, PDelayResp,
50            PDelayRespFollowUp, Signaling, Sync,
51        };
52
53        match value {
54            0x0 => Ok(Sync),
55            0x1 => Ok(DelayReq),
56            0x2 => Ok(PDelayReq),
57            0x3 => Ok(PDelayResp),
58            0x8 => Ok(FollowUp),
59            0x9 => Ok(DelayResp),
60            0xa => Ok(PDelayRespFollowUp),
61            0xb => Ok(Announce),
62            0xc => Ok(Signaling),
63            0xd => Ok(Management),
64            _ => Err(Error::Invalid),
65        }
66    }
67}
68
69/// A PTP version 2 Message.
70///
71/// For more details, see the individual parts, as well as *IEEE1588-2019 clause 13*
72#[derive(Debug, Clone, PartialEq, Eq)]
73pub struct Message<'a> {
74    /// The header of the message.
75    pub header: Header,
76    /// The main data in the message body.
77    pub body: MessageBody,
78    /// Any extensions sent along with the message.
79    pub suffix: TlvSet<'a>,
80}
81
82/// The main body of a message.
83///
84/// For more details, see *IEEE1588-2019 section 13.3*
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub enum MessageBody {
87    /// A synchronization message.
88    Sync(SyncMessage),
89    /// A delay request message.
90    DelayReq(DelayReqMessage),
91    /// A peer delay request message.
92    PDelayReq(PDelayReqMessage),
93    /// A peer delay response message.
94    PDelayResp(PDelayRespMessage),
95    /// A followup for a two-step timing message.
96    FollowUp(FollowUpMessage),
97    /// A delay response message.
98    DelayResp(DelayRespMessage),
99    /// A peer delay response follow up message used for
100    /// two step timing of peer delay response messages.
101    PDelayRespFollowUp(PDelayRespFollowUpMessage),
102    /// An announce message
103    Announce(AnnounceMessage),
104    /// A signalling message.
105    ///
106    /// These messages are used purely as a vehicle for TLVs.
107    Signaling(SignalingMessage),
108    /// A management message.
109    Management(ManagementMessage),
110}
111
112impl MessageBody {
113    /// The size this message will have once encoded for transmission.
114    fn wire_size(&self) -> usize {
115        match &self {
116            MessageBody::Sync(m) => m.content_size(),
117            MessageBody::DelayReq(m) => m.content_size(),
118            MessageBody::PDelayReq(m) => m.content_size(),
119            MessageBody::PDelayResp(m) => m.content_size(),
120            MessageBody::FollowUp(m) => m.content_size(),
121            MessageBody::DelayResp(m) => m.content_size(),
122            MessageBody::PDelayRespFollowUp(m) => m.content_size(),
123            MessageBody::Announce(m) => m.content_size(),
124            MessageBody::Signaling(m) => m.content_size(),
125            MessageBody::Management(m) => m.content_size(),
126        }
127    }
128
129    fn content_type(&self) -> MessageType {
130        match self {
131            MessageBody::Sync(_) => MessageType::Sync,
132            MessageBody::DelayReq(_) => MessageType::DelayReq,
133            MessageBody::PDelayReq(_) => MessageType::PDelayReq,
134            MessageBody::PDelayResp(_) => MessageType::PDelayResp,
135            MessageBody::FollowUp(_) => MessageType::FollowUp,
136            MessageBody::DelayResp(_) => MessageType::DelayResp,
137            MessageBody::PDelayRespFollowUp(_) => MessageType::PDelayRespFollowUp,
138            MessageBody::Announce(_) => MessageType::Announce,
139            MessageBody::Signaling(_) => MessageType::Signaling,
140            MessageBody::Management(_) => MessageType::Management,
141        }
142    }
143
144    /// Serialize this message into a buffer of bytes.
145    pub(crate) fn serialize(&self, buffer: &mut [u8]) -> Result<usize, super::Error> {
146        match &self {
147            MessageBody::Sync(m) => m.serialize_content(buffer)?,
148            MessageBody::DelayReq(m) => m.serialize_content(buffer)?,
149            MessageBody::PDelayReq(m) => m.serialize_content(buffer)?,
150            MessageBody::PDelayResp(m) => m.serialize_content(buffer)?,
151            MessageBody::FollowUp(m) => m.serialize_content(buffer)?,
152            MessageBody::DelayResp(m) => m.serialize_content(buffer)?,
153            MessageBody::PDelayRespFollowUp(m) => m.serialize_content(buffer)?,
154            MessageBody::Announce(m) => m.serialize_content(buffer)?,
155            MessageBody::Signaling(m) => m.serialize_content(buffer)?,
156            MessageBody::Management(m) => m.serialize_content(buffer)?,
157        }
158
159        Ok(self.wire_size())
160    }
161
162    /// Deserialize a message from a received buffer of bytes.
163    pub(crate) fn deserialize(
164        message_type: MessageType,
165        buffer: &[u8],
166    ) -> Result<Self, super::Error> {
167        let body = match message_type {
168            MessageType::Sync => MessageBody::Sync(SyncMessage::deserialize_content(buffer)?),
169            MessageType::DelayReq => {
170                MessageBody::DelayReq(DelayReqMessage::deserialize_content(buffer)?)
171            }
172            MessageType::PDelayReq => {
173                MessageBody::PDelayReq(PDelayReqMessage::deserialize_content(buffer)?)
174            }
175            MessageType::PDelayResp => {
176                MessageBody::PDelayResp(PDelayRespMessage::deserialize_content(buffer)?)
177            }
178            MessageType::FollowUp => {
179                MessageBody::FollowUp(FollowUpMessage::deserialize_content(buffer)?)
180            }
181            MessageType::DelayResp => {
182                MessageBody::DelayResp(DelayRespMessage::deserialize_content(buffer)?)
183            }
184            MessageType::PDelayRespFollowUp => MessageBody::PDelayRespFollowUp(
185                PDelayRespFollowUpMessage::deserialize_content(buffer)?,
186            ),
187            MessageType::Announce => {
188                MessageBody::Announce(AnnounceMessage::deserialize_content(buffer)?)
189            }
190            MessageType::Signaling => {
191                MessageBody::Signaling(SignalingMessage::deserialize_content(buffer)?)
192            }
193            MessageType::Management => {
194                MessageBody::Management(ManagementMessage::deserialize_content(buffer)?)
195            }
196        };
197
198        Ok(body)
199    }
200}
201
202/// Checks whether message is of a PTP revision compatible with this crate.
203#[must_use]
204pub fn is_compatible(buffer: &[u8]) -> bool {
205    // this ensures that versionPTP in the header is 2
206    // it will never happen in PTPv1 packets because this octet is the LSB of
207    // versionPTP there
208    (buffer.len() >= 2) && (buffer[1] & 0xf) == 2
209}
210
211impl<'a> Message<'a> {
212    /// The byte size on the wire of this message
213    #[must_use]
214    pub fn wire_size(&self) -> usize {
215        self.header.wire_size() + self.body.wire_size() + self.suffix.wire_size()
216    }
217
218    /// Serializes the object into the PTP wire format.
219    ///
220    /// Returns the ammount of buffer used to serialize the message.
221    ///
222    /// # Errors
223    /// The function fails when:
224    ///  - The message total size or any of its dynamically sized parts exceed 2^16 bytes
225    ///  - The message does not fit into the provided buffer.
226    pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize, super::Error> {
227        let (header, rest) = buffer
228            .split_at_mut_checked(34)
229            .ok_or(Error::BufferTooShort)?;
230        let (body, tlv) = rest
231            .split_at_mut_checked(self.body.wire_size())
232            .ok_or(Error::BufferTooShort)?;
233
234        self.header.serialize_header(
235            self.body.content_type(),
236            self.body.wire_size() + self.suffix.wire_size(),
237            header,
238        )?;
239
240        self.body.serialize(body)?;
241
242        self.suffix.serialize(tlv)?;
243
244        Ok(self.wire_size())
245    }
246
247    /// Deserializes a message from the PTP wire format.
248    ///
249    /// # Errors
250    /// This returns an error when the provided buffer does not contain a valid
251    /// PTP message, or when the provided message is incomplete.
252    pub fn deserialize(buffer: &'a [u8]) -> Result<Self, super::Error> {
253        let header_data = Header::deserialize_header(buffer)?;
254
255        if header_data.message_length < 34 {
256            return Err(Error::Invalid);
257        }
258
259        // Ensure we have the entire message and ignore potential padding
260        // Skip the header bytes and only keep the content
261        let content_buffer = buffer
262            .get(34..(header_data.message_length as usize))
263            .ok_or(Error::BufferTooShort)?;
264
265        let body = MessageBody::deserialize(header_data.message_type, content_buffer)?;
266
267        let tlv_buffer = &content_buffer
268            .get(body.wire_size()..)
269            .ok_or(super::Error::BufferTooShort)?;
270        let suffix = TlvSet::deserialize(tlv_buffer)?;
271
272        Ok(Message {
273            header: header_data.header,
274            body,
275            suffix,
276        })
277    }
278}