| @@ -5,13 +5,13 @@ authors = ["Isabelle L. <me@izzabelle.dev>"] | |||||
| edition = "2018" | edition = "2018" | ||||
| [dependencies] | [dependencies] | ||||
| structopt = "0.3.14" | |||||
| async-std = { version = "1.5.0",features = ["attributes"] } | async-std = { version = "1.5.0",features = ["attributes"] } | ||||
| chrono = "0.4.11" | |||||
| serde = { version = "1.0.107", features = ["derive"] } | serde = { version = "1.0.107", features = ["derive"] } | ||||
| serde_json = "1.0.52" | |||||
| uuid = { version = "0.8.1", features = ["v4"] } | uuid = { version = "0.8.1", features = ["v4"] } | ||||
| futures-util = "0.3.5" | |||||
| serde_json = "1.0.52" | |||||
| lazy_static = "1.4.0" | lazy_static = "1.4.0" | ||||
| structopt = "0.3.14" | |||||
| chrono = "0.4.11" | |||||
| futures = "0.3.5" | futures = "0.3.5" | ||||
| futures-util = "0.3.5" | |||||
| toml = "0.5.6" | toml = "0.5.6" | ||||
| @@ -1 +1 @@ | |||||
| username="Isabelle" | |||||
| user="Isabelle" | |||||
| @@ -1,3 +1,7 @@ | |||||
| alias rs := run-server | |||||
| alias rc := run-client | |||||
| alias b := build | |||||
| build: | build: | ||||
| cargo build | cargo build | ||||
| run-server: | run-server: | ||||
| @@ -1,18 +1,25 @@ | |||||
| // namespacing | // namespacing | ||||
| use crate::packet::{Message, Packet}; | |||||
| use crate::config::ClientConfig as Config; | |||||
| use crate::packet::{Join, Message, Packet, Sendable}; | |||||
| use crate::Result; | use crate::Result; | ||||
| use async_std::net::TcpStream; | use async_std::net::TcpStream; | ||||
| use std::convert::TryInto; | |||||
| use futures_util::io::AsyncReadExt; | |||||
| /// wraps the client | /// wraps the client | ||||
| pub async fn client(port: u16) -> Result<()> { | pub async fn client(port: u16) -> Result<()> { | ||||
| let mut stream = TcpStream::connect(format!("127.0.0.1:{}", &port)).await?; | |||||
| let config = Config::load()?; | |||||
| let stream = TcpStream::connect(format!("127.0.0.1:{}", &port)).await?; | |||||
| println!("connection established to: {}:{}", stream.peer_addr()?.ip(), port); | println!("connection established to: {}:{}", stream.peer_addr()?.ip(), port); | ||||
| let (_read, mut write) = stream.split(); | |||||
| let join: Packet = Join::new(config.user).to_packet()?; | |||||
| join.write(&mut write).await?; | |||||
| // testing stuffs | // testing stuffs | ||||
| let message: Packet = | let message: Packet = | ||||
| Message::new("Isabelle".to_owned(), "Hello Server".to_owned()).try_into()?; | |||||
| message.write(&mut stream).await?; | |||||
| Message::new("Isabelle".to_owned(), "Hello Server".to_owned()).to_packet()?; | |||||
| message.write(&mut write).await?; | |||||
| loop {} | loop {} | ||||
| } | } | ||||
| @@ -3,7 +3,7 @@ use serde::Deserialize; | |||||
| #[derive(Deserialize)] | #[derive(Deserialize)] | ||||
| pub struct ClientConfig { | pub struct ClientConfig { | ||||
| user: String, | |||||
| pub user: String, | |||||
| } | } | ||||
| impl ClientConfig { | impl ClientConfig { | ||||
| @@ -2,7 +2,7 @@ | |||||
| use crate::Result; | use crate::Result; | ||||
| use async_std::net::TcpStream; | use async_std::net::TcpStream; | ||||
| use async_std::prelude::*; | use async_std::prelude::*; | ||||
| use futures_util::io::ReadHalf; | |||||
| use futures_util::io::{ReadHalf, WriteHalf}; | |||||
| use std::convert::TryInto; | use std::convert::TryInto; | ||||
| mod join; | mod join; | ||||
| @@ -29,12 +29,13 @@ impl std::convert::Into<NetworkPacket> for Packet { | |||||
| } | } | ||||
| } | } | ||||
| pub trait Sendable { | |||||
| fn to_packet(self) -> Packet; | |||||
| fn from_packet(packet: Packet) -> Self; | |||||
| pub trait Sendable: Sized { | |||||
| fn to_packet(self) -> Result<Packet>; | |||||
| fn from_packet(packet: Packet) -> Result<Self>; | |||||
| } | } | ||||
| /// contains data to be turned into a network packet or into a more specific packet | /// contains data to be turned into a network packet or into a more specific packet | ||||
| #[derive(Debug, Clone)] | |||||
| pub struct Packet { | pub struct Packet { | ||||
| pub packet_type: PacketType, | pub packet_type: PacketType, | ||||
| packet_contents: Vec<u8>, | packet_contents: Vec<u8>, | ||||
| @@ -65,7 +66,7 @@ impl Packet { | |||||
| } | } | ||||
| /// write a packet to the tcpstream | /// write a packet to the tcpstream | ||||
| pub async fn write(self, stream: &mut TcpStream) -> Result<()> { | |||||
| pub async fn write(self, stream: &mut WriteHalf<TcpStream>) -> Result<()> { | |||||
| let network_packet: NetworkPacket = self.into(); | let network_packet: NetworkPacket = self.into(); | ||||
| stream.write(&network_packet.0).await?; | stream.write(&network_packet.0).await?; | ||||
| Ok(()) | Ok(()) | ||||
| @@ -73,6 +74,7 @@ impl Packet { | |||||
| } | } | ||||
| /// represent the specific packet type | /// represent the specific packet type | ||||
| #[derive(Debug, Clone)] | |||||
| #[repr(u8)] | #[repr(u8)] | ||||
| pub enum PacketType { | pub enum PacketType { | ||||
| Message = 0, | Message = 0, | ||||
| @@ -84,6 +86,7 @@ impl PacketType { | |||||
| pub fn from_u8(packet_type: u8) -> Option<Self> { | pub fn from_u8(packet_type: u8) -> Option<Self> { | ||||
| match packet_type { | match packet_type { | ||||
| 0 => Some(Self::Message), | 0 => Some(Self::Message), | ||||
| 1 => Some(Self::Join), | |||||
| _ => None, | _ => None, | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,5 +1,5 @@ | |||||
| use crate::packet::{Packet, PacketType}; | use crate::packet::{Packet, PacketType}; | ||||
| use crate::{Error, Result}; | |||||
| use crate::Result; | |||||
| use chrono::prelude::*; | use chrono::prelude::*; | ||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||
| @@ -10,29 +10,23 @@ pub struct Join { | |||||
| } | } | ||||
| impl Join { | impl Join { | ||||
| fn new(user: String) -> Self { | |||||
| pub fn new(user: String) -> Self { | |||||
| let timestamp = Utc::now().timestamp(); | let timestamp = Utc::now().timestamp(); | ||||
| Self { user, timestamp } | Self { user, timestamp } | ||||
| } | } | ||||
| } | } | ||||
| impl std::convert::TryFrom<Packet> for Join { | |||||
| type Error = Error; | |||||
| fn try_from(packet: Packet) -> Result<Self> { | |||||
| let packet_contents = | |||||
| &String::from_utf8(packet.packet_contents).expect("could not decode as utf8"); | |||||
| let message: Join = serde_json::from_str(packet_contents)?; | |||||
| Ok(message) | |||||
| } | |||||
| } | |||||
| impl std::convert::TryInto<Packet> for Join { | |||||
| type Error = Error; | |||||
| fn try_into(self) -> Result<Packet> { | |||||
| impl crate::packet::Sendable for Join { | |||||
| fn to_packet(self) -> Result<Packet> { | |||||
| let packet_contents: Vec<u8> = serde_json::to_string(&self)?.into_bytes(); | let packet_contents: Vec<u8> = serde_json::to_string(&self)?.into_bytes(); | ||||
| let packet_type = PacketType::Join; | let packet_type = PacketType::Join; | ||||
| Ok(Packet { packet_type, packet_contents }) | Ok(Packet { packet_type, packet_contents }) | ||||
| } | } | ||||
| fn from_packet(packet: Packet) -> Result<Self> { | |||||
| let packet_contents = | |||||
| &String::from_utf8(packet.packet_contents).expect("could not decode as utf8"); | |||||
| let join: Join = serde_json::from_str(packet_contents)?; | |||||
| Ok(join) | |||||
| } | |||||
| } | } | ||||
| @@ -1,6 +1,6 @@ | |||||
| // namespacing | // namespacing | ||||
| use crate::packet::{Packet, PacketType}; | use crate::packet::{Packet, PacketType}; | ||||
| use crate::{Error, Result}; | |||||
| use crate::Result; | |||||
| use chrono::prelude::*; | use chrono::prelude::*; | ||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||
| @@ -20,23 +20,17 @@ impl Message { | |||||
| } | } | ||||
| } | } | ||||
| impl std::convert::TryFrom<Packet> for Message { | |||||
| type Error = Error; | |||||
| impl crate::packet::Sendable for Message { | |||||
| fn to_packet(self) -> Result<Packet> { | |||||
| let packet_contents: Vec<u8> = serde_json::to_string(&self)?.into_bytes(); | |||||
| let packet_type = PacketType::Message; | |||||
| Ok(Packet { packet_type, packet_contents }) | |||||
| } | |||||
| fn try_from(packet: Packet) -> Result<Self> { | |||||
| fn from_packet(packet: Packet) -> Result<Self> { | |||||
| let packet_contents = | let packet_contents = | ||||
| &String::from_utf8(packet.packet_contents).expect("could not decode as utf8"); | &String::from_utf8(packet.packet_contents).expect("could not decode as utf8"); | ||||
| let message: Message = serde_json::from_str(packet_contents)?; | let message: Message = serde_json::from_str(packet_contents)?; | ||||
| Ok(message) | Ok(message) | ||||
| } | } | ||||
| } | } | ||||
| impl std::convert::TryInto<Packet> for Message { | |||||
| type Error = Error; | |||||
| fn try_into(self) -> Result<Packet> { | |||||
| let packet_contents: Vec<u8> = serde_json::to_string(&self)?.into_bytes(); | |||||
| let packet_type = PacketType::Message; | |||||
| Ok(Packet { packet_type, packet_contents }) | |||||
| } | |||||
| } | |||||
| @@ -1,17 +1,17 @@ | |||||
| // namespacing | // namespacing | ||||
| use crate::{ | use crate::{ | ||||
| packet::{Join, Message, Packet, PacketType}, | |||||
| packet::{Join, Message, Packet, PacketType, Sendable}, | |||||
| Result, | Result, | ||||
| }; | }; | ||||
| use async_std::{ | use async_std::{ | ||||
| net::{TcpListener, TcpStream}, | net::{TcpListener, TcpStream}, | ||||
| prelude::*, | |||||
| task, | task, | ||||
| }; | }; | ||||
| use futures::io::{ReadHalf, WriteHalf}; | use futures::io::{ReadHalf, WriteHalf}; | ||||
| use futures_util::io::AsyncReadExt; | use futures_util::io::AsyncReadExt; | ||||
| use futures_util::stream::StreamExt; | |||||
| use lazy_static::lazy_static; | use lazy_static::lazy_static; | ||||
| use std::{collections::HashMap, convert::TryFrom, sync::Mutex}; | |||||
| use std::{collections::HashMap, sync::Mutex}; | |||||
| use uuid::Uuid; | use uuid::Uuid; | ||||
| lazy_static! { | lazy_static! { | ||||
| @@ -60,11 +60,11 @@ async fn handle_stream(mut stream: ReadHalf<TcpStream>, stream_id: Uuid) -> Resu | |||||
| match packet.packet_type { | match packet.packet_type { | ||||
| PacketType::Message => { | PacketType::Message => { | ||||
| let msg = Message::try_from(packet)?; | |||||
| let msg = Message::from_packet(packet)?; | |||||
| println!("{:?}", msg); | println!("{:?}", msg); | ||||
| } | } | ||||
| PacketType::Join => { | PacketType::Join => { | ||||
| let join = Join::try_from(packet)?; | |||||
| let join = Join::from_packet(packet)?; | |||||
| println!("{:?}", join); | println!("{:?}", join); | ||||
| } | } | ||||
| } | } | ||||
| @@ -78,8 +78,17 @@ async fn handle_stream(mut stream: ReadHalf<TcpStream>, stream_id: Uuid) -> Resu | |||||
| Ok(()) | Ok(()) | ||||
| } | } | ||||
| /* | |||||
| async fn relay_packet() -> Result<()> { | |||||
| let locked_stream = WRITE_STREAMS.lock(). | |||||
| async fn relay_packet<T: Clone + Sendable>(packet: T) -> Result<()> { | |||||
| let mut locked_write_streams = WRITE_STREAMS.lock().expect("failed to aqcuire lock"); | |||||
| let stream = futures::stream::iter(locked_write_streams.iter_mut()); | |||||
| }*/ | |||||
| let packet = &packet; | |||||
| stream | |||||
| .for_each_concurrent(None, |(_, mut stream)| async move { | |||||
| let packet = packet.clone().to_packet().expect("failed to convert to packet"); | |||||
| // in case any of the writes fail just ignore them | |||||
| let _ = packet.write(&mut stream); | |||||
| }) | |||||
| .await; | |||||
| Ok(()) | |||||
| } | |||||