Add support for running behind firewall and NAT
This commit is contained in:
parent
20848303e9
commit
a194bb6c6f
5 changed files with 137 additions and 20 deletions
|
@ -22,6 +22,7 @@ use rtp::rfc5764::{DtlsSrtp, DtlsSrtpHandshakeResult};
|
|||
use rtp::traits::{ReadPacket, WritePacket};
|
||||
use std::collections::BTreeMap;
|
||||
use std::ffi::CString;
|
||||
use std::net::IpAddr;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::io;
|
||||
use tokio::prelude::*;
|
||||
|
@ -30,6 +31,7 @@ use webrtc_sdp::attribute_type::SdpAttribute;
|
|||
|
||||
use error::Error;
|
||||
use utils::EitherS;
|
||||
use Config;
|
||||
|
||||
type SessionId = u32;
|
||||
|
||||
|
@ -82,6 +84,7 @@ impl User {
|
|||
}
|
||||
|
||||
pub struct Connection {
|
||||
config: Config,
|
||||
inbound_client: Box<Stream<Item = ControlPacket<Serverbound>, Error = Error>>,
|
||||
outbound_client: Box<Sink<SinkItem = ControlPacket<Clientbound>, SinkError = Error>>,
|
||||
inbound_server: Box<Stream<Item = ControlPacket<Clientbound>, Error = Error>>,
|
||||
|
@ -109,6 +112,7 @@ pub struct Connection {
|
|||
|
||||
impl Connection {
|
||||
pub fn new<CSi, CSt, SSi, SSt>(
|
||||
config: Config,
|
||||
client_sink: CSi,
|
||||
client_stream: CSt,
|
||||
server_sink: SSi,
|
||||
|
@ -135,6 +139,7 @@ impl Connection {
|
|||
let cert = cert_builder.build();
|
||||
|
||||
Self {
|
||||
config,
|
||||
inbound_client: Box::new(client_stream),
|
||||
outbound_client: Box::new(client_sink),
|
||||
inbound_server: Box::new(server_stream),
|
||||
|
@ -192,7 +197,13 @@ impl Connection {
|
|||
agent.set_software("mumble-web-proxy");
|
||||
|
||||
// Setup ICE stream
|
||||
let mut stream = match agent.stream_builder(1).build() {
|
||||
let mut stream = match {
|
||||
let mut builder = agent.stream_builder(1);
|
||||
if self.config.min_port != 1 || self.config.max_port != u16::max_value() {
|
||||
builder.set_port_range(self.config.min_port, self.config.max_port);
|
||||
}
|
||||
builder.build()
|
||||
} {
|
||||
Ok(stream) => stream,
|
||||
Err(err) => {
|
||||
return stream::once(Err(io::Error::new(io::ErrorKind::Other, err).into()));
|
||||
|
@ -531,12 +542,24 @@ impl Future for Connection {
|
|||
|
||||
// Poll ice stream for new candidates
|
||||
if let Some((_, stream)) = &mut self.ice {
|
||||
if let Async::Ready(Some(candidate)) = stream.poll()? {
|
||||
let candidate = format!("candidate:{}", candidate.to_string());
|
||||
println!("Local ice candidate: {}", candidate);
|
||||
if let Async::Ready(Some(mut candidate)) = stream.poll()? {
|
||||
println!("Local ice candidate: {}", candidate.to_string());
|
||||
|
||||
// Map to public addresses (if configured)
|
||||
let config = &self.config;
|
||||
match (&mut candidate.address, config.public_v4, config.public_v6) {
|
||||
(IpAddr::V4(addr), Some(public), _) => {
|
||||
*addr = public;
|
||||
}
|
||||
(IpAddr::V6(addr), _, Some(public)) => {
|
||||
*addr = public;
|
||||
}
|
||||
_ => {} // non configured
|
||||
};
|
||||
|
||||
// Got a new candidate, send it to the client
|
||||
let mut msg = msgs::IceCandidate::new();
|
||||
msg.set_content(candidate.to_string());
|
||||
msg.set_content(format!("candidate:{}", candidate.to_string()));
|
||||
let frame = Frame::Client(msg.into());
|
||||
self.stream_to_be_sent = Some(Box::new(stream::once(Ok(frame))));
|
||||
continue 'poll;
|
||||
|
|
45
src/main.rs
45
src/main.rs
|
@ -19,6 +19,7 @@ extern crate tokio_tungstenite;
|
|||
extern crate tungstenite;
|
||||
extern crate webrtc_sdp;
|
||||
|
||||
use argparse::StoreOption;
|
||||
use argparse::StoreTrue;
|
||||
use argparse::{ArgumentParser, Store};
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
@ -30,6 +31,7 @@ use mumble_protocol::control::RawControlPacket;
|
|||
use mumble_protocol::Clientbound;
|
||||
use std::convert::Into;
|
||||
use std::convert::TryInto;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::net::Ipv6Addr;
|
||||
use std::net::ToSocketAddrs;
|
||||
use tokio::net::TcpListener;
|
||||
|
@ -48,10 +50,24 @@ mod utils;
|
|||
use connection::Connection;
|
||||
use error::Error;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
pub min_port: u16,
|
||||
pub max_port: u16,
|
||||
pub public_v4: Option<Ipv4Addr>,
|
||||
pub public_v6: Option<Ipv6Addr>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut ws_port = 0_u16;
|
||||
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,
|
||||
};
|
||||
|
||||
{
|
||||
let mut ap = ArgumentParser::new();
|
||||
|
@ -76,6 +92,26 @@ fn main() {
|
|||
"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();
|
||||
}
|
||||
|
||||
|
@ -138,6 +174,7 @@ fn main() {
|
|||
.from_err();
|
||||
|
||||
// Once both are done, begin proxy duty
|
||||
let config = config.clone();
|
||||
let f = client
|
||||
.join(server)
|
||||
.and_then(move |(client, server)| {
|
||||
|
@ -164,7 +201,13 @@ fn main() {
|
|||
let server_sink = server_sink.sink_from_err();
|
||||
let server_stream = server_stream.from_err();
|
||||
|
||||
Connection::new(client_sink, client_stream, server_sink, server_stream)
|
||||
Connection::new(
|
||||
config,
|
||||
client_sink,
|
||||
client_stream,
|
||||
server_sink,
|
||||
server_stream,
|
||||
)
|
||||
})
|
||||
.or_else(move |err| {
|
||||
if err.is_connection_closed() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue