runtime/mgmt: mgmt.rs consistency #69

Merged
sb10q merged 1 commits from pca006132/artiq-zynq:mgmt into master 2020-07-21 13:54:33 +08:00
3 changed files with 74 additions and 106 deletions
Showing only changes of commit 4ed2e6a8de - Show all commits

View File

@ -23,7 +23,6 @@ mod config;
mod net_settings; mod net_settings;
mod proto_core_io; mod proto_core_io;
mod proto_async; mod proto_async;
mod proto_mgmt;
mod comms; mod comms;
mod rpc; mod rpc;
#[path = "../../../build/pl.rs"] #[path = "../../../build/pl.rs"]

View File

@ -6,9 +6,63 @@ use alloc::rc::Rc;
use log::{self, info, warn, LevelFilter}; use log::{self, info, warn, LevelFilter};
use crate::logger::{BufferLogger, LogBufferRef}; use crate::logger::{BufferLogger, LogBufferRef};
use crate::proto_async; use crate::proto_async::*;
use crate::proto_mgmt::*; use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
NetworkError(smoltcp::Error),
UnknownLogLevel(u8),
UnexpectedPattern,
UnrecognizedPacket,
}
type Result<T> = core::result::Result<T, Error>;
impl core::fmt::Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
&Error::NetworkError(error) => write!(f, "network error: {}", error),
&Error::UnknownLogLevel(lvl) => write!(f, "unknown log level {}", lvl),
&Error::UnexpectedPattern => write!(f, "unexpected pattern"),
&Error::UnrecognizedPacket => write!(f, "unrecognized packet"),
}
}
}
impl From<smoltcp::Error> for Error {
fn from(error: smoltcp::Error) -> Self {
Error::NetworkError(error)
}
}
#[derive(Debug, FromPrimitive)]
pub enum Request {
GetLog = 1,
ClearLog = 2,
PullLog = 7,
SetLogFilter = 3,
SetUartLogFilter = 6,
}
#[repr(i8)]
pub enum Reply {
Success = 1,
LogContent = 2,
}
async fn read_log_level_filter(stream: &mut TcpStream) -> Result<log::LevelFilter> {
Ok(match read_i8(stream).await? {
0 => log::LevelFilter::Off,
1 => log::LevelFilter::Error,
2 => log::LevelFilter::Warn,
3 => log::LevelFilter::Info,
4 => log::LevelFilter::Debug,
5 => log::LevelFilter::Trace,
lv => return Err(Error::UnknownLogLevel(lv as u8)),
})
}
async fn get_logger_buffer_pred<F>(f: F) -> LogBufferRef<'static> async fn get_logger_buffer_pred<F>(f: F) -> LogBufferRef<'static>
where where
@ -31,23 +85,27 @@ async fn get_logger_buffer() -> LogBufferRef<'static> {
get_logger_buffer_pred(|_| true).await get_logger_buffer_pred(|_| true).await
} }
async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) -> Result<(), Error> { async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) -> Result<()> {
Request::read_magic(stream).await?; if !expect(&stream, b"ARTIQ management\n").await? {
return Err(Error::UnexpectedPattern);
}
loop { loop {
let req = Request::read_from(stream).await; let msg = read_i8(stream).await;
if let Err(Error::Io(smoltcp::Error::Illegal)) = req { if let Err(smoltcp::Error::Illegal) = msg {
return Ok(()); return Ok(());
} }
match req? { let msg: Request = FromPrimitive::from_i8(msg?).ok_or(Error::UnrecognizedPacket)?;
match msg {
Request::GetLog => { Request::GetLog => {
let mut buffer = get_logger_buffer().await; let mut buffer = get_logger_buffer().await;
Reply::LogContent(buffer.extract()).write_to(stream).await?; write_i8(stream, Reply::LogContent as i8).await?;
write_chunk(stream, buffer.extract().as_bytes()).await?;
} }
Request::ClearLog => { Request::ClearLog => {
let mut buffer = get_logger_buffer().await; let mut buffer = get_logger_buffer().await;
buffer.clear(); buffer.clear();
Reply::Success.write_to(stream).await?; write_i8(stream, Reply::Success as i8).await?;
} }
Request::PullLog => { Request::PullLog => {
let id = { let id = {
@ -63,7 +121,7 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
// abort this connection... // abort this connection...
break; break;
} }
proto_async::write_chunk(stream, bytes).await?; write_chunk(stream, bytes).await?;
if log::max_level() == LevelFilter::Trace { if log::max_level() == LevelFilter::Trace {
// Hold exclusive access over the logger until we get positive // Hold exclusive access over the logger until we get positive
// acknowledgement; otherwise we get an infinite loop of network // acknowledgement; otherwise we get an infinite loop of network
@ -77,12 +135,14 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
buffer.clear(); buffer.clear();
} }
}, },
Request::SetLogFilter(lvl) => { Request::SetLogFilter => {
let lvl = read_log_level_filter(stream).await?;
info!("Changing log level to {}", lvl); info!("Changing log level to {}", lvl);
log::set_max_level(lvl); log::set_max_level(lvl);
Reply::Success.write_to(stream).await?; write_i8(stream, Reply::Success as i8).await?;
} }
Request::SetUartLogFilter(lvl) => { Request::SetUartLogFilter => {
let lvl = read_log_level_filter(stream).await?;
info!("Changing UART log level to {}", lvl); info!("Changing UART log level to {}", lvl);
unsafe { unsafe {
BufferLogger::get_logger() BufferLogger::get_logger()
@ -90,7 +150,7 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
.unwrap() .unwrap()
.set_uart_log_level(lvl); .set_uart_log_level(lvl);
} }
Reply::Success.write_to(stream).await?; write_i8(stream, Reply::Success as i8).await?;
} }
} }
} }

View File

@ -1,91 +0,0 @@
use libasync::smoltcp::TcpStream;
use libboard_zynq::smoltcp::Error as IoError;
use log;
use crate::proto_async::*;
pub enum Error {
WrongMagic,
UnknownPacket(u8),
UnknownLogLevel(u8),
Io(IoError),
}
impl core::fmt::Debug for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use Error::*;
match self {
WrongMagic => write!(f, "Wrong magic string"),
UnknownPacket(v) => write!(f, "Unknown packet {:#02x}", v),
UnknownLogLevel(v) => write!(f, "Unknown log level {}", v),
Io(e) => write!(f, "{}", e),
}
}
}
impl From<IoError> for Error {
fn from(value: IoError) -> Error {
Error::Io(value)
}
}
#[derive(Debug)]
pub enum Request {
GetLog,
ClearLog,
PullLog,
SetLogFilter(log::LevelFilter),
SetUartLogFilter(log::LevelFilter),
}
pub enum Reply<'a> {
Success,
LogContent(&'a str),
}
impl Request {
pub async fn read_from(stream: &mut TcpStream) -> Result<Self, Error> {
async fn read_log_level_filter(stream: &mut TcpStream) -> Result<log::LevelFilter, Error> {
Ok(match read_i8(stream).await? {
0 => log::LevelFilter::Off,
1 => log::LevelFilter::Error,
2 => log::LevelFilter::Warn,
3 => log::LevelFilter::Info,
4 => log::LevelFilter::Debug,
5 => log::LevelFilter::Trace,
lv => return Err(Error::UnknownLogLevel(lv as u8)),
})
}
Ok(match read_i8(stream).await? {
1 => Request::GetLog,
2 => Request::ClearLog,
7 => Request::PullLog,
3 => Request::SetLogFilter(read_log_level_filter(stream).await?),
6 => Request::SetUartLogFilter(read_log_level_filter(stream).await?),
ty => return Err(Error::UnknownPacket(ty as u8)),
})
}
pub async fn read_magic(stream: &mut TcpStream) -> Result<(), Error> {
if !expect(&stream, b"ARTIQ management\n").await? {
return Err(Error::WrongMagic);
}
Ok(())
}
}
impl<'a> Reply<'a> {
pub async fn write_to(&self, stream: &mut TcpStream) -> Result<(), IoError> {
match *self {
Reply::Success => {
write_i8(stream, 1).await?;
}
Reply::LogContent(ref log) => {
write_i8(stream, 2).await?;
write_chunk(stream, log.as_bytes()).await?;
}
}
Ok(())
}
}