dmsc/protocol/frames.rs
1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of DMSC.
4//! The DMSC project belongs to the Dunimd Team.
5//!
6//! Licensed under the Apache License, Version 2.0 (the "License");
7//! You may not use this file except in compliance with the License.
8//! You may obtain a copy of the License at
9//!
10//! http://www.apache.org/licenses/LICENSE-2.0
11//!
12//! Unless required by applicable law or agreed to in writing, software
13//! distributed under the License is distributed on an "AS IS" BASIS,
14//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//! See the License for the specific language governing permissions and
16//! limitations under the License.
17
18#![allow(non_snake_case)]
19
20//! # Protocol Frame Format Module
21//!
22//! This module implements the real protocol frame format with serialization,
23//! checksums, and frame integrity verification for the DMSC private protocol.
24
25use std::convert::TryInto;
26use serde::{Deserialize, Serialize};
27use crc32fast::Hasher;
28
29use crate::core::{DMSCResult, DMSCError};
30
31/// Protocol frame type enumeration defining the categories of protocol frames.
32///
33/// This enumeration classifies all protocol frames used in the DMSC protocol
34/// for network communication. Each frame type serves a specific purpose in
35/// the communication lifecycle, from initial connection establishment through
36/// data transmission, authentication, and connection maintenance. Frame type
37/// identification enables proper routing and processing of incoming frames
38/// by protocol handlers.
39///
40/// ## Frame Type Hierarchy
41///
42/// - **Control Frames (0x01)**: Protocol management and state transitions
43/// - **Data Frames (0x02)**: Application data payload transmission
44/// - **Auth Frames (0x03)**: Authentication and authorization exchanges
45/// - **Keep-Alive Frames (0x04)**: Connection liveness verification
46/// - **Error Frames (0x05)**: Error reporting and status communication
47/// - **Encrypted Frames (0x06)**: Pre-encrypted payload transmission
48///
49/// ## Frame Processing Guidelines
50///
51/// Protocol implementations should process frames in the following order:
52/// 1. First validate the frame header magic number and version
53/// 2. Extract and validate the frame type from the header
54/// 3. Route the frame to the appropriate handler based on frame type
55/// 4. Process the frame payload according to type-specific rules
56/// 5. Send appropriate response frames if required
57///
58/// ## Python Bindings
59///
60/// When compiled with the `pyo3` feature, this enum provides Python bindings
61/// for frame type identification:
62/// ```python
63/// from dmsc import DMSCFrameType
64///
65/// # Identify frame types for protocol handling
66/// control_type = DMSCFrameType.Control()
67/// data_type = DMSCFrameType.Data()
68/// auth_type = DMSCFrameType.Auth()
69///
70/// # Convert between types and byte values
71/// frame_type_value = DMSCFrameType.from_u8(0x01)
72/// byte_value = data_type.to_u8() # Returns 0x02
73/// ```
74///
75/// ## Thread Safety
76///
77/// This enum is fully thread-safe and can be shared across concurrent contexts
78/// without additional synchronization. The Copy trait enables efficient passing
79/// of frame type values through function arguments and return types.
80///
81/// ## Storage and Transmission
82///
83/// Frame type values are stored as single bytes making them efficient for network
84/// transmission and compact storage. The Hash trait enables frame type usage as
85/// dictionary keys in collection types and provides efficient lookup performance.
86///
87/// # Examples
88///
89/// Basic frame type creation and conversion:
90/// ```rust,ignore
91/// use dmsc::protocol::frames::DMSCFrameType;
92///
93/// let control = DMSCFrameType::Control;
94/// let data = DMSCFrameType::Data;
95///
96/// assert_eq!(control as u8, 0x01);
97/// assert_eq!(data as u8, 0x02);
98/// assert_ne!(control, data);
99/// ```
100///
101/// Frame type matching in protocol handling:
102/// ```rust,ignore
103/// use dmsc::protocol::frames::DMSCFrameType;
104///
105/// fn handle_frame_type(frame_type: DMSCFrameType) -> &str {
106/// match frame_type {
107/// DMSCFrameType::Control => "Control frame - managing protocol state",
108/// DMSCFrameType::Data => "Data frame - processing payload",
109/// DMSCFrameType::Auth => "Auth frame - handling authentication",
110/// DMSCFrameType::KeepAlive => "Keep-alive frame - verifying connection",
111/// DMSCFrameType::Error => "Error frame - reporting error condition",
112/// DMSCFrameType::Encrypted => "Encrypted frame - processing secure payload",
113/// }
114/// }
115///
116/// assert_eq!(handle_frame_type(DMSCFrameType::Data), "Data frame - processing payload");
117/// ```
118///
119/// Converting between byte values and frame types:
120/// ```rust,ignore
121/// use dmsc::protocol::frames::DMSCFrameType;
122///
123/// // Convert byte to frame type
124/// let frame_type = DMSCFrameType::from_u8(0x03);
125/// assert_eq!(frame_type, Some(DMSCFrameType::Auth));
126///
127/// // Invalid byte value returns None
128/// let invalid = DMSCFrameType::from_u8(0xFF);
129/// assert_eq!(invalid, None);
130/// ```
131#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
133pub enum DMSCFrameType {
134 /// Control frame for protocol management operations.
135 ///
136 /// Control frames manage the protocol state machine and handle connection
137 /// lifecycle events. They are used for operations such as connection
138 /// initialization, version negotiation, feature flags exchange, and graceful
139 /// connection termination. Control frames must be processed before any data
140 /// frames to ensure proper protocol state establishment.
141 ///
142 /// ## Control Frame Payload Structure
143 ///
144 /// Control frame payloads contain a command identifier followed by
145 /// command-specific parameters encoded in a type-length-value (TLV) format.
146 ///
147 /// ## Common Control Commands
148 ///
149 /// - **Connection Request (0x01)**: Initiate new connection
150 /// - **Connection Ack (0x02)**: Confirm connection establishment
151 /// - **Disconnect Request (0x03)**: Initiate graceful disconnection
152 /// - **Ping (0x04)**: Request keep-alive response
153 /// - **Pong (0x05)**: Keep-alive response
154 /// - **Protocol Negotiation (0x10)**: Negotiate protocol features
155 Control = 0x01,
156
157 /// Data frame for application payload transmission.
158 ///
159 /// Data frames carry the primary application data through the protocol.
160 /// They are the most frequently used frame type in normal protocol operation
161 /// and support both streaming and message-based data transfer modes. Data
162 /// frames are sequenced and delivered in-order to ensure data integrity.
163 ///
164 /// ## Data Frame Characteristics
165 ///
166 /// - **Sequencing**: Each data frame has a unique sequence number
167 /// - **Ordering**: Frames are delivered in sequence number order
168 /// - **Flow Control**: Sliding window prevents buffer overflow
169 /// - **Aggregation**: Multiple small payloads can be aggregated
170 ///
171 /// ## Payload Considerations
172 ///
173 /// - Maximum payload size is defined by protocol configuration
174 /// - Large payloads may be fragmented across multiple frames
175 /// - Payload compression is available as an optional feature
176 Data = 0x02,
177
178 /// Authentication frame for credential exchange and verification.
179 ///
180 /// Authentication frames facilitate the authentication process between
181 /// communicating parties. They carry authentication tokens, certificates,
182 /// challenge-response pairs, and authentication results. All auth frames
183 /// are encrypted using the current session encryption keys.
184 ///
185 /// ## Authentication Flow
186 ///
187 /// 1. Client sends authentication request with credentials
188 /// 2. Server validates credentials and returns challenge
189 /// 3. Client responds to challenge with proof of possession
190 /// 4. Server confirms successful authentication
191 ///
192 /// ## Supported Authentication Methods
193 ///
194 /// - JWT token authentication
195 /// - Certificate-based mutual TLS
196 /// - Pre-shared key authentication
197 /// - OAuth 2.0 token exchange
198 Auth = 0x03,
199
200 /// Keep-alive frame for connection liveness verification.
201 ///
202 /// Keep-alive frames maintain connection vitality and detect unresponsive
203 /// peers. They are exchanged periodically between connected parties to
204 /// prevent connection timeout and detect connection failures. Keep-alive
205 /// frames have minimal overhead and contain no payload.
206 ///
207 KeepAlive = 0x04,
208
209 /// Error frame for error condition reporting.
210 ///
211 /// Error frames communicate error conditions from one protocol party to
212 /// another. They include an error code and human-readable error message
213 /// to facilitate debugging and error recovery. Error frames may be sent
214 /// in response to any invalid protocol message.
215 ///
216 Error = 0x05,
217
218 /// Encrypted frame for pre-encrypted payload transmission.
219 ///
220 /// Encrypted frames carry payloads that have been encrypted by the
221 /// application layer before being passed to the protocol. This allows
222 /// applications to use custom encryption schemes or to encrypt data
223 /// end-to-end between application endpoints. The protocol encrypts the
224 /// encrypted payload as normal data.
225 ///
226 /// ## Use Cases
227 ///
228 /// - End-to-end encrypted application data
229 /// - Custom encryption algorithm requirements
230 /// - Regulatory compliance requiring specific encryption
231 /// - Integration with external encryption systems
232 ///
233 /// ## Security Considerations
234 ///
235 /// When using encrypted frames, the outer protocol encryption provides
236 /// transport security while the inner encrypted payload provides
237 /// end-to-end security between application endpoints.
238 Encrypted = 0x06,
239}
240
241impl DMSCFrameType {
242 /// Convert from byte to frame type
243 pub fn from_u8(value: u8) -> Option<Self> {
244 match value {
245 0x01 => Some(DMSCFrameType::Control),
246 0x02 => Some(DMSCFrameType::Data),
247 0x03 => Some(DMSCFrameType::Auth),
248 0x04 => Some(DMSCFrameType::KeepAlive),
249 0x05 => Some(DMSCFrameType::Error),
250 0x06 => Some(DMSCFrameType::Encrypted),
251 _ => None,
252 }
253 }
254}
255
256/// Protocol frame header structure containing metadata for frame processing.
257///
258/// The frame header provides essential protocol metadata required for proper
259/// frame handling, transmission, and verification. It follows a fixed 32-byte
260/// format designed for efficient parsing and minimal overhead while maintaining
261/// comprehensive protocol information. All fields use big-endian byte ordering
262/// for consistent network transmission.
263///
264/// ## Header Field Layout
265///
266/// | Offset | Size | Field | Description |
267/// |--------|------|----------------|------------------------------------------|
268/// | 0 | 4 | magic | Protocol magic number (0x444D5350) |
269/// | 4 | 1 | frame_type | Frame type identifier (0x01-0x06) |
270/// | 5 | 1 | version | Protocol version (0x01) |
271/// | 6 | 2 | flags | Protocol flags for special handling |
272/// | 8 | 4 | payload_length | Length of frame payload in bytes |
273/// | 12 | 4 | sequence_number| Frame sequence number for ordering |
274/// | 16 | 8 | timestamp | Unix timestamp of frame creation |
275/// | 24 | 4 | checksum | CRC32 checksum for integrity verification|
276///
277/// ## Byte Ordering
278///
279/// All multi-byte fields use big-endian (network byte order) encoding to ensure
280/// consistent interpretation across different architectures and platforms.
281/// When serializing or deserializing, use the provided `to_bytes()` and
282/// `from_bytes()` methods to ensure proper byte ordering.
283///
284/// ## Magic Number Validation
285///
286/// The magic number `0x444D5350` decodes to ASCII "DMSP" (DMSC Protocol) and
287/// serves as a quick validation that incoming data represents a valid DMSC
288/// frame. Receiving a frame with an invalid magic number indicates either
289/// protocol mismatch or data corruption.
290///
291/// ## Python Bindings
292///
293/// When compiled with the `pyo3` feature, this struct provides Python bindings:
294/// ```python
295/// from dmsc import DMSCFrameHeader
296///
297/// # Create new header for a data frame
298/// header = DMSCFrameHeader.new(
299/// frame_type=DMSCFrameHeader.FrameType.Data,
300/// payload_length=1024,
301/// sequence_number=42
302/// )
303///
304/// # Serialize to bytes for transmission
305/// header_bytes = header.to_bytes()
306///
307/// # Access header fields
308/// print(f"Frame type: {header.frame_type}")
309/// print(f"Payload length: {header.payload_length}")
310/// print(f"Sequence: {header.sequence_number}")
311/// print(f"Timestamp: {header.timestamp}")
312/// ```
313///
314/// # Examples
315///
316/// Creating a new frame header:
317/// ```rust,ignore
318/// use dmsc::protocol::frames::{DMSCFrameHeader, DMSCFrameType};
319///
320/// let header = DMSCFrameHeader::new(
321/// DMSCFrameType::Data,
322/// 1024, // payload length
323/// 42 // sequence number
324/// ).expect("Failed to create frame header");
325///
326/// assert_eq!(header.magic, DMSCFrameHeader::MAGIC);
327/// assert_eq!(header.version, DMSCFrameHeader::VERSION);
328/// assert_eq!(header.frame_type, DMSCFrameType::Data as u8);
329/// ```
330///
331/// Serializing and deserializing headers:
332/// ```rust,ignore
333/// use dmsc::protocol::frames::{DMSCFrameHeader, DMSCFrameType};
334///
335/// let header = DMSCFrameHeader::new(
336/// DMSCFrameType::Control,
337/// 256,
338/// 100
339/// ).expect("Failed to create header");
340///
341/// let bytes = header.to_bytes();
342/// assert_eq!(bytes.len(), 32);
343///
344/// let reconstructed = DMSCFrameHeader::from_bytes(&bytes)
345/// .expect("Failed to parse header");
346///
347/// assert_eq!(header.magic, reconstructed.magic);
348/// assert_eq!(header.frame_type, reconstructed.frame_type);
349/// assert_eq!(header.sequence_number, reconstructed.sequence_number);
350/// ```
351///
352/// Verifying frame integrity:
353/// ```rust,ignore
354/// use dmsc::protocol::frames::{DMSCFrameHeader, DMSCFrameType};
355///
356/// let header = DMSCFrameHeader::new(
357/// DMSCFrameType::Data,
358/// 512,
359/// 200
360/// ).expect("Failed to create header");
361///
362/// let payload = b"This is the frame payload data";
363///
364/// let is_valid = header.verify_checksum(payload);
365/// assert!(is_valid);
366///
367/// // Modify payload and verify again
368/// let modified_payload = b"This payload has been modified!";
369/// let is_valid_modified = header.verify_checksum(modified_payload);
370/// assert!(!is_valid_modified);
371/// ```
372#[derive(Debug, Clone, Serialize, Deserialize)]
373#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
374pub struct DMSCFrameHeader {
375 /// Frame magic number identifying the DMSC protocol (4 bytes).
376 ///
377 /// The magic number is a 32-bit constant that uniquely identifies DMSC
378 /// protocol frames. It serves as a quick validation mechanism to detect
379 /// non-DMSC data or protocol version mismatches. The value 0x444D5350
380 /// corresponds to the ASCII encoding of "DMSP" (DMSC Protocol).
381 ///
382 /// ## Magic Number Details
383 ///
384 /// - **Value**: 0x444D5350
385 /// - **ASCII**: "DMSP"
386 /// - **Purpose**: Protocol identification
387 /// - **Validation**: Must match exactly on all received frames
388 ///
389 /// ## Usage
390 ///
391 /// The magic number is the first field in the frame header and should be
392 /// validated immediately upon receiving frame data. A mismatch indicates
393 /// either incorrect data or a protocol version incompatibility.
394 pub magic: u32,
395
396 /// Frame type identifier determining frame processing (1 byte).
397 ///
398 /// The frame type specifies how the frame payload should be interpreted
399 /// and processed. This 8-bit field identifies one of six possible frame
400 /// types defined in the DMSCFrameType enumeration.
401 pub frame_type: u8,
402
403 /// Protocol version for compatibility checking (1 byte).
404 ///
405 /// The version field enables protocol evolution while maintaining backward
406 /// compatibility. The current version is 0x01. Protocol implementations
407 /// should reject frames with unsupported versions.
408 pub version: u8,
409
410 /// Protocol flags for special frame handling (2 bytes).
411 ///
412 /// Flags provide additional processing instructions for frames. Common
413 /// flags include compression, priority, and streaming indicators.
414 ///
415 /// ## Flag Definitions
416 ///
417 /// - **Bit 0**: Compressed - Payload is compressed
418 /// - **Bit 1**: Priority - High priority frame
419 /// - **Bit 2**: Streaming - Part of streaming transfer
420 /// - **Bit 3**: Fragmented - Part of fragmented message
421 /// - **Bits 4-15**: Reserved for future use
422 pub flags: u16,
423
424 /// Length of the frame payload in bytes (4 bytes).
425 ///
426 /// This field specifies the exact number of bytes in the frame payload.
427 /// It enables proper memory allocation and bounds checking during frame
428 /// processing. The maximum payload length is 4GB.
429 pub payload_length: u32,
430
431 /// Frame sequence number for ordering and reliability (4 bytes).
432 ///
433 /// Sequence numbers enable in-order delivery, duplicate detection, and
434 /// loss detection for protocol frames. Each frame in a connection uses
435 /// a monotonically increasing sequence number with wraparound at 2^32.
436 ///
437 /// ## Sequence Number Semantics
438 ///
439 /// - **Initialization**: Sequence numbers start at 0 for new connections
440 /// - **Increment**: Each frame increments the sequence number by 1
441 /// - **Wraparound**: Sequence numbers wrap from 0xFFFFFFFF to 0
442 /// - **Ordering**: Receivers use sequence numbers to order frames
443 pub sequence_number: u32,
444
445 /// Unix timestamp of frame creation in seconds (8 bytes).
446 ///
447 /// The timestamp records when the frame was created, enabling temporal
448 /// validation, replay detection, and latency measurements. Timestamps
449 /// use seconds since Unix epoch (1970-01-01 00:00:00 UTC).
450 ///
451 /// ## Timestamp Considerations
452 ///
453 /// - **Precision**: Second-level precision (not milliseconds)
454 /// - **Clock Sync**: Requires loosely synchronized clocks
455 /// - **Replay Protection**: Used in conjunction with nonces
456 /// - **Age Limits**: Frames older than timeout are rejected
457 pub timestamp: u64,
458
459 /// CRC32 checksum for frame integrity verification (4 bytes).
460 ///
461 /// The checksum covers all header fields (except checksum itself) and
462 /// the complete frame payload. It enables detection of transmission
463 /// errors and data corruption. Uses the CRC32 algorithm with polynomial
464 /// 0x04C11DB7 (IEEE 802.3).
465 ///
466 /// ## Checksum Calculation
467 ///
468 /// The checksum is computed over the concatenation of all header fields
469 /// (excluding the checksum field) followed by the frame payload. This
470 /// provides comprehensive protection against single-bit errors and
471 /// many burst errors.
472 ///
473 /// ## Limitations
474 ///
475 /// CRC32 provides error detection but not error correction. It can detect
476 /// all single-bit errors, most double-bit errors, and many burst errors
477 /// up to 32 bits in length. It does not provide cryptographic integrity.
478 pub checksum: u32,
479}
480
481impl DMSCFrameHeader {
482 /// Frame magic number constant for protocol identification.
483 ///
484 /// This 32-bit constant uniquely identifies DMSC protocol frames. The value
485 /// 0x444D5350 corresponds to the ASCII encoding of "DMSP" (DMSC Protocol).
486 /// This magic number is placed at the beginning of every frame header and
487 /// is validated upon frame receipt to confirm protocol compatibility.
488 ///
489 /// ## Magic Number Details
490 ///
491 /// - **Hex Value**: 0x444D5350
492 /// - **ASCII Representation**: "DMSP"
493 /// - **Purpose**: Quick protocol identification
494 /// - **Validation**: Must match on all received frames
495 ///
496 /// ## Usage in Frame Processing
497 ///
498 /// When receiving frame data, the magic number should be validated first
499 /// before attempting to parse other header fields. A mismatch indicates:
500 ///
501 /// 1. The received data is not a DMSC frame
502 /// 2. Data corruption may have occurred
503 /// 3. The remote endpoint may be using a different protocol
504 pub const MAGIC: u32 = 0x444D5350; // "DMSCP" in ASCII
505
506 /// Current protocol version identifier.
507 ///
508 /// This version number enables protocol evolution while maintaining backward
509 /// compatibility. The current version is 0x01. Future protocol enhancements
510 /// may increment this version while maintaining support for earlier versions.
511 ///
512 /// ## Version Semantics
513 ///
514 /// - **Major Version Changes**: May introduce incompatible changes
515 /// - **Minor Version Changes**: Backward-compatible enhancements
516 /// - **Current Value**: 0x01 (initial protocol version)
517 ///
518 /// ## Version Negotiation
519 ///
520 /// During connection establishment, endpoints should negotiate a compatible
521 /// protocol version. Frames with unsupported versions should be rejected
522 /// with an appropriate error response.
523 pub const VERSION: u8 = 0x01;
524
525 /// Create a new frame header
526 pub fn new(frame_type: DMSCFrameType, payload_length: u32, sequence_number: u32) -> DMSCResult<Self> {
527 let timestamp = std::time::SystemTime::now()
528 .duration_since(std::time::UNIX_EPOCH)
529 .map_err(|e| DMSCError::InvalidState(format!("System time error: {}", e)))?
530 .as_secs();
531
532 Ok(Self {
533 magic: Self::MAGIC,
534 frame_type: frame_type as u8,
535 version: Self::VERSION,
536 flags: 0,
537 payload_length,
538 sequence_number,
539 timestamp,
540 checksum: 0, // Will be calculated later
541 })
542 }
543
544 /// Calculate CRC32 checksum for the header and payload
545 pub fn calculate_checksum(&self, payload: &[u8]) -> u32 {
546 let mut hasher = Hasher::new();
547
548 // Add header fields (excluding checksum)
549 hasher.update(&self.magic.to_be_bytes());
550 hasher.update(&self.frame_type.to_be_bytes());
551 hasher.update(&self.version.to_be_bytes());
552 hasher.update(&self.flags.to_be_bytes());
553 hasher.update(&self.payload_length.to_be_bytes());
554 hasher.update(&self.sequence_number.to_be_bytes());
555 hasher.update(&self.timestamp.to_be_bytes());
556
557 // Add payload
558 hasher.update(payload);
559
560 hasher.finalize()
561 }
562
563 /// Verify the checksum
564 pub fn verify_checksum(&self, payload: &[u8]) -> bool {
565 self.checksum == self.calculate_checksum(payload)
566 }
567
568 /// Serialize header to bytes
569 pub fn to_bytes(&self) -> Vec<u8> {
570 let mut bytes = Vec::with_capacity(32);
571
572 bytes.extend_from_slice(&self.magic.to_be_bytes());
573 bytes.extend_from_slice(&self.frame_type.to_be_bytes());
574 bytes.extend_from_slice(&self.version.to_be_bytes());
575 bytes.extend_from_slice(&self.flags.to_be_bytes());
576 bytes.extend_from_slice(&self.payload_length.to_be_bytes());
577 bytes.extend_from_slice(&self.sequence_number.to_be_bytes());
578 bytes.extend_from_slice(&self.timestamp.to_be_bytes());
579 bytes.extend_from_slice(&self.checksum.to_be_bytes());
580
581 bytes
582 }
583
584 /// Deserialize header from bytes
585 pub fn from_bytes(bytes: &[u8]) -> DMSCResult<Self> {
586 if bytes.len() < 32 {
587 return Err(DMSCError::FrameError("Invalid header length".to_string()));
588 }
589
590 let magic = u32::from_be_bytes(bytes[0..4].try_into()
591 .map_err(|_| DMSCError::FrameError("Invalid magic number bytes".to_string()))?);
592 let frame_type = bytes[4];
593 let version = bytes[5];
594 let flags = u16::from_be_bytes(bytes[6..8].try_into()
595 .map_err(|_| DMSCError::FrameError("Invalid flags bytes".to_string()))?);
596 let payload_length = u32::from_be_bytes(bytes[8..12].try_into()
597 .map_err(|_| DMSCError::FrameError("Invalid payload length bytes".to_string()))?);
598 let sequence_number = u32::from_be_bytes(bytes[12..16].try_into()
599 .map_err(|_| DMSCError::FrameError("Invalid sequence number bytes".to_string()))?);
600 let timestamp = u64::from_be_bytes(bytes[16..24].try_into()
601 .map_err(|_| DMSCError::FrameError("Invalid timestamp bytes".to_string()))?);
602 let checksum = u32::from_be_bytes(bytes[24..28].try_into()
603 .map_err(|_| DMSCError::FrameError("Invalid checksum bytes".to_string()))?);
604
605 Ok(Self {
606 magic,
607 frame_type,
608 version,
609 flags,
610 payload_length,
611 sequence_number,
612 timestamp,
613 checksum,
614 })
615 }
616}
617
618/// Complete protocol frame combining header and payload data.
619///
620/// A DMSCFrame represents the fundamental unit of data transmission in the
621/// DMSC protocol. Each frame consists of a fixed 32-byte header containing
622/// protocol metadata and a variable-length payload containing the actual
623/// application data. Frames are serialized for network transmission and
624/// deserialized upon receipt using CRC32 checksums for integrity verification.
625///
626/// ## Frame Structure
627///
628/// ```
629/// +------------------+-------------------+
630/// | Header (32B) | Payload (VAR) |
631/// +------------------+-------------------+
632/// | magic | type | v | flags | len | seq |
633/// | timestamp | checksum |
634/// +------------------+-------------------+
635/// ```
636///
637/// ## Frame Lifecycle
638///
639/// 1. **Creation**: Construct a frame using `new()` or one of the convenience
640/// constructors (`data_frame()`, `control_frame()`, etc.)
641/// 2. **Serialization**: Convert to bytes using `to_bytes()` for transmission
642/// 3. **Transmission**: Send bytes over the network connection
643/// 4. **Reception**: Receive bytes and add to frame parser buffer
644/// 5. **Deserialization**: Parse bytes back to frame using `from_bytes()`
645/// 6. **Processing**: Handle the frame based on its type
646///
647/// ## Frame Validity
648///
649/// A frame is considered valid when:
650/// - The magic number matches the DMSC protocol identifier
651/// - The protocol version is supported
652/// - The CRC32 checksum matches the computed checksum
653/// - The payload length matches the actual payload size
654///
655/// Use the `is_valid()` method for quick validation checking.
656///
657/// ## Python Bindings
658///
659/// When compiled with the `pyo3` feature, this struct provides Python bindings:
660/// ```python
661/// from dmsc import DMSCFrame, DMSCFrameType
662///
663/// # Create a data frame
664/// frame = DMSCFrame.data_frame(
665/// data=b"Hello, DMSC Protocol!",
666/// sequence_number=1
667/// )
668///
669/// # Serialize for transmission
670/// frame_bytes = frame.to_bytes()
671/// print(f"Frame size: {len(frame_bytes)} bytes")
672///
673/// # Access frame properties
674/// print(f"Frame type: {frame.frame_type()}")
675/// print(f"Sequence: {frame.sequence_number()}")
676/// print(f"Timestamp: {frame.timestamp()}")
677/// print(f"Valid: {frame.is_valid()}")
678///
679/// # Deserialize received frame
680/// received = DMSCFrame.from_bytes(frame_bytes)
681/// assert received.payload == b"Hello, DMSC Protocol!"
682/// ```
683///
684/// # Examples
685///
686/// Creating and serializing a data frame:
687/// ```rust,ignore
688/// use dmsc::protocol::frames::{DMSCFrame, DMSCFrameType};
689///
690/// let frame = DMSCFrame::data_frame(
691/// b"Hello, World!".to_vec(),
692/// 42
693/// ).expect("Failed to create frame");
694///
695/// let bytes = frame.to_bytes().expect("Failed to serialize frame");
696/// println!("Frame serialized to {} bytes", bytes.len());
697///
698/// assert!(frame.is_valid());
699/// assert_eq!(frame.sequence_number(), 42);
700/// ```
701///
702/// Creating different frame types:
703/// ```rust,ignore
704/// use dmsc::protocol::frames::{DMSCFrame, DMSCFrameType};
705///
706/// // Control frame with command data
707/// let control = DMSCFrame::control_frame(
708/// vec![0x01, 0x02, 0x03],
709/// 1
710/// ).expect("Failed to create control frame");
711///
712/// // Authentication frame with credentials
713/// let auth = DMSCFrame::auth_frame(
714/// b"token=abc123".to_vec(),
715/// 2
716/// ).expect("Failed to create auth frame");
717///
718/// // Keep-alive frame (no payload)
719/// let keepalive = DMSCFrame::keepalive_frame(3)
720/// .expect("Failed to create keepalive frame");
721///
722/// // Error frame with code and message
723/// let error = DMSCFrame::error_frame(
724/// 0x0401,
725/// "Connection timeout".to_string(),
726/// 4
727/// ).expect("Failed to create error frame");
728/// ```
729///
730/// Receiving and deserializing frames:
731/// ```rust,ignore
732/// use dmsc::protocol::frames::{DMSCFrame, DMSCFrameType};
733///
734/// let original = DMSCFrame::data_frame(
735/// b"Received data".to_vec(),
736/// 100
737/// ).expect("Failed to create frame");
738///
739/// let bytes = original.to_bytes().expect("Failed to serialize");
740///
741/// // Simulate network transmission
742/// let received = DMSCFrame::from_bytes(&bytes)
743/// .expect("Failed to deserialize frame");
744///
745/// assert_eq!(received.sequence_number(), 100);
746/// assert_eq!(received.payload, b"Received data");
747/// assert!(received.is_valid());
748/// ```
749#[derive(Debug, Clone)]
750#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
751pub struct DMSCFrame {
752 /// Frame header containing protocol metadata.
753 ///
754 /// The header provides essential information for frame processing including
755 /// the frame type, sequence number, timestamp, and integrity checksum.
756 /// It is always exactly 32 bytes in size and uses big-endian byte ordering.
757 pub header: DMSCFrameHeader,
758
759 /// Frame payload containing application data.
760 ///
761 /// The payload contains the actual data being transmitted. Its meaning
762 /// depends on the frame type:
763 /// - **Control**: Protocol management commands
764 /// - **Data**: Application-level message data
765 /// - **Auth**: Authentication credentials or tokens
766 /// - **KeepAlive**: Empty (no payload)
767 /// - **Error**: Error code + error message
768 /// - **Encrypted**: Pre-encrypted application data
769 pub payload: Vec<u8>,
770}
771
772impl DMSCFrame {
773 /// Create a new frame
774 pub fn new(frame_type: DMSCFrameType, payload: Vec<u8>, sequence_number: u32) -> DMSCResult<Self> {
775 let header = DMSCFrameHeader::new(frame_type, payload.len() as u32, sequence_number)?;
776 Ok(Self { header, payload })
777 }
778
779 /// Create a control frame
780 pub fn control_frame(control_data: Vec<u8>, sequence_number: u32) -> DMSCResult<Self> {
781 Self::new(DMSCFrameType::Control, control_data, sequence_number)
782 }
783
784 /// Create a data frame
785 pub fn data_frame(data: Vec<u8>, sequence_number: u32) -> DMSCResult<Self> {
786 Self::new(DMSCFrameType::Data, data, sequence_number)
787 }
788
789 /// Create an authentication frame
790 pub fn auth_frame(auth_data: Vec<u8>, sequence_number: u32) -> DMSCResult<Self> {
791 Self::new(DMSCFrameType::Auth, auth_data, sequence_number)
792 }
793
794 /// Create a keep-alive frame
795 pub fn keepalive_frame(sequence_number: u32) -> DMSCResult<Self> {
796 Self::new(DMSCFrameType::KeepAlive, vec![], sequence_number)
797 }
798
799 /// Create an error frame
800 pub fn error_frame(error_code: u32, error_message: String, sequence_number: u32) -> DMSCResult<Self> {
801 let mut payload = Vec::new();
802 payload.extend_from_slice(&error_code.to_be_bytes());
803 payload.extend_from_slice(error_message.as_bytes());
804 Self::new(DMSCFrameType::Error, payload, sequence_number)
805 }
806
807 /// Serialize frame to bytes
808 pub fn to_bytes(&self) -> DMSCResult<Vec<u8>> {
809 let mut header = self.header.clone();
810
811 // Calculate and set checksum
812 header.checksum = header.calculate_checksum(&self.payload);
813
814 let mut result = Vec::new();
815 result.extend_from_slice(&header.to_bytes());
816 result.extend_from_slice(&self.payload);
817
818 Ok(result)
819 }
820
821 /// Deserialize frame from bytes
822 pub fn from_bytes(bytes: &[u8]) -> DMSCResult<Self> {
823 if bytes.len() < 32 {
824 return Err(DMSCError::FrameError("Frame too short".to_string()));
825 }
826
827 let header = DMSCFrameHeader::from_bytes(&bytes[0..32])?;
828
829 // Verify magic number
830 if header.magic != DMSCFrameHeader::MAGIC {
831 return Err(DMSCError::FrameError(format!("Invalid magic number: 0x{:08X}", header.magic)));
832 }
833
834 // Verify version
835 if header.version != DMSCFrameHeader::VERSION {
836 return Err(DMSCError::FrameError(format!("Unsupported version: {}", header.version)));
837 }
838
839 // Check payload length
840 if bytes.len() < 32 + header.payload_length as usize {
841 return Err(DMSCError::FrameError("Incomplete frame".to_string()));
842 }
843
844 let payload = bytes[32..32 + header.payload_length as usize].to_vec();
845
846 // Verify checksum
847 if !header.verify_checksum(&payload) {
848 return Err(DMSCError::FrameError("Checksum verification failed".to_string()));
849 }
850
851 Ok(Self { header, payload })
852 }
853
854 /// Get frame type
855 pub fn frame_type(&self) -> Option<DMSCFrameType> {
856 DMSCFrameType::from_u8(self.header.frame_type)
857 }
858
859 /// Get sequence number
860 pub fn sequence_number(&self) -> u32 {
861 self.header.sequence_number
862 }
863
864 /// Get timestamp
865 pub fn timestamp(&self) -> u64 {
866 self.header.timestamp
867 }
868
869 /// Check if frame is valid
870 pub fn is_valid(&self) -> bool {
871 self.header.magic == DMSCFrameHeader::MAGIC &&
872 self.header.version == DMSCFrameHeader::VERSION &&
873 self.header.verify_checksum(&self.payload)
874 }
875}
876
877/// Frame parser for reading and assembling protocol frames from stream data.
878///
879/// The DMSCFrameParser handles the incremental parsing of frame data from network
880/// streams or byte sources. Network protocols often deliver data in chunks that
881/// may not align with protocol frame boundaries. This parser accumulates incoming
882/// data in an internal buffer and extracts complete frames when sufficient data
883/// is available. It also manages sequence number validation to ensure frame
884/// ordering integrity.
885///
886/// ## Parser Operation Model
887///
888/// ```
889/// Incoming Data: [partial][complete][partial][complete][partial]
890/// | | | |
891/// v v v v
892/// Parser Buffer: [======][==========][=========][=======]
893/// | | |
894/// v v v
895/// Extracted: [Frame1] [Frame2] [Frame3]
896/// ```
897///
898/// ## Sequence Number Validation
899///
900/// The parser maintains an expected sequence number counter. Each extracted frame
901/// must have a sequence number matching the expected value. This detects missing
902/// frames (gaps in sequence numbers) which may indicate packet loss. Use
903/// `reset_sequence()` to set a new expected sequence number, such as after
904/// reconnection.
905///
906/// ## Buffer Management
907///
908/// The parser maintains an internal buffer that grows as data is added. For
909/// long-running connections, periodically check `buffer_len()` and consider
910/// calling `clear_buffer()` if buffer accumulation indicates parsing issues.
911/// The parser automatically removes parsed data from the buffer.
912///
913/// ## Python Bindings
914///
915/// When compiled with the `pyo3` feature, this struct provides Python bindings:
916/// ```python
917/// from dmsc import DMSCFrameParser
918///
919/// # Create parser for incoming stream data
920/// parser = DMSCFrameParser.new()
921///
922/// # Simulate receiving data chunks
923/// chunks = [
924/// frame1_bytes[:20],
925/// frame1_bytes[20:] + frame2_bytes[:30],
926/// frame2_bytes[30:] + frame3_bytes
927/// ]
928///
929/// for chunk in chunks:
930/// parser.add_data(chunk)
931/// while True:
932/// frame = parser.parse_frame()
933/// if frame is None:
934/// break
935/// print(f"Received frame: {frame.sequence_number()}")
936///
937/// print(f"Buffer contains {parser.buffer_len()} bytes")
938/// ```
939///
940/// # Examples
941///
942/// Basic frame parsing from stream data:
943/// ```rust,ignore
944/// use dmsc::protocol::frames::{DMSCFrameParser, DMSCFrame};
945///
946/// let mut parser = DMSCFrameParser::new();
947///
948/// // Simulate receiving frame data in chunks
949/// let frame1 = DMSCFrame::data_frame(b"First message".to_vec(), 0)
950/// .expect("Failed to create frame");
951/// let frame2 = DMSCFrame::data_frame(b"Second message".to_vec(), 1)
952/// .expect("Failed to create frame");
953///
954/// let bytes1 = frame1.to_bytes().expect("Failed to serialize");
955/// let bytes2 = frame2.to_bytes().expect("Failed to serialize");
956///
957/// // Add first chunk (partial frame)
958/// parser.add_data(&bytes1[..20]);
959/// assert!(parser.parse_frame().unwrap().is_none());
960///
961/// // Add second chunk (completes frame1, starts frame2)
962/// parser.add_data(&bytes1[20..]);
963/// let parsed = parser.parse_frame().unwrap().expect("Should have complete frame");
964/// assert_eq!(parsed.sequence_number(), 0);
965///
966/// // Add remaining data
967/// parser.add_data(&bytes2);
968/// let parsed = parser.parse_frame().unwrap().expect("Should have complete frame");
969/// assert_eq!(parsed.sequence_number(), 1);
970/// ```
971///
972/// Handling sequence number reset:
973/// ```rust,ignore
974/// use dmsc::protocol::frames::DMSCFrameParser;
975///
976/// let mut parser = DMSCFrameParser::new();
977///
978/// // Parse some frames
979/// parser.add_data(&some_data);
980/// while let Ok(Some(frame)) = parser.parse_frame() {
981/// // Process frames
982/// }
983///
984/// // Reset sequence number for new session
985/// parser.reset_sequence();
986/// parser.clear_buffer();
987///
988/// // Now expecting sequence 0 again
989/// assert_eq!(parser.next_sequence, 0);
990/// ```
991///
992/// # Thread Safety
993///
994/// This struct is not thread-safe. Multiple threads should not concurrently
995/// access the same parser instance without external synchronization. For
996/// concurrent parsing, either use separate parser instances per thread or
997/// wrap access with a Mutex or RwLock.
998///
999/// # Performance Considerations
1000///
1001/// - The parser uses `Vec::extend_from_slice` for efficient buffer appending
1002/// - Frame extraction uses slice operations to avoid unnecessary copying
1003/// - Buffer memory is only reclaimed when frames are successfully parsed
1004/// - Large frames may cause temporary buffer growth; configure appropriate limits
1005#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
1006pub struct DMSCFrameParser {
1007 /// Internal buffer for accumulating incoming data.
1008 ///
1009 /// The buffer holds bytes that have been received but not yet assembled
1010 /// into complete frames. It grows dynamically as more data arrives.
1011 /// Data is automatically removed from the buffer once successfully parsed.
1012 buffer: Vec<u8>,
1013
1014 /// Next expected sequence number for validation.
1015 ///
1016 /// This counter tracks the sequence number of the next frame expected
1017 /// from the stream. Frames with mismatching sequence numbers indicate
1018 /// potential packet loss or protocol errors.
1019 next_sequence: u32,
1020}
1021
1022impl DMSCFrameParser {
1023 pub fn new() -> Self {
1024 Self {
1025 buffer: Vec::new(),
1026 next_sequence: 0,
1027 }
1028 }
1029
1030 pub fn add_data(&mut self, data: &[u8]) {
1031 self.buffer.extend_from_slice(data);
1032 }
1033
1034 pub fn parse_frame(&mut self) -> DMSCResult<Option<DMSCFrame>> {
1035 if self.buffer.len() < 32 {
1036 return Ok(None);
1037 }
1038
1039 let header = DMSCFrameHeader::from_bytes(&self.buffer[0..32])?;
1040 let total_length = 32 + header.payload_length as usize;
1041
1042 if self.buffer.len() < total_length {
1043 return Ok(None);
1044 }
1045
1046 let frame_bytes = self.buffer[0..total_length].to_vec();
1047 let frame = DMSCFrame::from_bytes(&frame_bytes)?;
1048
1049 if frame.header.sequence_number != self.next_sequence {
1050 return Ok(None);
1051 }
1052
1053 self.buffer.drain(0..total_length);
1054 self.next_sequence = self.next_sequence.wrapping_add(1);
1055
1056 Ok(Some(frame))
1057 }
1058
1059 pub fn buffer_len(&self) -> usize {
1060 self.buffer.len()
1061 }
1062
1063 pub fn clear_buffer(&mut self) {
1064 self.buffer.clear();
1065 }
1066
1067 pub fn reset_sequence(&mut self) {
1068 self.next_sequence = 0;
1069 }
1070}
1071
1072/// Frame builder for creating protocol frames with automatic sequence numbering.
1073///
1074/// The DMSCFrameBuilder provides a convenient interface for constructing DMSC frames
1075/// while automatically managing sequence numbers. Rather than manually tracking and
1076/// incrementing sequence numbers for each frame, the builder maintains an internal
1077/// counter that is automatically incremented after each frame construction. This
1078/// ensures proper sequence numbering without the risk of human error.
1079///
1080/// ## Builder Pattern Advantages
1081///
1082/// Using the frame builder provides several benefits over direct frame construction:
1083///
1084/// - **Automatic Sequencing**: No need to manually track and increment sequence numbers
1085/// - **Type Safety**: Compile-time checking of frame type construction
1086/// - **Convenience Methods**: Domain-specific constructors for each frame type
1087/// - **State Management**: Builder maintains state across frame constructions
1088///
1089/// ## Sequence Number Management
1090///
1091/// The builder maintains an internal sequence counter that is automatically incremented
1092/// after each frame construction. The counter uses wrapping arithmetic (modulo 2^32)
1093/// to handle overflow gracefully. You can query or set the current sequence number
1094/// using `next_sequence()` and `set_sequence()` methods.
1095///
1096/// ## Python Bindings
1097///
1098/// When compiled with the `pyo3` feature, this struct provides Python bindings:
1099/// ```python
1100/// from dmsc import DMSCFrameBuilder
1101///
1102/// # Create builder for convenient frame construction
1103/// builder = DMSCFrameBuilder.new()
1104///
1105/// # Build frames without manually tracking sequence numbers
1106/// control_frame = builder.build_control_frame(b"\x01\x02\x03")
1107/// data_frame = builder.build_data_frame(b"Hello, World!")
1108/// auth_frame = builder.build_auth_frame(b"token=abc123")
1109///
1110/// # Check current sequence number
1111/// print(f"Next sequence: {builder.next_sequence()}")
1112///
1113/// # Reset sequence for new session
1114/// builder.set_sequence(0)
1115/// ```
1116///
1117/// # Examples
1118///
1119/// Building multiple frames with automatic sequencing:
1120/// ```rust,ignore
1121/// use dmsc::protocol::frames::DMSCFrameBuilder;
1122///
1123/// let mut builder = DMSCFrameBuilder::new();
1124///
1125/// // Build a series of data frames
1126/// let frame1 = builder.build_data_frame(b"Message 1".to_vec())
1127/// .expect("Failed to build frame");
1128/// let frame2 = builder.build_data_frame(b"Message 2".to_vec())
1129/// .expect("Failed to build frame");
1130/// let frame3 = builder.build_data_frame(b"Message 3".to_vec())
1131/// .expect("Failed to build frame");
1132///
1133/// assert_eq!(frame1.sequence_number(), 0);
1134/// assert_eq!(frame2.sequence_number(), 1);
1135/// assert_eq!(frame3.sequence_number(), 2);
1136///
1137/// // Current sequence is now 3
1138/// assert_eq!(builder.next_sequence(), 3);
1139/// ```
1140///
1141/// Building different frame types:
1142/// ```rust,ignore
1143/// use dmsc::protocol::frames::DMSCFrameBuilder;
1144///
1145/// let mut builder = DMSCFrameBuilder::new();
1146///
1147/// // Control frame
1148/// let control = builder.build_control_frame(vec![0x01, 0x00, 0x01])
1149/// .expect("Failed to build control frame");
1150///
1151/// // Authentication frame
1152/// let auth = builder.build_auth_frame(b"credentials=secret".to_vec())
1153/// .expect("Failed to build auth frame");
1154///
1155/// // Keep-alive frame
1156/// let keepalive = builder.build_keepalive_frame()
1157/// .expect("Failed to build keepalive frame");
1158///
1159/// // Error frame
1160/// let error = builder.build_error_frame(0x0401, "Timeout".to_string())
1161/// .expect("Failed to build error frame");
1162/// ```
1163///
1164/// Managing sequence numbers:
1165/// ```rust,ignore
1166/// use dmsc::protocol::frames::DMSCFrameBuilder;
1167///
1168/// let mut builder = DMSCFrameBuilder::new();
1169///
1170/// // Build some frames
1171/// let _ = builder.build_data_frame(b"Frame 0".to_vec()).unwrap();
1172/// let _ = builder.build_data_frame(b"Frame 1".to_vec()).unwrap();
1173/// let _ = builder.build_data_frame(b"Frame 2".to_vec()).unwrap();
1174///
1175/// // Check current sequence
1176/// assert_eq!(builder.next_sequence(), 3);
1177///
1178/// // Set specific sequence for resend or new session
1179/// builder.set_sequence(100);
1180///
1181/// let next = builder.build_data_frame(b"Frame 100".to_vec()).unwrap();
1182/// assert_eq!(next.sequence_number(), 100);
1183/// assert_eq!(builder.next_sequence(), 101);
1184/// ```
1185///
1186/// # Thread Safety
1187///
1188/// This struct is not thread-safe. Multiple threads should not concurrently
1189/// access the same builder instance without external synchronization. For
1190/// concurrent frame building, either use separate builder instances per thread
1191/// or wrap access with a Mutex or RwLock.
1192///
1193/// # Performance Characteristics
1194///
1195/// - Frame construction is O(1) for fixed-size headers
1196/// - Payload copying is O(n) where n is payload size
1197/// - Sequence number operations are O(1)
1198/// - Minimal heap allocation for small payloads
1199#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
1200pub struct DMSCFrameBuilder {
1201 /// Internal counter for automatic sequence number generation.
1202 ///
1203 /// This counter tracks the sequence number to assign to the next frame
1204 /// constructed by the builder. It is automatically incremented after
1205 /// each frame construction using wrapping arithmetic.
1206 next_sequence: u32,
1207}
1208
1209impl DMSCFrameBuilder {
1210 pub fn new() -> Self {
1211 Self { next_sequence: 0 }
1212 }
1213
1214 pub fn build_control_frame(&mut self, control_data: Vec<u8>) -> DMSCResult<DMSCFrame> {
1215 let frame = DMSCFrame::control_frame(control_data, self.next_sequence)?;
1216 self.next_sequence = self.next_sequence.wrapping_add(1);
1217 Ok(frame)
1218 }
1219
1220 pub fn build_data_frame(&mut self, data: Vec<u8>) -> DMSCResult<DMSCFrame> {
1221 let frame = DMSCFrame::data_frame(data, self.next_sequence)?;
1222 self.next_sequence = self.next_sequence.wrapping_add(1);
1223 Ok(frame)
1224 }
1225
1226 pub fn build_auth_frame(&mut self, auth_data: Vec<u8>) -> DMSCResult<DMSCFrame> {
1227 let frame = DMSCFrame::auth_frame(auth_data, self.next_sequence)?;
1228 self.next_sequence = self.next_sequence.wrapping_add(1);
1229 Ok(frame)
1230 }
1231
1232 pub fn build_keepalive_frame(&mut self) -> DMSCResult<DMSCFrame> {
1233 let frame = DMSCFrame::keepalive_frame(self.next_sequence)?;
1234 self.next_sequence = self.next_sequence.wrapping_add(1);
1235 Ok(frame)
1236 }
1237
1238 pub fn build_error_frame(&mut self, error_code: u32, error_message: String) -> DMSCResult<DMSCFrame> {
1239 let frame = DMSCFrame::error_frame(error_code, error_message, self.next_sequence)?;
1240 self.next_sequence = self.next_sequence.wrapping_add(1);
1241 Ok(frame)
1242 }
1243
1244 pub fn next_sequence(&self) -> u32 {
1245 self.next_sequence
1246 }
1247
1248 pub fn set_sequence(&mut self, sequence: u32) {
1249 self.next_sequence = sequence;
1250 }
1251}
1252
1253