add WIP rust server
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use serde::ser::{Serialize, Serializer, SerializeTuple};
|
||||
use serde::de::{Deserialize, Deserializer, Visitor, SeqAccess, Error};
|
||||
|
||||
pub trait BigArray<'de>: Sized {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer;
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer<'de>;
|
||||
}
|
||||
|
||||
macro_rules! big_array {
|
||||
($($len:expr,)+) => {
|
||||
$(
|
||||
impl<'de, T> BigArray<'de> for [T; $len]
|
||||
where T: Default + Copy + Serialize + Deserialize<'de>
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
let mut seq = serializer.serialize_tuple(self.len())?;
|
||||
for elem in &self[..] {
|
||||
seq.serialize_element(elem)?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
|
||||
fn deserialize<D>(deserializer: D) -> Result<[T; $len], D::Error>
|
||||
where D: Deserializer<'de>
|
||||
{
|
||||
struct ArrayVisitor<T> {
|
||||
element: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'de, T> Visitor<'de> for ArrayVisitor<T>
|
||||
where T: Default + Copy + Deserialize<'de>
|
||||
{
|
||||
type Value = [T; $len];
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(concat!("an array of length ", $len))
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<[T; $len], A::Error>
|
||||
where A: SeqAccess<'de>
|
||||
{
|
||||
let mut arr = [T::default(); $len];
|
||||
for i in 0..$len {
|
||||
arr[i] = seq.next_element()?
|
||||
.ok_or_else(|| Error::invalid_length(i, &self))?;
|
||||
}
|
||||
Ok(arr)
|
||||
}
|
||||
}
|
||||
|
||||
let visitor = ArrayVisitor { element: PhantomData };
|
||||
deserializer.deserialize_tuple($len, visitor)
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
big_array! {
|
||||
40, 48, 50, 56, 64, 72, 96, 100, 128, 160, 192, 200, 224, 256, 384, 488, 512,
|
||||
768, 1024, 2048, 4096, 8192, 16384, 32768, 65536,
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
use bincode::{self, options, Options};
|
||||
use std::{net::{UdpSocket, SocketAddr}, io::Read};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use sha3::{Digest, Sha3_512};
|
||||
use sha2::Sha512;
|
||||
use regex::Regex;
|
||||
|
||||
mod big_array;
|
||||
use big_array::BigArray;
|
||||
|
||||
const MAX_FRAME_PAYLOAD:u16=508;
|
||||
const MAX_FRAME_PAYLOAD_U:usize=MAX_FRAME_PAYLOAD as usize;
|
||||
const HEADER_SIZE:u16 = 20;
|
||||
const MAX_PAYLOAD:u16 = MAX_FRAME_PAYLOAD - HEADER_SIZE;
|
||||
const MAX_PAYLOAD_U:usize = MAX_PAYLOAD as usize;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct PacketInformation {
|
||||
packet_numbers: u32, //4 bytes
|
||||
last_packet_size: u16, //2 bytes
|
||||
response_filename_checksum: u64, //8 bytes
|
||||
} //14 bytes
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Packet {
|
||||
packet_number: u32, //4 bytes
|
||||
payload_hash: [u8; 16], //16 bytes
|
||||
#[serde(with = "BigArray")]
|
||||
payload: [u8; MAX_PAYLOAD_U], //488 bytes
|
||||
} //512 bytes
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct StrPacket {
|
||||
#[serde(with = "BigArray")]
|
||||
payload: [u8; MAX_PAYLOAD_U]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let port = "1337";
|
||||
let timeout = 100;
|
||||
let local_addr: SocketAddr = ("0.0.0.0:".to_string()+port).parse().expect("Failed to parse address");
|
||||
let socket = UdpSocket::bind(local_addr).expect("Failed to bind socket");
|
||||
|
||||
socket.set_read_timeout(Some(std::time::Duration::from_millis(timeout))).expect("set_read_timeout call failed");
|
||||
|
||||
println!("UDP Server up and running on port {}", local_addr.port());
|
||||
|
||||
let _options = options().with_big_endian().allow_trailing_bytes().with_fixint_encoding();
|
||||
|
||||
let hash_request_regex = Regex::new(r"[a-zA-Z0-9.-_ ]+:").unwrap();
|
||||
|
||||
let missing_packet_request_regex = Regex::new(r"([a-zA-Z0-9.-_ ]+)(/[0-9]+)+").unwrap();
|
||||
|
||||
loop {
|
||||
let mut buffer = [0u8; MAX_FRAME_PAYLOAD_U];
|
||||
let res = socket.recv_from(&mut buffer);
|
||||
if let Ok((_received_bytes, remote_addr)) = res {
|
||||
let filled_buffer = &buffer;//[..received_bytes];
|
||||
|
||||
let request_packet = bincode::deserialize::<StrPacket>(filled_buffer).unwrap();
|
||||
let request: String = request_packet.payload.iter().map(|&c| c as char).collect();
|
||||
println!("Received request: {}", request);
|
||||
let req = request.as_str();
|
||||
|
||||
if hash_request_regex.is_match(req) {
|
||||
println!("Received hash request");
|
||||
continue;
|
||||
}
|
||||
|
||||
if missing_packet_request_regex.is_match(req) {
|
||||
println!("Received missing packet request");
|
||||
continue;
|
||||
}
|
||||
|
||||
println!("Received file request");
|
||||
|
||||
let request = "files/".to_string() + req;
|
||||
|
||||
let file_result = std::fs::File::open(request);
|
||||
|
||||
if file_result.is_err() {
|
||||
println!("File not found");
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut file = file_result.unwrap();
|
||||
|
||||
let mut file_buffer = [0u8; MAX_PAYLOAD_U];
|
||||
|
||||
let mut packet_number = 0u32;
|
||||
|
||||
let file_length = file.metadata().unwrap().len();
|
||||
println!("file length: {}", file_length);
|
||||
|
||||
let packet_information = PacketInformation {
|
||||
packet_numbers: (file_length/MAX_PAYLOAD as u64) as u32,
|
||||
last_packet_size: (file_length%MAX_PAYLOAD as u64) as u16,
|
||||
response_filename_checksum: request_packet.payload.iter().fold(0u64, |acc, &x| acc.wrapping_add(x as u64)),
|
||||
};
|
||||
|
||||
socket.send_to(bincode::serialize(&packet_information).unwrap().as_slice(), remote_addr).expect("Failed to send packet information");
|
||||
|
||||
//read file chunk by chunk
|
||||
|
||||
while let Ok(bytes_read) = file.read(&mut file_buffer) {
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
let mut hasher = Sha3_512::new();
|
||||
hasher.update(&file_buffer[..bytes_read]);
|
||||
let result = hasher.finalize();
|
||||
let mut packet = Packet {
|
||||
packet_number,
|
||||
payload_hash: [0u8; 16],
|
||||
payload: file_buffer[..bytes_read].try_into().unwrap(),
|
||||
};
|
||||
packet.payload_hash.copy_from_slice(&result[..16]);
|
||||
packet.payload[..bytes_read].copy_from_slice(&file_buffer[..bytes_read]);
|
||||
let packet_bytes = bincode::serialize(&packet).unwrap();
|
||||
socket.send_to(&packet_bytes, remote_addr).expect("Failed to send packet");
|
||||
packet_number += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user