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 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 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))); #[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 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 if suppressed {
660 return Ok(());
661 }
662 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 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 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, now: Instant,
773 ) -> Result<(), ServerError<H::Error>> {
774 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 let level = access_type - 1; 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 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, now: Instant,
923 ) -> Result<(), ServerError<H::Error>> {
924 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 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 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 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 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 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 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 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 }
1522
1523#[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}