further simplify proxy config
This commit is contained in:
Generated
+1
@@ -3606,6 +3606,7 @@ dependencies = [
|
|||||||
"toml",
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
+1
-3
@@ -1,9 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
|
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
|
||||||
pub struct GuiConfig {
|
pub struct ClientConfig {
|
||||||
#[serde(default)]
|
|
||||||
pub force_proxy: bool,
|
|
||||||
pub proxy_url: Option<String>,
|
pub proxy_url: Option<String>,
|
||||||
pub cert_hash: Option<Vec<u8>>,
|
pub cert_hash: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-4
@@ -1,8 +1,5 @@
|
|||||||
|
public_url = "https://127.0.0.1:4433"
|
||||||
https_listen_address = "127.0.0.1:4433"
|
https_listen_address = "127.0.0.1:4433"
|
||||||
http_listen_address = "127.0.0.1:8080"
|
http_listen_address = "127.0.0.1:8080"
|
||||||
mumble_server_url = "[SERVER_URL_HERE]"
|
mumble_server_url = "[SERVER_URL_HERE]"
|
||||||
gui_path = "target/dx/mumble-web2-gui/release/web/public"
|
gui_path = "target/dx/mumble-web2-gui/release/web/public"
|
||||||
|
|
||||||
[gui]
|
|
||||||
force_proxy = true
|
|
||||||
proxy_url = "https://127.0.0.1:4433/proxy"
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
|
public_url = "https://127.0.0.1:4433"
|
||||||
https_listen_address = "127.0.0.1:4433"
|
https_listen_address = "127.0.0.1:4433"
|
||||||
http_listen_address = "127.0.0.1:4400"
|
http_listen_address = "127.0.0.1:4400"
|
||||||
mumble_server_url = "127.0.0.1:64738"
|
mumble_server_url = "127.0.0.1:64738"
|
||||||
|
|
||||||
[gui]
|
|
||||||
force_proxy = true
|
|
||||||
proxy_url = "https://127.0.0.1:4433/proxy"
|
|
||||||
|
|||||||
+6
-6
@@ -3,7 +3,7 @@
|
|||||||
use base64::{display::Base64Display, prelude::BASE64_URL_SAFE};
|
use base64::{display::Base64Display, prelude::BASE64_URL_SAFE};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use mime_guess::Mime;
|
use mime_guess::Mime;
|
||||||
use mumble_web2_common::GuiConfig;
|
use mumble_web2_common::ClientConfig;
|
||||||
use ordermap::OrderSet;
|
use ordermap::OrderSet;
|
||||||
use sir::{css, global_css};
|
use sir::{css, global_css};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -26,7 +26,7 @@ pub enum Command {
|
|||||||
Connect {
|
Connect {
|
||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
config: GuiConfig,
|
config: ClientConfig,
|
||||||
},
|
},
|
||||||
SendChat {
|
SendChat {
|
||||||
markdown: String,
|
markdown: String,
|
||||||
@@ -437,7 +437,7 @@ pub fn ChatView() -> Element {
|
|||||||
//},
|
//},
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn ControlView(config: Resource<GuiConfig>) -> Element {
|
pub fn ControlView(config: Resource<ClientConfig>) -> Element {
|
||||||
let net: Coroutine<Command> = use_coroutine_handle();
|
let net: Coroutine<Command> = use_coroutine_handle();
|
||||||
let status = &STATE.status;
|
let status = &STATE.status;
|
||||||
let server = STATE.server.read();
|
let server = STATE.server.read();
|
||||||
@@ -705,7 +705,7 @@ pub fn ControlView(config: Resource<GuiConfig>) -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn ServerView(config: Resource<GuiConfig>) -> Element {
|
pub fn ServerView(config: Resource<ClientConfig>) -> Element {
|
||||||
let net: Coroutine<Command> = use_coroutine_handle();
|
let net: Coroutine<Command> = use_coroutine_handle();
|
||||||
let server = STATE.server.read();
|
let server = STATE.server.read();
|
||||||
let Some(&UserState {
|
let Some(&UserState {
|
||||||
@@ -803,7 +803,7 @@ pub fn ServerView(config: Resource<GuiConfig>) -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn LoginView(config: Resource<GuiConfig>) -> Element {
|
pub fn LoginView(config: Resource<ClientConfig>) -> Element {
|
||||||
let net: Coroutine<Command> = use_coroutine_handle();
|
let net: Coroutine<Command> = use_coroutine_handle();
|
||||||
|
|
||||||
let mut address_input = use_signal(|| None::<String>);
|
let mut address_input = use_signal(|| None::<String>);
|
||||||
@@ -931,7 +931,7 @@ pub fn app() -> Element {
|
|||||||
let config = use_resource(|| async move {
|
let config = use_resource(|| async move {
|
||||||
match imp::load_config().await {
|
match imp::load_config().await {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(_) => GuiConfig::default(),
|
Err(_) => ClientConfig::default(),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use dioxus::hooks::{UnboundedReceiver, UnboundedSender};
|
|||||||
use futures::io::{AsyncRead, AsyncWrite};
|
use futures::io::{AsyncRead, AsyncWrite};
|
||||||
use mumble_protocol::control::{ClientControlCodec, ControlPacket};
|
use mumble_protocol::control::{ClientControlCodec, ControlPacket};
|
||||||
use mumble_protocol::Serverbound;
|
use mumble_protocol::Serverbound;
|
||||||
use mumble_web2_common::GuiConfig;
|
use mumble_web2_common::ClientConfig;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::{fmt, io, sync::Arc};
|
use std::{fmt, io, sync::Arc};
|
||||||
@@ -188,7 +188,7 @@ pub async fn network_connect(
|
|||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
gui_config: &GuiConfig,
|
gui_config: &ClientConfig,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
info!("connecting");
|
info!("connecting");
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ pub fn load_username() -> Option<String> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn load_config() -> color_eyre::Result<GuiConfig> {
|
pub async fn load_config() -> color_eyre::Result<ClientConfig> {
|
||||||
color_eyre::eyre::bail!(
|
color_eyre::eyre::bail!(
|
||||||
"there is no config on desktop because desktops cannot be configured as they are tables"
|
"there is no config on desktop because desktops cannot be configured as they are tables"
|
||||||
)
|
)
|
||||||
|
|||||||
+12
-7
@@ -7,7 +7,7 @@ use gloo_timers::future::TimeoutFuture;
|
|||||||
use mumble_protocol::control::{ClientControlCodec, ControlPacket};
|
use mumble_protocol::control::{ClientControlCodec, ControlPacket};
|
||||||
use mumble_protocol::voice::{VoicePacket, VoicePacketPayload};
|
use mumble_protocol::voice::{VoicePacket, VoicePacketPayload};
|
||||||
use mumble_protocol::Serverbound;
|
use mumble_protocol::Serverbound;
|
||||||
use mumble_web2_common::GuiConfig;
|
use mumble_web2_common::ClientConfig;
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tracing::level_filters::LevelFilter;
|
use tracing::level_filters::LevelFilter;
|
||||||
@@ -178,8 +178,8 @@ impl AudioPlayer {
|
|||||||
// Borrowed from
|
// Borrowed from
|
||||||
// https://github.com/security-union/videocall-rs/blob/main/videocall-client/src/decode/config.rs#L6
|
// https://github.com/security-union/videocall-rs/blob/main/videocall-client/src/decode/config.rs#L6
|
||||||
fn configure_audio_context() -> AudioContext {
|
fn configure_audio_context() -> AudioContext {
|
||||||
let mut audio_context_options = AudioContextOptions::new();
|
let audio_context_options = AudioContextOptions::new();
|
||||||
audio_context_options.sample_rate(48000 as f32);
|
audio_context_options.set_sample_rate(48000 as f32);
|
||||||
let audio_context = AudioContext::new_with_context_options(&audio_context_options).unwrap();
|
let audio_context = AudioContext::new_with_context_options(&audio_context_options).unwrap();
|
||||||
audio_context
|
audio_context
|
||||||
}
|
}
|
||||||
@@ -198,12 +198,14 @@ async fn run_encoder_worklet(
|
|||||||
audio_context: &AudioContext,
|
audio_context: &AudioContext,
|
||||||
mut each: impl FnMut(Vec<u8>) + 'static,
|
mut each: impl FnMut(Vec<u8>) + 'static,
|
||||||
) -> Result<AudioWorkletNode, Error> {
|
) -> Result<AudioWorkletNode, Error> {
|
||||||
|
let constraints = MediaStreamConstraints::new();
|
||||||
|
constraints.set_audio(&JsValue::TRUE);
|
||||||
let stream = window()
|
let stream = window()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.navigator()
|
.navigator()
|
||||||
.media_devices()
|
.media_devices()
|
||||||
.ey()?
|
.ey()?
|
||||||
.get_user_media_with_constraints(MediaStreamConstraints::new().audio(&JsValue::TRUE))
|
.get_user_media_with_constraints(&constraints)
|
||||||
.ey()?
|
.ey()?
|
||||||
.into_future()
|
.into_future()
|
||||||
.await
|
.await
|
||||||
@@ -309,7 +311,7 @@ pub async fn network_connect(
|
|||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
gui_config: &GuiConfig,
|
gui_config: &ClientConfig,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
info!("connecting");
|
info!("connecting");
|
||||||
|
|
||||||
@@ -388,7 +390,7 @@ pub fn load_username() -> Option<String> {
|
|||||||
.ok()?
|
.ok()?
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn load_config() -> color_eyre::Result<GuiConfig> {
|
pub async fn load_config() -> color_eyre::Result<ClientConfig> {
|
||||||
let config_url = match option_env!("MUMBLE_WEB2_GUI_CONFIG_URL") {
|
let config_url = match option_env!("MUMBLE_WEB2_GUI_CONFIG_URL") {
|
||||||
Some(url) => Url::parse(url)?,
|
Some(url) => Url::parse(url)?,
|
||||||
None => {
|
None => {
|
||||||
@@ -399,7 +401,10 @@ pub async fn load_config() -> color_eyre::Result<GuiConfig> {
|
|||||||
};
|
};
|
||||||
info!("loading config from {}", config_url);
|
info!("loading config from {}", config_url);
|
||||||
|
|
||||||
let config = reqwest::get(config_url).await?.json::<GuiConfig>().await?;
|
let config = reqwest::get(config_url)
|
||||||
|
.await?
|
||||||
|
.json::<ClientConfig>()
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ use mumble_protocol::voice::VoicePacket;
|
|||||||
use mumble_protocol::voice::VoicePacketPayload;
|
use mumble_protocol::voice::VoicePacketPayload;
|
||||||
use mumble_protocol::Clientbound;
|
use mumble_protocol::Clientbound;
|
||||||
use mumble_protocol::Serverbound;
|
use mumble_protocol::Serverbound;
|
||||||
use mumble_web2_common::GuiConfig;
|
use mumble_web2_common::ClientConfig;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|||||||
Generated
-2567
File diff suppressed because it is too large
Load Diff
+13
-12
@@ -4,16 +4,16 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
color-eyre = "0.6.3"
|
color-eyre = "^0.6"
|
||||||
serde = { version = "1.0.214", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1.0.132"
|
serde_json = "1"
|
||||||
tokio = { version = "1.37.0", features = ["full"] }
|
tokio = { version = "^1.37", features = ["full"] }
|
||||||
tokio-rustls = "^0.26"
|
tokio-rustls = "0.26"
|
||||||
toml = "0.8.19"
|
toml = "0.8"
|
||||||
tracing = { version = "0.1.40", features = ["async-await"] }
|
tracing = { version = "^0.1.40", features = ["async-await"] }
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "^0.3.18", features = ["env-filter"] }
|
||||||
mumble-web2-common = { workspace = true }
|
mumble-web2-common = { workspace = true }
|
||||||
salvo = { version = "0.74.2", features = [
|
salvo = { version = "^0.74.2", features = [
|
||||||
"quinn",
|
"quinn",
|
||||||
"eyre",
|
"eyre",
|
||||||
"rustls",
|
"rustls",
|
||||||
@@ -22,8 +22,9 @@ salvo = { version = "0.74.2", features = [
|
|||||||
"craft",
|
"craft",
|
||||||
"cors",
|
"cors",
|
||||||
] }
|
] }
|
||||||
once_cell = "1.20.2"
|
once_cell = "^1.20"
|
||||||
rustls = { version = "^0.23", features = ["aws_lc_rs"] }
|
rustls = { version = "^0.23", features = ["aws_lc_rs"] }
|
||||||
rcgen = "0.13.2"
|
rcgen = "^0.13.2"
|
||||||
hmac-sha256 = "1.1.8"
|
hmac-sha256 = "^1.1.8"
|
||||||
time = "0.3"
|
time = "0.3"
|
||||||
|
url = "2"
|
||||||
|
|||||||
+75
-86
@@ -1,6 +1,5 @@
|
|||||||
use color_eyre::eyre::{anyhow, bail, Context, Result};
|
use color_eyre::eyre::{anyhow, bail, Context, Result};
|
||||||
use mumble_web2_common::GuiConfig;
|
use mumble_web2_common::ClientConfig;
|
||||||
use once_cell::sync::OnceCell;
|
|
||||||
use salvo::conn::rustls::{Keycert, RustlsConfig};
|
use salvo::conn::rustls::{Keycert, RustlsConfig};
|
||||||
use salvo::cors::{AllowOrigin, Cors};
|
use salvo::cors::{AllowOrigin, Cors};
|
||||||
use salvo::logging::Logger;
|
use salvo::logging::Logger;
|
||||||
@@ -9,14 +8,14 @@ use salvo::proto::quic::BidiStream;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::net::{SocketAddr, ToSocketAddrs};
|
use std::net::{SocketAddr, ToSocketAddrs};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::Arc;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::pin;
|
use tokio::pin;
|
||||||
use tokio_rustls::rustls::client::danger::{HandshakeSignatureValid, ServerCertVerifier};
|
use tokio_rustls::rustls::client::danger::{HandshakeSignatureValid, ServerCertVerifier};
|
||||||
use tokio_rustls::rustls::pki_types::{CertificateDer, ServerName, UnixTime};
|
use tokio_rustls::rustls::pki_types::{CertificateDer, ServerName, UnixTime};
|
||||||
use tokio_rustls::rustls::{ClientConfig, DigitallySignedStruct};
|
use tokio_rustls::rustls::{ClientConfig as RlsClientConfig, DigitallySignedStruct};
|
||||||
use tokio_rustls::{rustls, TlsConnector};
|
use tokio_rustls::{rustls, TlsConnector};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use tracing::info_span;
|
use tracing::info_span;
|
||||||
@@ -24,6 +23,7 @@ use tracing::Instrument;
|
|||||||
use tracing::{error, instrument};
|
use tracing::{error, instrument};
|
||||||
use tracing_subscriber::filter::LevelFilter;
|
use tracing_subscriber::filter::LevelFilter;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
fn default_cert_alt_names() -> Vec<String> {
|
fn default_cert_alt_names() -> Vec<String> {
|
||||||
vec!["localhost".into()]
|
vec!["localhost".into()]
|
||||||
@@ -31,6 +31,7 @@ fn default_cert_alt_names() -> Vec<String> {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
struct Config {
|
struct Config {
|
||||||
|
public_url: Url,
|
||||||
https_listen_address: SocketAddr,
|
https_listen_address: SocketAddr,
|
||||||
http_listen_address: Option<SocketAddr>,
|
http_listen_address: Option<SocketAddr>,
|
||||||
cert_path: Option<PathBuf>,
|
cert_path: Option<PathBuf>,
|
||||||
@@ -40,12 +41,9 @@ struct Config {
|
|||||||
mumble_server_url: String,
|
mumble_server_url: String,
|
||||||
mumble_server_address: Option<SocketAddr>,
|
mumble_server_address: Option<SocketAddr>,
|
||||||
gui_path: Option<PathBuf>,
|
gui_path: Option<PathBuf>,
|
||||||
gui: Mutex<GuiConfig>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CONFIG: OnceCell<Config> = OnceCell::new();
|
fn init_config() -> Result<Config> {
|
||||||
|
|
||||||
fn init_config() -> Result<()> {
|
|
||||||
let mut config: Config = toml::from_str(
|
let mut config: Config = toml::from_str(
|
||||||
&std::fs::read_to_string("./config.toml")
|
&std::fs::read_to_string("./config.toml")
|
||||||
.context("reading config.toml (try making a copy of config.toml.example)")?,
|
.context("reading config.toml (try making a copy of config.toml.example)")?,
|
||||||
@@ -63,24 +61,22 @@ fn init_config() -> Result<()> {
|
|||||||
config.mumble_server_url
|
config.mumble_server_url
|
||||||
))?;
|
))?;
|
||||||
config.mumble_server_address = Some(mumble_server_addr);
|
config.mumble_server_address = Some(mumble_server_addr);
|
||||||
CONFIG
|
Ok(config)
|
||||||
.set(config)
|
|
||||||
.map_err(|_| anyhow!("config already initialized"))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
init_logging();
|
init_logging();
|
||||||
init_config()?;
|
let server_config = Arc::new(init_config()?);
|
||||||
let config = CONFIG.get().unwrap();
|
info!("config:\n{}", toml::to_string_pretty(&*server_config)?);
|
||||||
info!("config\n{}", toml::to_string_pretty(&config)?);
|
|
||||||
|
|
||||||
rustls::crypto::aws_lc_rs::default_provider()
|
rustls::crypto::aws_lc_rs::default_provider()
|
||||||
.install_default()
|
.install_default()
|
||||||
.map_err(|e| anyhow!("could not install crypto provider {e:?}"))?;
|
.map_err(|e| anyhow!("could not install crypto provider {e:?}"))?;
|
||||||
|
|
||||||
let (cert, key) = match (&config.cert_path, &config.key_path) {
|
let mut client_config = ClientConfig::default();
|
||||||
|
client_config.proxy_url = Some(server_config.public_url.join("proxy")?.to_string());
|
||||||
|
let (cert, key) = match (&server_config.cert_path, &server_config.key_path) {
|
||||||
(None, None) => {
|
(None, None) => {
|
||||||
info!("generating self-signed cert");
|
info!("generating self-signed cert");
|
||||||
|
|
||||||
@@ -88,17 +84,15 @@ async fn main() -> Result<()> {
|
|||||||
let mut dname = rcgen::DistinguishedName::new();
|
let mut dname = rcgen::DistinguishedName::new();
|
||||||
dname.push(rcgen::DnType::CommonName, "mumble-web self-signed");
|
dname.push(rcgen::DnType::CommonName, "mumble-web self-signed");
|
||||||
let key_pair = rcgen::KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256)?;
|
let key_pair = rcgen::KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256)?;
|
||||||
let mut cert_params = rcgen::CertificateParams::new(config.cert_alt_names.clone())?;
|
let mut cert_params =
|
||||||
|
rcgen::CertificateParams::new(server_config.cert_alt_names.clone())?;
|
||||||
cert_params.distinguished_name = dname;
|
cert_params.distinguished_name = dname;
|
||||||
cert_params.not_before = time::OffsetDateTime::now_utc();
|
cert_params.not_before = time::OffsetDateTime::now_utc();
|
||||||
cert_params.not_after = cert_params.not_before + time::Duration::days(12);
|
cert_params.not_after = cert_params.not_before + time::Duration::days(12);
|
||||||
let cert = cert_params.self_signed(&key_pair)?;
|
let cert = cert_params.self_signed(&key_pair)?;
|
||||||
|
|
||||||
let hash = hmac_sha256::Hash::hash(cert.der().as_ref());
|
let hash = hmac_sha256::Hash::hash(cert.der().as_ref());
|
||||||
{
|
client_config.cert_hash = Some(hash.into());
|
||||||
let mut gui_config = config.gui.lock().unwrap();
|
|
||||||
gui_config.cert_hash = Some(hash.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
(cert.pem().into(), key_pair.serialize_pem().into())
|
(cert.pem().into(), key_pair.serialize_pem().into())
|
||||||
}
|
}
|
||||||
@@ -118,16 +112,22 @@ async fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
let rustls_config = RustlsConfig::new(Keycert::new().cert(cert.as_slice()).key(key.as_slice()));
|
let rustls_config = RustlsConfig::new(Keycert::new().cert(cert.as_slice()).key(key.as_slice()));
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"client config:\n{}",
|
||||||
|
toml::to_string_pretty(&client_config)?
|
||||||
|
);
|
||||||
|
|
||||||
let config_craft = ConfigCraft {
|
let config_craft = ConfigCraft {
|
||||||
client_config: config.gui.lock().unwrap().clone(),
|
server_config: server_config.clone(),
|
||||||
|
client_config,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Server routing
|
// Server routing
|
||||||
let mut router = Router::new()
|
let mut router = Router::new()
|
||||||
.push(Router::with_path("/proxy").goal(connect_proxy))
|
.push(Router::with_path("/proxy").goal(config_craft.connect_proxy()))
|
||||||
.push(Router::with_path("/config").get(config_craft.get_config()))
|
.push(Router::with_path("/config").get(config_craft.get_config()))
|
||||||
.hoop(Logger::new());
|
.hoop(Logger::new());
|
||||||
if let Some(gui_path) = config.gui_path.clone() {
|
if let Some(gui_path) = server_config.gui_path.clone() {
|
||||||
router =
|
router =
|
||||||
router.push(Router::with_path("/").get(StaticFile::new(gui_path.join("index.html"))));
|
router.push(Router::with_path("/").get(StaticFile::new(gui_path.join("index.html"))));
|
||||||
router = router.push(Router::with_path("/<*+rest>").get(StaticDir::new(gui_path)));
|
router = router.push(Router::with_path("/<*+rest>").get(StaticDir::new(gui_path)));
|
||||||
@@ -138,10 +138,10 @@ async fn main() -> Result<()> {
|
|||||||
let service = Service::new(router).hoop(cors);
|
let service = Service::new(router).hoop(cors);
|
||||||
|
|
||||||
// Create http listeners
|
// Create http listeners
|
||||||
let http_listener = config.http_listen_address.map(TcpListener::new);
|
let http_listener = server_config.http_listen_address.map(TcpListener::new);
|
||||||
let https_listener =
|
let https_listener =
|
||||||
TcpListener::new(config.https_listen_address).rustls(rustls_config.clone());
|
TcpListener::new(server_config.https_listen_address).rustls(rustls_config.clone());
|
||||||
let http3_listener = QuinnListener::new(rustls_config, config.https_listen_address);
|
let http3_listener = QuinnListener::new(rustls_config, server_config.https_listen_address);
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
match (http_listener, https_listener, http3_listener) {
|
match (http_listener, https_listener, http3_listener) {
|
||||||
@@ -160,76 +160,65 @@ async fn main() -> Result<()> {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ConfigCraft {
|
pub struct ConfigCraft {
|
||||||
client_config: GuiConfig,
|
server_config: Arc<Config>,
|
||||||
|
client_config: ClientConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[craft]
|
#[craft]
|
||||||
impl ConfigCraft {
|
impl ConfigCraft {
|
||||||
#[craft(handler)]
|
#[craft(handler)]
|
||||||
async fn get_config(&self) -> Json<GuiConfig> {
|
async fn get_config(&self) -> Json<ClientConfig> {
|
||||||
Json(self.client_config.clone())
|
Json(self.client_config.clone())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[handler]
|
#[craft(handler)]
|
||||||
#[instrument]
|
async fn connect_proxy(&self, req: &mut Request, res: &mut Response) {
|
||||||
async fn connect_proxy(req: &mut Request, res: &mut Response) {
|
info!("received proxy request");
|
||||||
info!("received proxy request");
|
let mumble_server_address = self.server_config.mumble_server_address.unwrap();
|
||||||
let mumble_server_address = CONFIG.get().unwrap().mumble_server_address.unwrap();
|
|
||||||
|
|
||||||
let wt = match req.web_transport_mut().await {
|
let wt = match req.web_transport_mut().await {
|
||||||
Ok(wt) => wt,
|
Ok(wt) => wt,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
res.status_code(StatusCode::BAD_REQUEST);
|
res.status_code(StatusCode::BAD_REQUEST);
|
||||||
res.render(format!("error with webtransport: {err:?}"));
|
res.render(format!("error with webtransport: {err:?}"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
info!("got webtransport for connection");
|
info!("got webtransport for connection");
|
||||||
|
|
||||||
use salvo::webtransport::server::AcceptedBi;
|
use salvo::webtransport::server::AcceptedBi;
|
||||||
let (id, bi) = match wt.accept_bi().await {
|
let (id, bi) = match wt.accept_bi().await {
|
||||||
Ok(Some(AcceptedBi::BidiStream(id, bi))) => (id, bi),
|
Ok(Some(AcceptedBi::BidiStream(id, bi))) => (id, bi),
|
||||||
Ok(Some(AcceptedBi::Request(req, _))) => {
|
Ok(Some(AcceptedBi::Request(req, _))) => {
|
||||||
res.status_code(StatusCode::BAD_REQUEST);
|
res.status_code(StatusCode::BAD_REQUEST);
|
||||||
res.render(format!(
|
res.render(format!(
|
||||||
"expected webtransport stream but got request {req:?}"
|
"expected webtransport stream but got request {req:?}"
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
res.status_code(StatusCode::BAD_REQUEST);
|
res.status_code(StatusCode::BAD_REQUEST);
|
||||||
res.render(format!("no bidirectional connection requested"));
|
res.render(format!("no bidirectional connection requested"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
|
res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
res.render(format!("error with bidirectional connection: {err:?}"));
|
res.render(format!("error with bidirectional connection: {err:?}"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
let (outgoing, incoming) = bi.split();
|
||||||
let id = wt.session_id();
|
let res = tokio::spawn(async move {
|
||||||
let bi = match wt.open_bi(id).await {
|
if let Err(error) = connect_proxy_impl(mumble_server_address, incoming, outgoing).await
|
||||||
Ok(bi) => bi,
|
{
|
||||||
Err(err) => {
|
error!("error connecting proxy {error:?}")
|
||||||
res.status_code(StatusCode::BAD_REQUEST);
|
}
|
||||||
res.render(format!("could not open bidirectional stream: {err:?}"));
|
})
|
||||||
return;
|
.await;
|
||||||
|
if let Err(err) = res {
|
||||||
|
error!("crash in connected proxy {err:?}");
|
||||||
}
|
}
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
let (outgoing, incoming) = bi.split();
|
|
||||||
let res = tokio::spawn(async move {
|
|
||||||
if let Err(error) = connect_proxy_impl(mumble_server_address, incoming, outgoing).await {
|
|
||||||
error!("error connecting proxy {error:?}")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
if let Err(err) = res {
|
|
||||||
error!("crash in connected proxy {err:?}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +230,7 @@ async fn connect_proxy_impl(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
info!("connecting to Mumble server...");
|
info!("connecting to Mumble server...");
|
||||||
|
|
||||||
let config = ClientConfig::builder()
|
let config = RlsClientConfig::builder()
|
||||||
.dangerous()
|
.dangerous()
|
||||||
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification))
|
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification))
|
||||||
.with_no_client_auth();
|
.with_no_client_auth();
|
||||||
|
|||||||
Reference in New Issue
Block a user