Using HashMap
This commit is contained in:
parent
e2b995a788
commit
f80f4b6035
1 changed files with 36 additions and 33 deletions
69
src/main.rs
69
src/main.rs
|
@ -1,18 +1,9 @@
|
||||||
use chrono::{DateTime, Local, Duration};
|
use chrono::{DateTime, Duration, Local};
|
||||||
use std::{
|
use std::{collections::HashMap, net::UdpSocket};
|
||||||
collections::{HashMap, HashSet},
|
|
||||||
net::UdpSocket,
|
|
||||||
};
|
|
||||||
|
|
||||||
const MAX_CLIENTS: usize = 10;
|
const MAX_CLIENTS: usize = 10;
|
||||||
const CLIENT_TIMEOUT: u32 = 300;
|
const CLIENT_TIMEOUT: u32 = 300;
|
||||||
const MY_SPEED: u8 = 20;
|
const MY_SPEED: u8 = 30;
|
||||||
|
|
||||||
#[derive(Hash, Eq, PartialEq, Debug, Clone)]
|
|
||||||
struct Client {
|
|
||||||
name: String,
|
|
||||||
time: DateTime<Local>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn strip_header(msg: &[u8]) -> Vec<u8> {
|
fn strip_header(msg: &[u8]) -> Vec<u8> {
|
||||||
//print_msg(msg);
|
//print_msg(msg);
|
||||||
|
@ -111,64 +102,76 @@ fn mopp(speed: u8, data: &[u8]) -> Vec<u8> {
|
||||||
res.to_owned()
|
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 {
|
for rec in receivers {
|
||||||
// Do not broadcast to origin
|
// Do not broadcast to origin
|
||||||
if rec.name == client.name {
|
if rec.0 == client {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
socket.send_to(&data, &rec.name).unwrap();
|
socket.send_to(&data, &rec.0).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
let socket = UdpSocket::bind("0.0.0.0:7373")?;
|
let socket = UdpSocket::bind("0.0.0.0:7373")?;
|
||||||
socket
|
socket
|
||||||
.set_read_timeout(None)
|
.set_read_timeout(None)
|
||||||
.expect("Could not set read timeout");
|
.expect("Could not set read timeout");
|
||||||
|
|
||||||
let mut receivers: HashSet<Client> = HashSet::new();
|
let mut receivers2: HashMap<String, DateTime<Local>> = HashMap::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut buf = [0; 64];
|
let mut buf = [0; 64];
|
||||||
let (number_of_bytes, src_addr) = socket.recv_from(&mut buf).expect("Didn't receive data");
|
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_addr = src_addr.to_string();
|
||||||
let client = Client {
|
|
||||||
name: client_addr.clone(),
|
|
||||||
time: Local::now(),
|
|
||||||
};
|
|
||||||
let speed = buf[1] >> 2;
|
let speed = buf[1] >> 2;
|
||||||
|
|
||||||
let data = &buf[0..number_of_bytes];
|
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.");
|
//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()) {
|
} else if strip_header(data) == strip_header(mopp(speed, b"hi").as_slice()) {
|
||||||
//println!("Welcome!");
|
//println!("Welcome!");
|
||||||
if receivers.len() < MAX_CLIENTS {
|
if receivers2.len() < MAX_CLIENTS {
|
||||||
receivers.insert(client.clone());
|
receivers2.insert(client_addr.to_owned(), Local::now());
|
||||||
socket
|
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();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
socket
|
socket
|
||||||
.send_to(mopp(MY_SPEED, b":qrl").as_slice(), &client.name)
|
.send_to(mopp(speed, b":qrl").as_slice(), &client_addr)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//println!("Unknown client - Ignoring");
|
//println!("Unknown client - Ignoring");
|
||||||
}
|
}
|
||||||
|
|
||||||
let timestamp = Local::now();
|
let timestamp = Local::now();
|
||||||
for cl in &receivers {
|
for cl in &receivers2 {
|
||||||
if cl.time + Duration::seconds(CLIENT_TIMEOUT as i64) < timestamp {
|
if *cl.1 + Duration::seconds(CLIENT_TIMEOUT as i64) < timestamp {
|
||||||
socket
|
socket
|
||||||
.send_to(mopp(MY_SPEED, b":bye").as_slice(), &client.name)
|
.send_to(mopp(MY_SPEED, b":bye").as_slice(), &client_addr)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
receivers.retain(|cl| cl.time + Duration::seconds(CLIENT_TIMEOUT as i64) >= timestamp);
|
receivers2.retain(|_, val| *val + Duration::seconds(CLIENT_TIMEOUT as i64) >= timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue