use crate::app::Command; use anyhow::Result; use dioxus::hooks::{UnboundedReceiver, UnboundedSender}; use futures::io::{AsyncRead, AsyncWrite}; use mumble_protocol::control::{ClientControlCodec, ControlPacket}; use mumble_protocol::Serverbound; use std::net::ToSocketAddrs; use std::{fmt, io, sync::Arc}; use tokio::net::TcpStream; use tokio::task::LocalSet; use tokio_rustls::rustls; use tokio_rustls::rustls::client::danger::{HandshakeSignatureValid, ServerCertVerifier}; use tokio_rustls::rustls::pki_types::{CertificateDer, ServerName, UnixTime}; use tokio_rustls::rustls::ClientConfig; use tokio_rustls::rustls::DigitallySignedStruct; use tokio_rustls::TlsConnector; use tokio_util::compat::{TokioAsyncReadCompatExt as _, TokioAsyncWriteCompatExt as _}; pub use tokio::task::spawn; pub use tokio::time::sleep; pub struct Error(anyhow::Error); pub trait ImpRead: AsyncRead + Unpin + Send + 'static {} impl ImpRead for T {} pub trait ImpWrite: AsyncWrite + Unpin + Send + 'static {} impl ImpWrite for T {} impl From for Error { fn from(value: anyhow::Error) -> Self { Error(value) } } impl From for Error { fn from(value: io::Error) -> Self { Error(value.into()) } } impl Error { pub fn new(text: String) -> Self { Self(anyhow::Error::msg(text)) } pub fn log(&self) { eprintln!("{}", self.0); } } impl std::error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } } pub struct AudioSystem(); impl AudioSystem { pub fn new(sender: UnboundedSender>) -> Result { // dbg!("todo"); Ok(AudioSystem()) } pub fn create_player(&mut self) -> Result { // dbg!("todo"); Ok(AudioPlayer()) } } pub struct AudioPlayer(); impl AudioPlayer { pub fn play_opus(&mut self, payload: &[u8]) { // dbg!("todo"); } } #[derive(Debug)] struct NoCertificateVerification; impl ServerCertVerifier for NoCertificateVerification { fn verify_server_cert( &self, _end_entity: &CertificateDer<'_>, _intermediates: &[CertificateDer<'_>], _server_name: &ServerName<'_>, _ocsp: &[u8], _now: UnixTime, ) -> Result { Ok(rustls::client::danger::ServerCertVerified::assertion()) } fn verify_tls12_signature( &self, _message: &[u8], _cert: &CertificateDer<'_>, _dss: &DigitallySignedStruct, ) -> Result { Ok(HandshakeSignatureValid::assertion()) } fn verify_tls13_signature( &self, _message: &[u8], _cert: &CertificateDer<'_>, _dss: &DigitallySignedStruct, ) -> Result { Ok(HandshakeSignatureValid::assertion()) } fn supported_verify_schemes(&self) -> Vec { vec![ rustls::SignatureScheme::RSA_PKCS1_SHA1, rustls::SignatureScheme::ECDSA_SHA1_Legacy, rustls::SignatureScheme::RSA_PKCS1_SHA256, rustls::SignatureScheme::ECDSA_NISTP256_SHA256, rustls::SignatureScheme::RSA_PKCS1_SHA384, rustls::SignatureScheme::ECDSA_NISTP384_SHA384, rustls::SignatureScheme::RSA_PKCS1_SHA512, rustls::SignatureScheme::ECDSA_NISTP521_SHA512, rustls::SignatureScheme::RSA_PSS_SHA256, rustls::SignatureScheme::RSA_PSS_SHA384, rustls::SignatureScheme::RSA_PSS_SHA512, rustls::SignatureScheme::ED25519, rustls::SignatureScheme::ED448, ] } } pub async fn network_connect( address: String, username: String, event_rx: &mut UnboundedReceiver, ) -> Result<(), Error> { let config = ClientConfig::builder() .dangerous() .with_custom_certificate_verifier(Arc::new(NoCertificateVerification)) .with_no_client_auth(); let connector = TlsConnector::from(Arc::new(config)); let addr = format!("{}:{}", address, 64738) .to_socket_addrs()? .next() .unwrap(); let server_tcp = TcpStream::connect(addr).await?; let server_stream = connector //.connect("127.0.0.1".try_into()?, server_tcp) .connect(address.try_into().map_err(anyhow::Error::from)?, server_tcp) .await?; let (read_server, write_server) = tokio::io::split(server_stream); let read_codec = ClientControlCodec::new(); let write_codec = ClientControlCodec::new(); let mut reader = asynchronous_codec::FramedRead::new(read_server.compat(), read_codec); let mut writer = asynchronous_codec::FramedWrite::new(write_server.compat_write(), write_codec); super::network_loop(username, event_rx, reader, writer).await } pub fn set_default_username(username: &str) -> Option<()> { None } pub fn load_username() -> Option { return None; }