break old loop if server changed and close both conns if one broke

This commit is contained in:
MeexReay 2024-07-16 22:40:58 +03:00
parent bd61673bcd
commit b83df07604

View File

@ -67,6 +67,7 @@ pub struct ProxyConfig {
pub talk_host: Option<String>, pub talk_host: Option<String>,
pub talk_secret: Option<String>, pub talk_secret: Option<String>,
pub player_forwarding: PlayerForwarding, pub player_forwarding: PlayerForwarding,
pub no_pf_for_ip_connect: bool,
} }
impl ProxyConfig { impl ProxyConfig {
@ -77,6 +78,7 @@ impl ProxyConfig {
talk_host: Option<String>, talk_host: Option<String>,
talk_secret: Option<String>, talk_secret: Option<String>,
player_forwarding: PlayerForwarding, player_forwarding: PlayerForwarding,
no_pf_for_ip_connect: bool,
) -> ProxyConfig { ) -> ProxyConfig {
ProxyConfig { ProxyConfig {
host, host,
@ -85,6 +87,7 @@ impl ProxyConfig {
talk_host, talk_host,
talk_secret, talk_secret,
player_forwarding, player_forwarding,
no_pf_for_ip_connect,
} }
} }
@ -103,6 +106,12 @@ impl ProxyConfig {
}, },
_ => PlayerForwarding::Handshake, _ => PlayerForwarding::Handshake,
}; };
let no_pf_for_ip_connect = data
.get(Value::String("no_pf_for_ip_connect".to_string()))
.or(Some(&Value::Bool(true)))
.ok_or(ProxyError::ConfigParse)?
.as_bool()
.ok_or(ProxyError::ConfigParse)?;
let mut servers = Vec::new(); let mut servers = Vec::new();
if let Some(servers_map) = data if let Some(servers_map) = data
@ -139,6 +148,7 @@ impl ProxyConfig {
talk_host, talk_host,
talk_secret, talk_secret,
player_forwarding, player_forwarding,
no_pf_for_ip_connect,
)) ))
} }
@ -181,11 +191,15 @@ impl ProxyConfig {
pub fn get_talk_secret(&self) -> Option<&String> { pub fn get_talk_secret(&self) -> Option<&String> {
self.talk_secret.as_ref() self.talk_secret.as_ref()
} }
pub fn get_no_pf_for_ip_connect(&self) -> bool {
self.no_pf_for_ip_connect
}
} }
pub struct ProxyPlayer { pub struct ProxyPlayer {
pub connection: TcpStream, pub client_conn: MinecraftConnection<TcpStream>,
pub connection_server: TcpStream, pub server_conn: MinecraftConnection<TcpStream>,
pub name: Option<String>, pub name: Option<String>,
pub uuid: Option<Uuid>, pub uuid: Option<Uuid>,
pub server: Option<ProxyServer>, pub server: Option<ProxyServer>,
@ -193,15 +207,15 @@ pub struct ProxyPlayer {
impl ProxyPlayer { impl ProxyPlayer {
pub fn new( pub fn new(
connection: TcpStream, client_conn: MinecraftConnection<TcpStream>,
connection_server: TcpStream, server_conn: MinecraftConnection<TcpStream>,
name: Option<String>, name: Option<String>,
uuid: Option<Uuid>, uuid: Option<Uuid>,
server: Option<ProxyServer>, server: Option<ProxyServer>,
) -> ProxyPlayer { ) -> ProxyPlayer {
ProxyPlayer { ProxyPlayer {
connection, client_conn,
connection_server, server_conn,
name, name,
uuid, uuid,
server, server,
@ -211,7 +225,7 @@ impl ProxyPlayer {
pub struct MeexProx { pub struct MeexProx {
pub config: ProxyConfig, pub config: ProxyConfig,
pub players: Vec<ProxyPlayer>, pub players: Vec<Arc<Mutex<ProxyPlayer>>>,
pub listener: Option<TcpListener>, pub listener: Option<TcpListener>,
} }
@ -224,11 +238,11 @@ impl MeexProx {
} }
} }
pub fn get_player(&self, uuid: Uuid) -> Option<&ProxyPlayer> { pub fn get_player(&self, uuid: Uuid) -> Option<Arc<Mutex<ProxyPlayer>>> {
for player in &self.players { for player in &self.players {
if let Some(player_uuid) = player.uuid { if let Some(player_uuid) = player.lock().unwrap().uuid {
if player_uuid == uuid { if player_uuid == uuid {
return Some(player); return Some(player.clone());
} }
} }
} }
@ -244,19 +258,7 @@ impl MeexProx {
let mut client_conn = MinecraftConnection::new(stream); let mut client_conn = MinecraftConnection::new(stream);
// TODO: remove this anti-ipv6 mrakobesie!! info!("connected stream {}", addr.to_string());
let SocketAddr::V4(addrv4) = addr else {
return Ok(());
};
debug!(
"accepted stream {}.{}.{}.{}:{}",
addrv4.ip().octets()[0],
addrv4.ip().octets()[1],
addrv4.ip().octets()[2],
addrv4.ip().octets()[3],
addrv4.port()
);
// TODO: remove this anti-ipv6 mrakobesie!!
let mut handshake = client_conn.read_packet()?; let mut handshake = client_conn.read_packet()?;
@ -300,14 +302,14 @@ impl MeexProx {
server_conn.write_packet(&handshake)?; server_conn.write_packet(&handshake)?;
if next_state == 1 { if next_state == 1 {
debug!("state: motd"); debug!("switched to motd state");
loop { loop {
server_conn.write_packet(&client_conn.read_packet()?)?; server_conn.write_packet(&client_conn.read_packet()?)?;
client_conn.write_packet(&server_conn.read_packet()?)?; client_conn.write_packet(&server_conn.read_packet()?)?;
} }
} else if next_state == 2 { } else if next_state == 2 {
debug!("state: login"); debug!("switched to login state");
let plugin_response_packet = Packet::build(0x02, |packet| { let plugin_response_packet = Packet::build(0x02, |packet| {
packet.write_i8_varint(-99)?; packet.write_i8_varint(-99)?;
@ -326,15 +328,35 @@ impl MeexProx {
Ok(()) Ok(())
})?; })?;
let player = Arc::new(Mutex::new(ProxyPlayer::new(
client_conn.try_clone().unwrap(),
server_conn.try_clone().unwrap(),
None,
None,
Some(server.clone()),
)));
this.lock().unwrap().players.push(player.clone());
thread::spawn({ thread::spawn({
let mut client_conn = client_conn.try_clone().unwrap(); let mut client_conn = client_conn.try_clone().unwrap();
let mut server_conn = server_conn.try_clone().unwrap(); let mut server_conn = server_conn.try_clone().unwrap();
let player = player.clone();
let server = server.clone();
move || { move || {
move || -> Result<(), ProtocolError> { let res = || -> Result<(), ProtocolError> {
let mut joined = false; let mut joined = false;
loop { loop {
if let Some(player_server) = player.lock().unwrap().server.as_ref() {
if player_server.host != server.host {
break;
}
} else {
break;
}
let mut packet = match client_conn.read_packet() { let mut packet = match client_conn.read_packet() {
Ok(packet) => packet, Ok(packet) => packet,
Err(_) => break, Err(_) => break,
@ -344,34 +366,35 @@ impl MeexProx {
let name = packet.read_string()?; let name = packet.read_string()?;
let uuid = packet.read_uuid()?; let uuid = packet.read_uuid()?;
this.lock().unwrap().players.push(ProxyPlayer::new( player.lock().unwrap().name = Some(name);
client_conn.get_ref().try_clone().unwrap(), player.lock().unwrap().uuid = Some(uuid);
server_conn.get_ref().try_clone().unwrap(),
Some(name),
Some(uuid),
Some(server.clone()),
));
joined = true; joined = true;
} }
// debug!("[C->S] sending packet {:#04X?} (size: {})", packet.id(), packet.len());
server_conn.write_packet(&packet)?; server_conn.write_packet(&packet)?;
} }
error!("serverbound error");
Ok(()) Ok(())
}() }();
.or_else(|e| {
error!("serverbound error: {:?}", e); if res.is_err() {
Ok::<(), ()>(()) client_conn.close();
}) server_conn.close();
.unwrap(); }
} }
}); });
move || -> Result<(), ProtocolError> { let res = || -> Result<(), ProtocolError> {
loop { loop {
if let Some(player_server) = player.lock().unwrap().server.as_ref() {
if player_server.host != server.host {
break;
}
} else {
break;
}
let mut packet = match server_conn.read_packet() { let mut packet = match server_conn.read_packet() {
Ok(packet) => packet, Ok(packet) => packet,
Err(_) => break, Err(_) => break,
@ -379,17 +402,10 @@ impl MeexProx {
if packet.id() == 0x02 { if packet.id() == 0x02 {
if let PlayerForwarding::PluginResponse = server_config.player_forwarding { if let PlayerForwarding::PluginResponse = server_config.player_forwarding {
debug!(
"[C->S] sending packet {:#04X?} (size: {})",
plugin_response_packet.id(),
plugin_response_packet.len()
);
server_conn.write_packet(&plugin_response_packet)?; server_conn.write_packet(&plugin_response_packet)?;
} }
} }
// debug!("[C<-S] sending packet {:#04X?} (size: {})", packet.id(), packet.len());
client_conn.write_packet(&packet)?; client_conn.write_packet(&packet)?;
if packet.id() == 0x03 { if packet.id() == 0x03 {
@ -406,15 +422,14 @@ impl MeexProx {
} }
} }
} }
error!("clientbound error");
Ok(()) Ok(())
}() }();
.or_else(|e| {
error!("clientbound error: {:?}", e); if res.is_err() {
Ok::<(), ()>(()) client_conn.close();
}) server_conn.close();
.unwrap(); }
} }
Ok(()) Ok(())
@ -431,7 +446,12 @@ impl MeexProx {
if let Ok(client) = client { if let Ok(client) = client {
let mutex_self_clone = mutex_self.clone(); let mutex_self_clone = mutex_self.clone();
thread::spawn(move || { thread::spawn(move || {
Self::accept(mutex_self_clone, client).expect("accept error"); match Self::accept(mutex_self_clone, client) {
Ok(_) => {}
Err(e) => {
error!("connection error: {:?}", e);
}
};
}); });
} }
} }