Skip to main content

acex_server/
handler.rs

1// region: Imports
2
3use crate::nrc::NrcError;
4use crate::security_provider::SecurityProvider;
5use crate::server::UdsRequestContext;
6// endregion: Imports
7
8// region: ServerHandler
9
10/// Application-level hook trait for UDS service handling.
11///
12/// The server state machine calls these hooks when a valid, session-permitted, security-cleared
13/// request arrives that requires application data or action. The server handles all protocol
14/// framing, session management, security access state, and periodic scheduling internally - the
15/// handler only sees the decoded parameters.
16///
17/// # Required vs Optional Hooks
18///
19/// Required hooks have no default implementation - the compiler enforces them. Optional hooks
20/// default to NRC 0x11 (Service Not Supported). Override only the services your ECU actually
21/// supports.
22///
23/// # Buffer Convention
24///
25/// Response data is written into the provided `buf` slice. The return value is the number of valid
26/// bytes written. The server sends only `buf[..len]`.
27///
28/// # Error Mapping
29///
30/// `type Error` must implement [`NrcError`] + `Into<u8>`. The server converts handler errors
31/// directly to NRC bytes in the negative response.
32pub trait ServerHandler<S>
33where
34    S: SecurityProvider
35{
36    type Error: NrcError;
37
38    // region: Required Hooks
39
40    /// Reads the value of a data identifier into `buf`.
41    ///
42    /// Called for `ReadDataByIdentifier` (0x22) and periodic scheduling (0x2A). Returns the number
43    /// of bytes written into `buf`.
44    fn read_did(
45        &self,
46        _ctx: &mut UdsRequestContext<S>,
47        _did: u16,
48        _buf: &mut [u8]
49    ) -> Result<usize, Self::Error> {
50        Err(Self::Error::service_not_supported())
51    }
52
53    /// Writes a value to a data identifier.
54    ///
55    /// Called for `WriteDataByIdentifier` (0x2E).
56    fn write_did(
57        &mut self,
58        _ctx: &mut UdsRequestContext<S>,
59        _did: u16,
60        _data: &[u8]
61    ) -> Result<(), Self::Error> {
62        Err(Self::Error::service_not_supported())
63    }
64
65    /// Executes an ECU Reset.
66    ///
67    /// Called for `EcuReset` (0x11). Reset Types: 0x01 Hard Reset, 0x02 KeyOffOnReset, 0x03
68    /// SoftReset. The positive response is sent before this hook is called.
69    fn ecu_reset(
70        &mut self,
71        _ctx: &mut UdsRequestContext<S>,
72        _reset_type: u8
73    ) -> Result<(), Self::Error> {
74        Err(Self::Error::service_not_supported())
75    }
76
77    // endregion: Required Hooks
78
79    // region: Optional Hooks
80
81    /// Executes a routine control operation.
82    ///
83    /// Called for `Routine Control` (0x31). Sub-Functions: 0x01 Start Routine, 0x02 Stop Routine,
84    /// 0x03 Request Routine Results.
85    ///
86    /// Return the number of bytes written into `buf`.
87    fn routine_control(
88        &mut self,
89        _ctx: &mut UdsRequestContext<S>,
90        _routine_id: u16,
91        _sub_function: u8,
92        _data: &[u8],
93        _buf: &mut [u8],
94    ) -> Result<usize, Self::Error> {
95        Err(Self::Error::service_not_supported())
96    }
97
98    /// Controls communication on a network channel.
99    ///
100    /// Called for `CommunicationControl` (0x28)
101    fn communication_control(
102        &mut self,
103        _ctx: &mut UdsRequestContext<S>,
104        _control_type: u8,
105        _comm_type: u8,
106    ) -> Result<usize, Self::Error> {
107        Err(Self::Error::service_not_supported())
108    }
109
110    /// Initiates a data download session.
111    ///
112    /// Called for `RequestDownload` (0x34).
113    ///
114    /// Returns max block length encoded in `buf`.
115    fn request_download(
116        &mut self,
117        _ctx: &mut UdsRequestContext<S>,
118        _memory_address: &[u8],
119        _memory_size: &[u8],
120        _compression_method: u8,
121        _encrypting_method: u8,
122        _buf: &mut [u8],
123    ) -> Result<usize, Self::Error> {
124        Err(Self::Error::service_not_supported())
125    }
126
127    /// Controls an input or output signal
128    ///
129    /// Called for `InputOutputControlByIdentifier` (0x2F).
130    ///
131    /// Returns the number of bytes written into `buf`.
132    fn io_control(
133        &mut self,
134        _ctx: &mut UdsRequestContext<S>,
135        _did: u16,
136        _parameter: u8,
137        _control_state: &[u8],
138        _buf: &mut [u8],
139    ) -> Result<usize, Self::Error> {
140        Err(Self::Error::service_not_supported())
141    }
142
143    /// Transfers a block of data.
144    ///
145    /// Called for `TransferData` (0x36).
146    ///
147    /// Returns the number of bytes written into `buf`.
148    fn transfer_data(
149        &mut self,
150        _ctx: &mut UdsRequestContext<S>,
151        _block_sequence_counter: u8,
152        _data: &[u8],
153        _buf: &mut [u8],
154    ) -> Result<usize, Self::Error> {
155        Err(Self::Error::service_not_supported())
156    }
157
158    /// Finalises a data transfer session.
159    ///
160    /// Called for `RequestTransferExit` (0x37).
161    ///
162    /// Returns the number of bytes written into `buf`.
163    fn request_transfer_exit(
164        &mut self,
165        _ctx: &mut UdsRequestContext<S>,
166        _parameter_record: &[u8],
167        _buf: &mut [u8],
168    ) -> Result<usize, Self::Error> {
169        Err(Self::Error::service_not_supported())
170    }
171
172    /// Initiates a file transfer operation.
173    ///
174    /// Called for `RequestFileTransfer` (0x38).
175    ///
176    /// Returns the number of bytes written into `buf`.
177    fn request_file_transfer(
178        &mut self,
179        _ctx: &mut UdsRequestContext<S>,
180        _operation: u8,
181        _path: &[u8],
182        _buf: &mut [u8],
183    ) -> Result<usize, Self::Error> {
184        Err(Self::Error::service_not_supported())
185    }
186
187    /// Session Control middleware.
188    fn session_control(
189        &mut self,
190        _ctx: &mut UdsRequestContext<S>,
191        _session_type: u8
192    ) -> Result<(), Self::Error> {
193        Ok(())
194    }
195
196    /// Security Access middleware.
197    fn security_access(
198        &mut self,
199        _ctx: &mut UdsRequestContext<S>,
200        _level: u8,
201        _key: &[u8]
202    ) -> Result<(), Self::Error> {
203        Ok(())
204    }
205
206    /// Read Data By Periodic Identifier middleware.
207    fn periodic_did(
208        &mut self,
209        _ctx: &mut UdsRequestContext<S>,
210        _mode: u8,
211        _dids: &[u8]
212    ) -> Result<(), Self::Error> {
213        Ok(())
214    }
215
216    // endregion: Optional Hooks
217}
218
219// endregion: ServerHandler