blob: 1a93f423f7a199ab1680a7c79625bdf6e8b409f5 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
use anyhow::{bail, Result};
use handler::TransportCommandHandler;
use mio::net::TcpListener;
use protocol::Message;
use socket_server::JsonSocketServer;
use std::net::SocketAddr;
use crate::app::TransportWrapper;
pub mod errors;
mod handler;
pub mod protocol;
mod socket_server;
/// Interface for handlers of protocol messages, responding to each message with a single
/// instance of the same protocol message.
pub trait CommandHandler<Msg> {
fn execute_cmd(&mut self, msg: &Msg) -> Result<Msg>;
}
/// This is the main entry point for the session proxy. This struct will either bind on a
/// specified port, or find an available port from a range, before entering an event loop.
pub struct SessionHandler<'a> {
port: u16,
socket_server: JsonSocketServer<Message, TransportCommandHandler<'a>>,
}
impl<'a> SessionHandler<'a> {
pub fn init(transport: &'a TransportWrapper, listen_port: Option<u16>) -> Result<Self> {
let mut port = listen_port.unwrap_or(9900);
let limit = listen_port.unwrap_or(9999);
// Find a suitable port to bind to.
let socket = loop {
let addr = SocketAddr::from(([0u8; 4], port));
match TcpListener::bind(addr) {
Ok(socket) => break socket,
Err(e) if port >= limit => bail!(e),
Err(_) => port += 1,
}
};
let socket_server = JsonSocketServer::new(TransportCommandHandler::new(transport), socket)?;
// Configure all GPIO pins to default direction and level, according to
// configuration files provided, and configures SPI port mode/speed, etc.
transport.apply_default_configuration()?;
Ok(Self {
port,
socket_server,
})
}
pub fn get_port(&self) -> u16 {
self.port
}
pub fn run_loop(&mut self) -> Result<()> {
self.socket_server.run_loop()
}
}