Allow arguments to be specified in toml file (closes #10)
This commit is contained in:
parent
2a95f11d30
commit
ab58196ee5
31
Cargo.lock
generated
31
Cargo.lock
generated
|
@ -650,10 +650,12 @@ dependencies = [
|
||||||
"native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
"openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rtp 0.1.0 (git+https://github.com/johni0702/rtp?rev=1444b3c)",
|
"rtp 0.1.0 (git+https://github.com/johni0702/rtp?rev=1444b3c)",
|
||||||
|
"serde 1.0.113 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"webrtc-sdp 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"webrtc-sdp 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -1093,6 +1095,24 @@ dependencies = [
|
||||||
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.113"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive 1.0.113 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.113"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha-1"
|
name = "sha-1"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
|
@ -1288,6 +1308,14 @@ dependencies = [
|
||||||
"tokio 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"serde 1.0.113 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "trackable"
|
name = "trackable"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
|
@ -1573,6 +1601,8 @@ dependencies = [
|
||||||
"checksum schannel 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19"
|
"checksum schannel 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19"
|
||||||
"checksum security-framework 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "572dfa3a0785509e7a44b5b4bebcf94d41ba34e9ed9eb9df722545c3b3c4144a"
|
"checksum security-framework 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "572dfa3a0785509e7a44b5b4bebcf94d41ba34e9ed9eb9df722545c3b3c4144a"
|
||||||
"checksum security-framework-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddb15a5fec93b7021b8a9e96009c5d8d51c15673569f7c0f6b7204e5b7b404f"
|
"checksum security-framework-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddb15a5fec93b7021b8a9e96009c5d8d51c15673569f7c0f6b7204e5b7b404f"
|
||||||
|
"checksum serde 1.0.113 (registry+https://github.com/rust-lang/crates.io-index)" = "6135c78461981c79497158ef777264c51d9d0f4f3fc3a4d22b915900e42dac6a"
|
||||||
|
"checksum serde_derive 1.0.113 (registry+https://github.com/rust-lang/crates.io-index)" = "93c5eaa17d0954cb481cdcfffe9d84fcfa7a1a9f2349271e678677be4c26ae31"
|
||||||
"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||||
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
||||||
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
|
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
|
||||||
|
@ -1593,6 +1623,7 @@ dependencies = [
|
||||||
"checksum tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828"
|
"checksum tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828"
|
||||||
"checksum tokio-tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b8fe88007ebc363512449868d7da4389c9400072a3f666f212c7280082882a"
|
"checksum tokio-tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b8fe88007ebc363512449868d7da4389c9400072a3f666f212c7280082882a"
|
||||||
"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
|
"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
|
||||||
|
"checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
|
||||||
"checksum trackable 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "65defd0876240a5301307e55ada18dea77372391c65cee3a421fac482be3a25a"
|
"checksum trackable 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "65defd0876240a5301307e55ada18dea77372391c65cee3a421fac482be3a25a"
|
||||||
"checksum tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e"
|
"checksum tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e"
|
||||||
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
||||||
|
|
|
@ -9,6 +9,8 @@ argparse = "0.2.2"
|
||||||
bytes = "0.5"
|
bytes = "0.5"
|
||||||
byteorder = "1.2"
|
byteorder = "1.2"
|
||||||
futures = { version = "0.3", features = ["compat", "io-compat"] }
|
futures = { version = "0.3", features = ["compat", "io-compat"] }
|
||||||
|
toml = "0.5"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tokio = { version = "0.2", features = ["full"] }
|
tokio = { version = "0.2", features = ["full"] }
|
||||||
tokio-util = { version = "0.3", features = ["codec"] }
|
tokio-util = { version = "0.3", features = ["codec"] }
|
||||||
tokio-tls = "0.3"
|
tokio-tls = "0.3"
|
||||||
|
|
|
@ -38,6 +38,12 @@ E.g. if you want the proxy to listen on port `64737` and connect to your Mumble
|
||||||
mumble-web-proxy --listen-ws 64737 --server mumbleserver:64738
|
mumble-web-proxy --listen-ws 64737 --server mumbleserver:64738
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Instead of specifying all the options directly in the arguments, you can also use `--config <file>` to point mumble-web-proxy at a toml file which contains them:
|
||||||
|
```
|
||||||
|
listen-ws = 64737
|
||||||
|
server = 'mumbleserver:64738'
|
||||||
|
```
|
||||||
|
|
||||||
#### Firewalls or NAT
|
#### Firewalls or NAT
|
||||||
If your mumble-web-proxy is running behind a firewall or NAT, you need to allocate a range of ports to it which it can use for ICE connection establishment.
|
If your mumble-web-proxy is running behind a firewall or NAT, you need to allocate a range of ports to it which it can use for ICE connection establishment.
|
||||||
```
|
```
|
||||||
|
|
|
@ -204,8 +204,8 @@ impl Connection {
|
||||||
// Setup ICE stream
|
// Setup ICE stream
|
||||||
let mut stream = match {
|
let mut stream = match {
|
||||||
let mut builder = agent.stream_builder(1);
|
let mut builder = agent.stream_builder(1);
|
||||||
if self.config.min_port != 1 || self.config.max_port != u16::max_value() {
|
if self.config.ice_min_port != 1 || self.config.ice_max_port != u16::max_value() {
|
||||||
builder.set_port_range(self.config.min_port, self.config.max_port);
|
builder.set_port_range(self.config.ice_min_port, self.config.ice_max_port);
|
||||||
}
|
}
|
||||||
builder.build()
|
builder.build()
|
||||||
} {
|
} {
|
||||||
|
@ -259,7 +259,11 @@ impl Connection {
|
||||||
|
|
||||||
// Map to public addresses (if configured)
|
// Map to public addresses (if configured)
|
||||||
let config = &self.config;
|
let config = &self.config;
|
||||||
match (&mut candidate.address, config.public_v4, config.public_v6) {
|
match (
|
||||||
|
&mut candidate.address,
|
||||||
|
config.ice_public_v4,
|
||||||
|
config.ice_public_v6,
|
||||||
|
) {
|
||||||
(webrtc_sdp::address::Address::Ip(IpAddr::V4(addr)), Some(public), _) => {
|
(webrtc_sdp::address::Address::Ip(IpAddr::V4(addr)), Some(public), _) => {
|
||||||
*addr = public;
|
*addr = public;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,12 @@ impl From<rtp::Error> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<toml::de::Error> for Error {
|
||||||
|
fn from(e: toml::de::Error) -> Self {
|
||||||
|
Error::Misc(Box::new(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<()> for Error {
|
impl From<()> for Error {
|
||||||
fn from(_: ()) -> Self {
|
fn from(_: ()) -> Self {
|
||||||
panic!();
|
panic!();
|
||||||
|
|
173
src/main.rs
173
src/main.rs
|
@ -12,6 +12,7 @@ use mumble_protocol::control::ClientControlCodec;
|
||||||
use mumble_protocol::control::ControlPacket;
|
use mumble_protocol::control::ControlPacket;
|
||||||
use mumble_protocol::control::RawControlPacket;
|
use mumble_protocol::control::RawControlPacket;
|
||||||
use mumble_protocol::Clientbound;
|
use mumble_protocol::Clientbound;
|
||||||
|
use serde::Deserialize;
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
|
@ -32,72 +33,128 @@ mod error;
|
||||||
use connection::Connection;
|
use connection::Connection;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub min_port: u16,
|
pub file: Option<String>,
|
||||||
pub max_port: u16,
|
#[serde(rename = "listen-ws")]
|
||||||
pub public_v4: Option<Ipv4Addr>,
|
pub ws_port: u16,
|
||||||
pub public_v6: Option<Ipv6Addr>,
|
#[serde(rename = "server")]
|
||||||
|
pub upstream: String,
|
||||||
|
#[serde(rename = "accept-invalid-certificate")]
|
||||||
|
pub accept_invalid_certs: bool,
|
||||||
|
pub ice_min_port: u16,
|
||||||
|
pub ice_max_port: u16,
|
||||||
|
pub ice_public_v4: Option<Ipv4Addr>,
|
||||||
|
pub ice_public_v6: Option<Ipv6Addr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Config {
|
||||||
|
Config {
|
||||||
|
file: None,
|
||||||
|
ws_port: 0_u16,
|
||||||
|
upstream: "".to_string(),
|
||||||
|
accept_invalid_certs: false,
|
||||||
|
ice_min_port: 1,
|
||||||
|
ice_max_port: u16::max_value(),
|
||||||
|
ice_public_v4: None,
|
||||||
|
ice_public_v6: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_argparser(config: &mut Config) -> ArgumentParser {
|
||||||
|
let mut ap = ArgumentParser::new();
|
||||||
|
ap.set_description("Run the Mumble-WebRTC proxy");
|
||||||
|
ap.refer(&mut config.file).add_option(
|
||||||
|
&["--config"],
|
||||||
|
StoreOption,
|
||||||
|
"Toml file to read options from",
|
||||||
|
);
|
||||||
|
ap.refer(&mut config.ws_port).add_option(
|
||||||
|
&["--listen-ws"],
|
||||||
|
Store,
|
||||||
|
"Port to listen for WebSocket (non TLS) connections on",
|
||||||
|
);
|
||||||
|
ap.refer(&mut config.upstream).add_option(
|
||||||
|
&["--server"],
|
||||||
|
Store,
|
||||||
|
"Hostname and (optionally) port of the upstream Mumble server",
|
||||||
|
);
|
||||||
|
ap.refer(&mut config.accept_invalid_certs).add_option(
|
||||||
|
&["--accept-invalid-certificate"],
|
||||||
|
StoreTrue,
|
||||||
|
"Connect to upstream server even when its certificate is invalid.
|
||||||
|
Only ever use this if know that your server is using a self-signed certificate!",
|
||||||
|
);
|
||||||
|
ap.refer(&mut config.ice_min_port).add_option(
|
||||||
|
&["--ice-port-min"],
|
||||||
|
Store,
|
||||||
|
"Minimum port number to use for ICE host candidates.",
|
||||||
|
);
|
||||||
|
ap.refer(&mut config.ice_max_port).add_option(
|
||||||
|
&["--ice-port-max"],
|
||||||
|
Store,
|
||||||
|
"Maximum port number to use for ICE host candidates.",
|
||||||
|
);
|
||||||
|
ap.refer(&mut config.ice_public_v4).add_option(
|
||||||
|
&["--ice-ipv4"],
|
||||||
|
StoreOption,
|
||||||
|
"Set a public IPv4 address to be used for ICE host candidates.",
|
||||||
|
);
|
||||||
|
ap.refer(&mut config.ice_public_v6).add_option(
|
||||||
|
&["--ice-ipv6"],
|
||||||
|
StoreOption,
|
||||||
|
"Set a public IPv6 address to be used for ICE host candidates.",
|
||||||
|
);
|
||||||
|
ap
|
||||||
|
}
|
||||||
|
|
||||||
|
fn error_missing_arg(arg: &str) {
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
let name = if args.len() > 0 {
|
||||||
|
&args[0][..]
|
||||||
|
} else {
|
||||||
|
"unknown"
|
||||||
|
};
|
||||||
|
let mut config = Config::default();
|
||||||
|
let ap = create_argparser(&mut config);
|
||||||
|
ap.error(
|
||||||
|
name,
|
||||||
|
&format!("Option [\"--{}\"] is required", arg),
|
||||||
|
&mut std::io::stderr(),
|
||||||
|
);
|
||||||
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), Error> {
|
||||||
let mut ws_port = 0_u16;
|
let mut config = Config::default();
|
||||||
let mut upstream = "".to_string();
|
|
||||||
let mut accept_invalid_certs = false;
|
|
||||||
let mut config = Config {
|
|
||||||
min_port: 1,
|
|
||||||
max_port: u16::max_value(),
|
|
||||||
public_v4: None,
|
|
||||||
public_v6: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
{
|
// First pass to get the config file path
|
||||||
let mut ap = ArgumentParser::new();
|
create_argparser(&mut config).parse_args_or_exit();
|
||||||
ap.set_description("Run the Mumble-WebRTC proxy");
|
if let Some(file) = config.file {
|
||||||
ap.refer(&mut ws_port)
|
// Then read in the config defaults
|
||||||
.add_option(
|
config = toml::from_str(&std::fs::read_to_string(file)?)?;
|
||||||
&["--listen-ws"],
|
// Second pass to allow for overwrites
|
||||||
Store,
|
create_argparser(&mut config).parse_args_or_exit();
|
||||||
"Port to listen for WebSocket (non TLS) connections on",
|
|
||||||
)
|
|
||||||
.required();
|
|
||||||
ap.refer(&mut upstream)
|
|
||||||
.add_option(
|
|
||||||
&["--server"],
|
|
||||||
Store,
|
|
||||||
"Hostname and (optionally) port of the upstream Mumble server",
|
|
||||||
)
|
|
||||||
.required();
|
|
||||||
ap.refer(&mut accept_invalid_certs).add_option(
|
|
||||||
&["--accept-invalid-certificate"],
|
|
||||||
StoreTrue,
|
|
||||||
"Connect to upstream server even when its certificate is invalid.
|
|
||||||
Only ever use this if know that your server is using a self-signed certificate!",
|
|
||||||
);
|
|
||||||
ap.refer(&mut config.min_port).add_option(
|
|
||||||
&["--ice-port-min"],
|
|
||||||
Store,
|
|
||||||
"Minimum port number to use for ICE host candidates.",
|
|
||||||
);
|
|
||||||
ap.refer(&mut config.max_port).add_option(
|
|
||||||
&["--ice-port-max"],
|
|
||||||
Store,
|
|
||||||
"Maximum port number to use for ICE host candidates.",
|
|
||||||
);
|
|
||||||
ap.refer(&mut config.public_v4).add_option(
|
|
||||||
&["--ice-ipv4"],
|
|
||||||
StoreOption,
|
|
||||||
"Set a public IPv4 address to be used for ICE host candidates.",
|
|
||||||
);
|
|
||||||
ap.refer(&mut config.public_v6).add_option(
|
|
||||||
&["--ice-ipv6"],
|
|
||||||
StoreOption,
|
|
||||||
"Set a public IPv6 address to be used for ICE host candidates.",
|
|
||||||
);
|
|
||||||
ap.parse_args_or_exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.ws_port == 0 {
|
||||||
|
error_missing_arg("listen-ws");
|
||||||
|
}
|
||||||
|
if config.upstream == "" {
|
||||||
|
error_missing_arg("server");
|
||||||
|
}
|
||||||
|
|
||||||
|
let Config {
|
||||||
|
ws_port,
|
||||||
|
upstream,
|
||||||
|
accept_invalid_certs,
|
||||||
|
..
|
||||||
|
} = config.clone();
|
||||||
|
|
||||||
// Try parsing as raw IPv6 address first
|
// Try parsing as raw IPv6 address first
|
||||||
let (upstream_host, upstream_port) = match upstream.parse::<Ipv6Addr>() {
|
let (upstream_host, upstream_port) = match upstream.parse::<Ipv6Addr>() {
|
||||||
Ok(_) => (upstream.as_ref(), 64738),
|
Ok(_) => (upstream.as_ref(), 64738),
|
||||||
|
|
Loading…
Reference in a new issue