opentitanlib/proxy/
mod.rs

1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use anyhow::{Result, bail};
6use handler::TransportCommandHandler;
7use protocol::Message;
8use socket_server::{Connection, JsonSocketServer};
9use std::net::SocketAddr;
10use std::sync::{Arc, Mutex};
11use tokio::net::TcpListener;
12
13use crate::app::TransportWrapper;
14
15pub mod errors;
16mod handler;
17mod nonblocking_uart;
18pub mod protocol;
19mod socket_server;
20
21/// Interface for handlers of protocol messages, responding to each message with a single
22/// instance of the same protocol message.
23pub trait CommandHandler<Msg> {
24    fn execute_cmd(&mut self, conn: &Arc<Mutex<Connection>>, msg: &Msg) -> Result<Msg>;
25}
26
27/// This is the main entry point for the session proxy.  This struct will either bind on a
28/// specified port, or find an available port from a range, before entering an event loop.
29pub struct SessionHandler {
30    port: u16,
31    socket_server: JsonSocketServer<Message, TransportCommandHandler>,
32}
33
34impl SessionHandler {
35    pub fn init(transport: TransportWrapper, listen_port: Option<u16>) -> Result<Self> {
36        let mut port = listen_port.unwrap_or(9900);
37        let limit = listen_port.unwrap_or(9999);
38        // Find a suitable port to bind to.
39        let socket = loop {
40            let addr = SocketAddr::from(([0u8; 4], port));
41            match crate::util::runtime::block_on(async { TcpListener::bind(addr).await }) {
42                Ok(socket) => break socket,
43                Err(e) if port >= limit => bail!(e),
44                Err(_) => port += 1,
45            }
46        };
47        let socket_server =
48            JsonSocketServer::new(TransportCommandHandler::new(transport)?, socket)?;
49        Ok(Self {
50            port,
51            socket_server,
52        })
53    }
54
55    pub fn get_port(&self) -> u16 {
56        self.port
57    }
58
59    pub fn run_loop(&mut self) -> Result<()> {
60        crate::util::runtime::block_on(crate::util::runtime::with_graceful_shutdown(
61            self.socket_server.run_loop(),
62        ))
63    }
64}