|  | // 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() | 
|  | } | 
|  | } |