forked from M-Labs/nac3
parent
e0560a2db9
commit
d11e3fdad8
|
@ -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"]
|
||||||
|
|
|
@ -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?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue