wip downloading (it doesnt work)

This commit is contained in:
Luuk van Oijen
2023-11-08 21:35:13 +01:00
parent ebc0dba4ef
commit 5011ae280c
9 changed files with 110 additions and 18 deletions

1
Cargo.lock generated
View File

@@ -97,6 +97,7 @@ dependencies = [
"anyhow",
"async-trait",
"flate2",
"lazy_static",
"log",
"nalgebra",
"num_enum",

View File

@@ -9,6 +9,8 @@ edition = "2021"
log = "0.4"
pretty_env_logger = "0.4.0"
lazy_static = "1"
anyhow = "1.0.66"
nalgebra = "0.31"
num_enum = "0.5.7"

Binary file not shown.

Binary file not shown.

View File

@@ -2,6 +2,9 @@ use serde::Deserialize;
#[derive(Deserialize)]
pub struct Config {
#[serde(skip)] // Skipping uses Default::default, which makes a new vector for us :)
pub mods: Vec<(String, usize)>,
#[serde(rename = "General")]
pub general: GeneralSettings,
}

View File

@@ -1,12 +1,16 @@
#[macro_use] extern crate async_trait;
#[macro_use] extern crate log;
#[macro_use] extern crate async_trait;
#[macro_use] extern crate lazy_static;
mod server;
mod config;
#[tokio::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")
.map_err(|_| error!("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!"))
.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 mut server = server::Server::new(user_config)

View File

@@ -24,6 +24,10 @@ use super::packet::*;
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)]
pub enum ClientState {
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);
'waiting_for_c: loop {
@@ -128,6 +132,11 @@ impl Client {
debug!("code: '{}' / {}", code as char, code);
match code as char {
'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
trace!("Client version packet");
self.socket.readable().await?;
@@ -136,10 +145,54 @@ impl Client {
break 'waiting_for_c;
}
'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!("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());
@@ -186,7 +239,7 @@ impl Client {
);
self.sync(config).await?;
Ok(())
Ok(true)
}
// 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 {
'S' if packet.data.len() > 1 => match packet.data[1] as char {
'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_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))
.await?
}
@@ -218,13 +282,6 @@ impl Client {
let mut file_name = packet.data_as_string().clone();
file_name.remove(0); // Remove f
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),
}

View File

@@ -80,11 +80,11 @@ impl Server {
let ci_ref = clients_incoming_ref.clone();
set.spawn(async move {
socket.set_nodelay(true);
socket.set_nodelay(true); // TODO: Is this good?
let mut client = Client::new(socket);
match client.authenticate(&cfg_ref).await {
Ok(_) => {
Ok(b) if b => {
let mut lock = ci_ref
.lock()
.map_err(|e| error!("{:?}", e))
@@ -92,6 +92,9 @@ impl Server {
lock.push(client);
drop(lock);
},
Ok(b) => {
debug!("Downloader?");
},
Err(e) => {
error!("Authentication error occured, kicking player...");
error!("{:?}", e);

View File

@@ -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 {
let data = str_data.as_bytes().to_vec();
Self {