1pub(crate) use announce::*;
4pub(crate) use delay_req::*;
5pub(crate) use delay_resp::*;
6pub(crate) use follow_up::*;
7pub use header::*;
8pub(crate) use p_delay_req::*;
9pub(crate) use p_delay_resp::*;
10pub(crate) use p_delay_resp_follow_up::*;
11pub(crate) use sync::*;
12
13use self::{management::ManagementMessage, signalling::SignalingMessage};
14use super::{
15 common::{PortIdentity, TimeInterval, TlvSet, WireTimestamp},
16 datasets::InternalDefaultDS,
17 WireFormatError,
18};
19use crate::{
20 config::LeapIndicator,
21 ptp_instance::PtpInstanceState,
22 time::{Interval, Time},
23};
24
25mod announce;
26mod control_field;
27mod delay_req;
28mod delay_resp;
29mod follow_up;
30mod header;
31mod management;
32mod p_delay_req;
33mod p_delay_resp;
34mod p_delay_resp_follow_up;
35mod signalling;
36mod sync;
37
38pub const MAX_DATA_LEN: usize = 1024;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45#[repr(u8)]
46pub enum MessageType {
47 Sync = 0x0,
48 DelayReq = 0x1,
49 PDelayReq = 0x2,
50 PDelayResp = 0x3,
51 FollowUp = 0x8,
52 DelayResp = 0x9,
53 PDelayRespFollowUp = 0xa,
54 Announce = 0xb,
55 Signaling = 0xc,
56 Management = 0xd,
57}
58
59pub struct EnumConversionError;
60
61impl TryFrom<u8> for MessageType {
62 type Error = EnumConversionError;
63
64 fn try_from(value: u8) -> Result<Self, Self::Error> {
65 use MessageType::*;
66
67 match value {
68 0x0 => Ok(Sync),
69 0x1 => Ok(DelayReq),
70 0x2 => Ok(PDelayReq),
71 0x3 => Ok(PDelayResp),
72 0x8 => Ok(FollowUp),
73 0x9 => Ok(DelayResp),
74 0xa => Ok(PDelayRespFollowUp),
75 0xb => Ok(Announce),
76 0xc => Ok(Signaling),
77 0xd => Ok(Management),
78 _ => Err(EnumConversionError),
79 }
80 }
81}
82
83#[cfg(feature = "fuzz")]
84pub use fuzz::FuzzMessage;
85
86#[cfg(feature = "fuzz")]
87#[allow(missing_docs)] mod fuzz {
89 use super::*;
90 use crate::datastructures::{common::Tlv, WireFormatError};
91
92 #[derive(Debug, Clone, PartialEq, Eq)]
93 pub struct FuzzMessage<'a> {
94 inner: Message<'a>,
95 }
96
97 #[derive(Debug, Clone, PartialEq, Eq)]
98 pub struct FuzzTlv<'a>(Tlv<'a>);
99
100 impl<'a> FuzzMessage<'a> {
101 pub fn deserialize(buffer: &'a [u8]) -> Result<Self, impl std::error::Error> {
102 Ok::<FuzzMessage, WireFormatError>(FuzzMessage {
103 inner: Message::deserialize(buffer)?,
104 })
105 }
106
107 pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize, impl std::error::Error> {
108 self.inner.serialize(buffer)
109 }
110
111 pub fn tlv(&self) -> impl Iterator<Item = FuzzTlv<'_>> + '_ {
112 self.inner.suffix.tlv().map(FuzzTlv)
113 }
114 }
115}
116
117#[derive(Debug, Clone, PartialEq, Eq)]
118pub(crate) struct Message<'a> {
119 pub(crate) header: Header,
120 pub(crate) body: MessageBody,
121 pub(crate) suffix: TlvSet<'a>,
122}
123
124#[derive(Debug, Clone, PartialEq, Eq)]
125pub(crate) enum MessageBody {
126 Sync(SyncMessage),
127 DelayReq(DelayReqMessage),
128 PDelayReq(PDelayReqMessage),
129 PDelayResp(PDelayRespMessage),
130 FollowUp(FollowUpMessage),
131 DelayResp(DelayRespMessage),
132 PDelayRespFollowUp(PDelayRespFollowUpMessage),
133 Announce(AnnounceMessage),
134 Signaling(SignalingMessage),
135 Management(ManagementMessage),
136}
137
138impl MessageBody {
139 fn wire_size(&self) -> usize {
140 match &self {
141 MessageBody::Sync(m) => m.content_size(),
142 MessageBody::DelayReq(m) => m.content_size(),
143 MessageBody::PDelayReq(m) => m.content_size(),
144 MessageBody::PDelayResp(m) => m.content_size(),
145 MessageBody::FollowUp(m) => m.content_size(),
146 MessageBody::DelayResp(m) => m.content_size(),
147 MessageBody::PDelayRespFollowUp(m) => m.content_size(),
148 MessageBody::Announce(m) => m.content_size(),
149 MessageBody::Signaling(m) => m.content_size(),
150 MessageBody::Management(m) => m.content_size(),
151 }
152 }
153
154 fn content_type(&self) -> MessageType {
155 match self {
156 MessageBody::Sync(_) => MessageType::Sync,
157 MessageBody::DelayReq(_) => MessageType::DelayReq,
158 MessageBody::PDelayReq(_) => MessageType::PDelayReq,
159 MessageBody::PDelayResp(_) => MessageType::PDelayResp,
160 MessageBody::FollowUp(_) => MessageType::FollowUp,
161 MessageBody::DelayResp(_) => MessageType::DelayResp,
162 MessageBody::PDelayRespFollowUp(_) => MessageType::PDelayRespFollowUp,
163 MessageBody::Announce(_) => MessageType::Announce,
164 MessageBody::Signaling(_) => MessageType::Signaling,
165 MessageBody::Management(_) => MessageType::Management,
166 }
167 }
168
169 pub(crate) fn serialize(&self, buffer: &mut [u8]) -> Result<usize, super::WireFormatError> {
170 match &self {
171 MessageBody::Sync(m) => m.serialize_content(buffer)?,
172 MessageBody::DelayReq(m) => m.serialize_content(buffer)?,
173 MessageBody::PDelayReq(m) => m.serialize_content(buffer)?,
174 MessageBody::PDelayResp(m) => m.serialize_content(buffer)?,
175 MessageBody::FollowUp(m) => m.serialize_content(buffer)?,
176 MessageBody::DelayResp(m) => m.serialize_content(buffer)?,
177 MessageBody::PDelayRespFollowUp(m) => m.serialize_content(buffer)?,
178 MessageBody::Announce(m) => m.serialize_content(buffer)?,
179 MessageBody::Signaling(m) => m.serialize_content(buffer)?,
180 MessageBody::Management(m) => m.serialize_content(buffer)?,
181 }
182
183 Ok(self.wire_size())
184 }
185
186 pub(crate) fn deserialize(
187 message_type: MessageType,
188 header: &Header,
189 buffer: &[u8],
190 ) -> Result<Self, super::WireFormatError> {
191 let body = match message_type {
192 MessageType::Sync => MessageBody::Sync(SyncMessage::deserialize_content(buffer)?),
193 MessageType::DelayReq => {
194 MessageBody::DelayReq(DelayReqMessage::deserialize_content(buffer)?)
195 }
196 MessageType::PDelayReq => {
197 MessageBody::PDelayReq(PDelayReqMessage::deserialize_content(buffer)?)
198 }
199 MessageType::PDelayResp => {
200 MessageBody::PDelayResp(PDelayRespMessage::deserialize_content(buffer)?)
201 }
202 MessageType::FollowUp => {
203 MessageBody::FollowUp(FollowUpMessage::deserialize_content(buffer)?)
204 }
205 MessageType::DelayResp => {
206 MessageBody::DelayResp(DelayRespMessage::deserialize_content(buffer)?)
207 }
208 MessageType::PDelayRespFollowUp => MessageBody::PDelayRespFollowUp(
209 PDelayRespFollowUpMessage::deserialize_content(buffer)?,
210 ),
211 MessageType::Announce => {
212 MessageBody::Announce(AnnounceMessage::deserialize_content(*header, buffer)?)
213 }
214 MessageType::Signaling => {
215 MessageBody::Signaling(SignalingMessage::deserialize_content(buffer)?)
216 }
217 MessageType::Management => {
218 MessageBody::Management(ManagementMessage::deserialize_content(buffer)?)
219 }
220 };
221
222 Ok(body)
223 }
224}
225
226fn base_header(
227 default_ds: &InternalDefaultDS,
228 port_identity: PortIdentity,
229 sequence_id: u16,
230 minor_ptp_version: u8,
231) -> Header {
232 Header {
233 sdo_id: default_ds.sdo_id,
234 domain_number: default_ds.domain_number,
235 source_port_identity: port_identity,
236 sequence_id,
237 ..Header::new(minor_ptp_version)
238 }
239}
240
241pub fn is_compatible(buffer: &[u8]) -> bool {
243 (buffer.len() >= 2) && (buffer[1] & 0xf) == 2
247}
248
249impl Message<'_> {
250 pub(crate) fn sync(
251 default_ds: &InternalDefaultDS,
252 port_identity: PortIdentity,
253 sequence_id: u16,
254 minor_ptp_version: u8,
255 ) -> Self {
256 let header = Header {
257 two_step_flag: true,
258 ..base_header(default_ds, port_identity, sequence_id, minor_ptp_version)
259 };
260
261 Message {
262 header,
263 body: MessageBody::Sync(SyncMessage {
264 origin_timestamp: Default::default(),
265 }),
266 suffix: TlvSet::default(),
267 }
268 }
269
270 pub(crate) fn follow_up(
271 default_ds: &InternalDefaultDS,
272 port_identity: PortIdentity,
273 sequence_id: u16,
274 timestamp: Time,
275 minor_ptp_version: u8,
276 ) -> Self {
277 let header = Header {
278 correction_field: timestamp.subnano(),
279 ..base_header(default_ds, port_identity, sequence_id, minor_ptp_version)
280 };
281
282 Message {
283 header,
284 body: MessageBody::FollowUp(FollowUpMessage {
285 precise_origin_timestamp: timestamp.into(),
286 }),
287 suffix: TlvSet::default(),
288 }
289 }
290
291 pub(crate) fn announce(
292 global: &PtpInstanceState,
293 port_identity: PortIdentity,
294 sequence_id: u16,
295 minor_ptp_version: u8,
296 ) -> Self {
297 let time_properties_ds = &global.time_properties_ds;
298
299 let header = Header {
300 leap59: time_properties_ds.leap_indicator == LeapIndicator::Leap59,
301 leap61: time_properties_ds.leap_indicator == LeapIndicator::Leap61,
302 current_utc_offset_valid: time_properties_ds.current_utc_offset.is_some(),
303 ptp_timescale: time_properties_ds.ptp_timescale,
304 time_tracable: time_properties_ds.time_traceable,
305 frequency_tracable: time_properties_ds.frequency_traceable,
306 ..base_header(
307 &global.default_ds,
308 port_identity,
309 sequence_id,
310 minor_ptp_version,
311 )
312 };
313
314 let body = MessageBody::Announce(AnnounceMessage {
315 header,
316 origin_timestamp: Default::default(),
317 current_utc_offset: time_properties_ds.current_utc_offset.unwrap_or_default(),
318 grandmaster_priority_1: global.parent_ds.grandmaster_priority_1,
319 grandmaster_clock_quality: global.parent_ds.grandmaster_clock_quality,
320 grandmaster_priority_2: global.parent_ds.grandmaster_priority_2,
321 grandmaster_identity: global.parent_ds.grandmaster_identity,
322 steps_removed: global.current_ds.steps_removed,
323 time_source: time_properties_ds.time_source,
324 });
325
326 Message {
327 header,
328 body,
329 suffix: TlvSet::default(),
330 }
331 }
332
333 pub(crate) fn delay_req(
334 default_ds: &InternalDefaultDS,
335 port_identity: PortIdentity,
336 sequence_id: u16,
337 minor_ptp_version: u8,
338 ) -> Self {
339 let header = Header {
340 log_message_interval: 0x7f,
341 ..base_header(default_ds, port_identity, sequence_id, minor_ptp_version)
342 };
343
344 Message {
345 header,
346 body: MessageBody::DelayReq(DelayReqMessage {
347 origin_timestamp: WireTimestamp::default(),
348 }),
349 suffix: TlvSet::default(),
350 }
351 }
352
353 pub(crate) fn delay_resp(
354 request_header: Header,
355 request: DelayReqMessage,
356 port_identity: PortIdentity,
357 min_delay_req_interval: Interval,
358 timestamp: Time,
359 ) -> Self {
360 let _ = request;
362
363 let header = Header {
364 two_step_flag: false,
365 source_port_identity: port_identity,
366 correction_field: TimeInterval(
367 request_header.correction_field.0 + timestamp.subnano().0,
368 ),
369 log_message_interval: min_delay_req_interval.as_log_2(),
370 ..request_header
371 };
372
373 let body = MessageBody::DelayResp(DelayRespMessage {
374 receive_timestamp: timestamp.into(),
375 requesting_port_identity: request_header.source_port_identity,
376 });
377
378 Message {
379 header,
380 body,
381 suffix: TlvSet::default(),
382 }
383 }
384
385 pub(crate) fn pdelay_req(
386 default_ds: &InternalDefaultDS,
387 port_identity: PortIdentity,
388 sequence_id: u16,
389 minor_ptp_version: u8,
390 ) -> Self {
391 Message {
392 header: base_header(default_ds, port_identity, sequence_id, minor_ptp_version),
393 body: MessageBody::PDelayReq(PDelayReqMessage {
394 origin_timestamp: WireTimestamp::default(),
395 }),
396 suffix: TlvSet::default(),
397 }
398 }
399
400 pub(crate) fn pdelay_resp(
401 default_ds: &InternalDefaultDS,
402 port_identity: PortIdentity,
403 request_header: Header,
404 timestamp: Time,
405 minor_ptp_version: u8,
406 ) -> Self {
407 Message {
409 header: Header {
410 two_step_flag: true,
411 correction_field: request_header.correction_field,
412 ..base_header(
413 default_ds,
414 port_identity,
415 request_header.sequence_id,
416 minor_ptp_version,
417 )
418 },
419 body: MessageBody::PDelayResp(PDelayRespMessage {
420 request_receive_timestamp: timestamp.into(),
421 requesting_port_identity: request_header.source_port_identity,
422 }),
423 suffix: TlvSet::default(),
424 }
425 }
426
427 pub(crate) fn pdelay_resp_follow_up(
428 default_ds: &InternalDefaultDS,
429 port_identity: PortIdentity,
430 requestor_identity: PortIdentity,
431 sequence_id: u16,
432 timestamp: Time,
433 minor_ptp_version: u8,
434 ) -> Self {
435 Message {
436 header: base_header(default_ds, port_identity, sequence_id, minor_ptp_version),
437 body: MessageBody::PDelayRespFollowUp(PDelayRespFollowUpMessage {
438 response_origin_timestamp: timestamp.into(),
439 requesting_port_identity: requestor_identity,
440 }),
441 suffix: TlvSet::default(),
442 }
443 }
444}
445
446impl<'a> Message<'a> {
447 pub(crate) fn header(&self) -> &Header {
448 &self.header
449 }
450
451 pub(crate) fn wire_size(&self) -> usize {
453 self.header.wire_size() + self.body.wire_size() + self.suffix.wire_size()
454 }
455
456 pub(crate) fn serialize(&self, buffer: &mut [u8]) -> Result<usize, super::WireFormatError> {
460 let (header, rest) = buffer.split_at_mut(34);
461 let (body, tlv) = rest.split_at_mut(self.body.wire_size());
462
463 self.header
464 .serialize_header(
465 self.body.content_type(),
466 self.body.wire_size() + self.suffix.wire_size(),
467 header,
468 )
469 .unwrap();
470
471 self.body.serialize(body).unwrap();
472
473 self.suffix.serialize(tlv).unwrap();
474
475 Ok(self.wire_size())
476 }
477
478 pub(crate) fn deserialize(buffer: &'a [u8]) -> Result<Self, super::WireFormatError> {
482 let header_data = Header::deserialize_header(buffer)?;
483
484 if header_data.message_length < 34 {
485 return Err(WireFormatError::Invalid);
486 }
487
488 let content_buffer = buffer
491 .get(34..(header_data.message_length as usize))
492 .ok_or(WireFormatError::BufferTooShort)?;
493
494 let body = MessageBody::deserialize(
495 header_data.message_type,
496 &header_data.header,
497 content_buffer,
498 )?;
499
500 let tlv_buffer = &content_buffer
501 .get(body.wire_size()..)
502 .ok_or(super::WireFormatError::BufferTooShort)?;
503 let suffix = TlvSet::deserialize(tlv_buffer)?;
504
505 Ok(Message {
506 header: header_data.header,
507 body,
508 suffix,
509 })
510 }
511}