(rust) macaddress type tests
This commit is contained in:
+57
-200
@@ -1,224 +1,81 @@
|
||||
#![allow(dead_code, unused)]
|
||||
|
||||
use std::{num, path::PathBuf, str::FromStr};
|
||||
|
||||
use chrono::{DateTime, Local, Utc};
|
||||
use ciborium::ser;
|
||||
use dirs::{config_dir, home_dir};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::{
|
||||
fs,
|
||||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
net::{TcpListener, TcpStream},
|
||||
sync::{
|
||||
mpsc::{channel, Receiver, Sender},
|
||||
Mutex,
|
||||
},
|
||||
time::{sleep, Duration},
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let (running, mut stop) = channel::<bool>(1);
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let test_address: MacAddress = MacAddress::from_array([0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F]);
|
||||
|
||||
let send_handle = tokio::spawn(sender_process(running.clone()));
|
||||
let recv_handle = tokio::spawn(receiver_process());
|
||||
|
||||
_ = recv_handle.await??;
|
||||
stop.close();
|
||||
_ = send_handle.await??;
|
||||
println!("as string: {}", test_address.to_string());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn sender_process(running: Sender<bool>) -> anyhow::Result<()> {
|
||||
const BLOCK_SIZE: usize = 128;
|
||||
const FILE_PATH: &str = "repositories/test-projects/";
|
||||
const FILE_NAME: &str = "small-lorem.md";
|
||||
|
||||
let listener: TcpListener = TcpListener::bind("127.0.0.1:9090").await?;
|
||||
let mut connection = match listener.accept().await {
|
||||
Ok((mut stream, address)) => {
|
||||
println!("accepted connection request from {}", address);
|
||||
stream
|
||||
}
|
||||
Err(error) => {
|
||||
println!("this is unexpected.. {}", error.to_string());
|
||||
return Err(std::io::Error::other("failed to open tcp connection").try_into()?);
|
||||
}
|
||||
};
|
||||
|
||||
let mut filepath: PathBuf = home_dir().expect("failed to determine home directory");
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
|
||||
filepath.push(FILE_PATH);
|
||||
filepath.push(FILE_NAME);
|
||||
|
||||
let mut file: Vec<u8> = match fs::read(filepath).await {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
println!("{}", error.to_string());
|
||||
panic!("failed to read file");
|
||||
}
|
||||
};
|
||||
let length: usize = file.len();
|
||||
let blocks: usize = if length % BLOCK_SIZE == 0 {
|
||||
length / BLOCK_SIZE
|
||||
} else {
|
||||
(length / BLOCK_SIZE) + 1
|
||||
};
|
||||
let mut index: usize = 0;
|
||||
|
||||
connection.writable().await;
|
||||
while index < blocks {
|
||||
if index >= blocks {
|
||||
panic!("index >= blocks !@#$!%");
|
||||
}
|
||||
let end_index: usize = if file.len() < BLOCK_SIZE {
|
||||
file.len()
|
||||
} else {
|
||||
BLOCK_SIZE
|
||||
};
|
||||
let message: Message = Message::FileSection(FileSection {
|
||||
name: "lorem.md".to_owned(),
|
||||
size: length as u64,
|
||||
sections: blocks as u64,
|
||||
index: index as u64,
|
||||
data: file.drain(0..end_index).collect(),
|
||||
});
|
||||
let serialised: Vec<u8> = message.to_vec();
|
||||
connection.try_write(&serialised[..]);
|
||||
index += 1;
|
||||
|
||||
sleep(Duration::from_millis(20)).await;
|
||||
}
|
||||
println!("send loop done");
|
||||
|
||||
while !running.is_closed() {
|
||||
sleep(Duration::from_millis(20)).await;
|
||||
}
|
||||
|
||||
println!("send loop exiting -> dropping connection");
|
||||
|
||||
Ok(())
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct MacAddress {
|
||||
bytes: [u8;6],
|
||||
}
|
||||
|
||||
async fn receiver_process() -> anyhow::Result<()> {
|
||||
let mut connection = TcpStream::connect("127.0.0.1:9090").await?;
|
||||
let mut buffer: Vec<u8> = Vec::with_capacity(8192);
|
||||
let mut file: Vec<u8> = Vec::new();
|
||||
let mut index: usize = 0;
|
||||
let mut blocks: usize = 0;
|
||||
let mut name: String = "".to_owned();
|
||||
let mut counter: usize = 3;
|
||||
impl MacAddress {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
bytes: [0u8;6],
|
||||
}
|
||||
}
|
||||
|
||||
'receive: loop {
|
||||
sleep(Duration::from_millis(20)).await;
|
||||
if counter > 0 || buffer.is_empty() {
|
||||
connection.readable().await;
|
||||
let num_bytes: usize = match connection.read_buf(&mut buffer).await {
|
||||
Ok(0) => {
|
||||
println!("connection dropped .........");
|
||||
break 'receive;
|
||||
}
|
||||
pub fn from_array(bytes: [u8;6]) -> Self {
|
||||
Self {
|
||||
bytes: bytes,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(string: &str) -> std::io::Result<Self> {
|
||||
let mut address: Self = Self::new();
|
||||
let bytes: Vec<&str> = string.split(":").collect();
|
||||
|
||||
if bytes.len() != address.bytes.len() {
|
||||
return Err(std::io::Error::other("invalid length or format for mac address"));
|
||||
}
|
||||
|
||||
for (index, byte) in bytes.iter().enumerate() {
|
||||
address.bytes[index] = match u8::from_str_radix(byte, 16) {
|
||||
Ok(value) => value,
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => continue 'receive,
|
||||
Err(_) => panic!("fuck you!"),
|
||||
Err(error) => return Err(std::io::Error::other(error.to_string())),
|
||||
};
|
||||
}
|
||||
|
||||
if counter > 0 {
|
||||
counter -= 1;
|
||||
continue 'receive;
|
||||
}
|
||||
|
||||
let message: FileSection = match Message::from_vec(&mut buffer) {
|
||||
Ok(Message::FileSection(value)) => value,
|
||||
Ok(unexpected) => panic!(".. {:#?}", unexpected),
|
||||
Err(Error::IncompleteFrame) => continue 'receive,
|
||||
Err(Error::EmptyBuffer) => panic!("don't be stupid!"),
|
||||
Err(error) => panic!(".. {:#?}", error),
|
||||
};
|
||||
|
||||
if blocks == 0 {
|
||||
blocks = message.sections as usize;
|
||||
name = message.name;
|
||||
}
|
||||
index = message.index as usize;
|
||||
|
||||
file.extend(message.data);
|
||||
|
||||
if index >= blocks - 1 {
|
||||
break 'receive;
|
||||
};
|
||||
}
|
||||
println!("decoding done");
|
||||
println!("receive loop done");
|
||||
|
||||
fs::write("./received.md", file).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
type FileName = String;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub enum Message {
|
||||
Acknowledge(bool),
|
||||
FileRequest(FileName),
|
||||
FileSection(FileSection),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct FileSection {
|
||||
pub name: String,
|
||||
pub size: u64,
|
||||
pub sections: u64,
|
||||
pub index: u64,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("serialisation with cbor failed")]
|
||||
Serialisation(#[from] ciborium::de::Error<std::io::Error>),
|
||||
|
||||
#[error("framing with cobs failed")]
|
||||
Framing(#[from] cobs::DecodeError),
|
||||
|
||||
#[error("can't deserialise from an empty buffer")]
|
||||
EmptyBuffer,
|
||||
|
||||
#[error("no framedelimiter found, the frame is probably not fully received yet")]
|
||||
IncompleteFrame,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
/// serialises the message and returns a vector of `u8`
|
||||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
let mut serialised: Vec<u8> = Vec::with_capacity(1024);
|
||||
_ = ciborium::into_writer(self, &mut serialised);
|
||||
let mut framed: Vec<u8> = cobs::encode_vec(&serialised);
|
||||
framed.push(0x00u8);
|
||||
framed
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
/// deserialises a message from a vector
|
||||
pub fn from_vec(buffer: &mut Vec<u8>) -> Result<Message, Error> {
|
||||
if buffer.is_empty() { return Err(Error::EmptyBuffer); }
|
||||
if !buffer.contains(&0u8) { return Err(Error::IncompleteFrame); }
|
||||
pub fn from_string(string: &String) -> std::io::Result<Self> {
|
||||
let mut address: Self = Self::new();
|
||||
let bytes: Vec<&str> = string.split(":").collect();
|
||||
|
||||
let mut index: usize = 0;
|
||||
for (n, byte) in buffer.iter().enumerate() {
|
||||
if byte == &0u8 {
|
||||
index = n;
|
||||
break;
|
||||
println!("debug: {:#?}", bytes);
|
||||
|
||||
if bytes.len() != address.bytes.len() {
|
||||
return Err(std::io::Error::other("invalid length or format for mac address"));
|
||||
}
|
||||
|
||||
for (index, byte) in bytes.iter().enumerate() {
|
||||
address.bytes[index] = match u8::from_str_radix(byte, 16) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(std::io::Error::other(error.to_string())),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
let mut string: String = String::new();
|
||||
|
||||
for (index, byte) in self.bytes.iter().enumerate() {
|
||||
string.push_str(&format!("{:02x?}", byte));
|
||||
if index < self.bytes.len() - 1 {
|
||||
string.push_str(":");
|
||||
}
|
||||
}
|
||||
|
||||
let serialised: Vec<u8> = cobs::decode_vec(&buffer.drain(0..=index).collect::<Vec<u8>>())?;
|
||||
let message: Message = ciborium::from_reader(&serialised[..])?;
|
||||
|
||||
Ok(message)
|
||||
string
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user