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