some changes refactor and wowowow shkebede lavadovski

This commit is contained in:
MeexReay 2024-07-31 19:38:07 +03:00
parent df79d3c704
commit e41c006060
7 changed files with 1127 additions and 1056 deletions

1053
src/lib.rs

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ use rust_mc_proto::DataBufferReader;
use simplelog::{
ColorChoice, CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode, WriteLogger,
};
use std::{error::Error, fs::File};
use std::{error::Error, fs::File, sync::atomic::Ordering};
pub struct MyEventListener {}
@ -22,10 +22,18 @@ impl EventListener for MyEventListener {
RecvServerPacketEvent { packet, player } => {
// debug!("recv server packet event");
}
SendServerPacketEvent { packet, player } => {
SendServerPacketEvent {
packet,
player,
cancel,
} => {
// debug!("send server packet event");
}
SendClientPacketEvent { packet, player } => {
SendClientPacketEvent {
packet,
player,
cancel,
} => {
// debug!("send client packet event");
}
RecvClientPacketEvent { packet, player } => {
@ -35,6 +43,7 @@ impl EventListener for MyEventListener {
let command = packet.read_string()?;
if command == "reconnect" {
println!("reconnect wow");
ProxyPlayer::reconnect(player.clone(), this.clone(), "localhost", 25565)
.unwrap();
}
@ -43,10 +52,14 @@ impl EventListener for MyEventListener {
PlayerConnectedEvent { player } => {
debug!("player connected");
}
PlayerConnectingServerEvent { player, server } => {
PlayerConnectingServerEvent {
player,
server,
cancel,
} => {
debug!("player connecting server");
}
PlayerConnectingIPEvent { player, ip } => {
PlayerConnectingIPEvent { player, ip, cancel } => {
debug!("player connecting ip");
}
PlayerDisconnectedEvent { player } => {
@ -57,8 +70,10 @@ impl EventListener for MyEventListener {
client_address,
server_address,
server_port,
cancel,
} => {
debug!("status request");
*status = String::from("123123");
}
}

187
src/meexprox/config.rs Normal file
View File

@ -0,0 +1,187 @@
use super::ProxyError;
use serde_yml::Value;
use std::fs;
#[derive(Clone, Debug)]
pub struct ProxyServer {
name: String,
host: String,
forced_host: Option<String>,
}
impl ProxyServer {
pub fn new(name: String, host: String, forced_host: Option<String>) -> ProxyServer {
ProxyServer {
name,
host,
forced_host,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn host(&self) -> &str {
&self.host
}
pub fn forced_host(&self) -> Option<&String> {
self.forced_host.as_ref()
}
}
macro_rules! extract_string {
($data:expr, $key:expr) => {
match $data.get(&Value::String($key.to_string())) {
Some(Value::String(val)) => Some(val.clone()),
_ => None,
}
};
}
#[derive(Clone)]
pub enum PlayerForwarding {
Handshake,
Disabled,
}
#[derive(Clone)]
pub struct ProxyConfig {
host: String,
servers: Vec<ProxyServer>,
default_server: Option<ProxyServer>,
talk_host: Option<String>,
talk_secret: Option<String>,
player_forwarding: PlayerForwarding,
no_pf_for_ip_connect: bool,
}
impl ProxyConfig {
pub fn new(
host: String,
servers: Vec<ProxyServer>,
default_server: Option<ProxyServer>,
talk_host: Option<String>,
talk_secret: Option<String>,
player_forwarding: PlayerForwarding,
no_pf_for_ip_connect: bool,
) -> ProxyConfig {
ProxyConfig {
host,
servers,
default_server,
talk_host,
talk_secret,
player_forwarding,
no_pf_for_ip_connect,
}
}
pub fn host(&self) -> &str {
&self.host
}
pub fn servers(&self) -> &Vec<ProxyServer> {
&self.servers
}
pub fn talk_host(&self) -> Option<&String> {
self.talk_host.as_ref()
}
pub fn talk_secret(&self) -> Option<&String> {
self.talk_secret.as_ref()
}
pub fn default_server(&self) -> Option<&ProxyServer> {
self.default_server.as_ref()
}
pub fn player_forwarding(&self) -> &PlayerForwarding {
&self.player_forwarding
}
pub fn no_pf_for_ip_connect(&self) -> bool {
self.no_pf_for_ip_connect
}
pub fn load(path: &str) -> Result<ProxyConfig, Box<dyn std::error::Error>> {
let data = serde_yml::from_str::<Value>(&fs::read_to_string(path)?)?;
let data = data.as_mapping().ok_or(ProxyError::ConfigParse)?;
let host = extract_string!(data, "host").ok_or(ProxyError::ConfigParse)?;
let talk_host = extract_string!(data, "talk_host");
let talk_secret = extract_string!(data, "talk_secret");
let player_forwarding = match extract_string!(data, "player_forwarding") {
Some(pf) => match pf.as_str() {
"disabled" => PlayerForwarding::Disabled,
_ => 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();
if let Some(servers_map) = data
.get(&Value::String("servers".to_string()))
.and_then(Value::as_mapping)
{
for (name, addr) in servers_map {
if let (Value::String(name), Value::String(addr)) = (name, addr) {
servers.push(ProxyServer::new(name.clone(), addr.clone(), None));
}
}
}
if let Some(forced_hosts_map) = data
.get(&Value::String("forced_hosts".to_string()))
.and_then(Value::as_mapping)
{
for (name, host) in forced_hosts_map {
if let (Value::String(name), Value::String(host)) = (name, host) {
if let Some(server) = servers.iter_mut().find(|s| s.name == *name) {
server.forced_host = Some(host.clone());
}
}
}
}
let default_server = extract_string!(data, "default_server")
.and_then(|ds| servers.iter().find(|s| s.name == ds).cloned());
Ok(ProxyConfig::new(
host,
servers,
default_server,
talk_host,
talk_secret,
player_forwarding,
no_pf_for_ip_connect,
))
}
pub fn get_server_by_name(&self, name: &str) -> Option<ProxyServer> {
for server in &self.servers {
if &server.name == name {
return Some(server.clone());
}
}
None
}
pub fn get_server_by_forced_host(&self, forced_host: &str) -> Option<ProxyServer> {
for server in &self.servers {
if let Some(server_forced_host) = &server.forced_host {
if server_forced_host == forced_host {
return Some(server.clone());
}
}
}
None
}
}

14
src/meexprox/error.rs Normal file
View File

@ -0,0 +1,14 @@
#[derive(Debug)]
pub enum ProxyError {
ConfigParse,
ServerConnect,
EventChanged,
}
impl std::fmt::Display for ProxyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({:?})", self)
}
}
impl std::error::Error for ProxyError {}

230
src/meexprox/event.rs Normal file
View File

@ -0,0 +1,230 @@
use super::{MeexProx, MeexProxMutex, PlayerMutex, ProxyServer};
use rust_mc_proto::Packet;
use std::{
error::Error,
net::SocketAddr,
sync::atomic::{AtomicBool, Ordering},
};
#[derive(Debug)]
pub enum ProxyEvent {
/// client <- proxy <- server \
/// &nbsp; | \
/// &nbsp; RecvServerPacketEvent
RecvServerPacketEvent {
packet: Packet,
player: PlayerMutex,
},
/// client -> proxy -> server \
/// &nbsp; | \
/// &nbsp; SendServerPacketEvent
SendServerPacketEvent {
packet: Packet,
player: PlayerMutex,
cancel: AtomicBool,
},
/// client <- proxy <- server \
/// &nbsp; | \
/// &nbsp; SendClientPacketEvent
SendClientPacketEvent {
packet: Packet,
player: PlayerMutex,
cancel: AtomicBool,
},
/// client -> proxy -> server \
/// &nbsp; | \
/// &nbsp; RecvClientPacketEvent
RecvClientPacketEvent {
packet: Packet,
player: PlayerMutex,
},
PlayerConnectedEvent {
player: PlayerMutex,
},
PlayerDisconnectedEvent {
player: PlayerMutex,
},
PlayerConnectingServerEvent {
player: PlayerMutex,
server: ProxyServer,
cancel: AtomicBool,
},
PlayerConnectingIPEvent {
player: PlayerMutex,
ip: String,
cancel: AtomicBool,
},
StatusRequestEvent {
status: String,
client_address: SocketAddr,
server_address: String,
server_port: u16,
cancel: AtomicBool,
},
}
impl ProxyEvent {
pub fn status_request(
meexprox: MeexProxMutex,
status: String,
client_address: SocketAddr,
server_address: String,
server_port: u16,
) -> (String, bool) {
let ProxyEvent::StatusRequestEvent {
status,
client_address: _,
server_address: _,
server_port: _,
cancel,
} = MeexProx::trigger_event(
meexprox,
ProxyEvent::StatusRequestEvent {
status: status.clone(),
client_address,
server_address,
server_port,
cancel: AtomicBool::from(false),
},
)
else {
return (status, false);
};
(status, cancel.load(Ordering::Relaxed))
}
pub fn player_connecting_server(
meexprox: MeexProxMutex,
player: PlayerMutex,
server: ProxyServer,
) -> (ProxyServer, bool) {
let ProxyEvent::PlayerConnectingServerEvent {
server,
player: _,
cancel,
} = MeexProx::trigger_event(
meexprox,
ProxyEvent::PlayerConnectingServerEvent {
server: server.clone(),
player,
cancel: AtomicBool::from(false),
},
)
else {
return (server, false);
};
(server, cancel.load(Ordering::Relaxed))
}
pub fn player_disconnected(meexprox: MeexProxMutex, player: PlayerMutex) -> () {
let ProxyEvent::PlayerDisconnectedEvent { player: _ } =
MeexProx::trigger_event(meexprox, ProxyEvent::PlayerDisconnectedEvent { player })
else {
return;
};
}
pub fn player_connected(meexprox: MeexProxMutex, player: PlayerMutex) -> () {
let ProxyEvent::PlayerConnectedEvent { player: _ } =
MeexProx::trigger_event(meexprox, ProxyEvent::PlayerConnectedEvent { player })
else {
return;
};
}
pub fn send_client_packet(
meexprox: MeexProxMutex,
packet: Packet,
player: PlayerMutex,
) -> (Packet, bool) {
let ProxyEvent::SendClientPacketEvent {
packet,
player: _,
cancel,
} = MeexProx::trigger_event(
meexprox,
ProxyEvent::SendClientPacketEvent {
packet: packet.clone(),
player,
cancel: AtomicBool::from(false),
},
)
else {
return (packet, false);
};
(packet, cancel.load(Ordering::Relaxed))
}
pub fn send_server_packet(
meexprox: MeexProxMutex,
packet: Packet,
player: PlayerMutex,
) -> (Packet, bool) {
let ProxyEvent::SendServerPacketEvent {
packet,
player: _,
cancel,
} = MeexProx::trigger_event(
meexprox,
ProxyEvent::SendServerPacketEvent {
packet: packet.clone(),
player,
cancel: AtomicBool::from(false),
},
)
else {
return (packet, false);
};
(packet, cancel.load(Ordering::Relaxed))
}
pub fn recv_server_packet(
meexprox: MeexProxMutex,
packet: Packet,
player: PlayerMutex,
) -> Packet {
let ProxyEvent::RecvServerPacketEvent { packet, player: _ } = MeexProx::trigger_event(
meexprox,
ProxyEvent::RecvServerPacketEvent {
packet: packet.clone(),
player,
},
) else {
return packet;
};
packet
}
pub fn recv_client_packet(
meexprox: MeexProxMutex,
packet: Packet,
player: PlayerMutex,
) -> Packet {
let ProxyEvent::RecvClientPacketEvent { packet, player: _ } = MeexProx::trigger_event(
meexprox,
ProxyEvent::RecvClientPacketEvent {
packet: packet.clone(),
player,
},
) else {
return packet;
};
packet
}
}
pub trait EventListener {
fn on_event(
&mut self,
meexprox: MeexProxMutex,
event: &mut ProxyEvent,
) -> Result<(), Box<dyn Error>>;
}

665
src/meexprox/meexprox.rs Normal file
View File

@ -0,0 +1,665 @@
use super::{EventListener, PlayerForwarding, ProxyConfig, ProxyError, ProxyEvent, ProxyServer};
use derivative::Derivative;
use log::info;
use rust_mc_proto::{
DataBufferReader, DataBufferWriter, MinecraftConnection, Packet, ProtocolError, Zigzag,
};
use std::{
error::Error,
net::{SocketAddr, TcpListener, TcpStream},
sync::{
atomic::{AtomicUsize, Ordering},
Arc, Mutex,
},
thread,
};
use uuid::Uuid;
#[derive(Derivative)]
#[derivative(Debug)]
pub struct ProxyPlayer {
#[derivative(Debug = "ignore")]
client_conn: MinecraftConnection<TcpStream>,
#[derivative(Debug = "ignore")]
server_conn: MinecraftConnection<TcpStream>,
name: Option<String>,
uuid: Option<Uuid>,
protocol_version: u16,
server: Option<ProxyServer>,
shared_secret: Option<Vec<u8>>,
verify_token: Option<Vec<u8>>,
connection_id: Arc<AtomicUsize>,
}
impl ProxyPlayer {
pub fn new(
client_conn: MinecraftConnection<TcpStream>,
server_conn: MinecraftConnection<TcpStream>,
name: Option<String>,
uuid: Option<Uuid>,
protocol_version: u16,
server: Option<ProxyServer>,
shared_secret: Option<Vec<u8>>,
verify_token: Option<Vec<u8>>,
connection_id: Arc<AtomicUsize>,
) -> ProxyPlayer {
ProxyPlayer {
client_conn,
server_conn,
name,
uuid,
protocol_version,
server,
shared_secret,
verify_token,
connection_id,
}
}
pub fn client_conn(&self) -> &MinecraftConnection<TcpStream> {
&self.client_conn
}
pub fn server_conn(&self) -> &MinecraftConnection<TcpStream> {
&self.client_conn
}
pub fn client_conn_mut(&mut self) -> &mut MinecraftConnection<TcpStream> {
&mut self.client_conn
}
pub fn server_conn_mut(&mut self) -> &mut MinecraftConnection<TcpStream> {
&mut self.client_conn
}
pub fn name(&self) -> Option<&String> {
self.name.as_ref()
}
pub fn uuid(&self) -> Option<&Uuid> {
self.uuid.as_ref()
}
pub fn protocol_version(&self) -> u16 {
self.protocol_version
}
pub fn server(&self) -> Option<&ProxyServer> {
self.server.as_ref()
}
pub fn shared_secret(&self) -> Option<&Vec<u8>> {
self.shared_secret.as_ref()
}
pub fn verify_token(&self) -> Option<&Vec<u8>> {
self.verify_token.as_ref()
}
pub fn connection_id(&self) -> Arc<AtomicUsize> {
self.connection_id.clone()
}
pub fn connect_to_ip(
this: PlayerMutex,
meexprox: MeexProxMutex,
ip: &str,
server_address: &str,
server_port: u16,
) -> Result<(), Box<dyn Error>> {
this.lock()
.unwrap()
.connection_id
.fetch_add(1, Ordering::Relaxed);
this.lock().unwrap().server_conn.close();
this.lock().unwrap().server_conn = MinecraftConnection::connect(ip)?;
thread::spawn({
let player_forwarding = meexprox.lock().unwrap().config.player_forwarding().clone();
let server_address = server_address.to_string();
move || {
let _ = ProxyPlayer::connect(
this,
meexprox,
player_forwarding,
&server_address,
server_port,
false,
);
}
});
Ok(())
}
pub fn connect_to_server(
this: PlayerMutex,
meexprox: MeexProxMutex,
server: ProxyServer,
server_address: &str,
server_port: u16,
) -> Result<(), Box<dyn Error>> {
this.lock()
.unwrap()
.connection_id
.fetch_add(1, Ordering::Relaxed);
this.lock().unwrap().server = Some(server.clone());
this.lock().unwrap().server_conn.close();
this.lock().unwrap().server_conn = MinecraftConnection::connect(server.host())?;
thread::spawn({
let player_forwarding = meexprox.lock().unwrap().config.player_forwarding().clone();
let server_address = server_address.to_string();
move || {
let _ = ProxyPlayer::connect(
this,
meexprox,
player_forwarding,
&server_address,
server_port,
false,
);
}
});
Ok(())
}
pub fn reconnect(
this: PlayerMutex,
meexprox: MeexProxMutex,
server_address: &str,
server_port: u16,
) -> Result<(), Box<dyn Error>> {
this.lock()
.unwrap()
.connection_id
.fetch_add(1, Ordering::Relaxed);
this.lock().unwrap().server_conn.close();
this.lock().unwrap().server_conn =
MinecraftConnection::connect(this.lock().unwrap().server().unwrap().host())?;
thread::spawn({
let player_forwarding = meexprox.lock().unwrap().config.player_forwarding().clone();
let server_address = server_address.to_string();
move || {
let _ = ProxyPlayer::connect(
this,
meexprox,
player_forwarding,
&server_address,
server_port,
false,
);
}
});
Ok(())
}
fn send_handshake(
this: PlayerMutex,
meexprox: MeexProxMutex,
player_forwarding: PlayerForwarding,
addr: SocketAddr,
server_address: &str,
server_port: u16,
) -> Result<(), ProtocolError> {
let protocol_version = this.lock().unwrap().protocol_version;
let packet = Packet::build(0x00, move |packet| {
packet.write_u16_varint(protocol_version)?;
packet.write_string(&server_address)?;
packet.write_unsigned_short(server_port)?;
packet.write_u8_varint(2)?;
if let PlayerForwarding::Handshake = player_forwarding {
if let SocketAddr::V4(addr) = addr {
packet.write_boolean(false)?; // is ipv6
packet.write_unsigned_short(addr.port())?; // port
packet.write_bytes(&addr.ip().octets())?; // octets
} else if let SocketAddr::V6(addr) = addr {
packet.write_boolean(true)?;
packet.write_unsigned_short(addr.port())?;
packet.write_bytes(&addr.ip().octets())?;
}
}
Ok(())
})?;
let (packet, cancel) = ProxyEvent::send_server_packet(meexprox, packet, this.clone());
if !cancel {
this.lock().unwrap().server_conn.write_packet(&packet)?;
}
Ok(())
}
fn send_login(this: PlayerMutex, meexprox: MeexProxMutex) -> Result<(), ProtocolError> {
if let Some(player_name) = this.lock().unwrap().name.as_ref() {
if let Some(player_uuid) = this.lock().unwrap().uuid.as_ref() {
let packet = Packet::build(0x00, move |packet| {
packet.write_string(&player_name)?;
packet.write_uuid(&player_uuid)?;
Ok(())
})?;
let (packet, cancel) =
ProxyEvent::send_server_packet(meexprox, packet, this.clone());
if !cancel {
this.lock().unwrap().server_conn.write_packet(&packet)?;
}
}
}
Ok(())
}
fn connect(
this: PlayerMutex,
meexprox: MeexProxMutex,
player_forwarding: PlayerForwarding,
server_address: &str,
server_port: u16,
logged: bool,
) -> Result<(), Box<dyn Error>> {
let mut client_conn = this.lock().unwrap().client_conn.try_clone().unwrap();
let mut server_conn = this.lock().unwrap().server_conn.try_clone().unwrap();
let server = this.lock().unwrap().server.clone();
let addr = client_conn.get_ref().peer_addr().unwrap();
let Some(name) = this.lock().unwrap().name.clone() else {
return Ok(());
};
let server_config = meexprox.lock().unwrap().config.clone();
let atomic_connection_id = this.lock().unwrap().connection_id.clone();
let connection_id = this.lock().unwrap().connection_id.load(Ordering::Relaxed);
if !logged {
ProxyPlayer::send_handshake(
this.clone(),
meexprox.clone(),
player_forwarding,
addr,
server_address,
server_port,
)?;
ProxyPlayer::send_login(this.clone(), meexprox.clone())?;
while let Ok(mut packet) = server_conn.read_packet() {
if packet.id() == 0x01 {
if let Some(shared_secret) = this.lock().unwrap().shared_secret.clone() {
if let Some(verify_token) = this.lock().unwrap().verify_token.clone() {
let mut enc_response = Packet::empty(0x01);
enc_response.write_usize_varint(shared_secret.len())?;
enc_response.write_bytes(&shared_secret)?;
enc_response.write_usize_varint(shared_secret.len())?;
enc_response.write_bytes(&verify_token)?;
let (enc_response, cancel) = ProxyEvent::send_server_packet(
meexprox.clone(),
enc_response,
this.clone(),
);
if !cancel {
server_conn.write_packet(&enc_response)?;
}
}
}
}
if packet.id() == 0x03 {
let threshold = packet.read_isize_varint()?;
if threshold >= 0 {
let threshold = threshold.zigzag();
server_conn.set_compression(Some(threshold));
client_conn.set_compression(Some(threshold));
} else {
server_conn.set_compression(None);
client_conn.set_compression(None);
}
}
if packet.id() == 0x02 {
break;
}
}
let login_ack = Packet::empty(0x03);
let (login_ack, cancel) =
ProxyEvent::send_server_packet(meexprox.clone(), login_ack, this.clone());
if !cancel {
server_conn.write_packet(&login_ack)?;
}
}
thread::spawn({
let mut client_conn = client_conn.try_clone().unwrap();
let mut server_conn = server_conn.try_clone().unwrap();
let this = this.clone();
let meexprox = meexprox.clone();
let name = name.clone();
let atomic_connection_id = atomic_connection_id.clone();
move || {
let _ = || -> Result<(), ProtocolError> {
while atomic_connection_id.load(Ordering::Relaxed) == connection_id {
let packet = match client_conn.read_packet() {
Ok(packet) => packet,
Err(_) => break,
};
let packet =
ProxyEvent::recv_client_packet(meexprox.clone(), packet, this.clone());
let (packet, cancel) =
ProxyEvent::send_server_packet(meexprox.clone(), packet, this.clone());
if !cancel {
server_conn.write_packet(&packet)?;
}
}
Ok(())
}();
if atomic_connection_id.load(Ordering::Relaxed) == connection_id {
if meexprox.lock().unwrap().remove_player(this.clone()) {
info!("{} disconnected player {}", addr.to_string(), name);
ProxyEvent::player_disconnected(meexprox.clone(), this.clone());
}
}
}
});
let _ = || -> Result<(), ProtocolError> {
while atomic_connection_id.load(Ordering::Relaxed) == connection_id {
let packet = match server_conn.read_packet() {
Ok(packet) => packet,
Err(_) => break,
};
let packet = ProxyEvent::recv_server_packet(meexprox.clone(), packet, this.clone());
let (packet, cancel) =
ProxyEvent::send_client_packet(meexprox.clone(), packet, this.clone());
if !cancel {
client_conn.write_packet(&packet)?;
}
}
Ok(())
}();
if atomic_connection_id.load(Ordering::Relaxed) == connection_id {
if meexprox.lock().unwrap().remove_player(this.clone()) {
info!("{} disconnected player {}", addr.to_string(), name);
ProxyEvent::player_disconnected(meexprox.clone(), this.clone());
}
}
Ok(())
}
}
pub struct MeexProx {
config: ProxyConfig,
players: Vec<PlayerMutex>,
event_listeners: Vec<Box<dyn EventListener + Send + Sync>>,
}
impl MeexProx {
pub fn new(config: ProxyConfig) -> MeexProx {
MeexProx {
config,
players: Vec::new(),
event_listeners: Vec::new(),
}
}
pub fn add_event_listener(&mut self, event_listener: Box<dyn EventListener + Send + Sync>) {
self.event_listeners.push(event_listener);
}
pub fn trigger_event(this: MeexProxMutex, mut event: ProxyEvent) -> ProxyEvent {
for event_listener in &mut this.lock().unwrap().event_listeners {
let _ = event_listener.on_event(this.clone(), &mut event);
}
event
}
pub fn get_player(&self, uuid: Uuid) -> Option<PlayerMutex> {
for player in &self.players {
if let Some(player_uuid) = player.lock().unwrap().uuid {
if player_uuid == uuid {
return Some(player.clone());
}
}
}
None
}
pub fn remove_player(&mut self, player: PlayerMutex) -> bool {
match self.players.iter().position(|x| Arc::ptr_eq(x, &player)) {
Some(i) => {
self.players.remove(i);
true
}
None => false,
}
}
pub fn accept_client(this: MeexProxMutex, stream: TcpStream) -> Result<(), Box<dyn Error>> {
let Ok(addr) = stream.peer_addr() else {
return Ok(());
};
let server_config = this.lock().unwrap().config.clone();
let mut client_conn = MinecraftConnection::new(stream);
let mut handshake = client_conn.read_packet()?;
if handshake.id() != 0x00 {
return Ok(());
}
let protocol_version = handshake.read_u16_varint()?;
let server_address = handshake.read_string()?;
let server_port = handshake.read_unsigned_short()?;
let next_state = handshake.read_u8_varint()?;
let server = server_config
.get_server_by_forced_host(&server_address)
.or(server_config.default_server().cloned())
.ok_or(ProxyError::ConfigParse)?;
let mut server_conn = MinecraftConnection::connect(&server.host())?;
let handshake = Packet::build(0x00, |handshake| {
handshake.write_u16_varint(protocol_version)?;
handshake.write_string(&server_address)?;
handshake.write_unsigned_short(server_port)?;
handshake.write_u8_varint(next_state)?;
if let PlayerForwarding::Handshake = server_config.player_forwarding() {
if let SocketAddr::V4(addr) = addr {
handshake.write_boolean(false)?; // is ipv6
handshake.write_unsigned_short(addr.port())?; // port
handshake.write_bytes(&addr.ip().octets())?; // octets
} else if let SocketAddr::V6(addr) = addr {
handshake.write_boolean(true)?;
handshake.write_unsigned_short(addr.port())?;
handshake.write_bytes(&addr.ip().octets())?;
}
}
Ok(())
})?;
server_conn.write_packet(&handshake)?;
if next_state == 1 {
loop {
let client_packet = client_conn.read_packet()?;
server_conn.write_packet(&client_packet)?;
let mut server_packet = server_conn.read_packet()?;
if client_packet.id() == 0x00 {
let server_status = server_packet.read_string()?;
let (status, cancel) = ProxyEvent::status_request(
this.clone(),
server_status.clone(),
addr.clone(),
server_address.clone(),
server_port,
);
if cancel {
break;
}
server_packet = Packet::build(0x00, |p| p.write_string(&status))?;
}
client_conn.write_packet(&server_packet)?;
}
} else if next_state == 2 {
let player = Arc::new(Mutex::new(ProxyPlayer::new(
client_conn.try_clone().unwrap(),
server_conn.try_clone().unwrap(),
None,
None,
protocol_version,
Some(server.clone()),
None,
None,
Arc::new(AtomicUsize::new(0)),
)));
this.lock().unwrap().players.push(player.clone());
let mut login_start = client_conn.read_packet()?;
player.lock().unwrap().name = Some(login_start.read_string()?);
player.lock().unwrap().uuid = Some(login_start.read_uuid()?);
server_conn.write_packet(&login_start)?;
while let Ok(mut packet) = server_conn.read_packet() {
client_conn.write_packet(&packet)?;
if packet.id() == 0x01 {
let mut enc_response = client_conn.read_packet()?;
let shared_secret_length = enc_response.read_usize_varint()?;
player.lock().unwrap().shared_secret =
Some(enc_response.read_bytes(shared_secret_length)?);
let verify_token_length = enc_response.read_usize_varint()?;
player.lock().unwrap().verify_token =
Some(enc_response.read_bytes(verify_token_length)?);
server_conn.write_packet(&enc_response)?;
}
if packet.id() == 0x03 {
let threshold = packet.read_isize_varint()?;
if threshold >= 0 {
let threshold = threshold.zigzag();
server_conn.set_compression(Some(threshold));
client_conn.set_compression(Some(threshold));
} else {
server_conn.set_compression(None);
client_conn.set_compression(None);
}
}
if packet.id() == 0x02 {
break;
}
}
// println!("lac re");
// let login_ack = client_conn.read_packet()?;
// println!("lac {}", login_ack.id());
// if login_ack.id() != 0x03 {
// return Ok(());
// }
thread::spawn({
let this = this.clone();
move || {
info!(
"{} connected player {}",
addr.to_string(),
player.lock().unwrap().name.clone().unwrap()
);
ProxyEvent::player_connected(this.clone(), player.clone());
let _ = ProxyPlayer::connect(
player,
this,
server_config.player_forwarding().clone(),
&server_address,
server_port,
true,
);
}
});
}
Ok(())
}
pub fn start(self) {
let listener = TcpListener::bind(self.config.host()).expect("invalid host");
info!("meexprox started on {}", self.config.host());
let mutex_self = Arc::new(Mutex::new(self));
for client in listener.incoming() {
if let Ok(client) = client {
let mutex_self_clone = mutex_self.clone();
thread::spawn(move || {
match Self::accept_client(mutex_self_clone, client) {
Ok(_) => {}
Err(_) => {
// error!("connection error: {:?}", e);
}
};
});
}
}
}
}
pub type PlayerMutex = Arc<Mutex<ProxyPlayer>>;
pub type MeexProxMutex = Arc<Mutex<MeexProx>>;

9
src/meexprox/mod.rs Normal file
View File

@ -0,0 +1,9 @@
pub mod config;
pub mod error;
pub mod event;
pub mod meexprox;
pub use config::*;
pub use error::*;
pub use event::*;
pub use meexprox::*;