use std::str::FromStr; use fltk::{ app, button::Button, enums::CallbackTrigger, frame::Frame, input::*, prelude::*, window::Window }; use structopt::StructOpt; use quic_demo::{ client_proxy::*, prelude::*, protocol::PeerId, }; #[derive (Debug, StructOpt)] struct Opt { #[structopt (long)] window_title: Option , #[structopt (long)] relay_addr: Option , #[structopt (long)] client_id: Option , #[structopt (long)] cert_url: Option , } #[derive (Clone, Copy)] enum Message { OpenPort (usize), ClosePort (usize), } fn main () -> anyhow::Result <()> { tracing_subscriber::fmt::init (); let rt = tokio::runtime::Runtime::new ()?; let opt = Opt::from_args (); let (fltk_tx, fltk_rx) = app::channel:: (); let app = app::App::default (); let window_title = opt.window_title.clone ().unwrap_or_else (|| "PTTH client proxy".to_string ()); let mut wind = Window::new (100, 100, 800, 600, None) .with_label (&window_title); let margin = 10; let h = 30; let mut x = margin; let mut y = margin; let mut frame_status = Frame::new (x, y, 800 - 20, h, "Forwarding 0 ports"); y += h + margin; x = margin; { let w = 80; Frame::new (x, y, w, h, "Local port"); x += w + margin; let w = 120; Frame::new (x, y, w, h, "Server ID"); x += w + margin; let w = 80; Frame::new (x, y, w, h, "Server port"); // x += w + margin; } y += h + margin; x = margin; let gui_port_0 = GuiPort::new (fltk_tx, &mut x, y, 0); y += h + margin; x = margin; let gui_port_1 = GuiPort::new (fltk_tx, &mut x, y, 1); y += h + margin; x = margin; let gui_port_2 = GuiPort::new (fltk_tx, &mut x, y, 2); // y += h + margin; // x = margin; let mut gui_ports = vec! [ gui_port_0, gui_port_1, gui_port_2, ]; let mut forwarding_instances = vec! [ None, None, None, ]; // y += h + margin; wind.end (); wind.show (); let connection_p2_p3 = rt.block_on (async move { let server_cert = match opt.cert_url.as_ref () { Some (url) => reqwest::get (url).await?.bytes ().await?, None => tokio::fs::read ("quic_server.crt").await?.into (), }; let relay_addr = opt.relay_addr .unwrap_or_else (|| String::from ("127.0.0.1:30380")) .parse () .context ("relay_addr should be like 127.0.0.1:30380")?; let endpoint = make_client_endpoint ("0.0.0.0:0".parse ()?, &[&server_cert])?; trace! ("Connecting to relay server"); let client_id = opt.client_id.unwrap_or_else (|| "bogus_client".to_string ()); let quinn::NewConnection { connection, .. } = protocol::p2_connect_to_p3 (&endpoint, &relay_addr, &client_id).await .context ("P2 can't connect to P3")?; Ok::<_, anyhow::Error> (connection) })?; while app.wait () { match fltk_rx.recv () { Some (Message::OpenPort (port_idx)) => { if let Ok (params) = gui_ports [port_idx].get_params () { let connection_p2_p3 = connection_p2_p3.clone (); let _guard = rt.enter (); forwarding_instances [port_idx].replace (ForwardingInstance::new ( connection_p2_p3, params, )); gui_ports [port_idx].set_forwarding (true); frame_status.set_label ("Forwarding 1 port"); } }, Some (Message::ClosePort (port_idx)) => { if let Some (old_instance) = forwarding_instances [port_idx].take () { rt.block_on (old_instance.close ())?; } gui_ports [port_idx].set_forwarding (false); frame_status.set_label ("Forwarding 0 ports"); }, None => (), } } Ok (()) } fn set_active (w: &mut W, b: bool) { if b { w.activate (); } else { w.deactivate (); } } struct GuiPort { input_client_port: Input, input_server_id: Input, input_server_port: Input, but_open: Button, but_close: Button, } impl GuiPort { fn new (fltk_tx: fltk::app::Sender , x: &mut i32, y: i32, port_idx: usize) -> Self { let margin = 10; let h = 30; let w = 80; let mut input_client_port = Input::new (*x, y, w, h, ""); *x += w + margin; let w = 120; let mut input_server_id = Input::new (*x, y, w, h, ""); *x += w + margin; let w = 80; let mut input_server_port = Input::new (*x, y, w, h, ""); *x += w + margin; let w = 80; let mut but_open = Button::new (*x, y, w, h, "Open"); *x += w + margin; let w = 80; let mut but_close = Button::new (*x, y, w, h, "Close"); // *x += w + margin; input_client_port.set_value ("5901"); input_server_id.set_value ("bogus_server"); input_server_port.set_value ("5900"); but_open.set_trigger (CallbackTrigger::Changed); but_open.emit (fltk_tx, Message::OpenPort (port_idx)); but_close.set_trigger (CallbackTrigger::Changed); but_close.emit (fltk_tx, Message::ClosePort (port_idx)); set_active (&mut but_open, true); set_active (&mut but_close, false); Self { input_client_port, input_server_id, input_server_port, but_open, but_close, } } fn get_params (&self) -> anyhow::Result { let client_tcp_port = u16::from_str (&self.input_client_port.value ())?; let server_id = self.input_server_id.value (); let server_tcp_port = u16::from_str (&self.input_server_port.value ())?; Ok (ForwardingParams { client_tcp_port, server_id, server_tcp_port, }) } fn set_forwarding (&mut self, x: bool) { set_active (&mut self.input_client_port, !x); set_active (&mut self.input_server_id, !x); set_active (&mut self.input_server_port, !x); set_active (&mut self.but_open, !x); set_active (&mut self.but_close, x); self.but_open.set (x); self.but_close.set (!x); } }