created protobuf structures

This commit is contained in:
michael-bailey 2024-05-11 16:38:39 +01:00
parent 74ca0a1a80
commit 05dd6e0d96
4 changed files with 525 additions and 0 deletions

View File

@ -0,0 +1,118 @@
use std::{io, net::SocketAddr};
use foundation::{
networking::protobuf::read_message,
prelude::{
connected_client_message,
ConnectedClientMessage,
Disconnect,
GetClients,
GetGlobalMessages,
SendGlobalMessage,
SendPrivateMessage,
},
};
use tokio::{io::ReadHalf, net::TcpStream, sync::mpsc::UnboundedSender};
use uuid::Uuid;
use crate::{
connection::connection_manager::ConnectionManagerMessage,
network::ClientReader,
};
pub struct ProtobufClientReader {
reader: ReadHalf<TcpStream>,
addr: SocketAddr,
uuid: Uuid,
}
impl ProtobufClientReader {
pub fn new(
reader: ReadHalf<TcpStream>,
addr: SocketAddr,
uuid: Uuid,
) -> Self {
Self { reader, addr, uuid }
}
// move to other one
pub async fn get_message(&mut self) -> io::Result<ConnectedClientMessage> {
read_message::<ConnectedClientMessage, ReadHalf<TcpStream>>(
&mut self.reader,
)
.await
}
pub fn handle_message(
&self,
msg: ConnectedClientMessage,
channel: &UnboundedSender<ConnectionManagerMessage>,
) {
use connected_client_message::Message;
println!("[ProtobufClientReader:{}] got message", self.addr);
let uuid = self.uuid;
_ = match msg {
ConnectedClientMessage {
message: Some(Message::GetClients(GetClients {})),
} => channel.send(ConnectionManagerMessage::SendClientsTo { uuid }),
ConnectedClientMessage {
message: Some(Message::GetGlobalMessage(GetGlobalMessages {})),
} => channel.send(ConnectionManagerMessage::SendGlobalMessages { uuid }),
ConnectedClientMessage {
message:
Some(Message::SendPrivateMessage(SendPrivateMessage {
uuid: message_uuid,
to,
content,
})),
} => channel.send(ConnectionManagerMessage::SendPrivateMessage {
uuid: message_uuid.parse().unwrap(),
from: uuid,
to: to.parse().unwrap(),
content,
}),
ConnectedClientMessage {
message: Some(Message::SendGlobalMessage(SendGlobalMessage { content })),
} => channel.send(ConnectionManagerMessage::BroadcastGlobalMessage {
from: uuid,
content,
}),
ConnectedClientMessage {
message: Some(Message::Disconnect(Disconnect {})),
} => channel.send(ConnectionManagerMessage::Disconnect { uuid }),
ConnectedClientMessage { message: None } => unimplemented!(),
};
}
}
impl ClientReader for ProtobufClientReader {
fn start_run(
mut self: Box<Self>,
uuid: Uuid,
channel: UnboundedSender<ConnectionManagerMessage>,
) -> tokio::task::JoinHandle<()> {
tokio::spawn(async move {
loop {
let msg = self.get_message().await;
let Ok(msg) = msg else {
let error = msg.unwrap_err();
println!(
"[ProtobufClientReader:{}] errored with '{}' disconnecting",
self.addr, error
);
_ = channel.send(ConnectionManagerMessage::Disconnected { uuid });
return;
};
self.handle_message(msg, &channel);
}
})
}
}

View File

@ -0,0 +1,175 @@
use std::net::SocketAddr;
use async_trait::async_trait;
use foundation::{
networking::protobuf::write_message,
prelude::{
connected_server_message,
ClientConnected,
ClientDetails,
ClientDisconnected,
ConnectedClients,
ConnectedServerMessage,
Disconnected,
GlobalMessage,
GlobalMessages,
PrivateMessage,
},
};
use tokio::{io::WriteHalf, net::TcpStream};
use uuid::Uuid;
use crate::network::ClientWriter;
#[allow(dead_code)]
pub struct ProtobufClientWriter {
writer: WriteHalf<TcpStream>,
addr: SocketAddr,
uuid: Uuid,
}
impl ProtobufClientWriter {
pub fn new(
writer: WriteHalf<TcpStream>,
addr: SocketAddr,
uuid: Uuid,
) -> Self {
Self { writer, addr, uuid }
}
#[deprecated]
pub async fn send_clients(&mut self, clients: Vec<ClientDetails>) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::ConnectedClients(
ConnectedClients { clients },
)),
};
println!("[ProtobufClientWriter:{}] sending clients", self.addr);
write_message(&mut self.writer, message).await.unwrap();
}
#[deprecated]
pub async fn send_global_messages(&mut self, messages: Vec<GlobalMessage>) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::GlobalMessages(
GlobalMessages { messages },
)),
};
println!(
"[ProtobufClientWriter:{}] sending global messages",
self.addr
);
write_message(&mut self.writer, message).await.unwrap();
}
#[deprecated]
pub async fn send_private_message(&mut self, message: PrivateMessage) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::PrivateMessage(message)),
};
println!(
"[ProtobufClientWriter:{}] sending private message",
self.addr
);
write_message(&mut self.writer, message).await.unwrap();
}
#[deprecated]
pub async fn send_disconnect(&mut self) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::Disconnected(
Disconnected {
reason: "shutting down".into(),
},
)),
};
println!("[ProtobufClientWriter:{}] sending disconnect", self.addr);
write_message(&mut self.writer, message).await.unwrap();
}
}
#[async_trait]
impl ClientWriter for ProtobufClientWriter {
async fn send_clients(&mut self, clients: Vec<ClientDetails>) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::ConnectedClients(
ConnectedClients { clients },
)),
};
println!("[ProtobufClientWriter:{}] sending clients", self.addr);
write_message(&mut self.writer, message).await.unwrap();
}
async fn send_client_joined(&mut self, details: ClientDetails) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::ClientConnected(
ClientConnected {
details: Some(details),
},
)),
};
println!(
"[ProtobufClientWriter:{}] sending client connected message",
self.addr
);
write_message(&mut self.writer, message).await.unwrap();
}
async fn send_client_left(&mut self, uuid: Uuid) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::ClientDisconnected(
ClientDisconnected {
uuid: uuid.to_string(),
},
)),
};
println!(
"[ProtobufClientWriter:{}] sending client connected message",
self.addr
);
write_message(&mut self.writer, message).await.unwrap();
}
async fn send_global_messages(&mut self, messages: Vec<GlobalMessage>) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::GlobalMessages(
GlobalMessages { messages },
)),
};
println!(
"[ProtobufClientWriter:{}] sending global messages",
self.addr
);
write_message(&mut self.writer, message).await.unwrap();
}
async fn send_global_message(&mut self, message: GlobalMessage) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::GlobalMessage(message)),
};
println!("[ProtobufClientWriter:{}] sending disconnect", self.addr);
write_message(&mut self.writer, message).await.unwrap();
}
async fn send_private_message(&mut self, message: PrivateMessage) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::PrivateMessage(message)),
};
println!(
"[ProtobufClientWriter:{}] sending private message",
self.addr
);
write_message(&mut self.writer, message).await.unwrap();
}
async fn send_disconnect(&mut self) {
let message = ConnectedServerMessage {
message: Some(connected_server_message::Message::Disconnected(
Disconnected {
reason: "shutting down".into(),
},
)),
};
println!("[ProtobufClientWriter:{}] sending disconnect", self.addr);
write_message(&mut self.writer, message).await.unwrap();
}
}

View File

@ -0,0 +1,58 @@
use async_trait::async_trait;
use tokio::{
net::TcpListener,
select,
sync::mpsc::UnboundedSender,
task::JoinHandle,
};
use crate::{
network::{ConnectionType, NetworkListener},
server_va::ServerMessages,
};
/// # Listener Manager
/// This stores and awaits for connections from listeners.
/// When a connection is received, it is passed to the server
pub struct ProtobufListener {
protobuf_listener: TcpListener,
sender: UnboundedSender<ServerMessages>,
}
#[async_trait]
impl NetworkListener for ProtobufListener {
/// Binds listeners and stores them in the ListenerManager
async fn new(channel: UnboundedSender<ServerMessages>) -> Self {
println!("[ProtobufListener] setting up listeners");
let protobuf_listener = TcpListener::bind("0.0.0.0:6500")
.await
.expect("[ProtobufListener] failed to bind to 0.0.0.0:6500");
Self {
protobuf_listener,
sender: channel,
}
}
async fn run(&self) {
loop {
println!("[ProtobufListener] waiting for connection");
let accept_protobuf = self.protobuf_listener.accept();
let msg = select! {
Ok((stream, addr)) = accept_protobuf => {
println!("[ProtobufListener] accepted connection");
ServerMessages::NewConnection(ConnectionType::ProtobufConnection(stream, addr))
}
};
println!("[ProtobufListener] passing message to server");
self.sender.send(msg).unwrap();
}
}
fn start_run(sender: UnboundedSender<ServerMessages>) -> JoinHandle<()> {
tokio::spawn(async move {
ProtobufListener::new(sender).await.run().await;
})
}
}

View File

@ -0,0 +1,174 @@
use std::{io, net::SocketAddr};
use async_trait::async_trait;
use foundation::{
networking::protobuf::{read_message, write_message},
prelude::{
network_client_message,
network_server_message,
Connect,
Connected,
GetInfo,
Info,
NetworkClientMessage,
NetworkServerMessage,
Request,
},
};
use tokio::{io::split, net::TcpStream};
use uuid::Uuid;
use crate::network::{
protobuf::{
protobuf_client_reader::ProtobufClientReader,
protobuf_client_writer::ProtobufClientWriter,
},
ClientReader,
ClientWriter,
NetworkConnection,
ServerRequest,
};
pub struct ProtobufNetworkConnection {
pub(super) stream: TcpStream,
pub(super) addr: SocketAddr,
}
impl ProtobufNetworkConnection {
pub fn new(stream: TcpStream, addr: SocketAddr) -> Self {
Self { stream, addr }
}
pub async fn get_request(&mut self) -> io::Result<ServerRequest> {
let message = NetworkServerMessage {
message: Some(network_server_message::Message::Request(Request {})),
};
println!("[ProtobufNetworkConnection] sending request");
write_message(&mut self.stream, message).await.unwrap();
println!("[ProtobufNetworkConnection] waiting for response");
let request =
read_message::<NetworkClientMessage, TcpStream>(&mut self.stream)
.await
.unwrap();
println!("[ProtobufNetworkConnection] returning request");
match request {
NetworkClientMessage {
message: Some(network_client_message::Message::GetInfo(GetInfo {})),
} => Ok(ServerRequest::GetInfo),
NetworkClientMessage {
message:
Some(network_client_message::Message::Connect(Connect {
username,
uuid,
})),
} => Ok(ServerRequest::Connect {
username,
uuid: uuid.parse().unwrap(),
addr: self.addr,
}),
_ => Ok(ServerRequest::Ignore),
}
}
pub async fn send_info(mut self, name: String, owner: String) {
let message = NetworkServerMessage {
message: Some(network_server_message::Message::GotInfo(Info {
server_name: name,
owner,
})),
};
println!("[ProtobufNetworkConnection] Sending info to client");
write_message(&mut self.stream, message).await.unwrap();
println!("[ProtobufNetworkConnection] droping connection");
}
pub async fn send_connected(
mut self,
uuid: Uuid,
) -> (ProtobufClientWriter, ProtobufClientReader) {
let message = NetworkServerMessage {
message: Some(network_server_message::Message::Connected(Connected {})),
};
write_message(&mut self.stream, message).await.unwrap();
self.into(uuid)
}
fn into(self, uuid: Uuid) -> (ProtobufClientWriter, ProtobufClientReader) {
let (read, write) = split(self.stream);
let writer = ProtobufClientWriter::new(write, self.addr, uuid);
let reader = ProtobufClientReader::new(read, self.addr, uuid);
(writer, reader)
}
}
#[async_trait]
impl NetworkConnection for ProtobufNetworkConnection {
async fn get_request(&mut self) -> io::Result<ServerRequest> {
let message = NetworkServerMessage {
message: Some(network_server_message::Message::Request(Request {})),
};
println!("[ProtobufNetworkConnection] sending request");
write_message(&mut self.stream, message).await.unwrap();
println!("[ProtobufNetworkConnection] waiting for response");
let request =
read_message::<NetworkClientMessage, TcpStream>(&mut self.stream)
.await
.unwrap();
println!("[ProtobufNetworkConnection] returning request");
match request {
NetworkClientMessage {
message: Some(network_client_message::Message::GetInfo(GetInfo {})),
} => Ok(ServerRequest::GetInfo),
NetworkClientMessage {
message:
Some(network_client_message::Message::Connect(Connect {
username,
uuid,
})),
} => Ok(ServerRequest::Connect {
username,
uuid: uuid.parse().unwrap(),
addr: self.addr,
}),
_ => Ok(ServerRequest::Ignore),
}
}
async fn send_info(mut self: Box<Self>, name: String, owner: String) {
let message = NetworkServerMessage {
message: Some(network_server_message::Message::GotInfo(Info {
server_name: name,
owner,
})),
};
println!("[ProtobufNetworkConnection] Sending info to client");
write_message(&mut self.stream, message).await.unwrap();
println!("[ProtobufNetworkConnection] droping connection");
}
async fn send_connected(
mut self: Box<Self>,
uuid: Uuid,
) -> (Box<dyn ClientWriter>, Box<dyn ClientReader>) {
let message = NetworkServerMessage {
message: Some(network_server_message::Message::Connected(Connected {})),
};
write_message(&mut self.stream, message).await.unwrap();
let (read, write) = split(self.stream);
let writer = Box::new(ProtobufClientWriter::new(write, self.addr, uuid));
let reader = Box::new(ProtobufClientReader::new(read, self.addr, uuid));
(writer, reader)
}
}