Skip to content

Commit 9ec389f

Browse files
authored
Minor MGS tweaks to support hubris work (#1396)
* IgnitionCommand: impl PartialEq * Replace `SpServer` with `handle_message()` (caller-managed output buffer)
1 parent d16cd60 commit 9ec389f

File tree

6 files changed

+87
-92
lines changed

6 files changed

+87
-92
lines changed

gateway-messages/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,9 @@ mod bulk_ignition_state_serde {
294294
}
295295
}
296296

297-
#[derive(Debug, Clone, Copy, SerializedSize, Serialize, Deserialize)]
297+
#[derive(
298+
Debug, Clone, Copy, SerializedSize, Serialize, Deserialize, PartialEq,
299+
)]
298300
pub enum IgnitionCommand {
299301
PowerOn,
300302
PowerOff,

gateway-messages/src/sp_impl.rs

Lines changed: 65 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

gateway-sp-comms/src/recv_handler/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,11 @@ impl RecvHandler {
275275
msg
276276
}
277277
Err(err) => {
278-
error!(&self.log, "discarding malformed message ({})", err);
278+
error!(
279+
&self.log, "discarding malformed message";
280+
"err" => %err,
281+
"raw" => ?buf,
282+
);
279283
return;
280284
}
281285
};

sp-sim/src/gimlet.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{Responsiveness, SimulatedSp};
1010
use anyhow::{anyhow, bail, Context, Result};
1111
use async_trait::async_trait;
1212
use futures::future;
13-
use gateway_messages::sp_impl::{SerialConsolePacketizer, SpHandler, SpServer};
13+
use gateway_messages::sp_impl::{SerialConsolePacketizer, SpHandler};
1414
use gateway_messages::version;
1515
use gateway_messages::DiscoverResponse;
1616
use gateway_messages::ResponseError;
@@ -416,15 +416,15 @@ impl UdpTask {
416416
}
417417

418418
async fn run(mut self) -> Result<()> {
419-
let mut server = SpServer::default();
419+
let mut out_buf = [0; SpMessage::MAX_SIZE];
420420
let mut responsiveness = Responsiveness::Responsive;
421421
loop {
422422
select! {
423423
recv0 = self.udp0.recv_from() => {
424424
if let Some((resp, addr)) = server::handle_request(
425425
&mut self.handler,
426426
recv0,
427-
&mut server,
427+
&mut out_buf,
428428
responsiveness,
429429
SpPort::One,
430430
).await? {
@@ -436,7 +436,7 @@ impl UdpTask {
436436
if let Some((resp, addr)) = server::handle_request(
437437
&mut self.handler,
438438
recv1,
439-
&mut server,
439+
&mut out_buf,
440440
responsiveness,
441441
SpPort::Two,
442442
).await? {

sp-sim/src/server.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ use anyhow::anyhow;
88
use anyhow::bail;
99
use anyhow::Context;
1010
use anyhow::Result;
11+
use gateway_messages::sp_impl;
1112
use gateway_messages::sp_impl::SpHandler;
12-
use gateway_messages::sp_impl::SpServer;
1313
use gateway_messages::Request;
1414
use gateway_messages::SerializedSize;
15+
use gateway_messages::SpMessage;
1516
use gateway_messages::SpPort;
1617
use slog::debug;
1718
use slog::error;
@@ -122,7 +123,7 @@ pub fn logger(config: &Config) -> Result<Logger> {
122123
pub(crate) async fn handle_request<'a, H: SpHandler>(
123124
handler: &mut H,
124125
recv: Result<(&[u8], SocketAddrV6)>,
125-
server: &'a mut SpServer,
126+
out: &'a mut [u8; SpMessage::MAX_SIZE],
126127
responsiveness: Responsiveness,
127128
port_num: SpPort,
128129
) -> Result<Option<(&'a [u8], SocketAddrV6)>> {
@@ -137,9 +138,8 @@ pub(crate) async fn handle_request<'a, H: SpHandler>(
137138
let (data, addr) =
138139
recv.with_context(|| format!("recv on {:?}", port_num))?;
139140

140-
let resp = server
141-
.dispatch(addr, port_num, data, handler)
141+
let n = sp_impl::handle_message(addr, port_num, data, handler, out)
142142
.map_err(|err| anyhow!("dispatching message failed: {:?}", err))?;
143143

144-
Ok(Some((resp, addr)))
144+
Ok(Some((&out[..n], addr)))
145145
}

sp-sim/src/sidecar.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ use anyhow::Result;
1414
use async_trait::async_trait;
1515
use futures::future;
1616
use gateway_messages::sp_impl::SpHandler;
17-
use gateway_messages::sp_impl::SpServer;
1817
use gateway_messages::BulkIgnitionState;
1918
use gateway_messages::DiscoverResponse;
2019
use gateway_messages::IgnitionCommand;
2120
use gateway_messages::IgnitionFlags;
2221
use gateway_messages::IgnitionState;
2322
use gateway_messages::ResponseError;
2423
use gateway_messages::SerialNumber;
24+
use gateway_messages::SerializedSize;
25+
use gateway_messages::SpMessage;
2526
use gateway_messages::SpPort;
2627
use gateway_messages::SpState;
2728
use slog::debug;
@@ -222,15 +223,15 @@ impl Inner {
222223
}
223224

224225
async fn run(mut self) -> Result<()> {
225-
let mut server = SpServer::default();
226+
let mut out_buf = [0; SpMessage::MAX_SIZE];
226227
let mut responsiveness = Responsiveness::Responsive;
227228
loop {
228229
select! {
229230
recv0 = self.udp0.recv_from() => {
230231
if let Some((resp, addr)) = server::handle_request(
231232
&mut self.handler,
232233
recv0,
233-
&mut server,
234+
&mut out_buf,
234235
responsiveness,
235236
SpPort::One,
236237
).await? {
@@ -242,7 +243,7 @@ impl Inner {
242243
if let Some((resp, addr)) = server::handle_request(
243244
&mut self.handler,
244245
recv1,
245-
&mut server,
246+
&mut out_buf,
246247
responsiveness,
247248
SpPort::Two,
248249
).await? {

0 commit comments

Comments
 (0)