client/common: support new login screen
This commit is contained in:
+7
-1
@@ -21,10 +21,16 @@ pub struct AudioSettings {
|
|||||||
pub denoise: bool,
|
pub denoise: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum ConnectTarget {
|
||||||
|
Direct { host: String, port: u16 },
|
||||||
|
Proxy(String),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Connect {
|
Connect {
|
||||||
address: String,
|
target: ConnectTarget,
|
||||||
username: String,
|
username: String,
|
||||||
config: ProxyOverrides,
|
config: ProxyOverrides,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::app::{Command, SharedState};
|
use crate::app::{Command, ConnectTarget, SharedState};
|
||||||
use color_eyre::eyre::Error;
|
use color_eyre::eyre::{bail, Error};
|
||||||
use futures_channel::mpsc::UnboundedReceiver;
|
use futures_channel::mpsc::UnboundedReceiver;
|
||||||
use mumble_protocol::control::ClientControlCodec;
|
use mumble_protocol::control::ClientControlCodec;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
@@ -70,7 +70,7 @@ impl ServerCertVerifier for NoCertificateVerification {
|
|||||||
|
|
||||||
#[instrument]
|
#[instrument]
|
||||||
pub async fn network_connect(
|
pub async fn network_connect(
|
||||||
address: String,
|
target: ConnectTarget,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
overrides: &ProxyOverrides,
|
overrides: &ProxyOverrides,
|
||||||
@@ -78,6 +78,13 @@ pub async fn network_connect(
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
info!("connecting");
|
info!("connecting");
|
||||||
|
|
||||||
|
let (host, port) = match target {
|
||||||
|
ConnectTarget::Direct { host, port } => (host, port),
|
||||||
|
ConnectTarget::Proxy(_) => {
|
||||||
|
bail!("desktop/mobile platform requires a direct host:port, not a proxy URL")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let config = ClientConfig::builder()
|
let config = ClientConfig::builder()
|
||||||
.dangerous()
|
.dangerous()
|
||||||
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification))
|
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification))
|
||||||
@@ -85,15 +92,14 @@ pub async fn network_connect(
|
|||||||
|
|
||||||
let connector = TlsConnector::from(Arc::new(config));
|
let connector = TlsConnector::from(Arc::new(config));
|
||||||
|
|
||||||
let addr = format!("{}:{}", address, 64738)
|
let addr = (&*host, port)
|
||||||
.to_socket_addrs()?
|
.to_socket_addrs()?
|
||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let server_tcp = TcpStream::connect(addr).await?;
|
let server_tcp = TcpStream::connect(addr).await?;
|
||||||
let server_stream = connector
|
let server_stream = connector
|
||||||
//.connect("127.0.0.1".try_into()?, server_tcp)
|
.connect(host.try_into()?, server_tcp)
|
||||||
.connect(address.try_into()?, server_tcp)
|
|
||||||
.await?;
|
.await?;
|
||||||
let (read_server, write_server) = tokio::io::split(server_stream);
|
let (read_server, write_server) = tokio::io::split(server_stream);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::app::{Command, SharedState};
|
use crate::app::{Command, ConnectTarget, SharedState};
|
||||||
use color_eyre::eyre::Error;
|
use color_eyre::eyre::Error;
|
||||||
use futures_channel::mpsc::UnboundedReceiver;
|
use futures_channel::mpsc::UnboundedReceiver;
|
||||||
use mumble_web2_common::{ProxyOverrides, ServerStatus};
|
use mumble_web2_common::{ProxyOverrides, ServerStatus};
|
||||||
@@ -24,20 +24,24 @@ impl super::PlatformInterface for DesktopPlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn network_connect(
|
async fn network_connect(
|
||||||
address: String,
|
target: ConnectTarget,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
overrides: &ProxyOverrides,
|
overrides: &ProxyOverrides,
|
||||||
state: SharedState,
|
state: SharedState,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
super::connect::network_connect(address, username, event_rx, overrides, state).await
|
super::connect::network_connect(target, username, event_rx, overrides, state).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_status(
|
async fn get_status(
|
||||||
_client: &reqwest::Client,
|
_client: &reqwest::Client,
|
||||||
address: &str,
|
address: &str,
|
||||||
) -> color_eyre::Result<ServerStatus> {
|
) -> color_eyre::Result<ServerStatus> {
|
||||||
mumble_web2_common::ping_server(address, 64738).await
|
let (host, port) = match address.rsplit_once(':') {
|
||||||
|
Some((h, p)) => (h, p.parse().unwrap_or(64738)),
|
||||||
|
None => (address, 64738),
|
||||||
|
};
|
||||||
|
mumble_web2_common::ping_server(host, port).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_logging() {
|
fn init_logging() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::app::{Command, SharedState};
|
use crate::app::{Command, ConnectTarget, SharedState};
|
||||||
use color_eyre::eyre::Error;
|
use color_eyre::eyre::Error;
|
||||||
use futures_channel::mpsc::UnboundedReceiver;
|
use futures_channel::mpsc::UnboundedReceiver;
|
||||||
use mumble_web2_common::{ProxyOverrides, ServerStatus};
|
use mumble_web2_common::{ProxyOverrides, ServerStatus};
|
||||||
@@ -20,20 +20,24 @@ impl super::PlatformInterface for MobilePlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn network_connect(
|
async fn network_connect(
|
||||||
address: String,
|
target: ConnectTarget,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
overrides: &ProxyOverrides,
|
overrides: &ProxyOverrides,
|
||||||
state: SharedState,
|
state: SharedState,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
super::connect::network_connect(address, username, event_rx, overrides, state).await
|
super::connect::network_connect(target, username, event_rx, overrides, state).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_status(
|
async fn get_status(
|
||||||
_client: &reqwest::Client,
|
_client: &reqwest::Client,
|
||||||
address: &str,
|
address: &str,
|
||||||
) -> color_eyre::Result<ServerStatus> {
|
) -> color_eyre::Result<ServerStatus> {
|
||||||
mumble_web2_common::ping_server(address, 64738).await
|
let (host, port) = match address.rsplit_once(':') {
|
||||||
|
Some((h, p)) => (h, p.parse().unwrap_or(64738)),
|
||||||
|
None => (address, 64738),
|
||||||
|
};
|
||||||
|
mumble_web2_common::ping_server(host, port).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_logging() {
|
fn init_logging() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//! The traits make the platform boundary explicit and provide compile-time verification.
|
//! The traits make the platform boundary explicit and provide compile-time verification.
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
|
|
||||||
use crate::app::{Command, SharedState};
|
use crate::app::{Command, ConnectTarget, SharedState};
|
||||||
use crate::effects::AudioProcessor;
|
use crate::effects::AudioProcessor;
|
||||||
use color_eyre::eyre::Error;
|
use color_eyre::eyre::Error;
|
||||||
use futures_channel::mpsc::UnboundedReceiver;
|
use futures_channel::mpsc::UnboundedReceiver;
|
||||||
@@ -79,7 +79,7 @@ pub trait PlatformInterface {
|
|||||||
|
|
||||||
/// Establish a connection to the Mumble server and run the network loop.
|
/// Establish a connection to the Mumble server and run the network loop.
|
||||||
fn network_connect(
|
fn network_connect(
|
||||||
address: String,
|
target: ConnectTarget,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
proxy_overrides: &ProxyOverrides,
|
proxy_overrides: &ProxyOverrides,
|
||||||
|
|||||||
@@ -28,12 +28,8 @@ impl super::ConfigSystemInterface for NativeConfigSystem {
|
|||||||
match serde_json::from_value::<T>(value_untyped) {
|
match serde_json::from_value::<T>(value_untyped) {
|
||||||
Ok(v) => Some(v),
|
Ok(v) => Some(v),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let default_value = config_get_default(key)
|
let default_value = config_get_default(key)?;
|
||||||
.expect("Default value required after config parse failure");
|
serde_json::from_value::<T>(default_value).ok()
|
||||||
Some(
|
|
||||||
serde_json::from_value::<T>(default_value)
|
|
||||||
.expect("Default value could not be parsed"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
/// Stub implementation of the platform interface, so that we can
|
/// Stub implementation of the platform interface, so that we can
|
||||||
/// `cargo check` without any --feature flags.
|
/// `cargo check` without any --feature flags.
|
||||||
use crate::{app::SharedState, effects::AudioProcessor};
|
use crate::{
|
||||||
|
app::{ConnectTarget, SharedState},
|
||||||
|
effects::AudioProcessor,
|
||||||
|
};
|
||||||
use color_eyre::eyre::Error;
|
use color_eyre::eyre::Error;
|
||||||
use futures_channel::mpsc::UnboundedReceiver;
|
use futures_channel::mpsc::UnboundedReceiver;
|
||||||
use mumble_web2_common::{ProxyOverrides, ServerStatus};
|
use mumble_web2_common::{ProxyOverrides, ServerStatus};
|
||||||
@@ -21,7 +24,7 @@ impl super::PlatformInterface for StubPlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn network_connect(
|
fn network_connect(
|
||||||
_address: String,
|
_target: ConnectTarget,
|
||||||
_username: String,
|
_username: String,
|
||||||
_event_rx: &mut UnboundedReceiver<crate::app::Command>,
|
_event_rx: &mut UnboundedReceiver<crate::app::Command>,
|
||||||
_overrides: &ProxyOverrides,
|
_overrides: &ProxyOverrides,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::app::{Command, SharedState};
|
use crate::app::{Command, ConnectTarget, SharedState};
|
||||||
use crate::effects::{AudioProcessor, AudioProcessorSender, TransmitState};
|
use crate::effects::{AudioProcessor, AudioProcessorSender, TransmitState};
|
||||||
use color_eyre::eyre::{bail, eyre, Error};
|
use color_eyre::eyre::{bail, eyre, Error};
|
||||||
use crossbeam::atomic::AtomicCell;
|
use crossbeam::atomic::AtomicCell;
|
||||||
@@ -108,13 +108,19 @@ impl super::PlatformInterface for WebPlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn network_connect(
|
async fn network_connect(
|
||||||
address: String,
|
target: ConnectTarget,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
overrides: &ProxyOverrides,
|
overrides: &ProxyOverrides,
|
||||||
state: SharedState,
|
state: SharedState,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
network_connect(address, username, event_rx, overrides, state).await
|
let url = match target {
|
||||||
|
ConnectTarget::Proxy(url) => url,
|
||||||
|
ConnectTarget::Direct { .. } => {
|
||||||
|
bail!("web platform requires a proxy URL, not a direct host:port")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
network_connect(url, username, event_rx, overrides, state).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_status(
|
async fn get_status(
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ use crate::imp::{
|
|||||||
pub async fn network_entrypoint(mut event_rx: UnboundedReceiver<Command>, state: SharedState) {
|
pub async fn network_entrypoint(mut event_rx: UnboundedReceiver<Command>, state: SharedState) {
|
||||||
loop {
|
loop {
|
||||||
let Some(Command::Connect {
|
let Some(Command::Connect {
|
||||||
address,
|
target,
|
||||||
username,
|
username,
|
||||||
config,
|
config,
|
||||||
}) = event_rx.next().await
|
}) = event_rx.next().await
|
||||||
@@ -50,7 +50,7 @@ pub async fn network_entrypoint(mut event_rx: UnboundedReceiver<Command>, state:
|
|||||||
*state.server.write_unchecked() = Default::default();
|
*state.server.write_unchecked() = Default::default();
|
||||||
*state.status.write_unchecked() = ConnectionState::Connecting;
|
*state.status.write_unchecked() = ConnectionState::Connecting;
|
||||||
if let Err(error) =
|
if let Err(error) =
|
||||||
Platform::network_connect(address, username, &mut event_rx, &config, state.clone())
|
Platform::network_connect(target, username, &mut event_rx, &config, state.clone())
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
error!("could not connect {:?}", error);
|
error!("could not connect {:?}", error);
|
||||||
|
|||||||
@@ -17,6 +17,16 @@ pub struct ServerStatus {
|
|||||||
pub bandwidth: Option<u32>,
|
pub bandwidth: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)]
|
||||||
|
pub struct ServerEntry {
|
||||||
|
pub name: String,
|
||||||
|
pub address: String,
|
||||||
|
pub port: u16,
|
||||||
|
pub username: String,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub password: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Mumble UDP ping protocol.
|
/// Mumble UDP ping protocol.
|
||||||
///
|
///
|
||||||
/// Send a 12-byte packet: 4 zero bytes + 8-byte identifier.
|
/// Send a 12-byte packet: 4 zero bytes + 8-byte identifier.
|
||||||
|
|||||||
Reference in New Issue
Block a user