ri/protocol/frames.rs
1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of Ri.
4//! The Ri 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 Ri private protocol.
24
25use std::convert::TryInto;
26use serde::{Deserialize, Serialize};
27use crc32fast::Hasher;
28
29use crate::core::{RiResult, RiError};
30
31/// Protocol frame type enumeration defining the categories of protocol frames.
32///
33/// This enumeration classifies all protocol frames used in the Ri 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 ri import RiFrameType
64///
65/// # Identify frame types for protocol handling
66/// control_type = RiFrameType.Control()
67/// data_type = RiFrameType.Data()
68/// auth_type = RiFrameType.Auth()
69///
70/// # Convert between types and byte values
71/// frame_type_value = RiFrameType.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 ri::protocol::frames::RiFrameType;
92///
93/// let control = RiFrameType::Control;
94/// let data = RiFrameType::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 ri::protocol::frames::RiFrameType;
104///
105/// fn handle_frame_type(frame_type: RiFrameType) -> &str {
106/// match frame_type {
107/// RiFrameType::Control => "Control frame - managing protocol state",
108/// RiFrameType::Data => "Data frame - processing payload",
109/// RiFrameType::Auth => "Auth frame - handling authentication",
110/// RiFrameType::KeepAlive => "Keep-alive frame - verifying connection",
111/// RiFrameType::Error => "Error frame - reporting error condition",
112/// RiFrameType::Encrypted => "Encrypted frame - processing secure payload",
113/// }
114/// }
115///
116/// assert_eq!(handle_frame_type(RiFrameType::Data), "Data frame - processing payload");
117/// ```
118///
119/// Converting between byte values and frame types:
120/// ```rust,ignore
121/// use ri::protocol::frames::RiFrameType;
122///
123/// // Convert byte to frame type
124/// let frame_type = RiFrameType::from_u8(0x03);
125/// assert_eq!(frame_type, Some(RiFrameType::Auth));
126///
127/// // Invalid byte value returns None
128/// let invalid = RiFrameType::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 RiFrameType {
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 RiFrameType {
242 /// Convert from byte to frame type
243 pub fn from_u8(value: u8) -> Option<Self> {
244 match value {
245 0x01 => Some(RiFrameType::Control),
246 0x02 => Some(RiFrameType::Data),
247 0x03 => Some(RiFrameType::Auth),
248 0x04 => Some(RiFrameType::KeepAlive),
249 0x05 => Some(RiFrameType::Error),
250 0x06 => Some(RiFrameType::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" (Ri Protocol) and
287/// serves as a quick validation that incoming data represents a valid Ri
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 ri import RiFrameHeader
296///
297/// # Create new header for a data frame
298/// header = RiFrameHeader.new(
299/// frame_type=RiFrameHeader.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 ri::protocol::frames::{RiFrameHeader, RiFrameType};
319///
320/// let header = RiFrameHeader::new(
321/// RiFrameType::Data,
322/// 1024, // payload length
323/// 42 // sequence number
324/// ).expect("Failed to create frame header");
325///
326/// assert_eq!(header.magic, RiFrameHeader::MAGIC);
327/// assert_eq!(header.version, RiFrameHeader::VERSION);
328/// assert_eq!(header.frame_type, RiFrameType::Data as u8);
329/// ```
330///
331/// Serializing and deserializing headers:
332/// ```rust,ignore
333/// use ri::protocol::frames::{RiFrameHeader, RiFrameType};
334///
335/// let header = RiFrameHeader::new(
336/// RiFrameType::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 = RiFrameHeader::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 ri::protocol::frames::{RiFrameHeader, RiFrameType};
355///
356/// let header = RiFrameHeader::new(
357/// RiFrameType::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 RiFrameHeader {
375 /// Frame magic number identifying the Ri protocol (4 bytes).
376 ///
377 /// The magic number is a 32-bit constant that uniquely identifies Ri
378 /// protocol frames. It serves as a quick validation mechanism to detect
379 /// non-Ri data or protocol version mismatches. The value 0x444D5350
380 /// corresponds to the ASCII encoding of "DMSP" (Ri 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 RiFrameType 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 RiFrameHeader {
482 /// Frame magic number constant for protocol identification.
483 ///
484 /// This 32-bit constant uniquely identifies Ri protocol frames. The value
485 /// 0x444D5350 corresponds to the ASCII encoding of "DMSP" (Ri 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 /// Maximum payload length (10 MB) to prevent memory exhaustion attacks.
502 /// This limit prevents attackers from sending frames with extremely large
503 /// payload_length values that could exhaust server memory.
504 pub const MAX_PAYLOAD_LENGTH: u32 = 10 * 1024 * 1024;
505 ///
506 /// 1. The received data is not a Ri frame
507 /// 2. Data corruption may have occurred
508 /// 3. The remote endpoint may be using a different protocol
509 pub const MAGIC: u32 = 0x444D5350; // "RiP" in ASCII
510
511 /// Current protocol version identifier.
512 ///
513 /// This version number enables protocol evolution while maintaining backward
514 /// compatibility. The current version is 0x01. Future protocol enhancements
515 /// may increment this version while maintaining support for earlier versions.
516 ///
517 /// ## Version Semantics
518 ///
519 /// - **Major Version Changes**: May introduce incompatible changes
520 /// - **Minor Version Changes**: Backward-compatible enhancements
521 /// - **Current Value**: 0x01 (initial protocol version)
522 ///
523 /// ## Version Negotiation
524 ///
525 /// During connection establishment, endpoints should negotiate a compatible
526 /// protocol version. Frames with unsupported versions should be rejected
527 /// with an appropriate error response.
528 pub const VERSION: u8 = 0x01;
529
530 /// Create a new frame header
531 pub fn new(frame_type: RiFrameType, payload_length: u32, sequence_number: u32) -> RiResult<Self> {
532 let timestamp = std::time::SystemTime::now()
533 .duration_since(std::time::UNIX_EPOCH)
534 .map_err(|e| RiError::InvalidState(format!("System time error: {}", e)))?
535 .as_secs();
536
537 Ok(Self {
538 magic: Self::MAGIC,
539 frame_type: frame_type as u8,
540 version: Self::VERSION,
541 flags: 0,
542 payload_length,
543 sequence_number,
544 timestamp,
545 checksum: 0, // Will be calculated later
546 })
547 }
548
549 /// Calculate CRC32 checksum for the header and payload
550 pub fn calculate_checksum(&self, payload: &[u8]) -> u32 {
551 let mut hasher = Hasher::new();
552
553 // Add header fields (excluding checksum)
554 hasher.update(&self.magic.to_be_bytes());
555 hasher.update(&self.frame_type.to_be_bytes());
556 hasher.update(&self.version.to_be_bytes());
557 hasher.update(&self.flags.to_be_bytes());
558 hasher.update(&self.payload_length.to_be_bytes());
559 hasher.update(&self.sequence_number.to_be_bytes());
560 hasher.update(&self.timestamp.to_be_bytes());
561
562 // Add payload
563 hasher.update(payload);
564
565 hasher.finalize()
566 }
567
568 /// Verify the checksum
569 pub fn verify_checksum(&self, payload: &[u8]) -> bool {
570 self.checksum == self.calculate_checksum(payload)
571 }
572
573 /// Serialize header to bytes
574 pub fn to_bytes(&self) -> Vec<u8> {
575 let mut bytes = Vec::with_capacity(32);
576
577 bytes.extend_from_slice(&self.magic.to_be_bytes());
578 bytes.extend_from_slice(&self.frame_type.to_be_bytes());
579 bytes.extend_from_slice(&self.version.to_be_bytes());
580 bytes.extend_from_slice(&self.flags.to_be_bytes());
581 bytes.extend_from_slice(&self.payload_length.to_be_bytes());
582 bytes.extend_from_slice(&self.sequence_number.to_be_bytes());
583 bytes.extend_from_slice(&self.timestamp.to_be_bytes());
584 bytes.extend_from_slice(&self.checksum.to_be_bytes());
585
586 bytes
587 }
588
589 /// Deserialize header from bytes
590 pub fn from_bytes(bytes: &[u8]) -> RiResult<Self> {
591 if bytes.len() < 32 {
592 return Err(RiError::FrameError("Invalid header length".to_string()));
593 }
594
595 let magic = u32::from_be_bytes(bytes[0..4].try_into()
596 .map_err(|_| RiError::FrameError("Invalid magic number bytes".to_string()))?);
597 let frame_type = bytes[4];
598 let version = bytes[5];
599 let flags = u16::from_be_bytes(bytes[6..8].try_into()
600 .map_err(|_| RiError::FrameError("Invalid flags bytes".to_string()))?);
601 let payload_length = u32::from_be_bytes(bytes[8..12].try_into()
602 .map_err(|_| RiError::FrameError("Invalid payload length bytes".to_string()))?);
603 let sequence_number = u32::from_be_bytes(bytes[12..16].try_into()
604 .map_err(|_| RiError::FrameError("Invalid sequence number bytes".to_string()))?);
605 let timestamp = u64::from_be_bytes(bytes[16..24].try_into()
606 .map_err(|_| RiError::FrameError("Invalid timestamp bytes".to_string()))?);
607 let checksum = u32::from_be_bytes(bytes[24..28].try_into()
608 .map_err(|_| RiError::FrameError("Invalid checksum bytes".to_string()))?);
609
610 Ok(Self {
611 magic,
612 frame_type,
613 version,
614 flags,
615 payload_length,
616 sequence_number,
617 timestamp,
618 checksum,
619 })
620 }
621}
622
623/// Complete protocol frame combining header and payload data.
624///
625/// A RiFrame represents the fundamental unit of data transmission in the
626/// Ri protocol. Each frame consists of a fixed 32-byte header containing
627/// protocol metadata and a variable-length payload containing the actual
628/// application data. Frames are serialized for network transmission and
629/// deserialized upon receipt using CRC32 checksums for integrity verification.
630///
631/// ## Frame Structure
632///
633/// ```
634/// +------------------+-------------------+
635/// | Header (32B) | Payload (VAR) |
636/// +------------------+-------------------+
637/// | magic | type | v | flags | len | seq |
638/// | timestamp | checksum |
639/// +------------------+-------------------+
640/// ```
641///
642/// ## Frame Lifecycle
643///
644/// 1. **Creation**: Construct a frame using `new()` or one of the convenience
645/// constructors (`data_frame()`, `control_frame()`, etc.)
646/// 2. **Serialization**: Convert to bytes using `to_bytes()` for transmission
647/// 3. **Transmission**: Send bytes over the network connection
648/// 4. **Reception**: Receive bytes and add to frame parser buffer
649/// 5. **Deserialization**: Parse bytes back to frame using `from_bytes()`
650/// 6. **Processing**: Handle the frame based on its type
651///
652/// ## Frame Validity
653///
654/// A frame is considered valid when:
655/// - The magic number matches the Ri protocol identifier
656/// - The protocol version is supported
657/// - The CRC32 checksum matches the computed checksum
658/// - The payload length matches the actual payload size
659///
660/// Use the `is_valid()` method for quick validation checking.
661///
662/// ## Python Bindings
663///
664/// When compiled with the `pyo3` feature, this struct provides Python bindings:
665/// ```python
666/// from ri import RiFrame, RiFrameType
667///
668/// # Create a data frame
669/// frame = RiFrame.data_frame(
670/// data=b"Hello, Ri Protocol!",
671/// sequence_number=1
672/// )
673///
674/// # Serialize for transmission
675/// frame_bytes = frame.to_bytes()
676/// print(f"Frame size: {len(frame_bytes)} bytes")
677///
678/// # Access frame properties
679/// print(f"Frame type: {frame.frame_type()}")
680/// print(f"Sequence: {frame.sequence_number()}")
681/// print(f"Timestamp: {frame.timestamp()}")
682/// print(f"Valid: {frame.is_valid()}")
683///
684/// # Deserialize received frame
685/// received = RiFrame.from_bytes(frame_bytes)
686/// assert received.payload == b"Hello, Ri Protocol!"
687/// ```
688///
689/// # Examples
690///
691/// Creating and serializing a data frame:
692/// ```rust,ignore
693/// use ri::protocol::frames::{RiFrame, RiFrameType};
694///
695/// let frame = RiFrame::data_frame(
696/// b"Hello, World!".to_vec(),
697/// 42
698/// ).expect("Failed to create frame");
699///
700/// let bytes = frame.to_bytes().expect("Failed to serialize frame");
701/// println!("Frame serialized to {} bytes", bytes.len());
702///
703/// assert!(frame.is_valid());
704/// assert_eq!(frame.sequence_number(), 42);
705/// ```
706///
707/// Creating different frame types:
708/// ```rust,ignore
709/// use ri::protocol::frames::{RiFrame, RiFrameType};
710///
711/// // Control frame with command data
712/// let control = RiFrame::control_frame(
713/// vec![0x01, 0x02, 0x03],
714/// 1
715/// ).expect("Failed to create control frame");
716///
717/// // Authentication frame with credentials
718/// let auth = RiFrame::auth_frame(
719/// b"token=abc123".to_vec(),
720/// 2
721/// ).expect("Failed to create auth frame");
722///
723/// // Keep-alive frame (no payload)
724/// let keepalive = RiFrame::keepalive_frame(3)
725/// .expect("Failed to create keepalive frame");
726///
727/// // Error frame with code and message
728/// let error = RiFrame::error_frame(
729/// 0x0401,
730/// "Connection timeout".to_string(),
731/// 4
732/// ).expect("Failed to create error frame");
733/// ```
734///
735/// Receiving and deserializing frames:
736/// ```rust,ignore
737/// use ri::protocol::frames::{RiFrame, RiFrameType};
738///
739/// let original = RiFrame::data_frame(
740/// b"Received data".to_vec(),
741/// 100
742/// ).expect("Failed to create frame");
743///
744/// let bytes = original.to_bytes().expect("Failed to serialize");
745///
746/// // Simulate network transmission
747/// let received = RiFrame::from_bytes(&bytes)
748/// .expect("Failed to deserialize frame");
749///
750/// assert_eq!(received.sequence_number(), 100);
751/// assert_eq!(received.payload, b"Received data");
752/// assert!(received.is_valid());
753/// ```
754#[derive(Debug, Clone)]
755#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
756pub struct RiFrame {
757 /// Frame header containing protocol metadata.
758 ///
759 /// The header provides essential information for frame processing including
760 /// the frame type, sequence number, timestamp, and integrity checksum.
761 /// It is always exactly 32 bytes in size and uses big-endian byte ordering.
762 pub header: RiFrameHeader,
763
764 /// Frame payload containing application data.
765 ///
766 /// The payload contains the actual data being transmitted. Its meaning
767 /// depends on the frame type:
768 /// - **Control**: Protocol management commands
769 /// - **Data**: Application-level message data
770 /// - **Auth**: Authentication credentials or tokens
771 /// - **KeepAlive**: Empty (no payload)
772 /// - **Error**: Error code + error message
773 /// - **Encrypted**: Pre-encrypted application data
774 pub payload: Vec<u8>,
775}
776
777impl RiFrame {
778 /// Create a new frame
779 pub fn new(frame_type: RiFrameType, payload: Vec<u8>, sequence_number: u32) -> RiResult<Self> {
780 let header = RiFrameHeader::new(frame_type, payload.len() as u32, sequence_number)?;
781 Ok(Self { header, payload })
782 }
783
784 /// Create a control frame
785 pub fn control_frame(control_data: Vec<u8>, sequence_number: u32) -> RiResult<Self> {
786 Self::new(RiFrameType::Control, control_data, sequence_number)
787 }
788
789 /// Create a data frame
790 pub fn data_frame(data: Vec<u8>, sequence_number: u32) -> RiResult<Self> {
791 Self::new(RiFrameType::Data, data, sequence_number)
792 }
793
794 /// Create an authentication frame
795 pub fn auth_frame(auth_data: Vec<u8>, sequence_number: u32) -> RiResult<Self> {
796 Self::new(RiFrameType::Auth, auth_data, sequence_number)
797 }
798
799 /// Create a keep-alive frame
800 pub fn keepalive_frame(sequence_number: u32) -> RiResult<Self> {
801 Self::new(RiFrameType::KeepAlive, vec![], sequence_number)
802 }
803
804 /// Create an error frame
805 pub fn error_frame(error_code: u32, error_message: String, sequence_number: u32) -> RiResult<Self> {
806 let mut payload = Vec::with_capacity(4 + error_message.len());
807 payload.extend_from_slice(&error_code.to_be_bytes());
808 payload.extend_from_slice(error_message.as_bytes());
809 Self::new(RiFrameType::Error, payload, sequence_number)
810 }
811
812 /// Serialize frame to bytes
813 pub fn to_bytes(&self) -> RiResult<Vec<u8>> {
814 let mut header = self.header.clone();
815
816 // Calculate and set checksum
817 header.checksum = header.calculate_checksum(&self.payload);
818
819 let mut result = Vec::with_capacity(32 + self.payload.len());
820 result.extend_from_slice(&header.to_bytes());
821 result.extend_from_slice(&self.payload);
822
823 Ok(result)
824 }
825
826 /// Deserialize frame from bytes
827 pub fn from_bytes(bytes: &[u8]) -> RiResult<Self> {
828 if bytes.len() < 32 {
829 return Err(RiError::FrameError("Frame too short".to_string()));
830 }
831
832 let header = RiFrameHeader::from_bytes(&bytes[0..32])?;
833
834 // Verify magic number
835 if header.magic != RiFrameHeader::MAGIC {
836 return Err(RiError::FrameError(format!("Invalid magic number: 0x{:08X}", header.magic)));
837 }
838
839 // Verify version
840 if header.version != RiFrameHeader::VERSION {
841 return Err(RiError::FrameError(format!("Unsupported version: {}", header.version)));
842 }
843
844 // Security: Check payload length limit to prevent memory exhaustion
845 if header.payload_length > RiFrameHeader::MAX_PAYLOAD_LENGTH {
846 return Err(RiError::FrameError(format!(
847 "Payload length {} exceeds maximum allowed {}",
848 header.payload_length, RiFrameHeader::MAX_PAYLOAD_LENGTH
849 )));
850 }
851
852 // Check payload length
853 if bytes.len() < 32 + header.payload_length as usize {
854 return Err(RiError::FrameError("Incomplete frame".to_string()));
855 }
856
857 let payload = bytes[32..32 + header.payload_length as usize].to_vec();
858
859 // Verify checksum
860 if !header.verify_checksum(&payload) {
861 return Err(RiError::FrameError("Checksum verification failed".to_string()));
862 }
863
864 Ok(Self { header, payload })
865 }
866
867 /// Get frame type
868 pub fn frame_type(&self) -> Option<RiFrameType> {
869 RiFrameType::from_u8(self.header.frame_type)
870 }
871
872 /// Get sequence number
873 pub fn sequence_number(&self) -> u32 {
874 self.header.sequence_number
875 }
876
877 /// Get timestamp
878 pub fn timestamp(&self) -> u64 {
879 self.header.timestamp
880 }
881
882 /// Check if frame is valid
883 pub fn is_valid(&self) -> bool {
884 self.header.magic == RiFrameHeader::MAGIC &&
885 self.header.version == RiFrameHeader::VERSION &&
886 self.header.verify_checksum(&self.payload)
887 }
888}
889
890/// Frame parser for reading and assembling protocol frames from stream data.
891///
892/// The RiFrameParser handles the incremental parsing of frame data from network
893/// streams or byte sources. Network protocols often deliver data in chunks that
894/// may not align with protocol frame boundaries. This parser accumulates incoming
895/// data in an internal buffer and extracts complete frames when sufficient data
896/// is available. It also manages sequence number validation to ensure frame
897/// ordering integrity.
898///
899/// ## Parser Operation Model
900///
901/// ```
902/// Incoming Data: [partial][complete][partial][complete][partial]
903/// | | | |
904/// v v v v
905/// Parser Buffer: [======][==========][=========][=======]
906/// | | |
907/// v v v
908/// Extracted: [Frame1] [Frame2] [Frame3]
909/// ```
910///
911/// ## Sequence Number Validation
912///
913/// The parser maintains an expected sequence number counter. Each extracted frame
914/// must have a sequence number matching the expected value. This detects missing
915/// frames (gaps in sequence numbers) which may indicate packet loss. Use
916/// `reset_sequence()` to set a new expected sequence number, such as after
917/// reconnection.
918///
919/// ## Buffer Management
920///
921/// The parser maintains an internal buffer that grows as data is added. For
922/// long-running connections, periodically check `buffer_len()` and consider
923/// calling `clear_buffer()` if buffer accumulation indicates parsing issues.
924/// The parser automatically removes parsed data from the buffer.
925///
926/// ## Python Bindings
927///
928/// When compiled with the `pyo3` feature, this struct provides Python bindings:
929/// ```python
930/// from ri import RiFrameParser
931///
932/// # Create parser for incoming stream data
933/// parser = RiFrameParser.new()
934///
935/// # Simulate receiving data chunks
936/// chunks = [
937/// frame1_bytes[:20],
938/// frame1_bytes[20:] + frame2_bytes[:30],
939/// frame2_bytes[30:] + frame3_bytes
940/// ]
941///
942/// for chunk in chunks:
943/// parser.add_data(chunk)
944/// while True:
945/// frame = parser.parse_frame()
946/// if frame is None:
947/// break
948/// print(f"Received frame: {frame.sequence_number()}")
949///
950/// print(f"Buffer contains {parser.buffer_len()} bytes")
951/// ```
952///
953/// # Examples
954///
955/// Basic frame parsing from stream data:
956/// ```rust,ignore
957/// use ri::protocol::frames::{RiFrameParser, RiFrame};
958///
959/// let mut parser = RiFrameParser::new();
960///
961/// // Simulate receiving frame data in chunks
962/// let frame1 = RiFrame::data_frame(b"First message".to_vec(), 0)
963/// .expect("Failed to create frame");
964/// let frame2 = RiFrame::data_frame(b"Second message".to_vec(), 1)
965/// .expect("Failed to create frame");
966///
967/// let bytes1 = frame1.to_bytes().expect("Failed to serialize");
968/// let bytes2 = frame2.to_bytes().expect("Failed to serialize");
969///
970/// // Add first chunk (partial frame)
971/// parser.add_data(&bytes1[..20]);
972/// assert!(parser.parse_frame().unwrap().is_none());
973///
974/// // Add second chunk (completes frame1, starts frame2)
975/// parser.add_data(&bytes1[20..]);
976/// let parsed = parser.parse_frame().unwrap().expect("Should have complete frame");
977/// assert_eq!(parsed.sequence_number(), 0);
978///
979/// // Add remaining data
980/// parser.add_data(&bytes2);
981/// let parsed = parser.parse_frame().unwrap().expect("Should have complete frame");
982/// assert_eq!(parsed.sequence_number(), 1);
983/// ```
984///
985/// Handling sequence number reset:
986/// ```rust,ignore
987/// use ri::protocol::frames::RiFrameParser;
988///
989/// let mut parser = RiFrameParser::new();
990///
991/// // Parse some frames
992/// parser.add_data(&some_data);
993/// while let Ok(Some(frame)) = parser.parse_frame() {
994/// // Process frames
995/// }
996///
997/// // Reset sequence number for new session
998/// parser.reset_sequence();
999/// parser.clear_buffer();
1000///
1001/// // Now expecting sequence 0 again
1002/// assert_eq!(parser.next_sequence, 0);
1003/// ```
1004///
1005/// # Thread Safety
1006///
1007/// This struct is not thread-safe. Multiple threads should not concurrently
1008/// access the same parser instance without external synchronization. For
1009/// concurrent parsing, either use separate parser instances per thread or
1010/// wrap access with a Mutex or RwLock.
1011///
1012/// # Performance Considerations
1013///
1014/// - The parser uses `Vec::extend_from_slice` for efficient buffer appending
1015/// - Frame extraction uses slice operations to avoid unnecessary copying
1016/// - Buffer memory is only reclaimed when frames are successfully parsed
1017/// - Large frames may cause temporary buffer growth; configure appropriate limits
1018#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
1019pub struct RiFrameParser {
1020 /// Internal buffer for accumulating incoming data.
1021 ///
1022 /// The buffer holds bytes that have been received but not yet assembled
1023 /// into complete frames. It grows dynamically as more data arrives.
1024 /// Data is automatically removed from the buffer once successfully parsed.
1025 buffer: Vec<u8>,
1026
1027 /// Next expected sequence number for validation.
1028 ///
1029 /// This counter tracks the sequence number of the next frame expected
1030 /// from the stream. Frames with mismatching sequence numbers indicate
1031 /// potential packet loss or protocol errors.
1032 next_sequence: u32,
1033}
1034
1035impl RiFrameParser {
1036 /// Maximum buffer size (20 MB) to prevent memory exhaustion attacks.
1037 /// This limit prevents attackers from sending endless streams of data
1038 /// that would cause unbounded buffer growth.
1039 const MAX_BUFFER_SIZE: usize = 20 * 1024 * 1024;
1040
1041 pub fn new() -> Self {
1042 Self {
1043 buffer: Vec::new(),
1044 next_sequence: 0,
1045 }
1046 }
1047
1048 /// Add data to the internal buffer for parsing.
1049 ///
1050 /// # Security
1051 ///
1052 /// This method enforces a maximum buffer size to prevent memory exhaustion
1053 /// attacks. If the buffer would exceed MAX_BUFFER_SIZE (20 MB), the data
1054 /// is rejected and an error is returned.
1055 pub fn add_data(&mut self, data: &[u8]) -> RiResult<()> {
1056 // Security: Check buffer size limit to prevent memory exhaustion
1057 let new_size = self.buffer.len().saturating_add(data.len());
1058 if new_size > Self::MAX_BUFFER_SIZE {
1059 log::warn!(
1060 "[Ri.FrameParser] Buffer size limit exceeded: {} bytes (max {} bytes)",
1061 new_size, Self::MAX_BUFFER_SIZE
1062 );
1063 return Err(RiError::FrameError(format!(
1064 "Buffer size limit exceeded: {} bytes (max {} bytes)",
1065 new_size, Self::MAX_BUFFER_SIZE
1066 )));
1067 }
1068
1069 self.buffer.extend_from_slice(data);
1070 Ok(())
1071 }
1072
1073 pub fn parse_frame(&mut self) -> RiResult<Option<RiFrame>> {
1074 if self.buffer.len() < 32 {
1075 return Ok(None);
1076 }
1077
1078 let header = RiFrameHeader::from_bytes(&self.buffer[0..32])?;
1079
1080 // Security: Check payload length limit
1081 if header.payload_length > RiFrameHeader::MAX_PAYLOAD_LENGTH {
1082 // Clear buffer to recover from attack
1083 self.buffer.clear();
1084 return Err(RiError::FrameError(format!(
1085 "Payload length {} exceeds maximum allowed {}",
1086 header.payload_length, RiFrameHeader::MAX_PAYLOAD_LENGTH
1087 )));
1088 }
1089
1090 let total_length = 32usize.saturating_add(header.payload_length as usize);
1091
1092 if self.buffer.len() < total_length {
1093 return Ok(None);
1094 }
1095
1096 let frame_bytes = self.buffer[0..total_length].to_vec();
1097 let frame = RiFrame::from_bytes(&frame_bytes)?;
1098
1099 if frame.header.sequence_number != self.next_sequence {
1100 return Ok(None);
1101 }
1102
1103 self.buffer.drain(0..total_length);
1104 self.next_sequence = self.next_sequence.wrapping_add(1);
1105
1106 Ok(Some(frame))
1107 }
1108
1109 pub fn buffer_len(&self) -> usize {
1110 self.buffer.len()
1111 }
1112
1113 pub fn clear_buffer(&mut self) {
1114 self.buffer.clear();
1115 }
1116
1117 pub fn reset_sequence(&mut self) {
1118 self.next_sequence = 0;
1119 }
1120}
1121
1122/// Frame builder for creating protocol frames with automatic sequence numbering.
1123///
1124/// The RiFrameBuilder provides a convenient interface for constructing Ri frames
1125/// while automatically managing sequence numbers. Rather than manually tracking and
1126/// incrementing sequence numbers for each frame, the builder maintains an internal
1127/// counter that is automatically incremented after each frame construction. This
1128/// ensures proper sequence numbering without the risk of human error.
1129///
1130/// ## Builder Pattern Advantages
1131///
1132/// Using the frame builder provides several benefits over direct frame construction:
1133///
1134/// - **Automatic Sequencing**: No need to manually track and increment sequence numbers
1135/// - **Type Safety**: Compile-time checking of frame type construction
1136/// - **Convenience Methods**: Domain-specific constructors for each frame type
1137/// - **State Management**: Builder maintains state across frame constructions
1138///
1139/// ## Sequence Number Management
1140///
1141/// The builder maintains an internal sequence counter that is automatically incremented
1142/// after each frame construction. The counter uses wrapping arithmetic (modulo 2^32)
1143/// to handle overflow gracefully. You can query or set the current sequence number
1144/// using `next_sequence()` and `set_sequence()` methods.
1145///
1146/// ## Python Bindings
1147///
1148/// When compiled with the `pyo3` feature, this struct provides Python bindings:
1149/// ```python
1150/// from ri import RiFrameBuilder
1151///
1152/// # Create builder for convenient frame construction
1153/// builder = RiFrameBuilder.new()
1154///
1155/// # Build frames without manually tracking sequence numbers
1156/// control_frame = builder.build_control_frame(b"\x01\x02\x03")
1157/// data_frame = builder.build_data_frame(b"Hello, World!")
1158/// auth_frame = builder.build_auth_frame(b"token=abc123")
1159///
1160/// # Check current sequence number
1161/// print(f"Next sequence: {builder.next_sequence()}")
1162///
1163/// # Reset sequence for new session
1164/// builder.set_sequence(0)
1165/// ```
1166///
1167/// # Examples
1168///
1169/// Building multiple frames with automatic sequencing:
1170/// ```rust,ignore
1171/// use ri::protocol::frames::RiFrameBuilder;
1172///
1173/// let mut builder = RiFrameBuilder::new();
1174///
1175/// // Build a series of data frames
1176/// let frame1 = builder.build_data_frame(b"Message 1".to_vec())
1177/// .expect("Failed to build frame");
1178/// let frame2 = builder.build_data_frame(b"Message 2".to_vec())
1179/// .expect("Failed to build frame");
1180/// let frame3 = builder.build_data_frame(b"Message 3".to_vec())
1181/// .expect("Failed to build frame");
1182///
1183/// assert_eq!(frame1.sequence_number(), 0);
1184/// assert_eq!(frame2.sequence_number(), 1);
1185/// assert_eq!(frame3.sequence_number(), 2);
1186///
1187/// // Current sequence is now 3
1188/// assert_eq!(builder.next_sequence(), 3);
1189/// ```
1190///
1191/// Building different frame types:
1192/// ```rust,ignore
1193/// use ri::protocol::frames::RiFrameBuilder;
1194///
1195/// let mut builder = RiFrameBuilder::new();
1196///
1197/// // Control frame
1198/// let control = builder.build_control_frame(vec![0x01, 0x00, 0x01])
1199/// .expect("Failed to build control frame");
1200///
1201/// // Authentication frame
1202/// let auth = builder.build_auth_frame(b"credentials=secret".to_vec())
1203/// .expect("Failed to build auth frame");
1204///
1205/// // Keep-alive frame
1206/// let keepalive = builder.build_keepalive_frame()
1207/// .expect("Failed to build keepalive frame");
1208///
1209/// // Error frame
1210/// let error = builder.build_error_frame(0x0401, "Timeout".to_string())
1211/// .expect("Failed to build error frame");
1212/// ```
1213///
1214/// Managing sequence numbers:
1215/// ```rust,ignore
1216/// use ri::protocol::frames::RiFrameBuilder;
1217///
1218/// let mut builder = RiFrameBuilder::new();
1219///
1220/// // Build some frames
1221/// let _ = builder.build_data_frame(b"Frame 0".to_vec()).unwrap();
1222/// let _ = builder.build_data_frame(b"Frame 1".to_vec()).unwrap();
1223/// let _ = builder.build_data_frame(b"Frame 2".to_vec()).unwrap();
1224///
1225/// // Check current sequence
1226/// assert_eq!(builder.next_sequence(), 3);
1227///
1228/// // Set specific sequence for resend or new session
1229/// builder.set_sequence(100);
1230///
1231/// let next = builder.build_data_frame(b"Frame 100".to_vec()).unwrap();
1232/// assert_eq!(next.sequence_number(), 100);
1233/// assert_eq!(builder.next_sequence(), 101);
1234/// ```
1235///
1236/// # Thread Safety
1237///
1238/// This struct is not thread-safe. Multiple threads should not concurrently
1239/// access the same builder instance without external synchronization. For
1240/// concurrent frame building, either use separate builder instances per thread
1241/// or wrap access with a Mutex or RwLock.
1242///
1243/// # Performance Characteristics
1244///
1245/// - Frame construction is O(1) for fixed-size headers
1246/// - Payload copying is O(n) where n is payload size
1247/// - Sequence number operations are O(1)
1248/// - Minimal heap allocation for small payloads
1249#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
1250pub struct RiFrameBuilder {
1251 /// Internal counter for automatic sequence number generation.
1252 ///
1253 /// This counter tracks the sequence number to assign to the next frame
1254 /// constructed by the builder. It is automatically incremented after
1255 /// each frame construction using wrapping arithmetic.
1256 next_sequence: u32,
1257}
1258
1259impl RiFrameBuilder {
1260 pub fn new() -> Self {
1261 Self { next_sequence: 0 }
1262 }
1263
1264 pub fn build_control_frame(&mut self, control_data: Vec<u8>) -> RiResult<RiFrame> {
1265 let frame = RiFrame::control_frame(control_data, self.next_sequence)?;
1266 self.next_sequence = self.next_sequence.wrapping_add(1);
1267 Ok(frame)
1268 }
1269
1270 pub fn build_data_frame(&mut self, data: Vec<u8>) -> RiResult<RiFrame> {
1271 let frame = RiFrame::data_frame(data, self.next_sequence)?;
1272 self.next_sequence = self.next_sequence.wrapping_add(1);
1273 Ok(frame)
1274 }
1275
1276 pub fn build_auth_frame(&mut self, auth_data: Vec<u8>) -> RiResult<RiFrame> {
1277 let frame = RiFrame::auth_frame(auth_data, self.next_sequence)?;
1278 self.next_sequence = self.next_sequence.wrapping_add(1);
1279 Ok(frame)
1280 }
1281
1282 pub fn build_keepalive_frame(&mut self) -> RiResult<RiFrame> {
1283 let frame = RiFrame::keepalive_frame(self.next_sequence)?;
1284 self.next_sequence = self.next_sequence.wrapping_add(1);
1285 Ok(frame)
1286 }
1287
1288 pub fn build_error_frame(&mut self, error_code: u32, error_message: String) -> RiResult<RiFrame> {
1289 let frame = RiFrame::error_frame(error_code, error_message, self.next_sequence)?;
1290 self.next_sequence = self.next_sequence.wrapping_add(1);
1291 Ok(frame)
1292 }
1293
1294 pub fn next_sequence(&self) -> u32 {
1295 self.next_sequence
1296 }
1297
1298 pub fn set_sequence(&mut self, sequence: u32) {
1299 self.next_sequence = sequence;
1300 }
1301}
1302
1303