docan_rs/server/server_impl/
mod.rs

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