mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-10-26 05:50:14 +00:00
wip downloading (it doesnt work)
This commit is contained in:
1 parent
ebc0dba4ef
commit
5011ae280c
9 files changed
+110
-18
No files matched your search
Generated
+1
@@ -97,6 +97,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"flate2",
|
"flate2",
|
||||||
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"nalgebra",
|
"nalgebra",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ edition = "2021"
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
pretty_env_logger = "0.4.0"
|
pretty_env_logger = "0.4.0"
|
||||||
|
|
||||||
|
lazy_static = "1"
|
||||||
|
|
||||||
anyhow = "1.0.66"
|
anyhow = "1.0.66"
|
||||||
nalgebra = "0.31"
|
nalgebra = "0.31"
|
||||||
num_enum = "0.5.7"
|
num_enum = "0.5.7"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -2,6 +2,9 @@ use serde::Deserialize;
|
|||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
#[serde(skip)] // Skipping uses Default::default, which makes a new vector for us :)
|
||||||
|
pub mods: Vec<(String, usize)>,
|
||||||
|
|
||||||
#[serde(rename = "General")]
|
#[serde(rename = "General")]
|
||||||
pub general: GeneralSettings,
|
pub general: GeneralSettings,
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-2
@@ -1,12 +1,16 @@
|
|||||||
#[macro_use] extern crate async_trait;
|
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
|
#[macro_use] extern crate async_trait;
|
||||||
|
#[macro_use] extern crate lazy_static;
|
||||||
|
|
||||||
mod server;
|
mod server;
|
||||||
mod config;
|
mod config;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let user_config: config::Config = toml::from_str(
|
pretty_env_logger::formatted_timed_builder().filter_level(log::LevelFilter::max()).init();
|
||||||
|
// pretty_env_logger::formatted_timed_builder().filter_level(log::LevelFilter::Info).init();
|
||||||
|
|
||||||
|
let mut user_config: config::Config = toml::from_str(
|
||||||
&std::fs::read_to_string("ServerConfig.toml")
|
&std::fs::read_to_string("ServerConfig.toml")
|
||||||
.map_err(|_| error!("Failed to read config file!"))
|
.map_err(|_| error!("Failed to read config file!"))
|
||||||
.expect("Failed to read config file!")
|
.expect("Failed to read config file!")
|
||||||
@@ -14,6 +18,21 @@ async fn main() {
|
|||||||
.map_err(|_| error!("Failed to parse config file!"))
|
.map_err(|_| error!("Failed to parse config file!"))
|
||||||
.expect("Failed to parse config file!");
|
.expect("Failed to parse config file!");
|
||||||
|
|
||||||
|
// TODO: This should not error lol
|
||||||
|
for entry in std::fs::read_dir("Resources/Client").expect("Failed to read Resources/Client!") {
|
||||||
|
if let Ok(entry) = entry {
|
||||||
|
if entry.path().is_file() {
|
||||||
|
if let Ok(metadata) = entry.metadata() {
|
||||||
|
if let Some(filename) = entry.path().file_name().map(|s| s.to_string_lossy()) {
|
||||||
|
user_config.mods.push((filename.to_string(), metadata.len() as usize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Mods: {:?}", user_config.mods);
|
||||||
|
|
||||||
let user_config = std::sync::Arc::new(user_config);
|
let user_config = std::sync::Arc::new(user_config);
|
||||||
|
|
||||||
let mut server = server::Server::new(user_config)
|
let mut server = server::Server::new(user_config)
|
||||||
|
|||||||
+71
-14
@@ -24,6 +24,10 @@ use super::packet::*;
|
|||||||
|
|
||||||
static ATOMIC_ID_COUNTER: AtomicU8 = AtomicU8::new(0);
|
static ATOMIC_ID_COUNTER: AtomicU8 = AtomicU8::new(0);
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref CLIENT_MOD_PROGRESS: Mutex<HashMap<usize, usize>> = Mutex::new(HashMap::new());
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum ClientState {
|
pub enum ClientState {
|
||||||
None,
|
None,
|
||||||
@@ -114,7 +118,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn authenticate(&mut self, config: &super::Config) -> anyhow::Result<()> {
|
pub async fn authenticate(&mut self, config: &super::Config) -> anyhow::Result<bool> {
|
||||||
debug!("Authenticating client {}...", self.id);
|
debug!("Authenticating client {}...", self.id);
|
||||||
|
|
||||||
'waiting_for_c: loop {
|
'waiting_for_c: loop {
|
||||||
@@ -128,6 +132,11 @@ impl Client {
|
|||||||
debug!("code: '{}' / {}", code as char, code);
|
debug!("code: '{}' / {}", code as char, code);
|
||||||
match code as char {
|
match code as char {
|
||||||
'C' => {
|
'C' => {
|
||||||
|
// We now delete existing data for this client ID, just in case.
|
||||||
|
// TODO: This seems like a recipe for disaster
|
||||||
|
let mut lock = CLIENT_MOD_PROGRESS.lock().await;
|
||||||
|
lock.remove(&(self.id as usize));
|
||||||
|
|
||||||
// TODO: Check client version
|
// TODO: Check client version
|
||||||
trace!("Client version packet");
|
trace!("Client version packet");
|
||||||
self.socket.readable().await?;
|
self.socket.readable().await?;
|
||||||
@@ -136,10 +145,54 @@ impl Client {
|
|||||||
break 'waiting_for_c;
|
break 'waiting_for_c;
|
||||||
}
|
}
|
||||||
'D' => {
|
'D' => {
|
||||||
let id = self.read_raw(1).await?[0];
|
// The download sequence is so awful
|
||||||
|
// It currently requires us to track what the next file is that
|
||||||
|
// we need to provide, which is hard to do with the current
|
||||||
|
// server design.
|
||||||
|
// I think I will simply keep a counter around that will
|
||||||
|
// track what the next mod is per client.
|
||||||
|
// TODO: Clean this up. It also needs to be moved out of the client code IMO
|
||||||
|
let id = self.read_raw(1).await?[0] as usize;
|
||||||
debug!("HandleDownload connection for client id: {}", id);
|
debug!("HandleDownload connection for client id: {}", id);
|
||||||
debug!("Not handling this for now!");
|
|
||||||
return Err(ClientError::IsDownloader.into());
|
self.write_packet(Packet::Raw(RawPacket::from_str("AG"))).await?;
|
||||||
|
|
||||||
|
// TODO: How does this work???
|
||||||
|
|
||||||
|
let mut lock = CLIENT_MOD_PROGRESS.lock().await;
|
||||||
|
if lock.get(&id).is_none() { lock.insert(id, 0); }
|
||||||
|
let next_id = lock.get_mut(&id).unwrap();
|
||||||
|
|
||||||
|
let bmod = &config.mods[*next_id]; // TODO: This is a bit uhh yeah
|
||||||
|
|
||||||
|
*next_id += 1;
|
||||||
|
|
||||||
|
debug!("Mod name: {}", bmod.0);
|
||||||
|
|
||||||
|
let mut mod_name = bmod.0.clone();
|
||||||
|
if mod_name.starts_with("/") == false {
|
||||||
|
mod_name = format!("/{mod_name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mod_path = format!("Resources/Client{mod_name}");
|
||||||
|
let file_data = std::fs::read(mod_path)?;
|
||||||
|
|
||||||
|
let packet = RawPacket::from_data(file_data);
|
||||||
|
// self.write_packet(Packet::Raw(packet)).await?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut lock = self.write_half.lock().await;
|
||||||
|
lock.writable().await?;
|
||||||
|
trace!("Sending packet!");
|
||||||
|
if let Err(e) = tcp_write_raw(lock.deref_mut(), Packet::Raw(packet)).await {
|
||||||
|
error!("{:?}", e);
|
||||||
|
}
|
||||||
|
trace!("Packet sent!");
|
||||||
|
drop(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return Err(ClientError::IsDownloader.into());
|
||||||
|
return Ok(false);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ClientError::AuthenticateError.into());
|
return Err(ClientError::AuthenticateError.into());
|
||||||
@@ -186,7 +239,7 @@ impl Client {
|
|||||||
);
|
);
|
||||||
self.sync(config).await?;
|
self.sync(config).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: https://github.com/BeamMP/BeamMP-Server/blob/master/src/TNetwork.cpp#L619
|
// TODO: https://github.com/BeamMP/BeamMP-Server/blob/master/src/TNetwork.cpp#L619
|
||||||
@@ -205,9 +258,20 @@ impl Client {
|
|||||||
match packet.data[0] as char {
|
match packet.data[0] as char {
|
||||||
'S' if packet.data.len() > 1 => match packet.data[1] as char {
|
'S' if packet.data.len() > 1 => match packet.data[1] as char {
|
||||||
'R' => {
|
'R' => {
|
||||||
let file_packet = RawPacket::from_code('-');
|
// let file_packet = RawPacket::from_code('-');
|
||||||
// let file_data = "/bepis_dysoon_uu201_v3.zip;/bepis_laudi_v8_revolution.zip;/simraceclubclient.zip;48353220;50283849;1937;";
|
// let file_data = "/bepis_dysoon_uu201_v3.zip;/bepis_laudi_v8_revolution.zip;/simraceclubclient.zip;48353220;50283849;1937;";
|
||||||
// let file_packet = RawPacket::from_str(file_data);
|
let mut file_data = String::new();
|
||||||
|
for (name, size) in &config.mods {
|
||||||
|
let mut mod_name = name.clone();
|
||||||
|
if mod_name.starts_with("/") == false {
|
||||||
|
mod_name = format!("/{mod_name}");
|
||||||
|
}
|
||||||
|
file_data.push_str(&format!("{mod_name};"));
|
||||||
|
}
|
||||||
|
for (name, size) in &config.mods {
|
||||||
|
file_data.push_str(&format!("{size};"));
|
||||||
|
}
|
||||||
|
let file_packet = RawPacket::from_str(&file_data);
|
||||||
self.write_packet(Packet::Raw(file_packet))
|
self.write_packet(Packet::Raw(file_packet))
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
@@ -218,13 +282,6 @@ impl Client {
|
|||||||
let mut file_name = packet.data_as_string().clone();
|
let mut file_name = packet.data_as_string().clone();
|
||||||
file_name.remove(0); // Remove f
|
file_name.remove(0); // Remove f
|
||||||
debug!("Client requested file {}", file_name);
|
debug!("Client requested file {}", file_name);
|
||||||
self.kick(&format!("You have not yet downloaded {}!", file_name)).await;
|
|
||||||
// let mut lock = self.write_half.lock().await;
|
|
||||||
// lock.writable().await?;
|
|
||||||
// trace!("Sending packet!");
|
|
||||||
// if let Err(e) = tcp_send_file(lock.deref_mut(), file_name).await {
|
|
||||||
// error!("{:?}", e);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
_ => error!("Unknown packet! {:?}", packet),
|
_ => error!("Unknown packet! {:?}", packet),
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -80,11 +80,11 @@ impl Server {
|
|||||||
let ci_ref = clients_incoming_ref.clone();
|
let ci_ref = clients_incoming_ref.clone();
|
||||||
|
|
||||||
set.spawn(async move {
|
set.spawn(async move {
|
||||||
socket.set_nodelay(true);
|
socket.set_nodelay(true); // TODO: Is this good?
|
||||||
|
|
||||||
let mut client = Client::new(socket);
|
let mut client = Client::new(socket);
|
||||||
match client.authenticate(&cfg_ref).await {
|
match client.authenticate(&cfg_ref).await {
|
||||||
Ok(_) => {
|
Ok(b) if b => {
|
||||||
let mut lock = ci_ref
|
let mut lock = ci_ref
|
||||||
.lock()
|
.lock()
|
||||||
.map_err(|e| error!("{:?}", e))
|
.map_err(|e| error!("{:?}", e))
|
||||||
@@ -92,6 +92,9 @@ impl Server {
|
|||||||
lock.push(client);
|
lock.push(client);
|
||||||
drop(lock);
|
drop(lock);
|
||||||
},
|
},
|
||||||
|
Ok(b) => {
|
||||||
|
debug!("Downloader?");
|
||||||
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Authentication error occured, kicking player...");
|
error!("Authentication error occured, kicking player...");
|
||||||
error!("{:?}", e);
|
error!("{:?}", e);
|
||||||
|
|||||||
@@ -73,6 +73,13 @@ impl RawPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_data(data: Vec<u8>) -> Self {
|
||||||
|
Self {
|
||||||
|
header: data.len() as u32,
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_str(str_data: &str) -> Self {
|
pub fn from_str(str_data: &str) -> Self {
|
||||||
let data = str_data.as_bytes().to_vec();
|
let data = str_data.as_bytes().to_vec();
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
Reference in new issue
Block a user