Skip to content

Commit 4177abf

Browse files
authored
重构 EasyTier 参数拼接逻辑 (#81)
* Refactor EasyTier argument building. * Remote unused imports. * Fix. * Refactor PortForward configuration.
1 parent 9485b0e commit 4177abf

File tree

6 files changed

+460
-375
lines changed

6 files changed

+460
-375
lines changed

src/controller/rooms/experimental/room.rs

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::controller::rooms::legacy;
33
use crate::controller::states::{AppState, AppStateCapture};
44
use crate::controller::{ExceptionType, Room, RoomKind, SCAFFOLDING_PORT};
55
use crate::easytier;
6+
use crate::easytier::argument::{Argument, PortForward, Proto};
67
use crate::mc::fakeserver::FakeServer;
78
use crate::ports::PortRequest;
89
use crate::scaffolding::client::ClientSession;
@@ -11,10 +12,12 @@ use crate::scaffolding::PacketResponse;
1112
use rand_chacha::ChaCha12Rng;
1213
use rand_core::{OsRng, RngCore, SeedableRng, TryRngCore};
1314
use serde_json::{json, Value};
15+
use std::borrow::Cow;
1416
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
1517
use std::str::FromStr;
1618
use std::time::{Duration, SystemTime};
1719
use std::{io, thread};
20+
use std::mem::{transmute, MaybeUninit};
1821

1922
static CHARS: &[u8] = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ".as_bytes();
2023

@@ -137,13 +140,11 @@ pub fn start_host(room: Room, port: u16, player: Option<String>, capture: AppSta
137140
let scaffolding = *SCAFFOLDING_PORT;
138141

139142
let mut args = compute_arguments(&room);
140-
args.push("--hostname".to_string());
141-
args.push(format!("scaffolding-mc-server-{}", scaffolding));
142-
args.push("--ipv4".to_string());
143-
args.push("10.144.144.1".to_string());
144-
args.push(format!("--tcp-whitelist={}", scaffolding));
145-
args.push(format!("--tcp-whitelist={}", port));
146-
args.push(format!("--udp-whitelist={}", port));
143+
args.push(Argument::HostName(Cow::Owned(format!("scaffolding-mc-server-{}", scaffolding))));
144+
args.push(Argument::IPv4(Ipv4Addr::new(10, 144, 144, 1)));
145+
args.push(Argument::TcpWhitelist(scaffolding));
146+
args.push(Argument::TcpWhitelist(port));
147+
args.push(Argument::UdpWhitelist(port));
147148

148149
let easytier = easytier::FACTORY.create(args);
149150
let capture = {
@@ -213,9 +214,9 @@ pub fn start_host(room: Room, port: u16, player: Option<String>, capture: AppSta
213214

214215
pub fn start_guest(room: Room, player: Option<String>, capture: AppStateCapture) {
215216
let mut args = compute_arguments(&room);
216-
args.push("-d".to_string());
217-
args.push("--tcp-whitelist=0".to_string());
218-
args.push("--udp-whitelist=0".to_string());
217+
args.push(Argument::DHCP);
218+
args.push(Argument::TcpWhitelist(0));
219+
args.push(Argument::UdpWhitelist(0));
219220
let easytier = easytier::FACTORY.create(args);
220221
let capture = {
221222
let Some(state) = capture.try_capture() else {
@@ -250,10 +251,11 @@ pub fn start_guest(room: Room, player: Option<String>, capture: AppStateCapture)
250251

251252
let local_port = PortRequest::Scaffolding.request();
252253

253-
if !easytier.add_port_forward(&[(
254-
SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, local_port).into(),
255-
SocketAddrV4::new(ip, port).into(),
256-
)]) {
254+
if !easytier.add_port_forward(&[PortForward {
255+
local: SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, local_port).into(),
256+
remote: SocketAddrV4::new(ip, port).into(),
257+
proto: Proto::TCP
258+
}]) {
257259
logging!("RoomExperiment", "Cannot create a port-forward {} -> {} for Scaffolding Connection.", local_port, port);
258260
state.set(AppState::Exception { kind: ExceptionType::GuestEasytierCrash });
259261
return;
@@ -346,17 +348,31 @@ pub fn start_guest(room: Room, player: Option<String>, capture: AppStateCapture)
346348
// If failed, use a dynamic free port instead.
347349
let local_port = PortRequest::request_specific(port).unwrap_or_else(|| PortRequest::Minecraft.request());
348350

349-
if !easytier.add_port_forward(&[(
350-
SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, local_port).into(),
351-
SocketAddrV4::new(host_ip, port).into()
352-
), (
353-
SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, local_port, 0, 0).into(),
354-
SocketAddrV4::new(host_ip, port).into()
355-
)]) {
351+
if !easytier.add_port_forward(&{
352+
let locals = [
353+
SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, local_port).into(),
354+
SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, local_port, 0, 0).into(),
355+
];
356+
let protos = [Proto::TCP, Proto::UDP];
357+
358+
// TODO: Compute SIZE automatically.
359+
const SIZE: usize = 4;
360+
assert_eq!(locals.len() * protos.len(), SIZE);
361+
let mut forwards: [MaybeUninit<PortForward>; SIZE] = [const { MaybeUninit::uninit() }; _];
362+
for (i, local) in locals.into_iter().enumerate() {
363+
for (j, proto) in protos.iter().enumerate() {
364+
forwards[i * 2 + j].write(PortForward {
365+
remote: SocketAddrV4::new(host_ip, port).into(), local, proto: proto.clone()
366+
});
367+
}
368+
}
369+
// SAFETY: These two types are of the same size and all elements have been properly initialized.
370+
unsafe { transmute::<[MaybeUninit<PortForward>; SIZE], [PortForward; SIZE]>(forwards) }
371+
}) {
356372
logging!("RoomExperiment", "Cannot create a port-forward {} -> {} for MC Connection.", local_port, port);
357373
state.set(AppState::Exception { kind: ExceptionType::GuestEasytierCrash });
358374
return;
359-
}
375+
} else {}
360376

361377
local_port
362378
};
@@ -549,44 +565,40 @@ static FALLBACK_SERVERS: [&str; 2] = [
549565
"tcp://public2.easytier.cn:54321",
550566
];
551567

552-
fn compute_arguments(room: &Room) -> Vec<String> {
553-
static DEFAULT_ARGUMENTS: [&str; 7] = [
554-
"--no-tun",
555-
"--compression=zstd",
556-
"--multi-thread",
557-
"--latency-first",
558-
"--enable-kcp-proxy",
559-
"-l",
560-
"udp://0.0.0.0:0",
568+
fn compute_arguments(room: &Room) -> Vec<Argument> {
569+
static DEFAULT_ARGUMENTS: [Argument; 6] = [
570+
Argument::NoTun,
571+
Argument::Compression(Cow::Borrowed("zstd")),
572+
Argument::MultiThread,
573+
Argument::LatencyFirst,
574+
Argument::EnableKcpProxy,
575+
Argument::Listener {
576+
address: SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0).into(),
577+
proto: Proto::UDP
578+
},
561579
];
562580

563-
let mut args: Vec<String> = Vec::with_capacity(32);
581+
let mut args: Vec<Argument> = Vec::with_capacity(32);
564582
args.extend_from_slice(&[
565-
"--network-name".to_string(),
566-
room.network_name.clone(),
567-
"--network-secret".to_string(),
568-
room.network_secret.clone(),
583+
Argument::NetworkName(Cow::Owned(room.network_name.clone())),
584+
Argument::NetworkSecret(Cow::Owned(room.network_secret.clone())),
569585
]);
570586

571587
match fetch_public_nodes(room) {
572588
Ok(nodes) => {
573589
for replay in nodes {
574-
args.push("-p".to_string());
575-
args.push(replay);
590+
args.push(Argument::PublicServer(Cow::Owned(replay)));
576591
}
577592
}
578593
Err(e) => {
579594
logging!("RoomExperiment", "Cannot fetch EasyTier public nodes: {:?}.", e);
580595
for replay in FALLBACK_SERVERS {
581-
args.push("-p".to_string());
582-
args.push(replay.to_string());
596+
args.push(Argument::PublicServer(Cow::Borrowed(replay)));
583597
}
584598
}
585599
}
586600

587-
for arg in DEFAULT_ARGUMENTS {
588-
args.push(arg.to_string());
589-
}
601+
args.extend_from_slice(&DEFAULT_ARGUMENTS);
590602
args
591603
}
592604

src/controller/rooms/legacy.rs

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use crate::controller::states::{AppState, AppStateCapture};
22
use crate::controller::{ExceptionType, Room, RoomKind};
33
use crate::easytier;
4+
use crate::easytier::argument::{Argument, PortForward, Proto};
45
use crate::mc::fakeserver::FakeServer;
56
use crate::ports::PortRequest;
67
use num_bigint::BigUint;
78
use socket2::{Domain, SockAddr, Socket, Type};
9+
use std::borrow::Cow;
810
use std::mem::MaybeUninit;
9-
use std::net::{Ipv4Addr, SocketAddrV4};
11+
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
1012
use std::thread;
1113
use std::time::{Duration, SystemTime};
1214

@@ -167,51 +169,47 @@ pub fn start_guest(room: Room, capture: AppStateCapture) {
167169
"tcp://et.01130328.xyz:11010",
168170
"tcp://et.gbc.moe:11011",
169171
];
170-
static DEFAULT_ARGUMENTS: [&'static str; 5] = [
171-
"--no-tun",
172-
"--compression=zstd",
173-
"--multi-thread",
174-
"--latency-first",
175-
"--enable-kcp-proxy",
172+
static DEFAULT_ARGUMENTS: [Argument; 5] = [
173+
Argument::NoTun,
174+
Argument::Compression(Cow::Borrowed("zstd")),
175+
Argument::MultiThread,
176+
Argument::LatencyFirst,
177+
Argument::EnableKcpProxy,
176178
];
177179

178180
let mut args = vec![
179-
"--network-name".to_string(),
180-
room.network_name.clone(),
181-
"--network-secret".to_string(),
182-
room.network_secret.clone(),
181+
Argument::NetworkName(Cow::Owned(room.network_name.clone())),
182+
Argument::NetworkSecret(Cow::Owned(room.network_secret.clone())),
183183
];
184184

185185
if matches!(room.kind, RoomKind::PCL2CE { .. }) {
186-
args.push("-p".to_string());
187-
args.push("tcp://43.139.42.188:11010".to_string())
186+
args.push(Argument::PublicServer(Cow::Borrowed("tcp://43.139.42.188:11010")));
188187
}
189188

190189
for replay in REPLAY_SERVERS.iter() {
191-
args.push("-p".to_string());
192-
args.push(replay.to_string());
193-
}
194-
for arg in DEFAULT_ARGUMENTS.iter() {
195-
args.push(arg.to_string());
190+
args.push(Argument::PublicServer(Cow::Borrowed(&replay)));
196191
}
192+
args.extend_from_slice(&DEFAULT_ARGUMENTS);
197193

198194
let local_port = PortRequest::Minecraft.request();
199195

200196
let (host_ip, remote_port) = match room.kind {
201-
RoomKind::TerracottaLegacy { mc_port, .. } => ("10.144.144.1", mc_port),
202-
RoomKind::PCL2CE { mc_port, .. } => ("10.114.51.41", mc_port),
197+
RoomKind::TerracottaLegacy { mc_port, .. } => (Ipv4Addr::new(10, 144, 144, 1), mc_port),
198+
RoomKind::PCL2CE { mc_port, .. } => (Ipv4Addr::new(10, 144, 51, 41), mc_port),
203199
_ => panic!("Should NOT be here"),
204200
};
205201

206-
args.push("-d".to_string());
207-
args.push(format!(
208-
"--port-forward=tcp://[::0]:{}/{}:{}",
209-
local_port, host_ip, remote_port
210-
));
211-
args.push(format!(
212-
"--port-forward=tcp://0.0.0.0:{}/{}:{}",
213-
local_port, host_ip, remote_port
214-
));
202+
args.push(Argument::DHCP);
203+
args.push(Argument::PortForward(PortForward {
204+
local: SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, local_port).into(),
205+
remote: SocketAddrV4::new(host_ip, remote_port).into(),
206+
proto: Proto::TCP,
207+
}));
208+
args.push(Argument::PortForward(PortForward {
209+
local: SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, local_port, 0, 0).into(),
210+
remote: SocketAddrV4::new(host_ip, remote_port).into(),
211+
proto: Proto::TCP,
212+
}));
215213

216214
let capture = {
217215
let easytier = easytier::FACTORY.create(args);

src/easytier/argument.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use std::borrow::Cow;
2+
use std::net::{Ipv4Addr, SocketAddr};
3+
4+
type CowString = Cow<'static, str>;
5+
6+
#[derive(Clone)]
7+
pub struct PortForward {
8+
pub(crate) local: SocketAddr,
9+
pub(crate) remote: SocketAddr,
10+
pub(crate) proto: Proto,
11+
}
12+
13+
#[derive(Clone)]
14+
pub enum Proto {
15+
TCP,
16+
UDP,
17+
}
18+
19+
impl Proto {
20+
pub fn name(&self) -> &'static str {
21+
match self {
22+
Proto::TCP => "tcp",
23+
Proto::UDP => "udp"
24+
}
25+
}
26+
}
27+
28+
#[derive(Clone)]
29+
pub enum Argument {
30+
NoTun,
31+
Compression(CowString),
32+
MultiThread,
33+
LatencyFirst,
34+
EnableKcpProxy,
35+
NetworkName(CowString),
36+
NetworkSecret(CowString),
37+
PublicServer(CowString),
38+
Listener {
39+
address: SocketAddr,
40+
proto: Proto,
41+
},
42+
PortForward(PortForward),
43+
DHCP,
44+
HostName(CowString),
45+
IPv4(Ipv4Addr),
46+
TcpWhitelist(u16),
47+
UdpWhitelist(u16),
48+
}

0 commit comments

Comments
 (0)