93 lines
2.5 KiB
Rust
93 lines
2.5 KiB
Rust
use crate::{
|
|
net::{
|
|
ClientMsg, Msg, ServerMsg,
|
|
server::{ClientSender, ConAccepter, listen},
|
|
transfer::{DisconnectReason, RecvHandler},
|
|
},
|
|
rsc::DataDir,
|
|
};
|
|
use std::{
|
|
collections::HashMap,
|
|
sync::{
|
|
Arc,
|
|
atomic::{AtomicU64, Ordering},
|
|
},
|
|
};
|
|
use tokio::sync::RwLock;
|
|
|
|
#[tokio::main]
|
|
pub async fn run_server() {
|
|
let dir = DataDir::default();
|
|
let path = dir.get();
|
|
let handler = ServerListener {
|
|
msgs: Default::default(),
|
|
senders: Default::default(),
|
|
count: 0.into(),
|
|
};
|
|
listen(path, handler).await;
|
|
}
|
|
|
|
type ClientId = u64;
|
|
|
|
struct ServerListener {
|
|
msgs: Arc<RwLock<Vec<Msg>>>,
|
|
senders: Arc<RwLock<HashMap<ClientId, ClientSender>>>,
|
|
count: AtomicU64,
|
|
}
|
|
|
|
impl ConAccepter for ServerListener {
|
|
async fn accept(&self, send: ClientSender) -> impl RecvHandler<ClientMsg> {
|
|
let id = self.count.fetch_add(1, Ordering::Release);
|
|
self.senders.write().await.insert(id, send.clone());
|
|
ClientHandler {
|
|
msgs: self.msgs.clone(),
|
|
senders: self.senders.clone(),
|
|
send,
|
|
id,
|
|
}
|
|
}
|
|
}
|
|
|
|
struct ClientHandler {
|
|
msgs: Arc<RwLock<Vec<Msg>>>,
|
|
send: ClientSender,
|
|
senders: Arc<RwLock<HashMap<ClientId, ClientSender>>>,
|
|
id: ClientId,
|
|
}
|
|
|
|
impl RecvHandler<ClientMsg> for ClientHandler {
|
|
async fn msg(&self, msg: ClientMsg) {
|
|
match msg {
|
|
ClientMsg::SendMsg(msg) => {
|
|
self.msgs.write().await.push(msg.clone());
|
|
let mut handles = Vec::new();
|
|
for (&id, send) in self.senders.read().await.iter() {
|
|
if id == self.id {
|
|
continue;
|
|
}
|
|
let send = send.clone();
|
|
let msg = msg.clone();
|
|
let fut = async move {
|
|
let _ = send.send(ServerMsg::SendMsg(msg)).await;
|
|
};
|
|
handles.push(tokio::spawn(fut));
|
|
}
|
|
for h in handles {
|
|
h.await.unwrap();
|
|
}
|
|
}
|
|
ClientMsg::RequestMsgs => {
|
|
let msgs = self.msgs.read().await.clone();
|
|
let _ = self.send.send(ServerMsg::LoadMsgs(msgs)).await;
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn disconnect(&self, reason: DisconnectReason) -> () {
|
|
match reason {
|
|
DisconnectReason::Closed | DisconnectReason::Timeout => (),
|
|
DisconnectReason::Other(e) => println!("connection issue: {e}"),
|
|
}
|
|
}
|
|
}
|