This commit is contained in:
parent
32c5437c5d
commit
1931cb8c7c
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1568,6 +1568,7 @@ dependencies = [
|
|||||||
"protobuf-codegen-pure",
|
"protobuf-codegen-pure",
|
||||||
"quinn",
|
"quinn",
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
|
"regex",
|
||||||
"serde 1.0.133",
|
"serde 1.0.133",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json 1.0.74",
|
"serde_json 1.0.74",
|
||||||
|
@ -28,6 +28,7 @@ confy = { git = "https://github.com/open-trade/confy" }
|
|||||||
dirs-next = "2.0"
|
dirs-next = "2.0"
|
||||||
filetime = "0.2"
|
filetime = "0.2"
|
||||||
sodiumoxide = "0.2"
|
sodiumoxide = "0.2"
|
||||||
|
regex = "1.4"
|
||||||
tokio-socks = { git = "https://github.com/fufesou/tokio-socks" }
|
tokio-socks = { git = "https://github.com/fufesou/tokio-socks" }
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
|
@ -27,6 +27,7 @@ pub use anyhow::{self, bail};
|
|||||||
pub use futures_util;
|
pub use futures_util;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
|
pub use regex;
|
||||||
pub use sodiumoxide;
|
pub use sodiumoxide;
|
||||||
pub use tokio_socks;
|
pub use tokio_socks;
|
||||||
pub use tokio_socks::IntoTargetAddr;
|
pub use tokio_socks::IntoTargetAddr;
|
||||||
|
@ -103,8 +103,33 @@ impl Drop for OboePlayer {
|
|||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub async fn start(peer: &str, conn_type: ConnType) -> ResultType<(Stream, bool)> {
|
pub async fn start(peer: &str, conn_type: ConnType) -> ResultType<(Stream, bool)> {
|
||||||
|
match Self::_start(peer, conn_type).await {
|
||||||
|
Err(err) => {
|
||||||
|
let err_str = err.to_string();
|
||||||
|
if err_str.starts_with("Failed") {
|
||||||
|
bail!(err_str + ": Please try later");
|
||||||
|
} else {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(x) => Ok(x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn _start(peer: &str, conn_type: ConnType) -> ResultType<(Stream, bool)> {
|
||||||
// to-do: remember the port for each peer, so that we can retry easier
|
// to-do: remember the port for each peer, so that we can retry easier
|
||||||
let any_addr = Config::get_any_listen_addr();
|
let any_addr = Config::get_any_listen_addr();
|
||||||
|
if crate::is_ip(peer) {
|
||||||
|
return Ok((
|
||||||
|
socket_client::connect_tcp(
|
||||||
|
crate::check_port(peer, RELAY_PORT + 1),
|
||||||
|
any_addr,
|
||||||
|
RENDEZVOUS_TIMEOUT,
|
||||||
|
)
|
||||||
|
.await?,
|
||||||
|
true,
|
||||||
|
));
|
||||||
|
}
|
||||||
let rendezvous_server = crate::get_rendezvous_server(1_000).await;
|
let rendezvous_server = crate::get_rendezvous_server(1_000).await;
|
||||||
log::info!("rendezvous server: {}", rendezvous_server);
|
log::info!("rendezvous server: {}", rendezvous_server);
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ async fn test_rendezvous_server_() {
|
|||||||
futs.push(tokio::spawn(async move {
|
futs.push(tokio::spawn(async move {
|
||||||
let tm = std::time::Instant::now();
|
let tm = std::time::Instant::now();
|
||||||
if socket_client::connect_tcp(
|
if socket_client::connect_tcp(
|
||||||
&crate::check_port(&host, RENDEZVOUS_PORT),
|
crate::check_port(&host, RENDEZVOUS_PORT),
|
||||||
Config::get_any_listen_addr(),
|
Config::get_any_listen_addr(),
|
||||||
RENDEZVOUS_TIMEOUT,
|
RENDEZVOUS_TIMEOUT,
|
||||||
)
|
)
|
||||||
@ -461,3 +461,10 @@ async fn _check_software_update() -> hbb_common::ResultType<()> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_ip(id: &str) -> bool {
|
||||||
|
hbb_common::regex::Regex::new(r"^\d+\.\d+\.\d+\.\d+$")
|
||||||
|
.unwrap()
|
||||||
|
.is_match(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -218,6 +218,8 @@ async fn handle(data: Data, stream: &mut Connection) {
|
|||||||
value = Some(Config::get_salt());
|
value = Some(Config::get_salt());
|
||||||
} else if name == "rendezvous_server" {
|
} else if name == "rendezvous_server" {
|
||||||
value = Some(Config::get_rendezvous_server());
|
value = Some(Config::get_rendezvous_server());
|
||||||
|
} else if name == "rendezvous_servers" {
|
||||||
|
value = Some(Config::get_rendezvous_servers().join(","));
|
||||||
} else {
|
} else {
|
||||||
value = None;
|
value = None;
|
||||||
}
|
}
|
||||||
@ -225,6 +227,7 @@ async fn handle(data: Data, stream: &mut Connection) {
|
|||||||
}
|
}
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
if name == "id" {
|
if name == "id" {
|
||||||
|
Config::set_key_confirmed(false);
|
||||||
Config::set_id(&value);
|
Config::set_id(&value);
|
||||||
} else if name == "password" {
|
} else if name == "password" {
|
||||||
Config::set_password(&value);
|
Config::set_password(&value);
|
||||||
|
@ -31,6 +31,7 @@ lazy_static::lazy_static! {
|
|||||||
static ref SOLVING_PK_MISMATCH: Arc<Mutex<String>> = Default::default();
|
static ref SOLVING_PK_MISMATCH: Arc<Mutex<String>> = Default::default();
|
||||||
}
|
}
|
||||||
static SHOULD_EXIT: AtomicBool = AtomicBool::new(false);
|
static SHOULD_EXIT: AtomicBool = AtomicBool::new(false);
|
||||||
|
const REG_INTERVAL: i64 = 12_000;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RendezvousMediator {
|
pub struct RendezvousMediator {
|
||||||
@ -54,6 +55,10 @@ impl RendezvousMediator {
|
|||||||
crate::common::test_nat_type();
|
crate::common::test_nat_type();
|
||||||
nat_tested = true;
|
nat_tested = true;
|
||||||
}
|
}
|
||||||
|
let server_cloned = server.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
allow_err!(direct_server(server_cloned).await);
|
||||||
|
});
|
||||||
loop {
|
loop {
|
||||||
Config::reset_online();
|
Config::reset_online();
|
||||||
if Config::get_option("stop-service").is_empty() {
|
if Config::get_option("stop-service").is_empty() {
|
||||||
@ -111,7 +116,6 @@ impl RendezvousMediator {
|
|||||||
const TIMER_OUT: Duration = Duration::from_secs(1);
|
const TIMER_OUT: Duration = Duration::from_secs(1);
|
||||||
let mut timer = interval(TIMER_OUT);
|
let mut timer = interval(TIMER_OUT);
|
||||||
let mut last_timer = SystemTime::UNIX_EPOCH;
|
let mut last_timer = SystemTime::UNIX_EPOCH;
|
||||||
const REG_INTERVAL: i64 = 12_000;
|
|
||||||
const REG_TIMEOUT: i64 = 3_000;
|
const REG_TIMEOUT: i64 = 3_000;
|
||||||
const MAX_FAILS1: i64 = 3;
|
const MAX_FAILS1: i64 = 3;
|
||||||
const MAX_FAILS2: i64 = 6;
|
const MAX_FAILS2: i64 = 6;
|
||||||
@ -246,7 +250,7 @@ impl RendezvousMediator {
|
|||||||
// old UDP socket not work any more after network recover
|
// old UDP socket not work any more after network recover
|
||||||
if let Some(s) = socket_client::rebind_udp(any_addr).await? {
|
if let Some(s) = socket_client::rebind_udp(any_addr).await? {
|
||||||
socket = s;
|
socket = s;
|
||||||
};
|
}
|
||||||
last_dns_check = now;
|
last_dns_check = now;
|
||||||
}
|
}
|
||||||
} else if fails > MAX_FAILS1 {
|
} else if fails > MAX_FAILS1 {
|
||||||
@ -457,3 +461,43 @@ impl RendezvousMediator {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn direct_server(server: ServerPtr) -> ResultType<()> {
|
||||||
|
let port = RENDEZVOUS_PORT + 2;
|
||||||
|
let addr = format!("0.0.0.0:{}", port);
|
||||||
|
let mut listener = None;
|
||||||
|
loop {
|
||||||
|
if !Config::get_option("direct-server").is_empty() && listener.is_none() {
|
||||||
|
listener = Some(hbb_common::tcp::new_listener(&addr, false).await?);
|
||||||
|
log::info!(
|
||||||
|
"Direct server listening on: {}",
|
||||||
|
&listener.as_ref().unwrap().local_addr()?
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(l) = listener.as_mut() {
|
||||||
|
if let Ok(Ok((stream, addr))) = hbb_common::timeout(1000, l.accept()).await {
|
||||||
|
if Config::get_option("direct-server").is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
log::info!("direct access from {}", addr);
|
||||||
|
let local_addr = stream.local_addr()?;
|
||||||
|
let server = server.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
allow_err!(
|
||||||
|
crate::server::create_tcp_connection(
|
||||||
|
server,
|
||||||
|
hbb_common::Stream::from(stream, local_addr),
|
||||||
|
addr,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sleep(0.1).await;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sleep(1.).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -589,7 +589,7 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if lr.username != Config::get_id() {
|
if !crate::is_ip(&lr.username) && lr.username != Config::get_id() {
|
||||||
self.send_login_error("Offline").await;
|
self.send_login_error("Offline").await;
|
||||||
} else if lr.password.is_empty() {
|
} else if lr.password.is_empty() {
|
||||||
self.try_start_cm(lr.my_id, lr.my_name, false).await;
|
self.try_start_cm(lr.my_id, lr.my_name, false).await;
|
||||||
|
@ -4,6 +4,7 @@ html {
|
|||||||
var(gray-bg): #eee;
|
var(gray-bg): #eee;
|
||||||
var(bg): white;
|
var(bg): white;
|
||||||
var(border): #ccc;
|
var(border): #ccc;
|
||||||
|
var(hover-border): #999;
|
||||||
var(text): #222;
|
var(text): #222;
|
||||||
var(placeholder): #aaa;
|
var(placeholder): #aaa;
|
||||||
var(lighter-text): #888;
|
var(lighter-text): #888;
|
||||||
@ -52,6 +53,10 @@ button.button:active, button.active {
|
|||||||
border-color: color(accent);
|
border-color: color(accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.button:hover, button.outline:hover {
|
||||||
|
border-color: color(hover-border);
|
||||||
|
}
|
||||||
|
|
||||||
input[type=text], input[type=password], input[type=number] {
|
input[type=text], input[type=password], input[type=number] {
|
||||||
width: *;
|
width: *;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
|
@ -62,6 +62,24 @@ function createNewConnect(id, type) {
|
|||||||
handler.new_remote(id, type);
|
handler.new_remote(id, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var direct_server;
|
||||||
|
class DirectServer: Reactor.Component {
|
||||||
|
function this() {
|
||||||
|
direct_server = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
var text = translate("Enable Direct IP Access");
|
||||||
|
var cls = handler.get_option("direct-server") == "Y" ? "selected" : "line-through";
|
||||||
|
return <li class={cls}><span>{svg_checkmark}</span>{text}</li>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClick() {
|
||||||
|
handler.set_option("direct-server", handler.get_option("direct-server") == "Y" ? "" : "Y");
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var myIdMenu;
|
var myIdMenu;
|
||||||
var audioInputMenu;
|
var audioInputMenu;
|
||||||
class AudioInputs: Reactor.Component {
|
class AudioInputs: Reactor.Component {
|
||||||
@ -138,6 +156,7 @@ class MyIdMenu: Reactor.Component {
|
|||||||
<li #socks5-server>{translate('Socks5 Proxy')}</li>
|
<li #socks5-server>{translate('Socks5 Proxy')}</li>
|
||||||
<div .separator />
|
<div .separator />
|
||||||
<li #stop-service class={service_stopped ? "line-through" : "selected"}><span>{svg_checkmark}</span>{translate("Enable Service")}</li>
|
<li #stop-service class={service_stopped ? "line-through" : "selected"}><span>{svg_checkmark}</span>{translate("Enable Service")}</li>
|
||||||
|
<DirectServer />
|
||||||
<div .separator />
|
<div .separator />
|
||||||
<li #about>{translate('About')} {" "} {handler.get_app_name()}</li>
|
<li #about>{translate('About')} {" "} {handler.get_app_name()}</li>
|
||||||
</menu>
|
</menu>
|
||||||
@ -147,6 +166,7 @@ class MyIdMenu: Reactor.Component {
|
|||||||
event click $(svg#menu) (_, me) {
|
event click $(svg#menu) (_, me) {
|
||||||
audioInputMenu.update({ show: true });
|
audioInputMenu.update({ show: true });
|
||||||
this.toggleMenuState();
|
this.toggleMenuState();
|
||||||
|
if (direct_server) direct_server.update();
|
||||||
var menu = $(menu#config-options);
|
var menu = $(menu#config-options);
|
||||||
me.popup(menu);
|
me.popup(menu);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user