1use 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#[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#[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#[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))); #[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))); #[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#[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#[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 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 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 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 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 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 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 pub fn tick(&mut self, now: Instant) -> Result<(), ServerError<H::Error>> {
493 self.check_s3(now);
494 self.dispatch_periodic(now)
495 }
496
497 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)); #[cfg(not(feature = "defmt"))]
508 let _ = out.push(item);
509 }
510 n
511 }
512
513 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 if !self.config.service_unlocked(sid, self.security_level()) {
545 return Err(H::Error::security_access_denied().into());
546 }
547 Ok(())
548 }
549
550 fn guard_security(&self, required: u8) -> Result<(), u8> {
551 if required > 0 && self.session.security_level < required {
552 return Err(H::Error::security_access_denied().into());
553 }
554 Ok(())
555 }
556
557 fn enqueue(
562 &mut self,
563 dst: NodeAddress,
564 frame: Vec<u8, MAX_FRAME>,
565 ) -> Result<(), ServerError<H::Error>> {
566 if self.outbox.len() >= MAX_OUTBOX {
567 Err(ServerError::OutboxFull)
568 } else {
569 #[cfg(feature = "defmt")]
570 defmt::unwrap!(self.outbox.push((dst, frame))); #[cfg(not(feature = "defmt"))]
573 self.outbox.push((dst, frame));
574
575 Ok(())
576 }
577 }
578
579 fn pos(
580 &mut self,
581 dst: &NodeAddress,
582 request_sid: u8,
583 payload: &[u8],
584 _now: Instant,
585 ) -> Result<(), ServerError<H::Error>> {
586 let mut frame: Vec<u8, MAX_FRAME> = Vec::new();
587
588 #[cfg(feature = "defmt")]
589 {
590 defmt::unwrap!(frame.push(request_sid | 0x40));
591 defmt::unwrap!(frame.extend_from_slice(payload));
592 }
593
594 #[cfg(not(feature = "defmt"))]
595 {
596 let _ = frame.push(request_sid | 0x40);
597 let _ = frame.extend_from_slice(payload);
598 }
599
600
601 self.enqueue(dst.clone(), frame)
602 }
603
604 fn nrc(
605 &mut self,
606 dst: &NodeAddress,
607 request_sid: u8,
608 error: H::Error,
609 _now: Instant,
610 ) -> Result<(), ServerError<H::Error>> {
611 let nrc_byte: u8 = error.into();
612 self.nrc_raw(dst, request_sid, nrc_byte, _now)
613 }
614
615 fn nrc_raw(
616 &mut self,
617 dst: &NodeAddress,
618 request_sid: u8,
619 nrc_byte: u8,
620 _now: Instant,
621 ) -> Result<(), ServerError<H::Error>> {
622 let mut frame: Vec<u8, MAX_FRAME> = Vec::new();
623
624 #[cfg(feature = "defmt")]
625 {
626 defmt::unwrap!(frame.push(0x7F));
627 defmt::unwrap!(frame.push(request_sid));
628 defmt::unwrap!(frame.push(nrc_byte));
629 }
630
631 #[cfg(not(feature = "defmt"))]
632 {
633 let _ = frame.push(0x7F);
634 let _ = frame.push(request_sid);
635 let _ = frame.push(nrc_byte);
636 }
637
638 self.enqueue(dst.clone(), frame)
639 }
640
641 fn on_tester_present(
654 &mut self,
655 src: &NodeAddress,
656 frame: &UdsFrame<'_>,
657 suppressed: bool,
658 now: Instant,
659 ) -> Result<(), ServerError<H::Error>> {
660 if suppressed {
663 return Ok(());
664 }
665 let sf = frame.sub_function_value().unwrap_or(0x00);
667 self.pos(src, 0x3E, &[sf], now)
668 }
669
670 fn on_session_control(
671 &mut self,
672 src: &NodeAddress,
673 frame: &UdsFrame<'_>,
674 suppressed: bool,
675 now: Instant,
676 ) -> Result<(), ServerError<H::Error>> {
677 let session_type = match frame.sub_function_value() {
679 Some(v) => v,
680 None => {
681 return self.nrc(
682 src,
683 0x10,
684 H::Error::incorrect_message_length_or_invalid_format(),
685 now,
686 )
687 }
688 };
689
690 if self.config.find_session(session_type).is_none() {
691 return self.nrc(src, 0x10, H::Error::sub_function_not_supported(), now);
692 }
693
694 let mut ctx = self.create_request_context();
695 let result = self.handler.session_control(&mut ctx, session_type);
696 self.handle_request_context(ctx);
697
698 if let Err(err) = result {
699 return self.nrc(src, 0x10, err, now);
700 }
701
702 self.session.session_type = session_type;
703 self.session.security_level = 0;
704 self.session.last_rx = now;
705 self.security.clear_pending();
706
707 if suppressed {
708 return Ok(());
709 }
710
711 let (p2_ms, p2_ext_ms) = self
712 .config
713 .find_session(session_type)
714 .map(|s| {
715 (
716 s.p2_timeout.as_millis(),
717 s.p2_extended_timeout.as_millis() / 10,
718 )
719 })
720 .unwrap_or((DEFAULT_P2, DEFAULT_P2_EXT));
721
722 let payload = [
723 session_type,
724 (p2_ms >> 8) as u8,
725 p2_ms as u8,
726 (p2_ext_ms >> 8) as u8,
727 p2_ext_ms as u8,
728 ];
729 self.pos(src, 0x10, &payload, now)
730 }
731
732 fn on_ecu_reset(
733 &mut self,
734 src: &NodeAddress,
735 frame: &UdsFrame<'_>,
736 suppressed: bool,
737 now: Instant,
738 ) -> Result<(), ServerError<H::Error>> {
739 let reset_type = match frame.sub_function_value() {
741 Some(v) => v,
742 None => {
743 return self.nrc(
744 src,
745 0x11,
746 H::Error::incorrect_message_length_or_invalid_format(),
747 now,
748 )
749 }
750 };
751
752 let mut ctx = self.create_request_context();
753
754 let result = self.handler
755 .ecu_reset(&mut ctx, reset_type);
756
757 self.handle_request_context(ctx);
758
759 if let Err(err) = result {
760 return self.nrc(src, 0x11, err, now);
761 }
762
763 if !suppressed {
764 self.pos(src, 0x11, &[reset_type], now)?;
765 }
766
767 Ok(())
768 }
769
770 fn on_security_access(
771 &mut self,
772 src: &NodeAddress,
773 frame: &UdsFrame<'_>,
774 _suppressed: bool, now: Instant,
776 ) -> Result<(), ServerError<H::Error>> {
777 let access_type = match frame.sub_function_value() {
779 Some(v) => v,
780 None => {
781 return self.nrc(
782 src,
783 0x27,
784 H::Error::incorrect_message_length_or_invalid_format(),
785 now,
786 )
787 }
788 };
789
790 let is_request_seed = access_type % 2 != 0;
791
792 if is_request_seed {
793 let level = access_type;
794
795 if self.security.is_locked(level, now) {
796 return self.nrc(src, 0x27, H::Error::required_time_delay_not_expired(), now);
797 }
798
799 let Some(config) = self.config.find_security_level(level) else {
800 return self.nrc(src, 0x27, H::Error::sub_function_not_supported(), now);
801 };
802
803 let mut frame: Vec<u8, MAX_FRAME> = Vec::new();
804
805 if self.security.pending_level == level
806 && !self.security.pending_seed.is_empty()
807 && self.security.pending_seed.len() == config.seed_length
808 {
809 #[cfg(feature = "defmt")]
810 {
811 defmt::unwrap!(frame.push(0x27 | 0x40));
812 defmt::unwrap!(frame.push(level));
813 defmt::unwrap!(frame.extend_from_slice(self.security.pending_seed.as_slice()));
814 }
815 #[cfg(not(feature = "defmt"))]
816 {
817 let _ = frame.push(0x27 | 0x40);
818 let _ = frame.push(level);
819 let _ = frame.extend_from_slice(self.security.pending_seed.as_slice());
820 }
821 return self.enqueue(src.clone(), frame);
822 }
823
824 let mut ctx = self.create_request_context();
825 let result = self.handler.security_access(&mut ctx, level, &[]);
826 self.handle_request_context(ctx);
827
828 if let Err(err) = result {
829 return self.nrc_raw(src, 0x27, err.into(), now);
830 }
831
832 let mut seed_buf = [0u8; MAX_SEED];
833 let result = self
834 .security_provider
835 .generate_seed(level, &mut seed_buf)
836 .map_err(|_| H::Error::conditions_not_correct());
837
838 let seed_len = match result {
839 Ok(v) => v,
840 Err(err) => {
841 return self.nrc_raw(src, 0x27, err.into(), now);
842 }
843 };
844
845 self.security.pending_seed.clear();
846 self.security.pending_level = level;
847
848 #[cfg(feature = "defmt")]
849 {
850 defmt::unwrap!(self.security.pending_seed.extend_from_slice(&seed_buf[..seed_len]));
851 defmt::unwrap!(frame.push(0x27 | 0x40));
852 defmt::unwrap!(frame.push(level));
853 defmt::unwrap!(frame.extend_from_slice(&seed_buf[..seed_len]));
854 }
855
856 #[cfg(not(feature = "defmt"))]
857 {
858 let _ = self.security.pending_seed.extend_from_slice(&seed_buf[..seed_len]);
859 let _ = frame.push(0x27 | 0x40);
860 let _ = frame.push(level);
861 let _ = frame.extend_from_slice(&seed_buf[..seed_len]);
862 }
863
864 self.enqueue(src.clone(), frame)
865 } else {
866 let level = access_type - 1; if self.security.is_locked(level, now) {
870 return self.nrc(src, 0x27, H::Error::required_time_delay_not_expired(), now);
871 }
872 if self.security.pending_level != level || self.security.pending_seed.is_empty() {
873 return self.nrc(src, 0x27, H::Error::request_sequence_error(), now);
874 }
875
876 let key = frame.payload().get(1..).unwrap_or(&[]);
879
880 let mut ctx = self.create_request_context();
881 let result = self.handler.security_access(&mut ctx, level, key);
882 self.handle_request_context(ctx);
883
884 if let Err(err) = result {
885 return self.nrc_raw(src, 0x27, err.into(), now);
886 }
887
888 let level_cfg = self.config.find_security_level(level);
889 let max_attempts = level_cfg
890 .map(|l| l.max_attempts)
891 .flatten()
892 .unwrap_or(DEFAULT_MAX_SECURITY_ATTEMPTS);
893 let lockout_dur = level_cfg
894 .map(|l| l.lockout_duration)
895 .flatten()
896 .unwrap_or(Duration::from_millis(DEFAULT_LOCKOUT));
897
898 let seed = self.security.pending_seed.clone();
899
900 match self.security_provider.validate_key(level, &seed, key) {
901 Ok(()) => {
902 self.security.reset_failed(level);
903 self.security.clear_pending();
904 self.session.security_level = level;
905 self.pos(src, 0x27, &[access_type], now)
906 }
907 Err(_) => {
908 self.security.increment_failed(level);
909 if self.security.failed_count(level) >= max_attempts {
910 self.security.set_lockout(level, now + lockout_dur);
911 self.security.clear_pending();
912 return self.nrc(src, 0x27, H::Error::exceeded_number_of_attempts(), now);
913 }
914 self.nrc(src, 0x27, H::Error::invalid_key(), now)
915 }
916 }
917 }
918 }
919
920 fn on_read_did(
921 &mut self,
922 src: &NodeAddress,
923 frame: &UdsFrame<'_>,
924 _suppressed: bool, now: Instant,
926 ) -> Result<(), ServerError<H::Error>> {
927 let payload = frame.payload();
929 if payload.len() < 2
930 || (!self.config.allow_read_many_dids && payload.len() != 2)
931 || payload.len() % 2 != 0
932 {
933 return self.nrc(
934 src,
935 0x22,
936 H::Error::incorrect_message_length_or_invalid_format(),
937 now,
938 );
939 }
940
941 let mut resp: Vec<u8, MAX_FRAME> = Vec::new();
942
943 for chunk in payload.chunks_exact(2) {
944 let did = u16::from_be_bytes([chunk[0], chunk[1]]);
945
946 if !self.config.did_readable(did, self.session.session_type) {
947 return self.nrc(src, 0x22, H::Error::request_out_of_range(), now);
948 }
949 let required_sec = self
950 .config
951 .find_did(did)
952 .map(|d| d.security_level)
953 .unwrap_or(0);
954 if let Err(nrc) = self.guard_security(required_sec) {
955 return self.nrc_raw(src, 0x22, nrc, now);
956 }
957
958 #[cfg(feature = "defmt")]
959 {
960 defmt::unwrap!(resp.push(chunk[0]));
961 defmt::unwrap!(resp.push(chunk[1]));
962 }
963
964 #[cfg(not(feature = "defmt"))]
965 {
966 let _ = resp.push(chunk[0]);
967 let _ = resp.push(chunk[1]);
968 }
969
970 let mut ctx = self.create_request_context();
971
972 let mut data_buf = [0u8; MAX_FRAME];
973 let result = self
974 .handler
975 .read_did(&mut ctx, did, &mut data_buf);
976
977 self.handle_request_context(ctx);
978
979 let len = match result {
980 Ok(v) => v,
981 Err(err) => {
982 return self.nrc_raw(src, 0x22, err.into(), now);
983 }
984 };
985
986 #[cfg(feature = "defmt")]
987 defmt::unwrap!(resp.extend_from_slice(&data_buf[..len]));
988
989 #[cfg(not(feature = "defmt"))]
990 let _ = resp.extend_from_slice(&data_buf[..len]);
991 }
992
993 self.pos(src, 0x22, &resp, now)
994 }
995
996 fn on_write_did(
997 &mut self,
998 src: &NodeAddress,
999 frame: &UdsFrame<'_>,
1000 _suppressed: bool,
1001 now: Instant,
1002 ) -> Result<(), ServerError<H::Error>> {
1003 let payload = frame.payload();
1004 if payload.len() < 3 {
1005 return self.nrc(
1006 src,
1007 0x2E,
1008 H::Error::incorrect_message_length_or_invalid_format(),
1009 now,
1010 );
1011 }
1012
1013 let did = u16::from_be_bytes([payload[0], payload[1]]);
1014 let data_rec = &payload[2..];
1015
1016 if !self.config.did_writable(did, self.session.session_type) {
1017 return self.nrc(src, 0x2E, H::Error::request_out_of_range(), now);
1018 }
1019 let required_sec = self
1020 .config
1021 .find_did(did)
1022 .map(|d| d.security_level)
1023 .unwrap_or(0);
1024 if let Err(nrc) = self.guard_security(required_sec) {
1025 return self.nrc_raw(src, 0x2E, nrc, now);
1026 }
1027
1028 let mut ctx = self.create_request_context();
1029
1030 let result = self.handler
1031 .write_did(&mut ctx, did, data_rec);
1032
1033 self.handle_request_context(ctx);
1034
1035 if let Err(err) = result {
1036 return self.nrc_raw(src, 0x2E, err.into(), now);
1037 }
1038
1039 self.pos(src, 0x2E, &payload[..2], now)
1040 }
1041
1042 fn on_periodic_did(
1043 &mut self,
1044 src: &NodeAddress,
1045 frame: &UdsFrame<'_>,
1046 _suppressed: bool,
1047 now: Instant,
1048 ) -> Result<(), ServerError<H::Error>> {
1049 let payload = frame.payload();
1050 if payload.is_empty() {
1051 return self.nrc(
1052 src,
1053 0x2A,
1054 H::Error::incorrect_message_length_or_invalid_format(),
1055 now,
1056 );
1057 }
1058
1059 let mode = payload[0];
1061 let periodic_ids = payload.get(1..).unwrap_or(&[]);
1062
1063 let mut ctx = self.create_request_context();
1064 let result = self.handler.periodic_did(&mut ctx, mode, periodic_ids);
1065 self.handle_request_context(ctx);
1066
1067 if let Err(err) = result {
1068 return self.nrc_raw(src, 0x2A, err.into(), now);
1069 }
1070
1071 match mode {
1072 0x04 => {
1074 for &id in periodic_ids {
1075 self.periodic.cancel(0xF200u16 | id as u16, src);
1076 }
1077 self.pos(src, 0x2A, &[mode], now)
1078 }
1079 0x01 | 0x02 | 0x03 => {
1080 let requested_interval = match mode {
1081 0x01 => periodic::SLOW,
1082 0x02 => periodic::MEDIUM,
1083 _ => periodic::FAST,
1084 };
1085
1086 for &id in periodic_ids {
1087 let did = 0xF200u16 | id as u16;
1088
1089 if !self.config.did_readable(did, self.session.session_type) {
1090 return self.nrc(src, 0x2A, H::Error::request_out_of_range(), now);
1091 }
1092
1093 let effective = self
1094 .config
1095 .find_did(did)
1096 .map(|d| requested_interval.max(d.min_periodic_interval))
1097 .unwrap_or(requested_interval);
1098
1099 self.periodic.register(did, effective, src.clone(), now);
1100 }
1101 self.pos(src, 0x2A, &[mode], now)
1102 }
1103 _ => self.nrc(src, 0x2A, H::Error::sub_function_not_supported(), now),
1104 }
1105 }
1106
1107 fn on_routine_control(
1108 &mut self,
1109 src: &NodeAddress,
1110 frame: &UdsFrame<'_>,
1111 suppressed: bool,
1112 now: Instant,
1113 ) -> Result<(), ServerError<H::Error>> {
1114 let payload = frame.payload();
1117 if payload.len() < 3 {
1118 return self.nrc(
1119 src,
1120 0x31,
1121 H::Error::incorrect_message_length_or_invalid_format(),
1122 now,
1123 );
1124 }
1125
1126 let sub_function = frame.sub_function_value().unwrap_or(0);
1127 let routine_id = u16::from_be_bytes([payload[1], payload[2]]);
1128 let option_record = payload.get(3..).unwrap_or(&[]);
1129
1130 let mut ctx = self.create_request_context();
1131
1132 let mut buf = [0u8; MAX_FRAME];
1133 let result = self
1134 .handler
1135 .routine_control(&mut ctx, routine_id, sub_function, option_record, &mut buf);
1136
1137 self.handle_request_context(ctx);
1138
1139 let len = match result {
1140 Ok(v) => v,
1141 Err(err) => {
1142 return self.nrc_raw(src, 0x31, err.into(), now);
1143 }
1144 };
1145
1146 if suppressed {
1147 return Ok(());
1148 }
1149
1150 let mut resp: Vec<u8, MAX_FRAME> = Vec::new();
1151
1152 #[cfg(feature = "defmt")]
1153 {
1154 defmt::unwrap!(resp.push(sub_function));
1155 defmt::unwrap!(resp.push(payload[1]));
1156 defmt::unwrap!(resp.push(payload[2]));
1157 defmt::unwrap!(resp.extend_from_slice(&buf[..len]));
1158 }
1159
1160 #[cfg(not(feature = "defmt"))]
1161 {
1162 let _ = resp.push(sub_function);
1163 let _ = resp.push(payload[1]);
1164 let _ = resp.push(payload[2]);
1165 let _ = resp.extend_from_slice(&buf[..len]);
1166 }
1167
1168 self.pos(src, 0x31, &resp, now)
1169 }
1170
1171 fn on_communication_control(
1172 &mut self,
1173 src: &NodeAddress,
1174 frame: &UdsFrame<'_>,
1175 suppressed: bool,
1176 now: Instant,
1177 ) -> Result<(), ServerError<H::Error>> {
1178 let payload = frame.payload();
1179 if payload.len() < 2 {
1180 return self.nrc(
1181 src,
1182 0x28,
1183 H::Error::incorrect_message_length_or_invalid_format(),
1184 now,
1185 );
1186 }
1187
1188 let control_type = frame.sub_function_value().unwrap_or(0);
1189 let comm_type = payload[1];
1190
1191 let mut ctx = self.create_request_context();
1192
1193 let result = self.handler
1194 .communication_control(&mut ctx, control_type, comm_type);
1195
1196 self.handle_request_context(ctx);
1197
1198 if let Err(err) = result {
1199 return self.nrc_raw(src, 0x28, err.into(), now);
1200 }
1201
1202 if suppressed {
1203 return Ok(());
1204 }
1205
1206 self.pos(src, 0x28, &[control_type], now)
1207 }
1208
1209 fn on_io_control(
1210 &mut self,
1211 src: &NodeAddress,
1212 frame: &UdsFrame<'_>,
1213 _suppressed: bool,
1214 now: Instant,
1215 ) -> Result<(), ServerError<H::Error>> {
1216 let payload = frame.payload();
1217 if payload.len() < 3 {
1218 return self.nrc(
1219 src,
1220 0x2F,
1221 H::Error::incorrect_message_length_or_invalid_format(),
1222 now,
1223 );
1224 }
1225
1226 let did = u16::from_be_bytes([payload[0], payload[1]]);
1227 let control_param = payload[2];
1228 let control_state = payload.get(3..).unwrap_or(&[]);
1229
1230 let mut ctx = self.create_request_context();
1231
1232 let mut buf = [0u8; MAX_FRAME];
1233 let result = self
1234 .handler
1235 .io_control(&mut ctx, did, control_param, control_state, &mut buf);
1236
1237 self.handle_request_context(ctx);
1238
1239 let len = match result {
1240 Ok(v) => v,
1241 Err(err) => {
1242 return self.nrc_raw(src, 0x2F, err.into(), now);
1243 }
1244 };
1245
1246 let mut resp: Vec<u8, MAX_FRAME> = Vec::new();
1247
1248 #[cfg(feature = "defmt")]
1249 {
1250 defmt::unwrap!(resp.push(payload[0]));
1251 defmt::unwrap!(resp.push(payload[1]));
1252 defmt::unwrap!(resp.extend_from_slice(&buf[..len]));
1253 }
1254
1255 #[cfg(not(feature = "defmt"))]
1256 {
1257 let _ = resp.push(payload[0]);
1258 let _ = resp.push(payload[1]);
1259 let _ = resp.extend_from_slice(&buf[..len]);
1260 }
1261
1262 self.pos(src, 0x2F, &resp, now)
1263 }
1264
1265 fn on_request_download(
1266 &mut self,
1267 src: &NodeAddress,
1268 frame: &UdsFrame<'_>,
1269 _suppressed: bool,
1270 now: Instant,
1271 ) -> Result<(), ServerError<H::Error>> {
1272 let payload = frame.payload();
1275 if payload.len() < 3 {
1276 return self.nrc(
1277 src,
1278 0x34,
1279 H::Error::incorrect_message_length_or_invalid_format(),
1280 now,
1281 );
1282 }
1283
1284 let data_format = payload[0];
1285 let addr_and_len_format = payload[1];
1286 let addr_len = (addr_and_len_format >> 4) as usize;
1287 let size_len = (addr_and_len_format & 0x0F) as usize;
1288
1289 if payload.len() < 2 + addr_len + size_len {
1290 return self.nrc(
1291 src,
1292 0x34,
1293 H::Error::incorrect_message_length_or_invalid_format(),
1294 now,
1295 );
1296 }
1297
1298 let memory_address = &payload[2..2 + addr_len];
1299 let memory_size = &payload[2 + addr_len..2 + addr_len + size_len];
1300
1301 let mut ctx = self.create_request_context();
1302
1303 let mut buf = [0u8; 64];
1304 let result = self
1305 .handler
1306 .request_download(&mut ctx, memory_address, memory_size, data_format, 0, &mut buf);
1307
1308 self.handle_request_context(ctx);
1309
1310 let len = match result {
1311 Ok(v) => v,
1312 Err(err) => {
1313 return self.nrc_raw(src, 0x34, err.into(), now);
1314 }
1315 };
1316
1317 self.pos(src, 0x34, &buf[..len], now)
1318 }
1319
1320 fn on_transfer_data(
1321 &mut self,
1322 src: &NodeAddress,
1323 frame: &UdsFrame<'_>,
1324 _suppressed: bool,
1325 now: Instant,
1326 ) -> Result<(), ServerError<H::Error>> {
1327 let payload = frame.payload();
1328 if payload.is_empty() {
1329 return self.nrc(
1330 src,
1331 0x36,
1332 H::Error::incorrect_message_length_or_invalid_format(),
1333 now,
1334 );
1335 }
1336
1337 let block_seq = payload[0];
1338 let data = payload.get(1..).unwrap_or(&[]);
1339
1340 let mut ctx = self.create_request_context();
1341
1342 let mut buf = [0u8; MAX_FRAME];
1343 let result = self
1344 .handler
1345 .transfer_data(&mut ctx, block_seq, data, &mut buf);
1346
1347 self.handle_request_context(ctx);
1348
1349 let len = match result {
1350 Ok(v) => v,
1351 Err(err) => {
1352 return self.nrc_raw(src, 0x36, err.into(), now);
1353 }
1354 };
1355
1356 let mut resp: Vec<u8, MAX_FRAME> = Vec::new();
1357
1358 #[cfg(feature = "defmt")]
1359 {
1360 defmt::unwrap!(resp.push(block_seq));
1361 defmt::unwrap!(resp.extend_from_slice(&buf[..len]));
1362 }
1363
1364 #[cfg(not(feature = "defmt"))]
1365 {
1366 let _ = resp.push(block_seq);
1367 let _ = resp.extend_from_slice(&buf[..len]);
1368 }
1369
1370 self.pos(src, 0x36, &resp, now)
1371 }
1372
1373 fn on_transfer_exit(
1374 &mut self,
1375 src: &NodeAddress,
1376 frame: &UdsFrame<'_>,
1377 _suppressed: bool,
1378 now: Instant,
1379 ) -> Result<(), ServerError<H::Error>> {
1380 let parameter_record = frame.payload();
1381
1382 let mut ctx = self.create_request_context();
1383
1384 let mut buf = [0u8; MAX_FRAME];
1385 let result = self
1386 .handler
1387 .request_transfer_exit(&mut ctx, parameter_record, &mut buf);
1388
1389 self.handle_request_context(ctx);
1390
1391 let len = match result {
1392 Ok(v) => v,
1393 Err(err) => {
1394 return self.nrc_raw(src, 0x37, err.into(), now);
1395 }
1396 };
1397
1398 self.pos(src, 0x37, &buf[..len], now)
1399 }
1400
1401 fn on_file_transfer(
1402 &mut self,
1403 src: &NodeAddress,
1404 frame: &UdsFrame<'_>,
1405 _suppressed: bool,
1406 now: Instant,
1407 ) -> Result<(), ServerError<H::Error>> {
1408 let payload = frame.payload();
1409 if payload.len() < 3 {
1410 return self.nrc(
1411 src,
1412 0x38,
1413 H::Error::incorrect_message_length_or_invalid_format(),
1414 now,
1415 );
1416 }
1417
1418 let operation = payload[0];
1419 let path_len = u16::from_be_bytes([payload[1], payload[2]]) as usize;
1421 let path = payload.get(3..3 + path_len).unwrap_or(&[]);
1422
1423 let mut ctx = self.create_request_context();
1424
1425 let mut buf = [0u8; MAX_FRAME];
1426 let result = self
1427 .handler
1428 .request_file_transfer(&mut ctx, operation, path, &mut buf);
1429
1430 self.handle_request_context(ctx);
1431
1432 let len = match result {
1433 Ok(v) => v,
1434 Err(err) => {
1435 return self.nrc_raw(src, 0x38, err.into(), now);
1436 }
1437 };
1438
1439 self.pos(src, 0x38, &buf[..len], now)
1440 }
1441
1442 fn dispatch_periodic(&mut self, now: Instant) -> Result<(), ServerError<H::Error>> {
1447 let mut due: Vec<(u16, NodeAddress), MAX_PERIODIC> = Vec::new();
1448 self.periodic.collect_due(now, &mut due);
1449
1450 for (did, client) in &due {
1451 let mut ctx = self.create_request_context();
1452
1453 let mut data_buf = [0u8; MAX_FRAME];
1454 let result = self
1455 .handler
1456 .read_did(&mut ctx, *did, &mut data_buf);
1457
1458 self.handle_request_context(ctx);
1459
1460 let len = match result {
1461 Ok(v) => v,
1462 Err(err) => {
1463 let nrc = err.into();
1464
1465 #[cfg(feature = "defmt")]
1466 defmt::error!("periodic error: {=u8}", nrc);
1467
1468 self.periodic.cancel(*did, client);
1469 continue;
1470 }
1471 };
1472
1473 let did_low = (*did & 0xFF) as u8;
1475 let mut frame = Vec::new();
1476
1477 #[cfg(feature = "defmt")]
1478 {
1479 defmt::unwrap!(frame.push(did_low));
1480 defmt::unwrap!(frame.extend_from_slice(&data_buf[..len]));
1481 }
1482
1483 #[cfg(not(feature = "defmt"))]
1484 {
1485 let _ = frame.push(did_low);
1486 let _ = frame.extend_from_slice(&data_buf[..len]);
1487 }
1488
1489
1490 self.enqueue(client.clone(), frame)?;
1491 self.periodic.advance(*did, client, now);
1492 }
1493
1494 Ok(())
1495 }
1496
1497 fn create_request_context(&mut self) -> UdsRequestContext<S> {
1498 UdsRequestContext {
1499 session: self.session.clone(),
1500 security_provider: self.security_provider.clone(),
1501 drop_requests: false,
1502 clear_outbox: false,
1503 reset_security_state: false
1504 }
1505 }
1506
1507 fn handle_request_context(&mut self, ctx: UdsRequestContext<S>) {
1508 if ctx.session != self.session {
1509 self.session.session_type = ctx.session.session_type;
1510 self.session.security_level = ctx.session.security_level;
1511 }
1512 if ctx.clear_outbox {
1513 self.outbox.clear();
1514 }
1515 if ctx.reset_security_state {
1516 self.security.reset();
1517 }
1518 if ctx.drop_requests {
1519 self.drop_requests = true;
1520 }
1521 }
1522
1523 }
1525
1526#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1529pub struct UdsRequestContext<T>
1530where
1531 T: SecurityProvider
1532{
1533 pub session: SessionState,
1534 pub security_provider: T,
1535 pub(crate) drop_requests: bool,
1536 pub(crate) clear_outbox: bool,
1537 pub(crate) reset_security_state: bool,
1538}
1539
1540impl<T> UdsRequestContext<T>
1541where
1542 T: SecurityProvider
1543{
1544 pub fn drop_requests(&mut self) {
1545 self.drop_requests = true;
1546 }
1547
1548 pub fn clear_outbox(&mut self) {
1549 self.clear_outbox = true;
1550 }
1551
1552 pub fn reset_security_state(&mut self) {
1553 self.reset_security_state = true;
1554 }
1555}