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