Skip to main content

bacnet_rs/app/
mod.rs

1//! BACnet Application Layer Module
2//!
3//! This module implements the application layer functionality for BACnet communication.
4//! The application layer is responsible for forming and processing Application Protocol
5//! Data Units (APDUs) that carry BACnet services.
6//!
7//! # Overview
8//!
9//! The application layer handles:
10//! - APDU formation and parsing
11//! - Service request/response handling
12//! - Segmentation of large messages
13//! - Transaction management
14//! - Error and reject PDU processing
15//!
16//! # APDU Types
17//!
18//! - Confirmed Request PDU
19//! - Unconfirmed Request PDU
20//! - SimpleACK PDU
21//! - ComplexACK PDU
22//! - SegmentACK PDU
23//! - Error PDU
24//! - Reject PDU
25//! - Abort PDU
26//!
27//! # Example
28//!
29//! ```no_run
30//! use bacnet_rs::app::*;
31//! use bacnet_rs::service::UnconfirmedServiceChoice;
32//!
33//! // Example of creating an APDU
34//! let apdu = Apdu::UnconfirmedRequest {
35//!     service_choice: UnconfirmedServiceChoice::WhoIs,
36//!     service_data: vec![],
37//! };
38//! ```
39
40#[cfg(feature = "std")]
41use std::error::Error;
42
43#[cfg(feature = "std")]
44use std::{fmt, time::Duration};
45
46#[cfg(not(feature = "std"))]
47use core::fmt;
48
49#[cfg(not(feature = "std"))]
50use alloc::{string::String, vec::Vec};
51
52#[cfg(not(feature = "std"))]
53use core::time::Duration;
54
55use crate::encoding::{decode_enumerated, encode_enumerated};
56use crate::object::Segmentation;
57use crate::service::{AbortReason, ConfirmedServiceChoice, RejectReason, UnconfirmedServiceChoice};
58
59/// Result type for application layer operations
60#[cfg(feature = "std")]
61pub type Result<T> = std::result::Result<T, ApplicationError>;
62
63#[cfg(not(feature = "std"))]
64pub type Result<T> = core::result::Result<T, ApplicationError>;
65
66/// Errors that can occur in application layer operations
67#[derive(Debug)]
68pub enum ApplicationError {
69    /// Invalid APDU format
70    InvalidApdu(String),
71    /// Unsupported APDU type
72    UnsupportedApduType,
73    /// Segmentation error
74    SegmentationError(String),
75    /// Transaction error
76    TransactionError(String),
77    /// Service error
78    ServiceError(String),
79    /// Timeout waiting for response
80    Timeout,
81    /// Maximum APDU length exceeded
82    MaxApduLengthExceeded,
83}
84
85impl fmt::Display for ApplicationError {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match self {
88            ApplicationError::InvalidApdu(msg) => write!(f, "Invalid APDU: {}", msg),
89            ApplicationError::UnsupportedApduType => write!(f, "Unsupported APDU type"),
90            ApplicationError::SegmentationError(msg) => write!(f, "Segmentation error: {}", msg),
91            ApplicationError::TransactionError(msg) => write!(f, "Transaction error: {}", msg),
92            ApplicationError::ServiceError(msg) => write!(f, "Service error: {}", msg),
93            ApplicationError::Timeout => write!(f, "Application timeout"),
94            ApplicationError::MaxApduLengthExceeded => write!(f, "Maximum APDU length exceeded"),
95        }
96    }
97}
98
99#[cfg(feature = "std")]
100impl Error for ApplicationError {}
101
102/// APDU types
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104#[repr(u8)]
105pub enum ApduType {
106    ConfirmedRequest = 0,
107    UnconfirmedRequest = 1,
108    SimpleAck = 2,
109    ComplexAck = 3,
110    SegmentAck = 4,
111    Error = 5,
112    Reject = 6,
113    Abort = 7,
114}
115
116/// Application Protocol Data Unit
117#[derive(Debug, Clone)]
118pub enum Apdu {
119    /// Confirmed service request
120    ConfirmedRequest {
121        segmented: bool,
122        more_follows: bool,
123        segmented_response_accepted: bool,
124        max_segments: MaxSegments,
125        max_response_size: MaxApduSize,
126        invoke_id: u8,
127        sequence_number: Option<u8>,
128        proposed_window_size: Option<u8>,
129        service_choice: ConfirmedServiceChoice,
130        service_data: Vec<u8>,
131    },
132
133    /// Unconfirmed service request
134    UnconfirmedRequest {
135        service_choice: UnconfirmedServiceChoice,
136        service_data: Vec<u8>,
137    },
138
139    /// Simple acknowledgment
140    SimpleAck { invoke_id: u8, service_choice: u8 },
141
142    /// Complex acknowledgment
143    ComplexAck {
144        segmented: bool,
145        more_follows: bool,
146        invoke_id: u8,
147        sequence_number: Option<u8>,
148        proposed_window_size: Option<u8>,
149        service_choice: ConfirmedServiceChoice,
150        service_data: Vec<u8>,
151    },
152
153    /// Segment acknowledgment
154    SegmentAck {
155        negative: bool,
156        server: bool,
157        invoke_id: u8,
158        sequence_number: u8,
159        window_size: u8,
160    },
161
162    /// Error PDU
163    Error {
164        invoke_id: u8,
165        service_choice: ConfirmedServiceChoice,
166        error_class: u8,
167        error_code: u8,
168    },
169
170    /// Reject PDU
171    Reject {
172        invoke_id: u8,
173        reject_reason: RejectReason,
174    },
175
176    /// Abort PDU
177    Abort {
178        server: bool,
179        invoke_id: u8,
180        abort_reason: u8,
181    },
182}
183
184/// Maximum segments that can be accepted
185#[derive(Debug, Clone, Copy, PartialEq, Eq)]
186pub enum MaxSegments {
187    Unspecified = 0,
188    Two = 1,
189    Four = 2,
190    Eight = 3,
191    Sixteen = 4,
192    ThirtyTwo = 5,
193    SixtyFour = 6,
194    GreaterThan64 = 7,
195}
196
197/// Maximum APDU size that can be accepted
198#[derive(Debug, Clone, Copy, PartialEq, Eq)]
199pub enum MaxApduSize {
200    Up50 = 0,
201    Up128 = 1,
202    Up206 = 2,
203    Up480 = 3,
204    Up1024 = 4,
205    Up1476 = 5,
206}
207
208impl MaxApduSize {
209    /// Get the actual size in bytes
210    pub fn size(&self) -> usize {
211        match self {
212            MaxApduSize::Up50 => 50,
213            MaxApduSize::Up128 => 128,
214            MaxApduSize::Up206 => 206,
215            MaxApduSize::Up480 => 480,
216            MaxApduSize::Up1024 => 1024,
217            MaxApduSize::Up1476 => 1476,
218        }
219    }
220}
221
222/// Transaction state for confirmed services
223#[derive(Debug, Clone)]
224pub struct Transaction {
225    /// Invoke ID
226    pub invoke_id: u8,
227    /// Service being invoked
228    pub service: u8,
229    /// Current state
230    pub state: TransactionState,
231    /// Timeout for this transaction
232    pub timeout: Duration,
233    /// Retry count
234    pub retries: u8,
235}
236
237/// Transaction states
238#[derive(Debug, Clone, Copy, PartialEq, Eq)]
239pub enum TransactionState {
240    /// Waiting for response
241    AwaitConfirmation,
242    /// Waiting for segment
243    AwaitSegment,
244    /// Segmented request in progress
245    SegmentedRequest,
246    /// Segmented response in progress
247    SegmentedResponse,
248    /// Transaction complete
249    Complete,
250}
251
252impl Apdu {
253    /// Encode APDU to bytes
254    pub fn encode(&self) -> Vec<u8> {
255        let mut buffer = Vec::new();
256
257        match self {
258            Apdu::ConfirmedRequest {
259                segmented,
260                more_follows,
261                segmented_response_accepted,
262                max_segments,
263                max_response_size,
264                invoke_id,
265                sequence_number,
266                proposed_window_size,
267                service_choice,
268                service_data,
269            } => {
270                // PDU Type and flags
271                let mut pdu_type = (ApduType::ConfirmedRequest as u8) << 4;
272                if *segmented {
273                    pdu_type |= 0x08;
274                }
275                if *more_follows {
276                    pdu_type |= 0x04;
277                }
278                if *segmented_response_accepted {
279                    pdu_type |= 0x02;
280                }
281                buffer.push(pdu_type);
282
283                // Max segments and APDU size
284                let max_info = ((*max_segments as u8) << 4) | (*max_response_size as u8);
285                buffer.push(max_info);
286
287                // Invoke ID
288                buffer.push(*invoke_id);
289
290                // Sequence number and window size (if segmented)
291                if *segmented {
292                    if let Some(seq_num) = sequence_number {
293                        buffer.push(*seq_num);
294                    }
295                    if let Some(window_size) = proposed_window_size {
296                        buffer.push(*window_size);
297                    }
298                }
299
300                // Service choice
301                buffer.push(*service_choice as u8);
302
303                // Service data
304                buffer.extend_from_slice(service_data);
305            }
306
307            Apdu::UnconfirmedRequest {
308                service_choice,
309                service_data,
310            } => {
311                // PDU Type
312                buffer.push((ApduType::UnconfirmedRequest as u8) << 4);
313                // Service choice
314                buffer.push(*service_choice as u8);
315                // Service data
316                buffer.extend_from_slice(service_data);
317            }
318
319            Apdu::SimpleAck {
320                invoke_id,
321                service_choice,
322            } => {
323                // PDU Type
324                buffer.push((ApduType::SimpleAck as u8) << 4);
325                // Invoke ID
326                buffer.push(*invoke_id);
327                // Service choice
328                buffer.push(*service_choice);
329            }
330
331            Apdu::ComplexAck {
332                segmented,
333                more_follows,
334                invoke_id,
335                sequence_number,
336                proposed_window_size,
337                service_choice,
338                service_data,
339            } => {
340                // PDU Type and flags
341                let mut pdu_type = (ApduType::ComplexAck as u8) << 4;
342                if *segmented {
343                    pdu_type |= 0x08;
344                }
345                if *more_follows {
346                    pdu_type |= 0x04;
347                }
348                buffer.push(pdu_type);
349
350                // Invoke ID
351                buffer.push(*invoke_id);
352
353                // Sequence number and window size (if segmented)
354                if *segmented {
355                    if let Some(seq_num) = sequence_number {
356                        buffer.push(*seq_num);
357                    }
358                    if let Some(window_size) = proposed_window_size {
359                        buffer.push(*window_size);
360                    }
361                }
362
363                // Service choice
364                buffer.push(*service_choice as u8);
365
366                // Service data
367                buffer.extend_from_slice(service_data);
368            }
369
370            Apdu::SegmentAck {
371                negative,
372                server,
373                invoke_id,
374                sequence_number,
375                window_size,
376            } => {
377                // PDU Type and flags
378                let mut pdu_type = (ApduType::SegmentAck as u8) << 4;
379                if *negative {
380                    pdu_type |= 0x02;
381                }
382                if *server {
383                    pdu_type |= 0x01;
384                }
385                buffer.push(pdu_type);
386
387                // Invoke ID
388                buffer.push(*invoke_id);
389                // Sequence number
390                buffer.push(*sequence_number);
391                // Window size
392                buffer.push(*window_size);
393            }
394
395            Apdu::Error {
396                invoke_id,
397                service_choice,
398                error_class,
399                error_code,
400            } => {
401                // PDU Type
402                buffer.push((ApduType::Error as u8) << 4);
403                // Invoke ID
404                buffer.push(*invoke_id);
405                // Service choice
406                buffer.push(*service_choice as u8);
407                encode_enumerated(&mut buffer, *error_class as u32);
408                encode_enumerated(&mut buffer, *error_code as u32);
409            }
410
411            Apdu::Reject {
412                invoke_id,
413                reject_reason,
414            } => {
415                // PDU Type
416                buffer.push((ApduType::Reject as u8) << 4);
417                // Invoke ID
418                buffer.push(*invoke_id);
419                // Reject reason
420                buffer.push(u8::from(*reject_reason));
421            }
422
423            Apdu::Abort {
424                server,
425                invoke_id,
426                abort_reason,
427            } => {
428                // PDU Type and flags
429                let mut pdu_type = (ApduType::Abort as u8) << 4;
430                if *server {
431                    pdu_type |= 0x01;
432                }
433                buffer.push(pdu_type);
434
435                // Invoke ID
436                buffer.push(*invoke_id);
437                // Abort reason
438                buffer.push(*abort_reason);
439            }
440        }
441
442        buffer
443    }
444
445    /// Decode APDU from bytes
446    pub fn decode(data: &[u8]) -> Result<Self> {
447        if data.is_empty() {
448            return Err(ApplicationError::InvalidApdu("Empty APDU".to_string()));
449        }
450
451        let pdu_type_byte = data[0];
452        let pdu_type_raw = (pdu_type_byte >> 4) & 0x0F;
453        let pdu_type = match pdu_type_raw {
454            0 => ApduType::ConfirmedRequest,
455            1 => ApduType::UnconfirmedRequest,
456            2 => ApduType::SimpleAck,
457            3 => ApduType::ComplexAck,
458            4 => ApduType::SegmentAck,
459            5 => ApduType::Error,
460            6 => ApduType::Reject,
461            7 => ApduType::Abort,
462            _ => return Err(ApplicationError::UnsupportedApduType),
463        };
464
465        match pdu_type {
466            ApduType::ConfirmedRequest => {
467                if data.len() < 4 {
468                    return Err(ApplicationError::InvalidApdu(
469                        "Confirmed request too short".to_string(),
470                    ));
471                }
472
473                let segmented = (pdu_type_byte & 0x08) != 0;
474                let more_follows = (pdu_type_byte & 0x04) != 0;
475                let segmented_response_accepted = (pdu_type_byte & 0x02) != 0;
476
477                let max_info = data[1];
478                let max_segments = match (max_info >> 4) & 0x07 {
479                    0 => MaxSegments::Unspecified,
480                    1 => MaxSegments::Two,
481                    2 => MaxSegments::Four,
482                    3 => MaxSegments::Eight,
483                    4 => MaxSegments::Sixteen,
484                    5 => MaxSegments::ThirtyTwo,
485                    6 => MaxSegments::SixtyFour,
486                    7 => MaxSegments::GreaterThan64,
487                    _ => MaxSegments::Unspecified,
488                };
489
490                let max_response_size = match max_info & 0x0F {
491                    0 => MaxApduSize::Up50,
492                    1 => MaxApduSize::Up128,
493                    2 => MaxApduSize::Up206,
494                    3 => MaxApduSize::Up480,
495                    4 => MaxApduSize::Up1024,
496                    5 => MaxApduSize::Up1476,
497                    _ => MaxApduSize::Up50,
498                };
499
500                let invoke_id = data[2];
501                let mut pos = 3;
502
503                let (sequence_number, proposed_window_size) = if segmented {
504                    let seq_num = if pos < data.len() {
505                        Some(data[pos])
506                    } else {
507                        None
508                    };
509                    pos += 1;
510                    let win_size = if pos < data.len() {
511                        Some(data[pos])
512                    } else {
513                        None
514                    };
515                    pos += 1;
516                    (seq_num, win_size)
517                } else {
518                    (None, None)
519                };
520
521                if pos >= data.len() {
522                    return Err(ApplicationError::InvalidApdu(
523                        "Missing service choice".to_string(),
524                    ));
525                }
526
527                let service_choice = data[pos].try_into().map_err(|_| {
528                    ApplicationError::InvalidApdu("Unknown confirmed service choice".to_string())
529                })?;
530                pos += 1;
531
532                let service_data = if pos < data.len() {
533                    data[pos..].to_vec()
534                } else {
535                    Vec::new()
536                };
537
538                Ok(Apdu::ConfirmedRequest {
539                    segmented,
540                    more_follows,
541                    segmented_response_accepted,
542                    max_segments,
543                    max_response_size,
544                    invoke_id,
545                    sequence_number,
546                    proposed_window_size,
547                    service_choice,
548                    service_data,
549                })
550            }
551
552            ApduType::UnconfirmedRequest => {
553                if data.len() < 2 {
554                    return Err(ApplicationError::InvalidApdu(
555                        "Unconfirmed request too short".to_string(),
556                    ));
557                }
558
559                let service_choice = data[1];
560                let service_data = if data.len() > 2 {
561                    data[2..].to_vec()
562                } else {
563                    Vec::new()
564                };
565
566                Ok(Apdu::UnconfirmedRequest {
567                    service_choice: service_choice.try_into().map_err(|_| {
568                        ApplicationError::InvalidApdu(
569                            "Unknown unconfirmed service choice".to_string(),
570                        )
571                    })?,
572                    service_data,
573                })
574            }
575
576            ApduType::SimpleAck => {
577                if data.len() < 3 {
578                    return Err(ApplicationError::InvalidApdu(
579                        "SimpleAck too short".to_string(),
580                    ));
581                }
582
583                let invoke_id = data[1];
584                let service_choice = data[2];
585
586                Ok(Apdu::SimpleAck {
587                    invoke_id,
588                    service_choice,
589                })
590            }
591
592            ApduType::ComplexAck => {
593                if data.len() < 3 {
594                    return Err(ApplicationError::InvalidApdu(
595                        "ComplexAck too short".to_string(),
596                    ));
597                }
598
599                let segmented = (pdu_type_byte & 0x08) != 0;
600                let more_follows = (pdu_type_byte & 0x04) != 0;
601
602                let invoke_id = data[1];
603                let mut pos = 2;
604
605                let (sequence_number, proposed_window_size) = if segmented {
606                    let seq_num = if pos < data.len() {
607                        Some(data[pos])
608                    } else {
609                        None
610                    };
611                    pos += 1;
612                    let win_size = if pos < data.len() {
613                        Some(data[pos])
614                    } else {
615                        None
616                    };
617                    pos += 1;
618                    (seq_num, win_size)
619                } else {
620                    (None, None)
621                };
622
623                if pos >= data.len() {
624                    return Err(ApplicationError::InvalidApdu(
625                        "Missing service choice".to_string(),
626                    ));
627                }
628
629                let service_choice = data[pos].try_into().map_err(|_| {
630                    ApplicationError::InvalidApdu("Unknown confirmed service choice".to_string())
631                })?;
632                pos += 1;
633
634                let service_data = if pos < data.len() {
635                    data[pos..].to_vec()
636                } else {
637                    Vec::new()
638                };
639
640                Ok(Apdu::ComplexAck {
641                    segmented,
642                    more_follows,
643                    invoke_id,
644                    sequence_number,
645                    proposed_window_size,
646                    service_choice,
647                    service_data,
648                })
649            }
650
651            ApduType::SegmentAck => {
652                if data.len() < 4 {
653                    return Err(ApplicationError::InvalidApdu(
654                        "SegmentAck too short".to_string(),
655                    ));
656                }
657
658                let negative = (pdu_type_byte & 0x02) != 0;
659                let server = (pdu_type_byte & 0x01) != 0;
660                let invoke_id = data[1];
661                let sequence_number = data[2];
662                let window_size = data[3];
663
664                Ok(Apdu::SegmentAck {
665                    negative,
666                    server,
667                    invoke_id,
668                    sequence_number,
669                    window_size,
670                })
671            }
672
673            ApduType::Error => {
674                if data.len() < 5 {
675                    return Err(ApplicationError::InvalidApdu(
676                        "Error PDU too short".to_string(),
677                    ));
678                }
679
680                let invoke_id = data[1];
681                let mut pos = 2;
682                let service_choice = data[pos].try_into().map_err(|_| {
683                    ApplicationError::InvalidApdu("Unknown confirmed service choice".to_string())
684                })?;
685                pos += 1;
686                let (error_class, offset) = decode_enumerated(&data[pos..]).map_err(|_| {
687                    ApplicationError::InvalidApdu("Invalid error class".to_string())
688                })?;
689                pos += offset;
690                let (error_code, _) = decode_enumerated(&data[pos..])
691                    .map_err(|_| ApplicationError::InvalidApdu("Invalid error code".to_string()))?;
692
693                Ok(Apdu::Error {
694                    invoke_id,
695                    service_choice,
696                    error_class: error_class as u8,
697                    error_code: error_code as u8,
698                })
699            }
700
701            ApduType::Reject => {
702                if data.len() < 3 {
703                    return Err(ApplicationError::InvalidApdu(
704                        "Reject PDU too short".to_string(),
705                    ));
706                }
707
708                let invoke_id = data[1];
709                let reject_reason = data[2];
710
711                Ok(Apdu::Reject {
712                    invoke_id,
713                    reject_reason: reject_reason.into(),
714                })
715            }
716
717            ApduType::Abort => {
718                if data.len() < 3 {
719                    return Err(ApplicationError::InvalidApdu(
720                        "Abort PDU too short".to_string(),
721                    ));
722                }
723
724                let server = (pdu_type_byte & 0x01) != 0;
725                let invoke_id = data[1];
726                let abort_reason = data[2];
727
728                Ok(Apdu::Abort {
729                    server,
730                    invoke_id,
731                    abort_reason,
732                })
733            }
734        }
735    }
736}
737
738/// Invoke ID manager for handling transaction IDs
739#[derive(Debug)]
740pub struct InvokeIdManager {
741    next_id: u8,
742    active_ids: Vec<u8>,
743}
744
745impl InvokeIdManager {
746    /// Create a new invoke ID manager
747    pub fn new() -> Self {
748        Self {
749            next_id: 0,
750            active_ids: Vec::new(),
751        }
752    }
753
754    /// Get the next available invoke ID
755    pub fn next_id(&mut self) -> Option<u8> {
756        let start_id = self.next_id;
757
758        loop {
759            if !self.active_ids.contains(&self.next_id) {
760                let id = self.next_id;
761                self.active_ids.push(id);
762                self.next_id = self.next_id.wrapping_add(1);
763                return Some(id);
764            }
765
766            self.next_id = self.next_id.wrapping_add(1);
767
768            // Prevent infinite loop
769            if self.next_id == start_id {
770                return None;
771            }
772        }
773    }
774
775    /// Release an invoke ID
776    pub fn release_id(&mut self, id: u8) {
777        self.active_ids.retain(|&x| x != id);
778    }
779
780    /// Check if an invoke ID is active
781    pub fn is_active(&self, id: u8) -> bool {
782        self.active_ids.contains(&id)
783    }
784}
785
786impl Default for InvokeIdManager {
787    fn default() -> Self {
788        Self::new()
789    }
790}
791
792/// Segmentation information for large APDUs
793#[derive(Debug, Clone, PartialEq, Eq)]
794pub struct SegmentationInfo {
795    /// More follows flag
796    pub more_follows: bool,
797    /// Segmented response accepted flag
798    pub segmented_response_accepted: bool,
799    /// Maximum segments accepted (0 = unspecified, 2-127)
800    pub max_segments_accepted: u8,
801    /// Maximum APDU length accepted
802    pub max_apdu_length_accepted: u16,
803    /// Sequence number (0-255)
804    pub sequence_number: u8,
805    /// Proposed window size (1-127)
806    pub proposed_window_size: u8,
807}
808
809impl SegmentationInfo {
810    /// Create new segmentation info
811    pub fn new(
812        more_follows: bool,
813        segmented_response_accepted: bool,
814        max_segments_accepted: u8,
815        max_apdu_length_accepted: u16,
816        sequence_number: u8,
817        proposed_window_size: u8,
818    ) -> Self {
819        Self {
820            more_follows,
821            segmented_response_accepted,
822            max_segments_accepted,
823            max_apdu_length_accepted,
824            sequence_number,
825            proposed_window_size,
826        }
827    }
828
829    /// Check if this is the first segment
830    pub fn is_first_segment(&self) -> bool {
831        self.sequence_number == 0
832    }
833
834    /// Check if this is the last segment
835    pub fn is_last_segment(&self) -> bool {
836        !self.more_follows
837    }
838
839    /// Calculate the maximum segment size based on max APDU length
840    pub fn max_segment_size(&self) -> usize {
841        // Account for APDU header overhead (typically 4-6 bytes)
842        (self.max_apdu_length_accepted as usize).saturating_sub(6)
843    }
844}
845
846/// Segment reassembly buffer for incoming segmented messages
847#[derive(Debug)]
848pub struct SegmentReassemblyBuffer {
849    /// Invoke ID of the segmented message
850    pub invoke_id: u8,
851    /// Expected total segments (if known)
852    pub total_segments: Option<u8>,
853    /// Received segments (sequence number -> data)
854    pub segments: Vec<(u8, Vec<u8>)>,
855    /// Maximum APDU length
856    pub max_apdu_length: u16,
857    /// Timestamp of last received segment (for timeout handling)
858    #[cfg(feature = "std")]
859    pub last_activity: std::time::Instant,
860}
861
862impl SegmentReassemblyBuffer {
863    /// Create a new reassembly buffer
864    pub fn new(invoke_id: u8, max_apdu_length: u16) -> Self {
865        Self {
866            invoke_id,
867            total_segments: None,
868            segments: Vec::new(),
869            max_apdu_length,
870            #[cfg(feature = "std")]
871            last_activity: std::time::Instant::now(),
872        }
873    }
874
875    /// Add a segment to the buffer
876    pub fn add_segment(&mut self, sequence_number: u8, data: Vec<u8>, is_last: bool) -> Result<()> {
877        // Update activity timestamp
878        #[cfg(feature = "std")]
879        {
880            self.last_activity = std::time::Instant::now();
881        }
882
883        // If this is the last segment, we know the total count
884        if is_last {
885            self.total_segments = Some(sequence_number + 1);
886        }
887
888        // Check for duplicate segments
889        if self.segments.iter().any(|(seq, _)| *seq == sequence_number) {
890            return Ok(()); // Ignore duplicates
891        }
892
893        // Add the segment
894        self.segments.push((sequence_number, data));
895
896        // Sort segments by sequence number
897        self.segments.sort_by_key(|(seq, _)| *seq);
898
899        Ok(())
900    }
901
902    /// Check if all segments have been received
903    pub fn is_complete(&self) -> bool {
904        if let Some(total) = self.total_segments {
905            self.segments.len() == total as usize
906                && self
907                    .segments
908                    .iter()
909                    .enumerate()
910                    .all(|(i, (seq, _))| *seq == i as u8)
911        } else {
912            false
913        }
914    }
915
916    /// Reassemble the complete message
917    pub fn reassemble(&self) -> Result<Vec<u8>> {
918        if !self.is_complete() {
919            return Err(ApplicationError::SegmentationError(
920                "Incomplete segments".to_string(),
921            ));
922        }
923
924        let mut result = Vec::new();
925        for (_, data) in &self.segments {
926            result.extend_from_slice(data);
927        }
928
929        if result.len() > self.max_apdu_length as usize {
930            return Err(ApplicationError::MaxApduLengthExceeded);
931        }
932
933        Ok(result)
934    }
935
936    /// Get missing segment numbers
937    pub fn missing_segments(&self) -> Vec<u8> {
938        if let Some(total) = self.total_segments {
939            let mut missing = Vec::new();
940            for i in 0..total {
941                if !self.segments.iter().any(|(seq, _)| *seq == i) {
942                    missing.push(i);
943                }
944            }
945            missing
946        } else {
947            Vec::new()
948        }
949    }
950
951    /// Check if the buffer has timed out
952    #[cfg(feature = "std")]
953    pub fn is_timed_out(&self, timeout_duration: std::time::Duration) -> bool {
954        self.last_activity.elapsed() > timeout_duration
955    }
956}
957
958/// Segmentation manager for handling message segmentation
959#[derive(Debug)]
960pub struct SegmentationManager {
961    /// Reassembly buffers for incoming segmented messages
962    reassembly_buffers: Vec<SegmentReassemblyBuffer>,
963    /// Maximum number of concurrent reassembly operations
964    max_concurrent_reassemblies: usize,
965    /// Segment timeout duration
966    #[cfg(feature = "std")]
967    segment_timeout: std::time::Duration,
968}
969
970impl SegmentationManager {
971    /// Create a new segmentation manager
972    pub fn new() -> Self {
973        Self {
974            reassembly_buffers: Vec::new(),
975            max_concurrent_reassemblies: 16,
976            #[cfg(feature = "std")]
977            segment_timeout: std::time::Duration::from_secs(60),
978        }
979    }
980
981    /// Split a large message into segments
982    pub fn segment_message(
983        &self,
984        data: &[u8],
985        max_segment_size: usize,
986        max_segments: u8,
987    ) -> Result<Vec<Vec<u8>>> {
988        if data.is_empty() {
989            return Ok(vec![Vec::new()]);
990        }
991
992        let segment_count = data.len().div_ceil(max_segment_size);
993
994        if segment_count > max_segments as usize {
995            return Err(ApplicationError::SegmentationError(
996                "Message too large for segmentation".to_string(),
997            ));
998        }
999
1000        let mut segments = Vec::new();
1001        let mut offset = 0;
1002
1003        for _ in 0..segment_count {
1004            let end = (offset + max_segment_size).min(data.len());
1005            segments.push(data[offset..end].to_vec());
1006            offset = end;
1007        }
1008
1009        Ok(segments)
1010    }
1011
1012    /// Process an incoming segment
1013    pub fn process_segment(
1014        &mut self,
1015        invoke_id: u8,
1016        sequence_number: u8,
1017        data: Vec<u8>,
1018        more_follows: bool,
1019        max_apdu_length: u16,
1020    ) -> Result<Option<Vec<u8>>> {
1021        // Find or create reassembly buffer
1022        let buffer_index = self
1023            .reassembly_buffers
1024            .iter()
1025            .position(|buffer| buffer.invoke_id == invoke_id);
1026
1027        let buffer = if let Some(index) = buffer_index {
1028            &mut self.reassembly_buffers[index]
1029        } else {
1030            // Create new buffer if we have capacity
1031            if self.reassembly_buffers.len() >= self.max_concurrent_reassemblies {
1032                // Remove oldest buffer
1033                self.cleanup_oldest_buffer();
1034            }
1035
1036            self.reassembly_buffers
1037                .push(SegmentReassemblyBuffer::new(invoke_id, max_apdu_length));
1038            self.reassembly_buffers.last_mut().unwrap()
1039        };
1040
1041        // Add the segment
1042        buffer.add_segment(sequence_number, data, !more_follows)?;
1043
1044        // Check if reassembly is complete
1045        if buffer.is_complete() {
1046            let result = buffer.reassemble()?;
1047            // Remove the completed buffer
1048            self.reassembly_buffers.retain(|b| b.invoke_id != invoke_id);
1049            Ok(Some(result))
1050        } else {
1051            Ok(None)
1052        }
1053    }
1054
1055    /// Get missing segments for a reassembly operation
1056    pub fn get_missing_segments(&self, invoke_id: u8) -> Vec<u8> {
1057        self.reassembly_buffers
1058            .iter()
1059            .find(|buffer| buffer.invoke_id == invoke_id)
1060            .map(|buffer| buffer.missing_segments())
1061            .unwrap_or_default()
1062    }
1063
1064    /// Cleanup timed out reassembly buffers
1065    #[cfg(feature = "std")]
1066    pub fn cleanup_timed_out_buffers(&mut self) {
1067        self.reassembly_buffers
1068            .retain(|buffer| !buffer.is_timed_out(self.segment_timeout));
1069    }
1070
1071    /// Remove the oldest reassembly buffer
1072    fn cleanup_oldest_buffer(&mut self) {
1073        if !self.reassembly_buffers.is_empty() {
1074            #[cfg(feature = "std")]
1075            {
1076                // Find the buffer with the oldest last_activity
1077                let oldest_index = self
1078                    .reassembly_buffers
1079                    .iter()
1080                    .enumerate()
1081                    .min_by_key(|(_, buffer)| buffer.last_activity)
1082                    .map(|(index, _)| index)
1083                    .unwrap_or(0);
1084                self.reassembly_buffers.remove(oldest_index);
1085            }
1086            #[cfg(not(feature = "std"))]
1087            {
1088                // Without std, just remove the first buffer
1089                self.reassembly_buffers.remove(0);
1090            }
1091        }
1092    }
1093
1094    /// Set the segment timeout duration
1095    #[cfg(feature = "std")]
1096    pub fn set_segment_timeout(&mut self, timeout: std::time::Duration) {
1097        self.segment_timeout = timeout;
1098    }
1099
1100    /// Get the number of active reassembly operations
1101    pub fn active_reassemblies(&self) -> usize {
1102        self.reassembly_buffers.len()
1103    }
1104}
1105
1106impl Default for SegmentationManager {
1107    fn default() -> Self {
1108        Self::new()
1109    }
1110}
1111
1112/// Application layer service handler
1113#[derive(Debug)]
1114pub struct ApplicationLayerHandler {
1115    /// Device instance for this application
1116    _device_instance: u32,
1117    /// Supported services
1118    supported_services: SupportedServices,
1119    /// Transaction manager
1120    transaction_manager: TransactionManager,
1121    /// Service processors
1122    service_processors: ServiceProcessors,
1123    /// Application statistics
1124    pub stats: ApplicationStatistics,
1125}
1126
1127/// Supported services configuration
1128#[derive(Debug, Clone)]
1129pub struct SupportedServices {
1130    /// Confirmed services
1131    pub confirmed: Vec<ConfirmedServiceChoice>,
1132    /// Unconfirmed services
1133    pub unconfirmed: Vec<UnconfirmedServiceChoice>,
1134}
1135
1136impl Default for SupportedServices {
1137    fn default() -> Self {
1138        Self {
1139            confirmed: vec![
1140                ConfirmedServiceChoice::ReadProperty,
1141                ConfirmedServiceChoice::WriteProperty,
1142                ConfirmedServiceChoice::ReadPropertyMultiple,
1143                ConfirmedServiceChoice::SubscribeCOV,
1144            ],
1145            unconfirmed: vec![
1146                UnconfirmedServiceChoice::WhoIs,
1147                UnconfirmedServiceChoice::IAm,
1148                UnconfirmedServiceChoice::UnconfirmedEventNotification,
1149            ],
1150        }
1151    }
1152}
1153
1154/// Type alias for service processor function
1155type ServiceProcessor = Box<dyn Fn(&[u8]) -> Result<Vec<u8>> + Send + Sync>;
1156
1157/// Type alias for optional service processor function
1158type OptionalServiceProcessor = Box<dyn Fn(&[u8]) -> Result<Option<Vec<u8>>> + Send + Sync>;
1159
1160/// Service processors for handling different service types
1161#[derive(Default)]
1162struct ServiceProcessors {
1163    /// Read property processor
1164    read_property: Option<ServiceProcessor>,
1165    /// Write property processor
1166    write_property: Option<ServiceProcessor>,
1167    /// Who-Is processor
1168    who_is: Option<OptionalServiceProcessor>,
1169}
1170
1171impl fmt::Debug for ServiceProcessors {
1172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1173        f.debug_struct("ServiceProcessors")
1174            .field("read_property", &self.read_property.is_some())
1175            .field("write_property", &self.write_property.is_some())
1176            .field("who_is", &self.who_is.is_some())
1177            .finish()
1178    }
1179}
1180
1181impl ApplicationLayerHandler {
1182    /// Create a new application layer handler
1183    pub fn new(device_instance: u32) -> Self {
1184        Self {
1185            _device_instance: device_instance,
1186            supported_services: SupportedServices::default(),
1187            transaction_manager: TransactionManager::new(),
1188            service_processors: ServiceProcessors::default(),
1189            stats: ApplicationStatistics::default(),
1190        }
1191    }
1192
1193    /// Process an incoming APDU
1194    pub fn process_apdu(&mut self, apdu: &Apdu, _source: &[u8]) -> Result<Option<Apdu>> {
1195        self.stats.apdus_received += 1;
1196
1197        match apdu {
1198            Apdu::ConfirmedRequest {
1199                segmented,
1200                more_follows,
1201                segmented_response_accepted,
1202                max_segments: _,
1203                max_response_size: _,
1204                invoke_id,
1205                sequence_number: _,
1206                proposed_window_size: _,
1207                service_choice,
1208                service_data,
1209            } => {
1210                let pdu_flags = PduFlags {
1211                    segmented: *segmented,
1212                    more_follows: *more_follows,
1213                    segmented_response_accepted: *segmented_response_accepted,
1214                };
1215                self.process_confirmed_request(pdu_flags, *invoke_id, *service_choice, service_data)
1216            }
1217            Apdu::UnconfirmedRequest {
1218                service_choice,
1219                service_data,
1220            } => self.process_unconfirmed_request(*service_choice, service_data),
1221            Apdu::SimpleAck {
1222                invoke_id,
1223                service_choice,
1224            } => self.process_simple_ack(*invoke_id, *service_choice),
1225            Apdu::ComplexAck {
1226                segmented,
1227                more_follows,
1228                invoke_id,
1229                sequence_number: _,
1230                proposed_window_size: _,
1231                service_choice,
1232                service_data,
1233            } => {
1234                let pdu_flags = PduFlags {
1235                    segmented: *segmented,
1236                    more_follows: *more_follows,
1237                    segmented_response_accepted: false,
1238                };
1239                self.process_complex_ack(pdu_flags, *invoke_id, *service_choice, service_data)
1240            }
1241            Apdu::Error {
1242                invoke_id,
1243                service_choice,
1244                error_class,
1245                error_code,
1246            } => self.process_error(*invoke_id, *service_choice, *error_class, *error_code),
1247            Apdu::Reject {
1248                invoke_id,
1249                reject_reason,
1250            } => self.process_reject(*invoke_id, *reject_reason),
1251            Apdu::Abort {
1252                server,
1253                invoke_id,
1254                abort_reason,
1255            } => self.process_abort(*server, *invoke_id, *abort_reason),
1256            _ => {
1257                self.stats.unknown_apdus += 1;
1258                Err(ApplicationError::UnsupportedApduType)
1259            }
1260        }
1261    }
1262
1263    /// Process a confirmed request
1264    fn process_confirmed_request(
1265        &mut self,
1266        _pdu_flags: PduFlags,
1267        invoke_id: u8,
1268        service_choice: ConfirmedServiceChoice,
1269        service_data: &[u8],
1270    ) -> Result<Option<Apdu>> {
1271        self.stats.confirmed_requests += 1;
1272
1273        if !self.supported_services.confirmed.contains(&service_choice) {
1274            return Ok(Some(Apdu::Reject {
1275                invoke_id,
1276                reject_reason: RejectReason::UnrecognizedService,
1277            }));
1278        }
1279
1280        // Process based on service type
1281        match service_choice {
1282            ConfirmedServiceChoice::ReadProperty => {
1283                if let Some(ref processor) = self.service_processors.read_property {
1284                    match processor(service_data) {
1285                        Ok(response_data) => Ok(Some(Apdu::ComplexAck {
1286                            segmented: false,
1287                            more_follows: false,
1288                            invoke_id,
1289                            sequence_number: None,
1290                            proposed_window_size: None,
1291                            service_choice,
1292                            service_data: response_data,
1293                        })),
1294                        Err(_) => {
1295                            Ok(Some(Apdu::Error {
1296                                invoke_id,
1297                                service_choice,
1298                                error_class: 0, // Object
1299                                error_code: 0,  // Unknown object
1300                            }))
1301                        }
1302                    }
1303                } else {
1304                    Ok(Some(Apdu::Abort {
1305                        server: true,
1306                        invoke_id,
1307                        abort_reason: u8::from(AbortReason::Other),
1308                    }))
1309                }
1310            }
1311            _ => Ok(Some(Apdu::Reject {
1312                invoke_id,
1313                reject_reason: RejectReason::UnrecognizedService,
1314            })),
1315        }
1316    }
1317
1318    /// Process an unconfirmed request
1319    fn process_unconfirmed_request(
1320        &mut self,
1321        service_choice: UnconfirmedServiceChoice,
1322        service_data: &[u8],
1323    ) -> Result<Option<Apdu>> {
1324        self.stats.unconfirmed_requests += 1;
1325
1326        // Unconfirmed requests don't get responses unless it's I-Am for Who-Is
1327        if service_choice == UnconfirmedServiceChoice::WhoIs {
1328            if let Some(ref processor) = self.service_processors.who_is {
1329                if let Ok(Some(response_data)) = processor(service_data) {
1330                    return Ok(Some(Apdu::UnconfirmedRequest {
1331                        service_choice: UnconfirmedServiceChoice::IAm,
1332                        service_data: response_data,
1333                    }));
1334                }
1335            }
1336        }
1337
1338        Ok(None)
1339    }
1340
1341    /// Process a simple ACK
1342    fn process_simple_ack(&mut self, invoke_id: u8, _service_choice: u8) -> Result<Option<Apdu>> {
1343        self.stats.simple_acks += 1;
1344        self.transaction_manager.complete_transaction(invoke_id);
1345        Ok(None)
1346    }
1347
1348    /// Process a complex ACK
1349    fn process_complex_ack(
1350        &mut self,
1351        _pdu_flags: PduFlags,
1352        invoke_id: u8,
1353        _service_choice: ConfirmedServiceChoice,
1354        _service_data: &[u8],
1355    ) -> Result<Option<Apdu>> {
1356        self.stats.complex_acks += 1;
1357        self.transaction_manager.complete_transaction(invoke_id);
1358        Ok(None)
1359    }
1360
1361    /// Process an error PDU
1362    fn process_error(
1363        &mut self,
1364        invoke_id: u8,
1365        _service_choice: ConfirmedServiceChoice,
1366        error_class: u8,
1367        error_code: u8,
1368    ) -> Result<Option<Apdu>> {
1369        self.stats.errors += 1;
1370        self.transaction_manager
1371            .error_transaction(invoke_id, error_class, error_code);
1372        Ok(None)
1373    }
1374
1375    /// Process a reject PDU
1376    fn process_reject(
1377        &mut self,
1378        invoke_id: u8,
1379        reject_reason: RejectReason,
1380    ) -> Result<Option<Apdu>> {
1381        self.stats.rejects += 1;
1382        self.transaction_manager
1383            .reject_transaction(invoke_id, reject_reason);
1384        Ok(None)
1385    }
1386
1387    /// Process an abort PDU
1388    fn process_abort(
1389        &mut self,
1390        _server: bool,
1391        invoke_id: u8,
1392        abort_reason: u8,
1393    ) -> Result<Option<Apdu>> {
1394        self.stats.aborts += 1;
1395        self.transaction_manager
1396            .abort_transaction(invoke_id, abort_reason);
1397        Ok(None)
1398    }
1399
1400    /// Set a service processor
1401    pub fn set_read_property_handler<F>(&mut self, handler: F)
1402    where
1403        F: Fn(&[u8]) -> Result<Vec<u8>> + Send + Sync + 'static,
1404    {
1405        self.service_processors.read_property = Some(Box::new(handler));
1406    }
1407
1408    /// Set Who-Is processor
1409    pub fn set_who_is_handler<F>(&mut self, handler: F)
1410    where
1411        F: Fn(&[u8]) -> Result<Option<Vec<u8>>> + Send + Sync + 'static,
1412    {
1413        self.service_processors.who_is = Some(Box::new(handler));
1414    }
1415}
1416
1417/// Transaction manager for tracking active transactions
1418#[derive(Debug)]
1419pub struct TransactionManager {
1420    /// Active transactions
1421    transactions: Vec<Transaction>,
1422    /// Maximum concurrent transactions
1423    max_transactions: usize,
1424    /// Transaction timeout
1425    #[cfg(feature = "std")]
1426    _timeout: Duration,
1427}
1428
1429impl TransactionManager {
1430    /// Create a new transaction manager
1431    pub fn new() -> Self {
1432        Self {
1433            transactions: Vec::new(),
1434            max_transactions: 255,
1435            #[cfg(feature = "std")]
1436            _timeout: Duration::from_secs(30),
1437        }
1438    }
1439
1440    /// Start a new transaction
1441    pub fn start_transaction(&mut self, invoke_id: u8, service_choice: u8) -> Result<()> {
1442        if self.transactions.len() >= self.max_transactions {
1443            return Err(ApplicationError::TransactionError(
1444                "Too many active transactions".to_string(),
1445            ));
1446        }
1447
1448        // Check for duplicate invoke ID
1449        if self
1450            .transactions
1451            .iter()
1452            .any(|t| t.invoke_id == invoke_id && t.state == TransactionState::AwaitConfirmation)
1453        {
1454            return Err(ApplicationError::TransactionError(
1455                "Duplicate invoke ID".to_string(),
1456            ));
1457        }
1458
1459        self.transactions.push(Transaction {
1460            invoke_id,
1461            service: service_choice,
1462            state: TransactionState::AwaitConfirmation,
1463            timeout: Duration::from_secs(30),
1464            retries: 0,
1465        });
1466
1467        Ok(())
1468    }
1469
1470    /// Complete a transaction
1471    pub fn complete_transaction(&mut self, invoke_id: u8) {
1472        if let Some(transaction) = self
1473            .transactions
1474            .iter_mut()
1475            .find(|t| t.invoke_id == invoke_id)
1476        {
1477            transaction.state = TransactionState::Complete;
1478        }
1479    }
1480
1481    /// Mark transaction as error
1482    pub fn error_transaction(&mut self, invoke_id: u8, _error_class: u8, _error_code: u8) {
1483        if let Some(transaction) = self
1484            .transactions
1485            .iter_mut()
1486            .find(|t| t.invoke_id == invoke_id)
1487        {
1488            transaction.state = TransactionState::Complete;
1489        }
1490    }
1491
1492    /// Mark transaction as rejected
1493    pub fn reject_transaction(&mut self, invoke_id: u8, _reject_reason: RejectReason) {
1494        if let Some(transaction) = self
1495            .transactions
1496            .iter_mut()
1497            .find(|t| t.invoke_id == invoke_id)
1498        {
1499            transaction.state = TransactionState::Complete;
1500        }
1501    }
1502
1503    /// Mark transaction as aborted
1504    pub fn abort_transaction(&mut self, invoke_id: u8, _abort_reason: u8) {
1505        if let Some(transaction) = self
1506            .transactions
1507            .iter_mut()
1508            .find(|t| t.invoke_id == invoke_id)
1509        {
1510            transaction.state = TransactionState::Complete;
1511        }
1512    }
1513
1514    /// Clean up completed transactions
1515    pub fn cleanup_completed(&mut self) {
1516        self.transactions
1517            .retain(|t| t.state != TransactionState::Complete);
1518    }
1519
1520    /// Get active transaction count
1521    pub fn active_count(&self) -> usize {
1522        self.transactions
1523            .iter()
1524            .filter(|t| t.state != TransactionState::Complete)
1525            .count()
1526    }
1527}
1528
1529impl Default for TransactionManager {
1530    fn default() -> Self {
1531        Self::new()
1532    }
1533}
1534
1535/// Application layer statistics
1536#[derive(Debug, Default)]
1537pub struct ApplicationStatistics {
1538    /// Total APDUs received
1539    pub apdus_received: u64,
1540    /// Total APDUs sent
1541    pub apdus_sent: u64,
1542    /// Confirmed requests received
1543    pub confirmed_requests: u64,
1544    /// Unconfirmed requests received
1545    pub unconfirmed_requests: u64,
1546    /// Simple ACKs received
1547    pub simple_acks: u64,
1548    /// Complex ACKs received
1549    pub complex_acks: u64,
1550    /// Errors received
1551    pub errors: u64,
1552    /// Rejects received
1553    pub rejects: u64,
1554    /// Aborts received
1555    pub aborts: u64,
1556    /// Unknown APDU types
1557    pub unknown_apdus: u64,
1558    /// Segmentation errors
1559    pub segmentation_errors: u64,
1560}
1561
1562/// Priority queue for application messages
1563#[derive(Debug)]
1564pub struct ApplicationPriorityQueue {
1565    /// High priority queue
1566    high: Vec<QueuedMessage>,
1567    /// Normal priority queue
1568    normal: Vec<QueuedMessage>,
1569    /// Low priority queue
1570    low: Vec<QueuedMessage>,
1571    /// Maximum queue size per priority
1572    max_queue_size: usize,
1573}
1574
1575/// Queued message
1576#[derive(Debug)]
1577struct QueuedMessage {
1578    /// APDU to send
1579    apdu: Apdu,
1580    /// Destination address
1581    destination: Vec<u8>,
1582    /// Timestamp
1583    #[cfg(feature = "std")]
1584    _timestamp: std::time::Instant,
1585    /// Retry count
1586    _retry_count: u8,
1587}
1588
1589impl ApplicationPriorityQueue {
1590    /// Create a new priority queue
1591    pub fn new(max_queue_size: usize) -> Self {
1592        Self {
1593            high: Vec::with_capacity(max_queue_size),
1594            normal: Vec::with_capacity(max_queue_size),
1595            low: Vec::with_capacity(max_queue_size),
1596            max_queue_size,
1597        }
1598    }
1599
1600    /// Queue a message
1601    pub fn enqueue(
1602        &mut self,
1603        apdu: Apdu,
1604        destination: Vec<u8>,
1605        priority: MessagePriority,
1606    ) -> Result<()> {
1607        let queue = match priority {
1608            MessagePriority::High => &mut self.high,
1609            MessagePriority::Normal => &mut self.normal,
1610            MessagePriority::Low => &mut self.low,
1611        };
1612
1613        if queue.len() >= self.max_queue_size {
1614            return Err(ApplicationError::TransactionError("Queue full".to_string()));
1615        }
1616
1617        queue.push(QueuedMessage {
1618            apdu,
1619            destination,
1620            #[cfg(feature = "std")]
1621            _timestamp: std::time::Instant::now(),
1622            _retry_count: 0,
1623        });
1624
1625        Ok(())
1626    }
1627
1628    /// Dequeue next message
1629    pub fn dequeue(&mut self) -> Option<(Apdu, Vec<u8>)> {
1630        if let Some(msg) = self.high.pop() {
1631            return Some((msg.apdu, msg.destination));
1632        }
1633        if let Some(msg) = self.normal.pop() {
1634            return Some((msg.apdu, msg.destination));
1635        }
1636        if let Some(msg) = self.low.pop() {
1637            return Some((msg.apdu, msg.destination));
1638        }
1639        None
1640    }
1641
1642    /// Get total queued messages
1643    pub fn total_queued(&self) -> usize {
1644        self.high.len() + self.normal.len() + self.low.len()
1645    }
1646
1647    /// Clear all queues
1648    pub fn clear(&mut self) {
1649        self.high.clear();
1650        self.normal.clear();
1651        self.low.clear();
1652    }
1653}
1654
1655/// Message priority levels
1656#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1657pub enum MessagePriority {
1658    /// High priority (alarms, life safety)
1659    High,
1660    /// Normal priority (most messages)
1661    Normal,
1662    /// Low priority (non-critical)
1663    Low,
1664}
1665
1666/// PDU flags for segmentation control
1667#[derive(Debug, Clone, Copy, Default)]
1668pub struct PduFlags {
1669    /// Segmented message
1670    pub segmented: bool,
1671    /// More segments follow
1672    pub more_follows: bool,
1673    /// Segmented response accepted
1674    pub segmented_response_accepted: bool,
1675}
1676
1677/// Application layer configuration
1678#[derive(Debug, Clone)]
1679pub struct ApplicationConfig {
1680    /// Maximum APDU length
1681    pub max_apdu_length: u16,
1682    /// Segmentation support
1683    pub segmentation: Segmentation,
1684    /// APDU timeout (milliseconds)
1685    pub apdu_timeout: u16,
1686    /// Number of APDU retries
1687    pub apdu_retries: u8,
1688    /// Maximum segments accepted
1689    pub max_segments: u8,
1690    /// Invoke ID start value
1691    pub invoke_id_start: u8,
1692}
1693
1694impl Default for ApplicationConfig {
1695    fn default() -> Self {
1696        Self {
1697            max_apdu_length: 1476,
1698            segmentation: Segmentation::Both,
1699            apdu_timeout: 6000,
1700            apdu_retries: 3,
1701            max_segments: 64,
1702            invoke_id_start: 0,
1703        }
1704    }
1705}
1706
1707#[cfg(test)]
1708mod tests {
1709    use super::*;
1710
1711    #[test]
1712    fn test_unconfirmed_request_encode_decode() {
1713        let apdu = Apdu::UnconfirmedRequest {
1714            service_choice: UnconfirmedServiceChoice::WhoIs, // WhoIs
1715            service_data: vec![0x08, 0x7B, 0x18, 0x7B],      // Range 123-123
1716        };
1717
1718        let encoded = apdu.encode();
1719        let decoded = Apdu::decode(&encoded).unwrap();
1720
1721        match decoded {
1722            Apdu::UnconfirmedRequest {
1723                service_choice,
1724                service_data,
1725            } => {
1726                assert_eq!(service_choice, UnconfirmedServiceChoice::WhoIs);
1727                assert_eq!(service_data, vec![0x08, 0x7B, 0x18, 0x7B]);
1728            }
1729            _ => panic!("Expected UnconfirmedRequest"),
1730        }
1731    }
1732
1733    #[test]
1734    fn test_simple_ack_encode_decode() {
1735        let apdu = Apdu::SimpleAck {
1736            invoke_id: 42,
1737            service_choice: 12, // ReadProperty
1738        };
1739
1740        let encoded = apdu.encode();
1741        let decoded = Apdu::decode(&encoded).unwrap();
1742
1743        match decoded {
1744            Apdu::SimpleAck {
1745                invoke_id,
1746                service_choice,
1747            } => {
1748                assert_eq!(invoke_id, 42);
1749                assert_eq!(service_choice, 12);
1750            }
1751            _ => panic!("Expected SimpleAck"),
1752        }
1753    }
1754
1755    #[test]
1756    fn test_confirmed_request_encode_decode() {
1757        let apdu = Apdu::ConfirmedRequest {
1758            segmented: false,
1759            more_follows: false,
1760            segmented_response_accepted: true,
1761            max_segments: MaxSegments::Unspecified,
1762            max_response_size: MaxApduSize::Up1476,
1763            invoke_id: 123,
1764            sequence_number: None,
1765            proposed_window_size: None,
1766            service_choice: ConfirmedServiceChoice::ReadProperty, // ReadProperty
1767            service_data: vec![0x0C, 0x02, 0x00, 0x00, 0x08, 0x19, 0x55],
1768        };
1769
1770        let encoded = apdu.encode();
1771        let decoded = Apdu::decode(&encoded).unwrap();
1772
1773        match decoded {
1774            Apdu::ConfirmedRequest {
1775                invoke_id,
1776                service_choice,
1777                segmented_response_accepted,
1778                ..
1779            } => {
1780                assert_eq!(invoke_id, 123);
1781                assert_eq!(service_choice, ConfirmedServiceChoice::ReadProperty);
1782                assert!(segmented_response_accepted);
1783            }
1784            _ => panic!("Expected ConfirmedRequest"),
1785        }
1786    }
1787
1788    #[test]
1789    fn test_invoke_id_manager() {
1790        let mut manager = InvokeIdManager::new();
1791
1792        // Get some IDs
1793        let id1 = manager.next_id().unwrap();
1794        let id2 = manager.next_id().unwrap();
1795        let id3 = manager.next_id().unwrap();
1796
1797        assert_ne!(id1, id2);
1798        assert_ne!(id2, id3);
1799        assert_ne!(id1, id3);
1800
1801        // Check if they're active
1802        assert!(manager.is_active(id1));
1803        assert!(manager.is_active(id2));
1804        assert!(manager.is_active(id3));
1805
1806        // Release one
1807        manager.release_id(id2);
1808        assert!(!manager.is_active(id2));
1809        assert!(manager.is_active(id1));
1810        assert!(manager.is_active(id3));
1811    }
1812
1813    #[test]
1814    fn test_max_apdu_size() {
1815        assert_eq!(MaxApduSize::Up50.size(), 50);
1816        assert_eq!(MaxApduSize::Up128.size(), 128);
1817        assert_eq!(MaxApduSize::Up1476.size(), 1476);
1818    }
1819
1820    #[test]
1821    fn test_segmentation_info() {
1822        let seg_info = SegmentationInfo::new(
1823            true, // more_follows
1824            true, // segmented_response_accepted
1825            64,   // max_segments_accepted
1826            1476, // max_apdu_length_accepted
1827            5,    // sequence_number
1828            10,   // proposed_window_size
1829        );
1830
1831        assert!(seg_info.more_follows);
1832        assert!(seg_info.segmented_response_accepted);
1833        assert_eq!(seg_info.max_segments_accepted, 64);
1834        assert_eq!(seg_info.max_apdu_length_accepted, 1476);
1835        assert_eq!(seg_info.sequence_number, 5);
1836        assert_eq!(seg_info.proposed_window_size, 10);
1837
1838        assert!(!seg_info.is_first_segment());
1839        assert!(!seg_info.is_last_segment());
1840        assert_eq!(seg_info.max_segment_size(), 1470); // 1476 - 6 bytes overhead
1841
1842        // Test first segment
1843        let first_seg = SegmentationInfo::new(false, true, 32, 1024, 0, 8);
1844        assert!(first_seg.is_first_segment());
1845        assert!(first_seg.is_last_segment()); // more_follows is false
1846
1847        // Test last segment
1848        let last_seg = SegmentationInfo::new(false, true, 16, 480, 3, 5);
1849        assert!(!last_seg.is_first_segment());
1850        assert!(last_seg.is_last_segment());
1851    }
1852
1853    #[test]
1854    fn test_segment_reassembly_buffer() {
1855        let mut buffer = SegmentReassemblyBuffer::new(42, 1024);
1856        assert_eq!(buffer.invoke_id, 42);
1857        assert_eq!(buffer.max_apdu_length, 1024);
1858        assert!(!buffer.is_complete());
1859        assert_eq!(buffer.missing_segments(), Vec::<u8>::new());
1860
1861        // Add segments
1862        buffer.add_segment(0, vec![1, 2, 3], false).unwrap();
1863        buffer.add_segment(1, vec![4, 5, 6], false).unwrap();
1864        buffer.add_segment(2, vec![7, 8, 9], true).unwrap(); // Last segment
1865
1866        assert!(buffer.is_complete());
1867        assert_eq!(buffer.total_segments, Some(3));
1868
1869        // Test reassembly
1870        let reassembled = buffer.reassemble().unwrap();
1871        assert_eq!(reassembled, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
1872
1873        // Test missing segments with incomplete buffer
1874        let mut incomplete_buffer = SegmentReassemblyBuffer::new(43, 1024);
1875        incomplete_buffer.add_segment(0, vec![1, 2], false).unwrap();
1876        incomplete_buffer.add_segment(2, vec![5, 6], true).unwrap(); // Missing segment 1
1877
1878        assert!(!incomplete_buffer.is_complete());
1879        assert_eq!(incomplete_buffer.missing_segments(), vec![1]);
1880    }
1881
1882    #[test]
1883    fn test_segmentation_manager() {
1884        let mut manager = SegmentationManager::new();
1885        assert_eq!(manager.active_reassemblies(), 0);
1886
1887        // Test message segmentation
1888        let large_data = vec![0u8; 100]; // 100 bytes of data
1889        let segments = manager.segment_message(&large_data, 30, 10).unwrap();
1890        assert_eq!(segments.len(), 4); // 100 / 30 = 3.33, rounded up to 4
1891        assert_eq!(segments[0].len(), 30);
1892        assert_eq!(segments[1].len(), 30);
1893        assert_eq!(segments[2].len(), 30);
1894        assert_eq!(segments[3].len(), 10); // Remaining 10 bytes
1895
1896        // Test segment processing
1897        let invoke_id = 100;
1898        let max_apdu = 1024;
1899
1900        // Process first segment
1901        let result1 = manager
1902            .process_segment(invoke_id, 0, vec![1, 2, 3], true, max_apdu)
1903            .unwrap();
1904        assert!(result1.is_none()); // Not complete yet
1905        assert_eq!(manager.active_reassemblies(), 1);
1906
1907        // Process second segment
1908        let result2 = manager
1909            .process_segment(invoke_id, 1, vec![4, 5, 6], false, max_apdu)
1910            .unwrap();
1911        assert!(result2.is_some()); // Complete!
1912        assert_eq!(result2.unwrap(), vec![1, 2, 3, 4, 5, 6]);
1913        assert_eq!(manager.active_reassemblies(), 0); // Buffer was removed
1914
1915        // Test missing segments query
1916        manager
1917            .process_segment(200, 0, vec![10, 20], true, max_apdu)
1918            .unwrap();
1919        manager
1920            .process_segment(200, 2, vec![50, 60], false, max_apdu)
1921            .unwrap();
1922        let missing = manager.get_missing_segments(200);
1923        assert_eq!(missing, vec![1]);
1924    }
1925
1926    #[test]
1927    fn test_segmentation_error_cases() {
1928        let manager = SegmentationManager::new();
1929
1930        // Test message too large for segmentation
1931        let huge_data = vec![0u8; 1000];
1932        let result = manager.segment_message(&huge_data, 100, 5); // Only 5 segments allowed
1933        assert!(result.is_err());
1934        match result.unwrap_err() {
1935            ApplicationError::SegmentationError(msg) => {
1936                assert!(msg.contains("too large"));
1937            }
1938            _ => panic!("Expected SegmentationError"),
1939        }
1940
1941        // Test reassembling incomplete segments
1942        let mut buffer = SegmentReassemblyBuffer::new(1, 100);
1943        buffer.add_segment(0, vec![1, 2], false).unwrap();
1944        // Missing segment 1, but we don't know total count yet
1945        let result = buffer.reassemble();
1946        assert!(result.is_err());
1947        match result.unwrap_err() {
1948            ApplicationError::SegmentationError(msg) => {
1949                assert!(msg.contains("Incomplete"));
1950            }
1951            _ => panic!("Expected SegmentationError"),
1952        }
1953    }
1954
1955    #[test]
1956    fn test_segmentation_duplicate_handling() {
1957        let mut buffer = SegmentReassemblyBuffer::new(1, 1024);
1958
1959        // Add segment 0
1960        buffer.add_segment(0, vec![1, 2, 3], false).unwrap();
1961        assert_eq!(buffer.segments.len(), 1);
1962
1963        // Add duplicate segment 0 (should be ignored)
1964        buffer.add_segment(0, vec![4, 5, 6], false).unwrap();
1965        assert_eq!(buffer.segments.len(), 1);
1966        assert_eq!(buffer.segments[0].1, vec![1, 2, 3]); // Original data preserved
1967
1968        // Add segment 1 as last
1969        buffer.add_segment(1, vec![7, 8, 9], true).unwrap();
1970        assert_eq!(buffer.segments.len(), 2);
1971        assert!(buffer.is_complete());
1972
1973        let reassembled = buffer.reassemble().unwrap();
1974        assert_eq!(reassembled, vec![1, 2, 3, 7, 8, 9]);
1975    }
1976}