Skip to main content

docan_rs/server/
mod.rs

1mod context;
2mod service;
3mod session;
4mod util;
5
6use crate::{constants::LOG_TAG_SERVER, server::session::SessionManager, DoCanError, SecurityAlgo};
7use iso14229_1::{response::SessionTiming, Configuration, DataIdentifier};
8use rsutil::types::ByteOrder;
9use serde::{Deserialize, Deserializer};
10use std::collections::HashMap;
11
12use iso14229_1::{
13    request::Request,
14    response::{Code, Response},
15    Iso14229Error, Service,
16};
17use iso15765_2::{
18    can::{Address, AddressType, CanIsoTp},
19    IsoTp, IsoTpError,
20};
21use rs_can::{CanDevice, CanFrame};
22use std::{fmt::Display, sync::Arc};
23use tokio::{spawn, task::JoinHandle};
24
25pub type DidSaLevel = HashMap<DataIdentifier, u8>;
26
27fn did_sa_level_deserialize<'de, D>(deserializer: D) -> Result<DidSaLevel, D::Error>
28where
29    D: Deserializer<'de>,
30{
31    let raw_map: HashMap<u16, u8> = HashMap::deserialize(deserializer)?;
32
33    let res = raw_map
34        .into_iter()
35        .map(|(k, v)| (DataIdentifier::from(k), v))
36        .collect::<HashMap<_, _>>();
37
38    Ok(res)
39}
40
41#[allow(unused)]
42#[derive(Debug, Clone, Deserialize)]
43pub struct Config {
44    pub(crate) address: Address,
45    pub(crate) timing: SessionTiming,
46    /// extend session security access level
47    pub(crate) extend_sa_level: u8,
48    /// program session security access level
49    pub(crate) program_sa_level: u8,
50    pub(crate) seed_len: usize,
51    pub(crate) sa_salt: Vec<u8>,
52    pub(crate) cfg: Configuration,
53    #[serde(deserialize_with = "did_sa_level_deserialize")]
54    pub(crate) did_sa_level: DidSaLevel,
55    pub(crate) byte_order: ByteOrder,
56}
57
58#[async_trait::async_trait]
59pub trait Server {
60    async fn update_address(&self, address: Address);
61    async fn update_security_algo(&self, algo: SecurityAlgo);
62    async fn service_forever(&mut self, interval_us: u64);
63
64    async fn service_stop(&mut self);
65}
66
67#[derive(Clone)]
68pub struct DoCanServer<D, C, F> {
69    isotp: CanIsoTp<D, C, F>,
70    session: SessionManager,
71    context: context::Context,
72    handles: Vec<Arc<JoinHandle<()>>>,
73}
74
75impl<D, C, F> DoCanServer<D, C, F>
76where
77    D: CanDevice<Channel = C, Frame = F> + Clone + Send + 'static,
78    C: Clone + Eq + Display + Send + Sync + 'static,
79    F: CanFrame<Channel = C> + Clone + Display + 'static,
80{
81    pub async fn new(device: D, channel: C) -> Result<Self, DoCanError> {
82        let context = context::Context::new().await?;
83        Ok(Self {
84            isotp: CanIsoTp::new(device, channel, context.config.address, true).await,
85            session: SessionManager::new(None),
86            context,
87            handles: Default::default(),
88        })
89    }
90
91    #[inline(always)]
92    pub fn tp_layer(&mut self) -> CanIsoTp<D, C, F> {
93        self.isotp.clone()
94    }
95
96    async fn server(&mut self) {
97        loop {
98            let timing = self.context.get_active_timing().await;
99            let cfg = self.context.get_cfg().clone();
100            if let Ok(data) = self.isotp.wait_data(timing.p2_ms()).await {
101                // rsutil::info!("{} Received data: {}", LOG_TAG_SERVER, hex::encode(&data));
102                match data.len() {
103                    0 => {}
104                    _ => match Service::try_from(data[0]) {
105                        Ok(service) => match Request::try_from((service, &data[1..], &cfg)) {
106                            Ok(req) => {
107                                if let Err(e) = match service {
108                                    Service::SessionCtrl => {
109                                        self.session_ctrl(req, &cfg, timing.into()).await
110                                    }
111                                    Service::ECUReset => self.ecu_reset(req, &cfg).await,
112                                    Service::ClearDiagnosticInfo => {
113                                        self.clear_diagnostic_info(req, &cfg).await
114                                    }
115                                    Service::ReadDTCInfo => self.read_dtc_info(req, &cfg).await,
116                                    Service::ReadDID => self.read_did(req, &cfg).await,
117                                    Service::ReadMemByAddr => {
118                                        self.read_mem_by_addr(req, &cfg).await
119                                    }
120                                    Service::ReadScalingDID => {
121                                        self.read_scaling_did(req, &cfg).await
122                                    }
123                                    Service::SecurityAccess => {
124                                        self.security_access(req, &cfg).await
125                                    }
126                                    Service::CommunicationCtrl => {
127                                        self.communication_ctrl(req, &cfg).await
128                                    }
129                                    #[cfg(any(feature = "std2020"))]
130                                    Service::Authentication => self.authentication(req, &cfg).await,
131                                    Service::ReadDataByPeriodId => {
132                                        self.read_data_by_pid(req, &cfg).await
133                                    }
134                                    Service::DynamicalDefineDID => {
135                                        self.dynamically_define_did(req, &cfg).await
136                                    }
137                                    Service::WriteDID => self.write_did(req, &cfg).await,
138                                    Service::IOCtrl => self.io_ctrl(req, &cfg).await,
139                                    Service::RoutineCtrl => self.routine_ctrl(req, &cfg).await,
140                                    Service::RequestDownload => {
141                                        self.request_download(req, &cfg).await
142                                    }
143                                    Service::RequestUpload => self.request_upload(req, &cfg).await,
144                                    Service::TransferData => self.transfer_data(req, &cfg).await,
145                                    Service::RequestTransferExit => {
146                                        self.request_transfer_exit(req, &cfg).await
147                                    }
148                                    #[cfg(any(feature = "std2013", feature = "std2020"))]
149                                    Service::RequestFileTransfer => {
150                                        self.request_file_transfer(req, &cfg).await
151                                    }
152                                    Service::WriteMemByAddr => {
153                                        self.write_mem_by_addr(req, &cfg).await
154                                    }
155                                    Service::TesterPresent => self.tester_present(req, &cfg).await,
156                                    #[cfg(any(feature = "std2006", feature = "std2013"))]
157                                    Service::AccessTimingParam => {
158                                        self.access_timing_parameter(req, &cfg).await
159                                    }
160                                    Service::SecuredDataTrans => {
161                                        self.secured_data_trans(req, &cfg).await
162                                    }
163                                    Service::CtrlDTCSetting => {
164                                        self.ctrl_dtc_setting(req, &cfg).await
165                                    }
166                                    Service::ResponseOnEvent => {
167                                        self.response_on_event(req, &cfg).await
168                                    }
169                                    Service::LinkCtrl => self.link_ctrl(req, &cfg).await,
170                                    Service::NRC => {
171                                        self.negative_service(
172                                            Service::NRC.into(),
173                                            Code::ServiceNotSupported,
174                                        )
175                                        .await;
176                                        Ok(())
177                                    }
178                                } {
179                                    self.process_uds_error(service, e).await;
180                                }
181                            }
182                            Err(e) => {
183                                rsutil::warn!(
184                                    "{} error: {} when data: {} to request",
185                                    LOG_TAG_SERVER,
186                                    e,
187                                    hex::encode(&data)
188                                );
189                                self.process_uds_error(service, e).await;
190                            }
191                        },
192                        Err(_) => {
193                            // can't parse service
194                            self.negative_service(data[0], Code::ServiceNotSupported)
195                                .await
196                        }
197                    },
198                }
199            }
200        }
201    }
202
203    async fn negative_service(&self, service: u8, code: Code) {
204        let data = vec![Service::NRC.into(), service, code.into()];
205        if let Err(e) = self.isotp.transmit(AddressType::Physical, data).await {
206            rsutil::error!(
207                "{} can't transmit negative response, because of: {}",
208                LOG_TAG_SERVER,
209                e
210            );
211        }
212    }
213
214    async fn process_uds_error(&self, service: Service, e: Iso14229Error) {
215        let code = match e {
216            // Iso14229Error::InvalidParam(_) => {}
217            // Iso14229Error::InvalidData(_) => {}
218            Iso14229Error::InvalidDataLength { .. } => Code::IncorrectMessageLengthOrInvalidFormat,
219            // Iso14229Error::DidNotSupported(_) => {}
220            // Iso14229Error::InvalidDynamicallyDefinedDID(_) => {}
221            // Iso14229Error::InvalidSessionData(_) => {}
222            // Iso14229Error::ReservedError(_) => {}
223            // Iso14229Error::SubFunctionError(_) => {}
224            Iso14229Error::ServiceError(_) => Code::ConditionsNotCorrect,
225            // Iso14229Error::OtherError(_) => {}
226            // Iso14229Error::NotImplement => {}
227            _ => Code::GeneralReject, // TODO
228        };
229        self.transmit_response(Response::new_negative(service, code), true)
230            .await;
231    }
232
233    pub(crate) async fn transmit_response(&self, resp: Response, flag: bool) {
234        let service = resp.service();
235        let data: Vec<_> = resp.into();
236        if let Err(e) = self.isotp.transmit(AddressType::Physical, data).await {
237            rsutil::warn!("{} transmit error: {:?}", LOG_TAG_SERVER, e);
238            if !flag {
239                // resend negative response is no-need
240                return;
241            }
242
243            if let Some(code) = match e {
244                // IsoTpError::DeviceError => {}
245                IsoTpError::EmptyPdu => Some(Code::IncorrectMessageLengthOrInvalidFormat),
246                IsoTpError::InvalidPdu(_) => Some(Code::GeneralReject),
247                IsoTpError::InvalidParam(_) => Some(Code::GeneralReject),
248                IsoTpError::InvalidDataLength { .. } => {
249                    Some(Code::IncorrectMessageLengthOrInvalidFormat)
250                }
251                IsoTpError::LengthOutOfRange(_) => Some(Code::RequestOutOfRange),
252                IsoTpError::InvalidStMin(_) => Some(Code::GeneralReject),
253                IsoTpError::InvalidSequence { .. } => Some(Code::WrongBlockSequenceCounter),
254                IsoTpError::MixFramesError => Some(Code::GeneralReject),
255                IsoTpError::Timeout { .. } => Some(Code::GeneralReject),
256                IsoTpError::OverloadFlow => Some(Code::RequestOutOfRange),
257                _ => None,
258            } {
259                let resp = Response::new_negative(service, code);
260                Box::pin(self.transmit_response(resp, false)).await;
261            }
262        }
263    }
264}
265
266#[async_trait::async_trait]
267impl<D, C, F> Server for DoCanServer<D, C, F>
268where
269    D: CanDevice<Channel = C, Frame = F> + Clone + Send + 'static,
270    C: Clone + Eq + Display + Send + Sync + 'static,
271    F: CanFrame<Channel = C> + Clone + Display + 'static,
272{
273    #[inline(always)]
274    async fn update_address(&self, address: Address) {
275        self.isotp.update_address(address).await;
276    }
277
278    #[inline(always)]
279    async fn update_security_algo(&self, algo: SecurityAlgo) {
280        self.context.set_security_algo(algo).await;
281    }
282
283    async fn service_forever(&mut self, interval_us: u64) {
284        self.isotp.start(interval_us).await;
285        let mut clone = self.clone();
286        let session = self.session.clone();
287        let handle = spawn(async move { session.work().await });
288        self.handles.push(Arc::new(handle));
289        let handle = spawn(async move { clone.server().await });
290        self.handles.push(Arc::new(handle));
291    }
292
293    async fn service_stop(&mut self) {
294        self.isotp.stop().await;
295        for handle in &self.handles {
296            handle.abort();
297        }
298        rsutil::info!("{} stopped", LOG_TAG_SERVER);
299    }
300}