pounder_test/src/server.rs

279 lines
8.9 KiB
Rust
Raw Normal View History

2020-04-29 01:26:43 +08:00
use core::fmt::Write;
use heapless::{consts::*, String, Vec};
2020-06-16 22:22:12 +08:00
use serde::{Deserialize, Serialize};
use serde_json_core::{de::from_slice, ser::to_string};
2021-01-18 23:47:47 +08:00
use smoltcp as net;
use dsp::iir;
#[macro_export]
2021-01-18 23:47:47 +08:00
macro_rules! route_request {
($request:ident,
readable_attributes: [$($read_attribute:tt: $getter:tt),*],
modifiable_attributes: [$($write_attribute:tt: $TYPE:ty, $setter:tt),*]) => {
match $request.req {
server::AccessRequest::Read => {
match $request.attribute {
$(
$read_attribute => {
#[allow(clippy::redundant_closure_call)]
let value = match $getter() {
Ok(data) => data,
Err(_) => return server::Response::error($request.attribute,
"Failed to read attribute"),
};
let encoded_data: String<U256> = match serde_json_core::to_string(&value) {
Ok(data) => data,
Err(_) => return server::Response::error($request.attribute,
"Failed to encode attribute value"),
};
server::Response::success($request.attribute, &encoded_data)
},
)*
_ => server::Response::error($request.attribute, "Unknown attribute")
}
},
server::AccessRequest::Write => {
match $request.attribute {
$(
$write_attribute => {
let new_value = match serde_json_core::from_str::<$TYPE>(&$request.value) {
Ok(data) => data,
Err(_) => return server::Response::error($request.attribute,
"Failed to decode value"),
};
#[allow(clippy::redundant_closure_call)]
match $setter(new_value) {
Ok(_) => server::Response::success($request.attribute, &$request.value),
Err(_) => server::Response::error($request.attribute,
"Failed to set attribute"),
}
}
)*
_ => server::Response::error($request.attribute, "Unknown attribute")
}
}
}
}
}
#[derive(Deserialize, Serialize, Debug)]
2020-06-09 20:16:01 +08:00
pub enum AccessRequest {
Read,
Write,
}
#[derive(Deserialize, Serialize, Debug)]
pub struct Request<'a> {
2020-06-09 20:16:01 +08:00
pub req: AccessRequest,
pub attribute: &'a str,
pub value: String<U256>,
2020-04-29 01:26:43 +08:00
}
2020-06-03 23:15:57 +08:00
#[derive(Serialize, Deserialize)]
pub struct IirRequest {
pub channel: u8,
pub iir: iir::IIR,
}
2020-04-29 01:26:43 +08:00
#[derive(Serialize)]
2020-06-03 22:53:25 +08:00
pub struct Response {
2020-04-29 01:26:43 +08:00
code: i32,
attribute: String<U256>,
value: String<U256>,
}
impl<'a> Request<'a> {
pub fn restore_value(&mut self) {
let mut new_value: String<U256> = String::new();
for byte in self.value.as_str().chars() {
if byte == '\'' {
new_value.push('"').unwrap();
} else {
new_value.push(byte).unwrap();
}
}
self.value = new_value;
}
}
2020-06-03 22:53:25 +08:00
impl Response {
2020-06-11 17:51:52 +08:00
/// Remove all double quotation marks from the `value` field of a response.
fn sanitize_value(&mut self) {
let mut new_value: String<U256> = String::new();
for byte in self.value.as_str().chars() {
if byte == '"' {
new_value.push('\'').unwrap();
} else {
new_value.push(byte).unwrap();
}
}
self.value = new_value;
}
2020-06-11 17:51:52 +08:00
/// Remove all double quotation marks from the `value` field of a response and wrap it in single
/// quotes.
fn wrap_and_sanitize_value(&mut self) {
let mut new_value: String<U256> = String::new();
new_value.push('\'').unwrap();
for byte in self.value.as_str().chars() {
if byte == '"' {
new_value.push('\'').unwrap();
} else {
new_value.push(byte).unwrap();
}
}
new_value.push('\'').unwrap();
self.value = new_value;
}
2020-06-11 17:51:52 +08:00
/// Construct a successful reply.
///
/// Note: `value` will be sanitized to convert all single quotes to double quotes.
///
/// Args:
/// * `attrbute` - The attribute of the success.
/// * `value` - The value of the attribute.
2020-11-26 23:24:42 +08:00
pub fn success(attribute: &str, value: &str) -> Self {
2020-06-16 22:22:12 +08:00
let mut res = Self {
code: 200,
attribute: String::from(attribute),
value: String::from(value),
};
res.sanitize_value();
res
}
2020-06-11 17:51:52 +08:00
/// Construct an error reply.
///
/// Note: `message` will be sanitized to convert all single quotes to double quotes.
///
/// Args:
/// * `attrbute` - The attribute of the success.
/// * `message` - The message denoting the error.
2020-11-26 23:24:42 +08:00
pub fn error(attribute: &str, message: &str) -> Self {
2020-06-16 22:22:12 +08:00
let mut res = Self {
code: 400,
attribute: String::from(attribute),
value: String::from(message),
};
res.wrap_and_sanitize_value();
res
}
2020-06-11 17:51:52 +08:00
/// Construct a custom reply.
///
/// Note: `message` will be sanitized to convert all single quotes to double quotes.
///
/// Args:
/// * `attrbute` - The attribute of the success.
/// * `message` - The message denoting the status.
2020-11-26 23:24:42 +08:00
pub fn custom(code: i32, message: &str) -> Self {
2020-06-16 22:22:12 +08:00
let mut res = Self {
code,
2020-06-16 22:22:12 +08:00
attribute: String::from(""),
value: String::from(message),
};
res.wrap_and_sanitize_value();
res
}
2020-04-29 01:26:43 +08:00
}
#[derive(Serialize)]
pub struct Status {
pub t: u32,
pub x0: f32,
pub y0: f32,
pub x1: f32,
pub y1: f32,
}
pub fn json_reply<T: Serialize>(socket: &mut net::socket::TcpSocket, msg: &T) {
let mut u: String<U512> = to_string(msg).unwrap();
2020-04-29 01:26:43 +08:00
u.push('\n').unwrap();
socket.write_str(&u).unwrap();
}
pub struct Server {
data: Vec<u8, U256>,
discard: bool,
}
impl Server {
2020-06-11 17:51:52 +08:00
/// Construct a new server object for managing requests.
2020-04-29 01:26:43 +08:00
pub fn new() -> Self {
Self {
data: Vec::new(),
discard: false,
}
}
2020-06-11 17:51:52 +08:00
/// Poll the server for potential data updates.
///
/// Args:
/// * `socket` - The socket to check contents from.
/// * `f` - A closure that can be called if a request has been received on the server.
2020-06-16 22:22:12 +08:00
pub fn poll<F>(&mut self, socket: &mut net::socket::TcpSocket, mut f: F)
2020-04-29 01:26:43 +08:00
where
2020-06-16 22:22:12 +08:00
F: FnMut(&Request) -> Response,
2020-04-29 01:26:43 +08:00
{
while socket.can_recv() {
2020-06-16 22:22:12 +08:00
let found = socket
.recv(|buf| {
let (len, found) =
match buf.iter().position(|&c| c as char == '\n') {
Some(end) => (end + 1, true),
None => (buf.len(), false),
};
if self.data.len() + len >= self.data.capacity() {
self.discard = true;
self.data.clear();
} else if !self.discard && len > 0 {
self.data.extend_from_slice(&buf[..len]).unwrap();
}
(len, found)
})
.unwrap();
2020-04-29 01:26:43 +08:00
if found {
if self.discard {
self.discard = false;
2020-06-16 22:22:12 +08:00
json_reply(
socket,
&Response::custom(520, "command buffer overflow"),
);
2020-04-29 01:26:43 +08:00
} else {
2020-06-16 22:22:12 +08:00
let r = from_slice::<Request>(
&self.data[..self.data.len() - 1],
);
2020-04-29 01:26:43 +08:00
match r {
Ok(mut res) => {
2020-06-11 17:51:52 +08:00
// Note that serde_json_core doesn't escape quotations within a string.
// To account for this, we manually translate all single quotes to
// double quotes. This occurs because we doubly-serialize this field in
// some cases.
res.restore_value();
let response = f(&res);
json_reply(socket, &response);
2020-06-16 22:22:12 +08:00
}
2020-04-29 01:26:43 +08:00
Err(err) => {
warn!("parse error {:?}", err);
2020-06-16 22:22:12 +08:00
json_reply(
socket,
&Response::custom(550, "parse error"),
);
2020-04-29 01:26:43 +08:00
}
}
}
2020-06-03 22:53:25 +08:00
self.data.clear();
2020-04-29 01:26:43 +08:00
}
}
}
}