@@ -169,86 +169,74 @@ impl Iterator for SerialConsolePackets<'_, '_> {
169169 }
170170}
171171
172- #[ derive( Debug ) ]
173- pub struct SpServer {
174- buf : [ u8 ; SpMessage :: MAX_SIZE ] ,
175- }
172+ /// Handle a single incoming message.
173+ ///
174+ /// The incoming message is described by `sender` (the remote address of the
175+ /// sender), `port` (the local port the message arived on), and `data` (the raw
176+ /// message). It will be deserialized, and the appropriate method will be called
177+ /// on `handler` to craft a response. The response will then be serialized into
178+ /// `out`, and returned `Ok(n)` value specifies length of the serialized
179+ /// response.
180+ pub fn handle_message < H : SpHandler > (
181+ sender : SocketAddrV6 ,
182+ port : SpPort ,
183+ data : & [ u8 ] ,
184+ handler : & mut H ,
185+ out : & mut [ u8 ; SpMessage :: MAX_SIZE ] ,
186+ ) -> Result < usize , Error > {
187+ // parse request, with sanity checks on sizes
188+ if data. len ( ) > Request :: MAX_SIZE {
189+ return Err ( Error :: DataTooLarge ) ;
190+ }
191+ let ( request, leftover) = hubpack:: deserialize :: < Request > ( data) ?;
192+ if !leftover. is_empty ( ) {
193+ return Err ( Error :: LeftoverData ) ;
194+ }
176195
177- impl Default for SpServer {
178- fn default ( ) -> Self {
179- Self { buf : [ 0 ; SpMessage :: MAX_SIZE ] }
196+ // `version` is intentionally the first 4 bytes of the packet; we could
197+ // check it before trying to deserialize?
198+ if request. version != version:: V1 {
199+ return Err ( Error :: UnsupportedVersion ( request. version ) ) ;
180200 }
181- }
182201
183- impl SpServer {
184- /// Handler for incoming UDP requests.
185- ///
186- /// `data` should be a UDP packet that has arrived from `sender` on `port`.
187- /// It will be parsed (into a [`Request`]), the appropriate method will be
188- /// called on `handler`, and a serialized response will be returned, which
189- /// the caller should send back to the requester.
190- pub fn dispatch < H : SpHandler > (
191- & mut self ,
192- sender : SocketAddrV6 ,
193- port : SpPort ,
194- data : & [ u8 ] ,
195- handler : & mut H ,
196- ) -> Result < & [ u8 ] , Error > {
197- // parse request, with sanity checks on sizes
198- if data. len ( ) > Request :: MAX_SIZE {
199- return Err ( Error :: DataTooLarge ) ;
202+ // call out to handler to provide response
203+ let result = match request. kind {
204+ RequestKind :: Discover => {
205+ handler. discover ( sender, port) . map ( ResponseKind :: Discover )
200206 }
201- let ( request, leftover) = hubpack:: deserialize :: < Request > ( data) ?;
202- if !leftover. is_empty ( ) {
203- return Err ( Error :: LeftoverData ) ;
207+ RequestKind :: IgnitionState { target } => handler
208+ . ignition_state ( sender, port, target)
209+ . map ( ResponseKind :: IgnitionState ) ,
210+ RequestKind :: BulkIgnitionState => handler
211+ . bulk_ignition_state ( sender, port)
212+ . map ( ResponseKind :: BulkIgnitionState ) ,
213+ RequestKind :: IgnitionCommand { target, command } => handler
214+ . ignition_command ( sender, port, target, command)
215+ . map ( |( ) | ResponseKind :: IgnitionCommandAck ) ,
216+ RequestKind :: SpState => {
217+ handler. sp_state ( sender, port) . map ( ResponseKind :: SpState )
204218 }
205-
206- // `version` is intentionally the first 4 bytes of the packet; we could
207- // check it before trying to deserialize?
208- if request. version != version:: V1 {
209- return Err ( Error :: UnsupportedVersion ( request. version ) ) ;
210- }
211-
212- // call out to handler to provide response
213- let result = match request. kind {
214- RequestKind :: Discover => {
215- handler. discover ( sender, port) . map ( ResponseKind :: Discover )
216- }
217- RequestKind :: IgnitionState { target } => handler
218- . ignition_state ( sender, port, target)
219- . map ( ResponseKind :: IgnitionState ) ,
220- RequestKind :: BulkIgnitionState => handler
221- . bulk_ignition_state ( sender, port)
222- . map ( ResponseKind :: BulkIgnitionState ) ,
223- RequestKind :: IgnitionCommand { target, command } => handler
224- . ignition_command ( sender, port, target, command)
225- . map ( |( ) | ResponseKind :: IgnitionCommandAck ) ,
226- RequestKind :: SpState => {
227- handler. sp_state ( sender, port) . map ( ResponseKind :: SpState )
228- }
229- RequestKind :: SerialConsoleWrite ( packet) => handler
230- . serial_console_write ( sender, port, packet)
231- . map ( |( ) | ResponseKind :: SerialConsoleWriteAck ) ,
232- } ;
233-
234- // we control `SpMessage` and know all cases can successfully serialize
235- // into `self.buf`
236- let response = SpMessage {
237- version : version:: V1 ,
238- kind : SpMessageKind :: Response {
239- request_id : request. request_id ,
240- result,
241- } ,
242- } ;
243- let n = match hubpack:: serialize ( & mut self . buf , & response) {
244- Ok ( n) => n,
245- Err ( _) => panic ! ( ) ,
246- } ;
247-
248- // Do we want some mechanism for remembering `n` if our caller wants to
249- // resend this packet, which would have to happen before calling this
250- // method again? For now (and maybe forever), force them to just call us
251- // again, and we'll reserialize.
252- Ok ( & self . buf [ ..n] )
253- }
219+ RequestKind :: SerialConsoleWrite ( packet) => handler
220+ . serial_console_write ( sender, port, packet)
221+ . map ( |( ) | ResponseKind :: SerialConsoleWriteAck ) ,
222+ } ;
223+
224+ // we control `SpMessage` and know all cases can successfully serialize
225+ // into `self.buf`
226+ let response = SpMessage {
227+ version : version:: V1 ,
228+ kind : SpMessageKind :: Response {
229+ request_id : request. request_id ,
230+ result,
231+ } ,
232+ } ;
233+
234+ // We know `response` is well-formed and fits into `out` (since it's
235+ // statically sized for `SpMessage`), so we can unwrap serialization.
236+ let n = match hubpack:: serialize ( & mut out[ ..] , & response) {
237+ Ok ( n) => n,
238+ Err ( _) => panic ! ( ) ,
239+ } ;
240+
241+ Ok ( n)
254242}
0 commit comments