Skip to main content

acex_server/
server.rs

1// region: Imports
2
3use acex_core::Vec;
4use acex_proto::uds::UdsFrame;
5use acex_sim::clock::{Duration, Instant};
6use acex_sim::io::NodeAddress;
7use acex_uds::ext::UdsFrameExt;
8use acex_uds::message::service::UdsServiceRequest;
9use acex_uds::message::{DiagnosticSessionType, ServiceIdentifier};
10
11use crate::config::{periodic, ServerConfig, SessionConfig};
12use crate::handler::ServerHandler;
13use crate::nrc::NrcError;
14use crate::security_provider::SecurityProvider;
15
16// endregion: Imports
17
18// region: ServerError
19
20#[derive(Debug)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub enum ServerError<E: NrcError> {
23    Handler(E),
24    Codec(acex_uds::error::UdsError),
25    OutboxFull,
26}
27
28// endregion: ServerError
29
30// region: SessionState
31
32#[derive(Debug, Clone)]
33#[cfg_attr(feature = "defmt", derive(defmt::Format))]
34pub struct SessionState {
35    session_type: u8,
36    last_rx: Instant,
37    security_level: u8,
38}
39
40impl PartialEq for SessionState {
41    fn eq(&self, other: &Self) -> bool {
42        self.session_type == other.session_type
43            && self.security_level == other.security_level
44    }
45}
46
47impl SessionState {
48    fn new(session_type: u8) -> Self {
49        Self {
50            session_type,
51            last_rx: Instant::ZERO,
52            security_level: 0,
53        }
54    }
55
56    pub const fn is_default(&self) -> bool {
57        self.session_type == 0x01
58    }
59
60    pub const fn is_programming(&self) -> bool {
61        self.session_type == 0x02
62    }
63
64    pub const fn is_extended(&self) -> bool {
65        self.session_type == 0x03
66    }
67
68    pub const fn get_session_type(&self) -> u8 {
69        self.session_type
70    }
71
72    pub const fn get_last_rx(&self) -> Instant {
73        self.last_rx
74    }
75
76    pub const fn get_security_level(&self) -> u8 {
77        self.security_level
78    }
79}
80
81// endregion: SessionState
82
83// region: SecurityState
84
85#[derive(Debug, Clone)]
86#[cfg_attr(all(feature = "defmt", not(feature = "alloc")), derive(defmt::Format))]
87struct SecurityState<const MAX_SEED: usize, const MAX_SECURITY_LEVELS: usize> {
88    pending_seed: Vec<u8, MAX_SEED>,
89    pending_level: u8,
90    failed_attempts: Vec<(u8, u8), MAX_SECURITY_LEVELS>,
91    lockout_until: Vec<(u8, Instant), MAX_SECURITY_LEVELS>,
92}
93
94impl<
95    const MAX_SEED: usize,
96    const MAX_SECURITY_LEVELS: usize
97> SecurityState<
98    MAX_SEED,
99    MAX_SECURITY_LEVELS
100> {
101    fn new() -> Self {
102        Self {
103            pending_seed: Vec::new(),
104            pending_level: 0,
105            failed_attempts: Vec::new(),
106            lockout_until: Vec::new(),
107        }
108    }
109
110    fn is_locked(&self, level: u8, now: Instant) -> bool {
111        self.lockout_until
112            .iter()
113            .find(|(l, _)| *l == level)
114            .map(|(_, until)| now < *until)
115            .unwrap_or(false)
116    }
117
118    fn failed_count(&self, level: u8) -> u8 {
119        self.failed_attempts
120            .iter()
121            .find(|(l, _)| *l == level)
122            .map(|(_, c)| *c)
123            .unwrap_or(0)
124    }
125
126    fn increment_failed(&mut self, level: u8) {
127        if let Some(e) = self.failed_attempts.iter_mut().find(|(l, _)| *l == level) {
128            e.1 = e.1.saturating_add(1);
129        } else {
130            #[cfg(all(feature = "defmt", not(feature = "alloc")))]
131            defmt::unwrap!(self.failed_attempts.push((level, 1))); // unlikely
132
133            #[cfg(feature = "alloc")]
134            self.failed_attempts.push((level, 1));
135        }
136    }
137
138    fn reset_failed(&mut self, level: u8) {
139        if let Some(e) = self.failed_attempts.iter_mut().find(|(l, _)| *l == level) {
140            e.1 = 0;
141        }
142    }
143
144    fn set_lockout(&mut self, level: u8, until: Instant) {
145        if let Some(e) = self.lockout_until.iter_mut().find(|(l, _)| *l == level) {
146            e.1 = until;
147        } else {
148            #[cfg(all(feature = "defmt", not(feature = "alloc")))]
149            defmt::unwrap!(self.lockout_until.push((level, until))); // unlikely
150
151            #[cfg(feature = "alloc")]
152            self.lockout_until.push((level, until));
153        }
154    }
155
156    fn clear_pending(&mut self) {
157        self.pending_seed.clear();
158        self.pending_level = 0;
159    }
160
161    fn reset(&mut self) {
162        self.lockout_until.clear();
163        self.pending_seed.clear();
164        self.failed_attempts.clear();
165        self.pending_level = 0 ;
166    }
167}
168
169// endregion: SecurityState
170
171// region: PeriodicEntry / PeriodicState
172
173#[derive(Debug, Clone)]
174#[cfg_attr(feature = "defmt", derive(defmt::Format))]
175struct PeriodicEntry {
176    did: u16,
177    interval: Duration,
178    next_tx: Instant,
179    client: NodeAddress,
180}
181
182#[derive(Debug)]
183#[cfg_attr(all(feature = "defmt", not(feature = "alloc")), derive(defmt::Format))]
184struct PeriodicState<const MAX_PERIODIC: usize> {
185    entries: Vec<PeriodicEntry, MAX_PERIODIC>,
186}
187
188impl<const MAX_PERIODIC: usize> PeriodicState<MAX_PERIODIC> {
189    fn new() -> Self {
190        Self {
191            entries: Vec::new(),
192        }
193    }
194
195    fn register(&mut self, did: u16, interval: Duration, client: NodeAddress, now: Instant) {
196        if let Some(e) = self
197            .entries
198            .iter_mut()
199            .find(|e| e.did == did && e.client == client)
200        {
201            e.interval = interval;
202            e.next_tx = now + interval;
203            return;
204        }
205
206        #[cfg(feature = "defmt")]
207        defmt::unwrap!(self.entries.push(PeriodicEntry {
208            did,
209            interval,
210            next_tx: now + interval,
211            client,
212        }));
213
214        #[cfg(not(feature = "defmt"))]
215        let _ = self.entries.push(PeriodicEntry {
216            did,
217            interval,
218            next_tx: now + interval,
219            client,
220        });
221    }
222
223    fn cancel(&mut self, did: u16, client: &NodeAddress) {
224        self.entries
225            .retain(|e| !(e.did == did && &e.client == client));
226    }
227
228    fn collect_due(&self, now: Instant, out: &mut Vec<(u16, NodeAddress), MAX_PERIODIC>) {
229        for e in self.entries.iter().filter(|e| now >= e.next_tx) {
230            #[cfg(feature = "defmt")]
231            defmt::unwrap!(out.push((e.did, e.client.clone())));
232
233            #[cfg(not(feature = "defmt"))]
234            let _ = out.push((e.did, e.client.clone()));
235        }
236    }
237
238    fn advance(&mut self, did: u16, client: &NodeAddress, now: Instant) {
239        if let Some(e) = self
240            .entries
241            .iter_mut()
242            .find(|e| e.did == did && &e.client == client)
243        {
244            e.next_tx = now + e.interval;
245        }
246    }
247}
248
249// endregion: PeriodicEntry / PeriodicState
250
251// region: UdsServer
252
253/// Stateful UDS ECU server state machine.
254///
255/// Receives raw UDS frames via [`handle`], uses [`UdsFrameExt`] for
256/// protocol-level decisions (SID dispatch, suppress bit, sub-function),
257/// and decodes typed messages only where structured field access is needed.
258///
259/// All timing is driven by [`tick`] - no blocking, no hardware timers,
260/// no OS calls. Suitable for direct use as a `SimNode` in `ace-sim`.
261#[derive(Debug)]
262#[cfg_attr(all(feature = "defmt", not(feature = "alloc")), derive(defmt::Format))]
263pub struct UdsServer<
264    const MAX_FRAME: usize,
265    const MAX_OUTBOX: usize,
266    const MAX_SESSIONS: usize,
267    const MAX_SERVICES: usize,
268    const MAX_DIDS: usize,
269    const MAX_SECURITY_LEVELS: usize,
270    const DEFAULT_S3: u64,
271    const DEFAULT_P2: u64,
272    const DEFAULT_P2_EXT: u64,
273    const DEFAULT_LOCKOUT: u64,
274    const DEFAULT_MAX_SECURITY_ATTEMPTS: u8,
275    const MAX_SEED: usize,
276    const MAX_PERIODIC: usize,
277    H,
278    S,
279> where
280    H: ServerHandler<S>,
281    S: SecurityProvider,
282{
283    config: ServerConfig<MAX_SESSIONS, MAX_SERVICES, MAX_DIDS, MAX_SECURITY_LEVELS>,
284    handler: H,
285    security_provider: S,
286    address: NodeAddress,
287    session: SessionState,
288    security: SecurityState<MAX_SEED, MAX_SECURITY_LEVELS>,
289    periodic: PeriodicState<MAX_PERIODIC>,
290    outbox: Vec<(NodeAddress, Vec<u8, MAX_FRAME>), MAX_OUTBOX>,
291
292    /// Whether pending requests should be dropped.
293    drop_requests: bool,
294}
295
296impl<
297        const MAX_FRAME: usize,
298        const MAX_OUTBOX: usize,
299        const MAX_SESSIONS: usize,
300        const MAX_SERVICES: usize,
301        const MAX_DIDS: usize,
302        const MAX_SECURITY_LEVELS: usize,
303        const DEFAULT_S3: u64,
304        const DEFAULT_P2: u64,
305        const DEFAULT_P2_EXT: u64,
306        const DEFAULT_LOCKOUT: u64,
307        const DEFAULT_MAX_SECURITY_ATTEMPTS: u8,
308        const MAX_SEED: usize,
309        const MAX_PERIODIC: usize,
310        H,
311        S,
312    >
313    UdsServer<
314        MAX_FRAME,
315        MAX_OUTBOX,
316        MAX_SESSIONS,
317        MAX_SERVICES,
318        MAX_DIDS,
319        MAX_SECURITY_LEVELS,
320        DEFAULT_S3,
321        DEFAULT_P2,
322        DEFAULT_P2_EXT,
323        DEFAULT_LOCKOUT,
324        DEFAULT_MAX_SECURITY_ATTEMPTS,
325        MAX_SEED,
326        MAX_PERIODIC,
327        H,
328        S,
329    >
330where
331    H: ServerHandler<S>,
332    S: SecurityProvider,
333{
334    pub fn new(
335        config: ServerConfig<MAX_SESSIONS, MAX_SERVICES, MAX_DIDS, MAX_SECURITY_LEVELS>,
336        handler: H,
337        security_provider: S,
338        address: NodeAddress,
339    ) -> Self {
340        Self {
341            session: SessionState::new(config.default_session_type.into()),
342            config,
343            handler,
344            security_provider,
345            address,
346            security: SecurityState::new(),
347            periodic: PeriodicState::new(),
348            outbox: Vec::new(),
349            drop_requests: false
350        }
351    }
352
353    // region: SimNode surface
354
355    pub fn set_drop_requests(&mut self, status: bool) {
356        self.drop_requests = status;
357    }
358
359    pub fn drop_requests(&self) -> bool {
360        self.drop_requests
361    }
362
363    pub fn address(&self) -> &NodeAddress {
364        &self.address
365    }
366
367    pub fn set_session_type(&mut self, session_type: u8) {
368        self.session.session_type = session_type;
369    }
370
371    pub fn session_type(&self) -> u8 {
372        self.session.session_type
373    }
374
375    pub fn set_security_level(&mut self, level: u8) {
376        self.session.security_level = level;
377    }
378
379    pub fn security_level(&self) -> u8 {
380        self.session.security_level
381    }
382
383    pub fn reset_security_state(&mut self) {
384        self.security.reset();
385    }
386
387    /// Receives a raw UDS frame from `src`.
388    ///
389    /// Wraps the bytes in a [`UdsFrame`] and uses [`UdsFrameExt`] for
390    /// protocol-level decisions before dispatching to service handlers.
391    /// Typed message decode via `to_message()` is deferred to individual
392    /// handlers that need structured field access.
393    pub fn handle(
394        &mut self,
395        src: &NodeAddress,
396        data: &[u8],
397        now: Instant,
398    ) -> Result<(), ServerError<H::Error>> {
399        if self.drop_requests {
400            #[cfg(feature = "defmt")]
401            defmt::info!("uds request dropped: {=[u8]}", data);
402
403            return Ok(());
404        }
405
406        self.session.last_rx = now;
407
408        let frame = UdsFrame::from_slice(data);
409
410        // Validate frame has at minimum a SID byte
411        if let Err(e) = frame.validate() {
412            return Err(ServerError::Codec(e));
413        }
414
415        let sid = match frame.service_identifier() {
416            Some(s) => s,
417            None => return self.nrc_raw(src, 0x00, H::Error::service_not_supported().into(), now),
418        };
419
420        // Guard: service must be supported in the active session
421        let sid_byte = sid.discriminant();
422        if let Err(nrc) = self.guard_service(sid_byte) {
423            return self.nrc_raw(src, sid_byte, nrc, now);
424        }
425
426        // Suppress bit - extracted here at the frame level before any
427        // typed decode. Each handler receives this as a plain bool.
428        let suppressed = frame.is_suppressed();
429
430        match sid {
431            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::TesterPresent) => {
432                self.on_tester_present(src, &frame, suppressed, now)
433            }
434
435            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::DiagnosticSessionControl) => {
436                self.on_session_control(src, &frame, suppressed, now)
437            }
438
439            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::EcuReset) => {
440                self.on_ecu_reset(src, &frame, suppressed, now)
441            }
442
443            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::SecurityAccess) => {
444                self.on_security_access(src, &frame, suppressed, now)
445            }
446
447            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::ReadDataByIdentifier) => {
448                self.on_read_did(src, &frame, suppressed, now)
449            }
450
451            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::WriteDataByIdentifier) => {
452                self.on_write_did(src, &frame, suppressed, now)
453            }
454
455            ServiceIdentifier::UdsServiceRequest(
456                UdsServiceRequest::ReadDataByPeriodicIdentifier,
457            ) => self.on_periodic_did(src, &frame, suppressed, now),
458
459            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::RoutineControl) => {
460                self.on_routine_control(src, &frame, suppressed, now)
461            }
462
463            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::CommunicationControl) => {
464                self.on_communication_control(src, &frame, suppressed, now)
465            }
466
467            ServiceIdentifier::UdsServiceRequest(
468                UdsServiceRequest::InputOutputControlByIdentifier,
469            ) => self.on_io_control(src, &frame, suppressed, now),
470
471            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::RequestDownload) => {
472                self.on_request_download(src, &frame, suppressed, now)
473            }
474
475            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::TransferData) => {
476                self.on_transfer_data(src, &frame, suppressed, now)
477            }
478
479            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::RequestTransferExit) => {
480                self.on_transfer_exit(src, &frame, suppressed, now)
481            }
482
483            ServiceIdentifier::UdsServiceRequest(UdsServiceRequest::RequestFileTransfer) => {
484                self.on_file_transfer(src, &frame, suppressed, now)
485            }
486
487            _ => self.nrc_raw(src, sid_byte, H::Error::service_not_supported().into(), now),
488        }
489    }
490
491    /// Advances internal timers - S3 watchdog and periodic DID scheduling.
492    pub fn tick(&mut self, now: Instant) -> Result<(), ServerError<H::Error>> {
493        self.check_s3(now);
494        self.dispatch_periodic(now)
495    }
496
497    /// Drains pending outbound frames into `out`.
498    pub fn drain_outbox(
499        &mut self,
500        out: &mut Vec<(NodeAddress, Vec<u8, MAX_FRAME>), MAX_OUTBOX>,
501    ) -> usize {
502        let n = self.outbox.len();
503        for item in self.outbox.drain(..) {
504            #[cfg(feature = "defmt")]
505            defmt::unwrap!(out.push(item)); // unlikely
506
507            #[cfg(not(feature = "defmt"))]
508            let _ = out.push(item);
509        }
510        n
511    }
512
513    // endregion: SimNode surface
514
515    // region: Session helpers
516
517    fn current_session(&self) -> Option<&SessionConfig> {
518        self.config.find_session(self.session.session_type)
519    }
520
521    fn check_s3(&mut self, now: Instant) {
522        if self.session.is_default() {
523            return;
524        }
525
526        let s3 = self
527            .current_session()
528            .map(|s| s.s3_timeout)
529            .unwrap_or(Duration::from_millis(DEFAULT_S3));
530
531        if let Some(elapsed) = now.checked_duration_since(self.session.last_rx) && s3.as_micros() > 0 {
532            if elapsed > s3 {
533                self.session.session_type = self.config.default_session_type.into();
534                self.session.security_level = 0;
535                self.security.clear_pending();
536            }
537        }
538    }
539
540    fn guard_service(&self, sid: u8) -> Result<(), u8> {
541        if !self.config.service_allowed(sid, self.session.session_type) {
542            return Err(H::Error::service_not_supported_in_active_session().into());
543        }
544        Ok(())
545    }
546
547    fn guard_security(&self, required: u8) -> Result<(), u8> {
548        if required > 0 && self.session.security_level < required {
549            return Err(H::Error::security_access_denied().into());
550        }
551        Ok(())
552    }
553
554    // endregion: Session helpers
555
556    // region: Response helpers
557
558    fn enqueue(
559        &mut self,
560        dst: NodeAddress,
561        frame: Vec<u8, MAX_FRAME>,
562    ) -> Result<(), ServerError<H::Error>> {
563        if self.outbox.len() >= MAX_OUTBOX {
564            Err(ServerError::OutboxFull)
565        } else {
566            #[cfg(feature = "defmt")]
567            defmt::unwrap!(self.outbox.push((dst, frame))); // unlikely
568
569            #[cfg(not(feature = "defmt"))]
570            self.outbox.push((dst, frame));
571
572            Ok(())
573        }
574    }
575
576    fn pos(
577        &mut self,
578        dst: &NodeAddress,
579        request_sid: u8,
580        payload: &[u8],
581        _now: Instant,
582    ) -> Result<(), ServerError<H::Error>> {
583        let mut frame: Vec<u8, MAX_FRAME> = Vec::new();
584
585        #[cfg(feature = "defmt")]
586        {
587            defmt::unwrap!(frame.push(request_sid | 0x40));
588            defmt::unwrap!(frame.extend_from_slice(payload));
589        }
590
591        #[cfg(not(feature = "defmt"))]
592        {
593            let _ = frame.push(request_sid | 0x40);
594            let _ = frame.extend_from_slice(payload);
595        }
596
597
598        self.enqueue(dst.clone(), frame)
599    }
600
601    fn nrc(
602        &mut self,
603        dst: &NodeAddress,
604        request_sid: u8,
605        error: H::Error,
606        _now: Instant,
607    ) -> Result<(), ServerError<H::Error>> {
608        let nrc_byte: u8 = error.into();
609        self.nrc_raw(dst, request_sid, nrc_byte, _now)
610    }
611
612    fn nrc_raw(
613        &mut self,
614        dst: &NodeAddress,
615        request_sid: u8,
616        nrc_byte: u8,
617        _now: Instant,
618    ) -> Result<(), ServerError<H::Error>> {
619        let mut frame: Vec<u8, MAX_FRAME> = Vec::new();
620
621        #[cfg(feature = "defmt")]
622        {
623            defmt::unwrap!(frame.push(0x7F));
624            defmt::unwrap!(frame.push(request_sid));
625            defmt::unwrap!(frame.push(nrc_byte));
626        }
627
628        #[cfg(not(feature = "defmt"))]
629        {
630            let _ = frame.push(0x7F);
631            let _ = frame.push(request_sid);
632            let _ = frame.push(nrc_byte);
633        }
634
635        self.enqueue(dst.clone(), frame)
636    }
637
638    // endregion: Response helpers
639
640    // region: Service handlers
641    //
642    // Each handler receives:
643    //   - `frame` - the raw UdsFrame for sub-function/payload access
644    //   - `suppressed` - suppress bit already extracted at dispatch
645    //
646    // Typed decode via `frame.to_message()` is used only where structured
647    // field access is needed. Services that only need the sub-function value
648    // and a payload slice never allocate a typed message.
649
650    fn on_tester_present(
651        &mut self,
652        src: &NodeAddress,
653        frame: &UdsFrame<'_>,
654        suppressed: bool,
655        now: Instant,
656    ) -> Result<(), ServerError<H::Error>> {
657        // TesterPresent: sub-function is always 0x00.
658        // The only meaningful information is the suppress bit.
659        if suppressed {
660            return Ok(());
661        }
662        // Echo sub-function value (suppress bit cleared) in response.
663        let sf = frame.sub_function_value().unwrap_or(0x00);
664        self.pos(src, 0x3E, &[sf], now)
665    }
666
667    fn on_session_control(
668        &mut self,
669        src: &NodeAddress,
670        frame: &UdsFrame<'_>,
671        suppressed: bool,
672        now: Instant,
673    ) -> Result<(), ServerError<H::Error>> {
674        // Sub-function value IS the session type byte.
675        let session_type = match frame.sub_function_value() {
676            Some(v) => v,
677            None => {
678                return self.nrc(
679                    src,
680                    0x10,
681                    H::Error::incorrect_message_length_or_invalid_format(),
682                    now,
683                )
684            }
685        };
686
687        if self.config.find_session(session_type).is_none() {
688            return self.nrc(src, 0x10, H::Error::sub_function_not_supported(), now);
689        }
690
691        let mut ctx = self.create_request_context();
692        let result = self.handler.session_control(&mut ctx, session_type);
693        self.handle_request_context(ctx);
694
695        if let Err(err) = result {
696            return self.nrc(src, 0x10, err, now);
697        }
698        
699        self.session.session_type = session_type;
700        self.session.security_level = 0;
701        self.session.last_rx = now;
702        self.security.clear_pending();
703        
704        if suppressed {
705            return Ok(());
706        }
707
708        let (p2_ms, p2_ext_ms) = self
709            .config
710            .find_session(session_type)
711            .map(|s| {
712                (
713                    s.p2_timeout.as_millis(),
714                    s.p2_extended_timeout.as_millis() / 10,
715                )
716            })
717            .unwrap_or((DEFAULT_P2, DEFAULT_P2_EXT));
718
719        let payload = [
720            session_type,
721            (p2_ms >> 8) as u8,
722            p2_ms as u8,
723            (p2_ext_ms >> 8) as u8,
724            p2_ext_ms as u8,
725        ];
726        self.pos(src, 0x10, &payload, now)
727    }
728
729    fn on_ecu_reset(
730        &mut self,
731        src: &NodeAddress,
732        frame: &UdsFrame<'_>,
733        suppressed: bool,
734        now: Instant,
735    ) -> Result<(), ServerError<H::Error>> {
736        // Sub-function value IS the reset type byte.
737        let reset_type = match frame.sub_function_value() {
738            Some(v) => v,
739            None => {
740                return self.nrc(
741                    src,
742                    0x11,
743                    H::Error::incorrect_message_length_or_invalid_format(),
744                    now,
745                )
746            }
747        };
748
749        let mut ctx = self.create_request_context();
750
751        let result = self.handler
752            .ecu_reset(&mut ctx, reset_type);
753
754        self.handle_request_context(ctx);
755
756        if let Err(err) = result {
757            return self.nrc(src, 0x11, err, now);
758        }
759
760        if !suppressed {
761            self.pos(src, 0x11, &[reset_type], now)?;
762        }
763
764        Ok(())
765    }
766
767    fn on_security_access(
768        &mut self,
769        src: &NodeAddress,
770        frame: &UdsFrame<'_>,
771        _suppressed: bool, // SecurityAccess has no suppress bit
772        now: Instant,
773    ) -> Result<(), ServerError<H::Error>> {
774        // Access type byte: odd = RequestSeed, even = SendKey.
775        let access_type = match frame.sub_function_value() {
776            Some(v) => v,
777            None => {
778                return self.nrc(
779                    src,
780                    0x27,
781                    H::Error::incorrect_message_length_or_invalid_format(),
782                    now,
783                )
784            }
785        };
786
787        let is_request_seed = access_type % 2 != 0;
788
789        if is_request_seed {
790            let level = access_type;
791
792            if self.security.is_locked(level, now) {
793                return self.nrc(src, 0x27, H::Error::required_time_delay_not_expired(), now);
794            }
795
796            let Some(config) = self.config.find_security_level(level) else {
797                return self.nrc(src, 0x27, H::Error::sub_function_not_supported(), now);
798            };
799
800            let mut frame: Vec<u8, MAX_FRAME> = Vec::new();
801
802            if self.security.pending_level == level
803                && !self.security.pending_seed.is_empty()
804                && self.security.pending_seed.len() == config.seed_length
805            {
806                #[cfg(feature = "defmt")]
807                {
808                    defmt::unwrap!(frame.push(0x27 | 0x40));
809                    defmt::unwrap!(frame.push(level));
810                    defmt::unwrap!(frame.extend_from_slice(self.security.pending_seed.as_slice()));
811                }
812                #[cfg(not(feature = "defmt"))]
813                {
814                    let _ = frame.push(0x27 | 0x40);
815                    let _ = frame.push(level);
816                    let _ = frame.extend_from_slice(self.security.pending_seed.as_slice());
817                }
818                return self.enqueue(src.clone(), frame);
819            }
820
821            let mut ctx = self.create_request_context();
822            let result = self.handler.security_access(&mut ctx, level, &[]);
823            self.handle_request_context(ctx);
824
825            if let Err(err) = result {
826                return self.nrc_raw(src, 0x27, err.into(), now);
827            }
828
829            let mut seed_buf = [0u8; MAX_SEED];
830            let result = self
831                .security_provider
832                .generate_seed(level, &mut seed_buf)
833                .map_err(|_| H::Error::conditions_not_correct());
834
835            let seed_len = match result {
836                Ok(v) => v,
837                Err(err) => {
838                    return self.nrc_raw(src, 0x27, err.into(), now);
839                }
840            };
841            
842            self.security.pending_seed.clear();
843            self.security.pending_level = level;
844
845            #[cfg(feature = "defmt")]
846            {
847                defmt::unwrap!(self.security.pending_seed.extend_from_slice(&seed_buf[..seed_len]));
848                defmt::unwrap!(frame.push(0x27 | 0x40));
849                defmt::unwrap!(frame.push(level));
850                defmt::unwrap!(frame.extend_from_slice(&seed_buf[..seed_len]));
851            }
852
853            #[cfg(not(feature = "defmt"))]
854            {
855                let _ = self.security.pending_seed.extend_from_slice(&seed_buf[..seed_len]);
856                let _ = frame.push(0x27 | 0x40);
857                let _ = frame.push(level);
858                let _ = frame.extend_from_slice(&seed_buf[..seed_len]);
859            }
860
861            self.enqueue(src.clone(), frame)
862        } else {
863            // SendKey - key bytes are the payload after the sub-function byte.
864            let level = access_type - 1; // RequestSeed level
865
866            if self.security.is_locked(level, now) {
867                return self.nrc(src, 0x27, H::Error::required_time_delay_not_expired(), now);
868            }
869            if self.security.pending_level != level || self.security.pending_seed.is_empty() {
870                return self.nrc(src, 0x27, H::Error::request_sequence_error(), now);
871            }
872
873            // Key bytes are the payload after the access_type byte.
874            // frame.payload() is everything after SID - key starts at payload[1].
875            let key = frame.payload().get(1..).unwrap_or(&[]);
876
877            let mut ctx = self.create_request_context();
878            let result = self.handler.security_access(&mut ctx, level, key);
879            self.handle_request_context(ctx);
880
881            if let Err(err) = result {
882                return self.nrc_raw(src, 0x27, err.into(), now);
883            }
884
885            let level_cfg = self.config.find_security_level(level);
886            let max_attempts = level_cfg
887                .map(|l| l.max_attempts)
888                .flatten()
889                .unwrap_or(DEFAULT_MAX_SECURITY_ATTEMPTS);
890            let lockout_dur = level_cfg
891                .map(|l| l.lockout_duration)
892                .flatten()
893                .unwrap_or(Duration::from_millis(DEFAULT_LOCKOUT));
894
895            let seed = self.security.pending_seed.clone();
896
897            match self.security_provider.validate_key(level, &seed, key) {
898                Ok(()) => {
899                    self.security.reset_failed(level);
900                    self.security.clear_pending();
901                    self.session.security_level = level;
902                    self.pos(src, 0x27, &[access_type], now)
903                }
904                Err(_) => {
905                    self.security.increment_failed(level);
906                    if self.security.failed_count(level) >= max_attempts {
907                        self.security.set_lockout(level, now + lockout_dur);
908                        self.security.clear_pending();
909                        return self.nrc(src, 0x27, H::Error::exceeded_number_of_attempts(), now);
910                    }
911                    self.nrc(src, 0x27, H::Error::invalid_key(), now)
912                }
913            }
914        }
915    }
916
917    fn on_read_did(
918        &mut self,
919        src: &NodeAddress,
920        frame: &UdsFrame<'_>,
921        _suppressed: bool, // ReadDataByIdentifier has no sub-function
922        now: Instant,
923    ) -> Result<(), ServerError<H::Error>> {
924        // Payload is pairs of DID bytes: [DID_high, DID_low, DID_high, DID_low, ...]
925        let payload = frame.payload();
926        if payload.len() < 2
927            || (!self.config.allow_read_many_dids && payload.len() != 2)
928            || payload.len() % 2 != 0
929        {
930            return self.nrc(
931                src,
932                0x22,
933                H::Error::incorrect_message_length_or_invalid_format(),
934                now,
935            );
936        }
937
938        let mut resp: Vec<u8, MAX_FRAME> = Vec::new();
939
940        for chunk in payload.chunks_exact(2) {
941            let did = u16::from_be_bytes([chunk[0], chunk[1]]);
942
943            if !self.config.did_readable(did, self.session.session_type) {
944                return self.nrc(src, 0x22, H::Error::request_out_of_range(), now);
945            }
946            let required_sec = self
947                .config
948                .find_did(did)
949                .map(|d| d.security_level)
950                .unwrap_or(0);
951            if let Err(nrc) = self.guard_security(required_sec) {
952                return self.nrc_raw(src, 0x22, nrc, now);
953            }
954
955            #[cfg(feature = "defmt")]
956            {
957                defmt::unwrap!(resp.push(chunk[0]));
958                defmt::unwrap!(resp.push(chunk[1]));
959            }
960
961            #[cfg(not(feature = "defmt"))]
962            {
963                let _ = resp.push(chunk[0]);
964                let _ = resp.push(chunk[1]);
965            }
966
967            let mut ctx = self.create_request_context();
968
969            let mut data_buf = [0u8; MAX_FRAME];
970            let result = self
971                .handler
972                .read_did(&mut ctx, did, &mut data_buf);
973
974            self.handle_request_context(ctx);
975
976            let len = match result {
977                Ok(v) => v,
978                Err(err) => {
979                    return self.nrc_raw(src, 0x22, err.into(), now);
980                }
981            };
982
983            #[cfg(feature = "defmt")]
984            defmt::unwrap!(resp.extend_from_slice(&data_buf[..len]));
985
986            #[cfg(not(feature = "defmt"))]
987            let _ = resp.extend_from_slice(&data_buf[..len]);
988        }
989
990        self.pos(src, 0x22, &resp, now)
991    }
992
993    fn on_write_did(
994        &mut self,
995        src: &NodeAddress,
996        frame: &UdsFrame<'_>,
997        _suppressed: bool,
998        now: Instant,
999    ) -> Result<(), ServerError<H::Error>> {
1000        let payload = frame.payload();
1001        if payload.len() < 3 {
1002            return self.nrc(
1003                src,
1004                0x2E,
1005                H::Error::incorrect_message_length_or_invalid_format(),
1006                now,
1007            );
1008        }
1009
1010        let did = u16::from_be_bytes([payload[0], payload[1]]);
1011        let data_rec = &payload[2..];
1012
1013        if !self.config.did_writable(did, self.session.session_type) {
1014            return self.nrc(src, 0x2E, H::Error::request_out_of_range(), now);
1015        }
1016        let required_sec = self
1017            .config
1018            .find_did(did)
1019            .map(|d| d.security_level)
1020            .unwrap_or(0);
1021        if let Err(nrc) = self.guard_security(required_sec) {
1022            return self.nrc_raw(src, 0x2E, nrc, now);
1023        }
1024
1025        let mut ctx = self.create_request_context();
1026
1027        let result = self.handler
1028            .write_did(&mut ctx, did, data_rec);
1029
1030        self.handle_request_context(ctx);
1031
1032        if let Err(err) = result {
1033            return self.nrc_raw(src, 0x2E, err.into(), now);
1034        }
1035
1036        self.pos(src, 0x2E, &payload[..2], now)
1037    }
1038
1039    fn on_periodic_did(
1040        &mut self,
1041        src: &NodeAddress,
1042        frame: &UdsFrame<'_>,
1043        _suppressed: bool,
1044        now: Instant,
1045    ) -> Result<(), ServerError<H::Error>> {
1046        let payload = frame.payload();
1047        if payload.is_empty() {
1048            return self.nrc(
1049                src,
1050                0x2A,
1051                H::Error::incorrect_message_length_or_invalid_format(),
1052                now,
1053            );
1054        }
1055
1056        // Byte 0 is transmission mode, remaining bytes are periodic DID identifiers.
1057        let mode = payload[0];
1058        let periodic_ids = payload.get(1..).unwrap_or(&[]);
1059
1060        let mut ctx = self.create_request_context();
1061        let result = self.handler.periodic_did(&mut ctx, mode, periodic_ids);
1062        self.handle_request_context(ctx);
1063
1064        if let Err(err) = result {
1065            return self.nrc_raw(src, 0x2A, err.into(), now);
1066        }
1067
1068        match mode {
1069            // stopSending
1070            0x04 => {
1071                for &id in periodic_ids {
1072                    self.periodic.cancel(0xF200u16 | id as u16, src);
1073                }
1074                self.pos(src, 0x2A, &[mode], now)
1075            }
1076            0x01 | 0x02 | 0x03 => {
1077                let requested_interval = match mode {
1078                    0x01 => periodic::SLOW,
1079                    0x02 => periodic::MEDIUM,
1080                    _ => periodic::FAST,
1081                };
1082
1083                for &id in periodic_ids {
1084                    let did = 0xF200u16 | id as u16;
1085
1086                    if !self.config.did_readable(did, self.session.session_type) {
1087                        return self.nrc(src, 0x2A, H::Error::request_out_of_range(), now);
1088                    }
1089
1090                    let effective = self
1091                        .config
1092                        .find_did(did)
1093                        .map(|d| requested_interval.max(d.min_periodic_interval))
1094                        .unwrap_or(requested_interval);
1095
1096                    self.periodic.register(did, effective, src.clone(), now);
1097                }
1098                self.pos(src, 0x2A, &[mode], now)
1099            }
1100            _ => self.nrc(src, 0x2A, H::Error::sub_function_not_supported(), now),
1101        }
1102    }
1103
1104    fn on_routine_control(
1105        &mut self,
1106        src: &NodeAddress,
1107        frame: &UdsFrame<'_>,
1108        suppressed: bool,
1109        now: Instant,
1110    ) -> Result<(), ServerError<H::Error>> {
1111        // Sub-function value is the routine control type (0x01/0x02/0x03).
1112        // Payload after SID: [sub_function, routine_id_high, routine_id_low, option_record...]
1113        let payload = frame.payload();
1114        if payload.len() < 3 {
1115            return self.nrc(
1116                src,
1117                0x31,
1118                H::Error::incorrect_message_length_or_invalid_format(),
1119                now,
1120            );
1121        }
1122
1123        let sub_function = frame.sub_function_value().unwrap_or(0);
1124        let routine_id = u16::from_be_bytes([payload[1], payload[2]]);
1125        let option_record = payload.get(3..).unwrap_or(&[]);
1126
1127        let mut ctx = self.create_request_context();
1128
1129        let mut buf = [0u8; MAX_FRAME];
1130        let result = self
1131            .handler
1132            .routine_control(&mut ctx, routine_id, sub_function, option_record, &mut buf);
1133
1134        self.handle_request_context(ctx);
1135
1136        let len = match result {
1137            Ok(v) => v,
1138            Err(err) => {
1139                return self.nrc_raw(src, 0x31, err.into(), now);
1140            }
1141        };
1142
1143        if suppressed {
1144            return Ok(());
1145        }
1146
1147        let mut resp: Vec<u8, MAX_FRAME> = Vec::new();
1148
1149        #[cfg(feature = "defmt")]
1150        {
1151            defmt::unwrap!(resp.push(sub_function));
1152            defmt::unwrap!(resp.push(payload[1]));
1153            defmt::unwrap!(resp.push(payload[2]));
1154            defmt::unwrap!(resp.extend_from_slice(&buf[..len]));
1155        }
1156
1157        #[cfg(not(feature = "defmt"))]
1158        {
1159            let _ = resp.push(sub_function);
1160            let _ = resp.push(payload[1]);
1161            let _ = resp.push(payload[2]);
1162            let _ = resp.extend_from_slice(&buf[..len]);
1163        }
1164
1165        self.pos(src, 0x31, &resp, now)
1166    }
1167
1168    fn on_communication_control(
1169        &mut self,
1170        src: &NodeAddress,
1171        frame: &UdsFrame<'_>,
1172        suppressed: bool,
1173        now: Instant,
1174    ) -> Result<(), ServerError<H::Error>> {
1175        let payload = frame.payload();
1176        if payload.len() < 2 {
1177            return self.nrc(
1178                src,
1179                0x28,
1180                H::Error::incorrect_message_length_or_invalid_format(),
1181                now,
1182            );
1183        }
1184
1185        let control_type = frame.sub_function_value().unwrap_or(0);
1186        let comm_type = payload[1];
1187
1188        let mut ctx = self.create_request_context();
1189
1190        let result = self.handler
1191            .communication_control(&mut ctx, control_type, comm_type);
1192
1193        self.handle_request_context(ctx);
1194
1195        if let Err(err) = result {
1196            return self.nrc_raw(src, 0x28, err.into(), now);
1197        }
1198
1199        if suppressed {
1200            return Ok(());
1201        }
1202
1203        self.pos(src, 0x28, &[control_type], now)
1204    }
1205
1206    fn on_io_control(
1207        &mut self,
1208        src: &NodeAddress,
1209        frame: &UdsFrame<'_>,
1210        _suppressed: bool,
1211        now: Instant,
1212    ) -> Result<(), ServerError<H::Error>> {
1213        let payload = frame.payload();
1214        if payload.len() < 3 {
1215            return self.nrc(
1216                src,
1217                0x2F,
1218                H::Error::incorrect_message_length_or_invalid_format(),
1219                now,
1220            );
1221        }
1222
1223        let did = u16::from_be_bytes([payload[0], payload[1]]);
1224        let control_param = payload[2];
1225        let control_state = payload.get(3..).unwrap_or(&[]);
1226
1227        let mut ctx = self.create_request_context();
1228
1229        let mut buf = [0u8; MAX_FRAME];
1230        let result = self
1231            .handler
1232            .io_control(&mut ctx, did, control_param, control_state, &mut buf);
1233
1234        self.handle_request_context(ctx);
1235
1236        let len = match result {
1237            Ok(v) => v,
1238            Err(err) => {
1239                return self.nrc_raw(src, 0x2F, err.into(), now);
1240            }
1241        };
1242
1243        let mut resp: Vec<u8, MAX_FRAME> = Vec::new();
1244
1245        #[cfg(feature = "defmt")]
1246        {
1247            defmt::unwrap!(resp.push(payload[0]));
1248            defmt::unwrap!(resp.push(payload[1]));
1249            defmt::unwrap!(resp.extend_from_slice(&buf[..len]));
1250        }
1251
1252        #[cfg(not(feature = "defmt"))]
1253        {
1254            let _ = resp.push(payload[0]);
1255            let _ = resp.push(payload[1]);
1256            let _ = resp.extend_from_slice(&buf[..len]);
1257        }
1258
1259        self.pos(src, 0x2F, &resp, now)
1260    }
1261
1262    fn on_request_download(
1263        &mut self,
1264        src: &NodeAddress,
1265        frame: &UdsFrame<'_>,
1266        _suppressed: bool,
1267        now: Instant,
1268    ) -> Result<(), ServerError<H::Error>> {
1269        // Payload: [data_format_identifier, address_and_length_format,
1270        //           memory_address..., memory_size...]
1271        let payload = frame.payload();
1272        if payload.len() < 3 {
1273            return self.nrc(
1274                src,
1275                0x34,
1276                H::Error::incorrect_message_length_or_invalid_format(),
1277                now,
1278            );
1279        }
1280
1281        let data_format = payload[0];
1282        let addr_and_len_format = payload[1];
1283        let addr_len = (addr_and_len_format >> 4) as usize;
1284        let size_len = (addr_and_len_format & 0x0F) as usize;
1285
1286        if payload.len() < 2 + addr_len + size_len {
1287            return self.nrc(
1288                src,
1289                0x34,
1290                H::Error::incorrect_message_length_or_invalid_format(),
1291                now,
1292            );
1293        }
1294
1295        let memory_address = &payload[2..2 + addr_len];
1296        let memory_size = &payload[2 + addr_len..2 + addr_len + size_len];
1297
1298        let mut ctx = self.create_request_context();
1299
1300        let mut buf = [0u8; 64];
1301        let result = self
1302            .handler
1303            .request_download(&mut ctx, memory_address, memory_size, data_format, 0, &mut buf);
1304
1305        self.handle_request_context(ctx);
1306
1307        let len = match result {
1308            Ok(v) => v,
1309            Err(err) => {
1310                return self.nrc_raw(src, 0x34, err.into(), now);
1311            }
1312        };
1313
1314        self.pos(src, 0x34, &buf[..len], now)
1315    }
1316
1317    fn on_transfer_data(
1318        &mut self,
1319        src: &NodeAddress,
1320        frame: &UdsFrame<'_>,
1321        _suppressed: bool,
1322        now: Instant,
1323    ) -> Result<(), ServerError<H::Error>> {
1324        let payload = frame.payload();
1325        if payload.is_empty() {
1326            return self.nrc(
1327                src,
1328                0x36,
1329                H::Error::incorrect_message_length_or_invalid_format(),
1330                now,
1331            );
1332        }
1333
1334        let block_seq = payload[0];
1335        let data = payload.get(1..).unwrap_or(&[]);
1336
1337        let mut ctx = self.create_request_context();
1338
1339        let mut buf = [0u8; MAX_FRAME];
1340        let result = self
1341            .handler
1342            .transfer_data(&mut ctx, block_seq, data, &mut buf);
1343
1344        self.handle_request_context(ctx);
1345
1346        let len = match result {
1347            Ok(v) => v,
1348            Err(err) => {
1349                return self.nrc_raw(src, 0x36, err.into(), now);
1350            }
1351        };
1352
1353        let mut resp: Vec<u8, MAX_FRAME> = Vec::new();
1354
1355        #[cfg(feature = "defmt")]
1356        {
1357            defmt::unwrap!(resp.push(block_seq));
1358            defmt::unwrap!(resp.extend_from_slice(&buf[..len]));
1359        }
1360
1361        #[cfg(not(feature = "defmt"))]
1362        {
1363            let _ = resp.push(block_seq);
1364            let _ = resp.extend_from_slice(&buf[..len]);
1365        }
1366
1367        self.pos(src, 0x36, &resp, now)
1368    }
1369
1370    fn on_transfer_exit(
1371        &mut self,
1372        src: &NodeAddress,
1373        frame: &UdsFrame<'_>,
1374        _suppressed: bool,
1375        now: Instant,
1376    ) -> Result<(), ServerError<H::Error>> {
1377        let parameter_record = frame.payload();
1378
1379        let mut ctx = self.create_request_context();
1380
1381        let mut buf = [0u8; MAX_FRAME];
1382        let result = self
1383            .handler
1384            .request_transfer_exit(&mut ctx, parameter_record, &mut buf);
1385
1386        self.handle_request_context(ctx);
1387
1388        let len = match result {
1389            Ok(v) => v,
1390            Err(err) => {
1391                return self.nrc_raw(src, 0x37, err.into(), now);
1392            }
1393        };
1394
1395        self.pos(src, 0x37, &buf[..len], now)
1396    }
1397
1398    fn on_file_transfer(
1399        &mut self,
1400        src: &NodeAddress,
1401        frame: &UdsFrame<'_>,
1402        _suppressed: bool,
1403        now: Instant,
1404    ) -> Result<(), ServerError<H::Error>> {
1405        let payload = frame.payload();
1406        if payload.len() < 3 {
1407            return self.nrc(
1408                src,
1409                0x38,
1410                H::Error::incorrect_message_length_or_invalid_format(),
1411                now,
1412            );
1413        }
1414
1415        let operation = payload[0];
1416        // Bytes 1-2 are file path length (big-endian u16), rest is path
1417        let path_len = u16::from_be_bytes([payload[1], payload[2]]) as usize;
1418        let path = payload.get(3..3 + path_len).unwrap_or(&[]);
1419
1420        let mut ctx = self.create_request_context();
1421
1422        let mut buf = [0u8; MAX_FRAME];
1423        let result = self
1424            .handler
1425            .request_file_transfer(&mut ctx, operation, path, &mut buf);
1426
1427        self.handle_request_context(ctx);
1428
1429        let len = match result {
1430            Ok(v) => v,
1431            Err(err) => {
1432                return self.nrc_raw(src, 0x38, err.into(), now);
1433            }
1434        };
1435
1436        self.pos(src, 0x38, &buf[..len], now)
1437    }
1438
1439    // endregion: Service handlers
1440
1441    // region: Periodic dispatch
1442
1443    fn dispatch_periodic(&mut self, now: Instant) -> Result<(), ServerError<H::Error>> {
1444        let mut due: Vec<(u16, NodeAddress), MAX_PERIODIC> = Vec::new();
1445        self.periodic.collect_due(now, &mut due);
1446
1447        for (did, client) in &due {
1448            let mut ctx = self.create_request_context();
1449
1450            let mut data_buf = [0u8; MAX_FRAME];
1451            let result = self
1452                .handler
1453                .read_did(&mut ctx, *did, &mut data_buf);
1454
1455            self.handle_request_context(ctx);
1456
1457            let len = match result {
1458                Ok(v) => v,
1459                Err(err) => {
1460                    let nrc = err.into();
1461
1462                    #[cfg(feature = "defmt")]
1463                    defmt::error!("periodic error: {=u8}", nrc);
1464
1465                    self.periodic.cancel(*did, client);
1466                    continue;
1467                }
1468            };
1469
1470            // [periodic_data_identifier (1 byte), data_record (n bytes)]
1471            let did_low = (*did & 0xFF) as u8;
1472            let mut frame = Vec::new();
1473
1474            #[cfg(feature = "defmt")]
1475            {
1476                defmt::unwrap!(frame.push(did_low));
1477                defmt::unwrap!(frame.extend_from_slice(&data_buf[..len]));
1478            }
1479
1480            #[cfg(not(feature = "defmt"))]
1481            {
1482                let _ = frame.push(did_low);
1483                let _ = frame.extend_from_slice(&data_buf[..len]);
1484            }
1485
1486
1487            self.enqueue(client.clone(), frame)?;
1488            self.periodic.advance(*did, client, now);
1489        }
1490
1491        Ok(())
1492    }
1493
1494    fn create_request_context(&mut self) -> UdsRequestContext<S> {
1495        UdsRequestContext {
1496            session: self.session.clone(),
1497            security_provider: self.security_provider.clone(),
1498            drop_requests: false,
1499            clear_outbox: false,
1500            reset_security_state: false
1501        }
1502    }
1503
1504    fn handle_request_context(&mut self, ctx: UdsRequestContext<S>) {
1505        if ctx.session != self.session {
1506            self.session.session_type = ctx.session.session_type;
1507            self.session.security_level = ctx.session.security_level;
1508        }
1509        if ctx.clear_outbox {
1510            self.outbox.clear();
1511        }
1512        if ctx.reset_security_state {
1513            self.security.reset();
1514        }
1515        if ctx.drop_requests {
1516            self.drop_requests = true;
1517        }
1518    }
1519
1520    // endregion: Periodic dispatch
1521}
1522
1523// endregion: UdsServer
1524
1525#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1526pub struct UdsRequestContext<T>
1527where
1528    T: SecurityProvider
1529{
1530    pub session: SessionState,
1531    pub security_provider: T,
1532    pub(crate) drop_requests: bool,
1533    pub(crate) clear_outbox: bool,
1534    pub(crate) reset_security_state: bool,
1535}
1536
1537impl<T> UdsRequestContext<T>
1538where
1539    T: SecurityProvider
1540{
1541    pub fn drop_requests(&mut self) {
1542        self.drop_requests = true;
1543    }
1544
1545    pub fn clear_outbox(&mut self) {
1546        self.clear_outbox = true;
1547    }
1548
1549    pub fn reset_security_state(&mut self) {
1550        self.reset_security_state = true;
1551    }
1552}