Using HashMap

This commit is contained in:
Martin Brodbeck 2023-10-03 21:55:26 +02:00
parent e2b995a788
commit f80f4b6035

View file

@ -1,18 +1,9 @@
use chrono::{DateTime, Local, Duration};
use std::{
collections::{HashMap, HashSet},
net::UdpSocket,
};
use chrono::{DateTime, Duration, Local};
use std::{collections::HashMap, net::UdpSocket};
const MAX_CLIENTS: usize = 10;
const CLIENT_TIMEOUT: u32 = 300;
const MY_SPEED: u8 = 20;
#[derive(Hash, Eq, PartialEq, Debug, Clone)]
struct Client {
name: String,
time: DateTime<Local>,
}
const MY_SPEED: u8 = 30;
fn strip_header(msg: &[u8]) -> Vec<u8> {
//print_msg(msg);
@ -111,64 +102,76 @@ fn mopp(speed: u8, data: &[u8]) -> Vec<u8> {
res.to_owned()
}
fn broadcast(socket: &UdpSocket, receivers: &HashSet<Client>, client: &Client, data: &[u8]) {
fn broadcast(
socket: &UdpSocket,
receivers: &HashMap<String, DateTime<Local>>,
client: &str,
data: &[u8],
) {
for rec in receivers {
// Do not broadcast to origin
if rec.name == client.name {
if rec.0 == client {
continue;
}
socket.send_to(&data, &rec.name).unwrap();
socket.send_to(&data, &rec.0).unwrap();
}
}
fn main() -> std::io::Result<()> {
let socket = UdpSocket::bind("0.0.0.0:7373")?;
socket
.set_read_timeout(None)
.expect("Could not set read timeout");
let mut receivers: HashSet<Client> = HashSet::new();
let mut receivers2: HashMap<String, DateTime<Local>> = HashMap::new();
loop {
let mut buf = [0; 64];
let (number_of_bytes, src_addr) = socket.recv_from(&mut buf).expect("Didn't receive data");
let client_addr = src_addr.to_string();
let client = Client {
name: client_addr.clone(),
time: Local::now(),
};
let speed = buf[1] >> 2;
let data = &buf[0..number_of_bytes];
if receivers.iter().any(|x| x.name == client_addr) {
if receivers2.contains_key(&client_addr) {
//println!("Client already known.");
broadcast(&socket, &receivers, &client, data);
if strip_header(data) == strip_header(mopp(speed, b":bye").as_slice()) {
println!("TSCHAU");
socket
.send_to(mopp(speed, b":bye").as_slice(), &client_addr)
.unwrap();
receivers2.remove(&client_addr);
} else {
broadcast(&socket, &receivers2, &client_addr, data);
receivers2.insert(client_addr.to_owned(), Local::now());
}
} else if strip_header(data) == strip_header(mopp(speed, b"hi").as_slice()) {
//println!("Welcome!");
if receivers.len() < MAX_CLIENTS {
receivers.insert(client.clone());
if receivers2.len() < MAX_CLIENTS {
receivers2.insert(client_addr.to_owned(), Local::now());
socket
.send_to(mopp(MY_SPEED, b"hi").as_slice(), &client.name)
.send_to(
mopp(speed, format!("{}{}", ":hi ", receivers2.len()).as_bytes())
.as_slice(),
&client_addr,
)
.unwrap();
} else {
socket
.send_to(mopp(MY_SPEED, b":qrl").as_slice(), &client.name)
.send_to(mopp(speed, b":qrl").as_slice(), &client_addr)
.unwrap();
}
} else {
//println!("Unknown client - Ignoring");
}
let timestamp = Local::now();
for cl in &receivers {
if cl.time + Duration::seconds(CLIENT_TIMEOUT as i64) < timestamp {
let timestamp = Local::now();
for cl in &receivers2 {
if *cl.1 + Duration::seconds(CLIENT_TIMEOUT as i64) < timestamp {
socket
.send_to(mopp(MY_SPEED, b":bye").as_slice(), &client.name)
.send_to(mopp(MY_SPEED, b":bye").as_slice(), &client_addr)
.unwrap();
}
}
receivers.retain(|cl| cl.time + Duration::seconds(CLIENT_TIMEOUT as i64) >= timestamp);
receivers2.retain(|_, val| *val + Duration::seconds(CLIENT_TIMEOUT as i64) >= timestamp);
}
}