From b094402bf3c77c572b552c9e4efcd8ca8eccacec Mon Sep 17 00:00:00 2001 From: nworbnhoj Date: Tue, 12 Dec 2023 06:44:02 +1100 Subject: [PATCH] sigchat prepare tls connection to provisioning server --- apps/sigchat/src/manager.rs | 27 ++++++- apps/sigchat/src/manager/signal_ws.rs | 102 ++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 apps/sigchat/src/manager/signal_ws.rs diff --git a/apps/sigchat/src/manager.rs b/apps/sigchat/src/manager.rs index f9e06f3c9..6abeb80b5 100644 --- a/apps/sigchat/src/manager.rs +++ b/apps/sigchat/src/manager.rs @@ -1,11 +1,13 @@ mod group_permission; mod link_state; +mod signal_ws; mod trust_mode; -use crate::Account; +use crate::{Account, DEFAULT_DEVICE_NAME, DEFAULT_HOST_NAME}; use group_permission::GroupPermission; use link_state::LinkState; use std::io::Error; +use signal_ws::SignalWS; pub use trust_mode::TrustMode; // Structure modeled on signal-cli by AsamK and contributors - https://github.com/AsamK/signal-cli. @@ -14,8 +16,9 @@ pub use trust_mode::TrustMode; #[allow(dead_code)] pub struct Manager { - account:Account, + account: Account, trust_mode: TrustMode, + websocket: Option, log_verbose: bool, log_scrub: bool, log_send: bool, @@ -32,6 +35,7 @@ impl Manager { Manager { account, trust_mode, + websocket: None, log_verbose: false, log_scrub: false, log_send: false, @@ -128,7 +132,24 @@ impl Manager { /// #[allow(dead_code)] pub fn link(&mut self, name: Option<&str>, host: Option<&str>) -> Result { - todo!(); + // insert default values as required + let name = name.unwrap_or(DEFAULT_DEVICE_NAME); + let host = host.unwrap_or(DEFAULT_HOST_NAME); + match SignalWS::provision(&host) { + Ok(ws) => { + if let Some(prior_ws) = &mut self.websocket { + prior_ws.close(); + } + self.websocket = Some(ws); + + log::info!("websocket established to link {name} at {host}"); + log::warn!("Manager.link() not fully implemented."); + } + Err(e) => { + log::info!("failed to connect to server: {}", e); + Err(e) + } + } } /// Link another device to this device. Only works, if this is the primary device. diff --git a/apps/sigchat/src/manager/signal_ws.rs b/apps/sigchat/src/manager/signal_ws.rs new file mode 100644 index 000000000..92f08cfff --- /dev/null +++ b/apps/sigchat/src/manager/signal_ws.rs @@ -0,0 +1,102 @@ +use rustls::{ClientConnection, StreamOwned}; +use std::io::{Error, ErrorKind}; +use std::net::TcpStream; +use tls::Tls; + +const PROVISIONING_PATH: &str = "/provisioning/"; +const REGISTRATION_PATH: &str = "/v1/registration"; + +#[allow(dead_code)] +pub enum SignalWS { + Message { + ws: WebSocket>, + }, + Provision { + ws: WebSocket>, + }, + Register { + ws: WebSocket>, + }, +} + +impl SignalWS { + #[allow(dead_code)] + pub fn message(_host: &str) -> Result { + todo!(); + } + + pub fn provision(host: &str) -> Result { + let server = format!("wss://{host}{}", PROVISIONING_PATH); + // let mut conn = client_connection(&server); + match SignalWS::connect(server) { + Ok(ws) => Ok(Self::Provision { ws }), + Err(e) => Err(e), + } + } + + #[allow(dead_code)] + pub fn register(host: &str) -> Result { + let server = format!("wss://{host}{}", REGISTRATION_PATH); + // let mut conn = client_connection(&server); + match SignalWS::connect(server) { + Ok(ws) => Ok(Self::Register { ws }), + Err(e) => Err(e), + } + } + + pub fn close(&mut self) { + match self { + SignalWS::Message { ws, .. } + | SignalWS::Provision { ws, .. } + | SignalWS::Register { ws, .. } => { + ws.close(None) + .unwrap_or_else(|e| log::warn!("failed to close websocket: {e}")); + // TODO close properly https://docs.rs/tungstenite/0.20.1/tungstenite/protocol/struct.WebSocket.html + ws.flush() + .unwrap_or_else(|e| log::warn!("failed to flush websocket: {e}")); + } + } + } + + /// Make a websocket connection to host server + /// + /// # Arguments + /// * `server` - server + /// + /// # Returns + /// + fn connect( + server: String, + ) -> Result>, Error> { + log::info!("connecting websocket"); + match url::Url::parse(&server) { + Ok(url) => { + let host = url.host_str().expect("failed to extract host from url"); + match TcpStream::connect((host, 443)) { + Ok(sock) => { + log::info!("tcp connected"); + let xtls = Tls::new(); + match xtls.stream(host, sock) { + Ok(tls_stream) => { + log::info!("tls configured"); + log::info!("WEBSOCKET NOT IMPLEMENTED YET"); + } + Err(e) => { + log::warn!("failed to configure tls: {e}"); + Err(e) + } + } + } + Err(e) => { + log::warn!("failed to connect tcp: {e}"); + Err(e) + } + } + } + Err(e) => { + log::info!("failed to parse server url: {e}"); + Err(Error::new(ErrorKind::InvalidData, e)) + } + } + } +} \ No newline at end of file