| @@ -309,6 +309,19 @@ dependencies = [ | |||||
| "libc", | "libc", | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "ilmp" | |||||
| version = "0.1.0" | |||||
| dependencies = [ | |||||
| "chrono", | |||||
| "futures", | |||||
| "futures-util", | |||||
| "orion", | |||||
| "serde", | |||||
| "serde_json", | |||||
| "uuid", | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "iovec" | name = "iovec" | ||||
| version = "0.1.4" | version = "0.1.4" | ||||
| @@ -435,6 +448,7 @@ dependencies = [ | |||||
| "chrono", | "chrono", | ||||
| "futures", | "futures", | ||||
| "futures-util", | "futures-util", | ||||
| "ilmp", | |||||
| "lazy_static", | "lazy_static", | ||||
| "orion", | "orion", | ||||
| "serde", | "serde", | ||||
| @@ -651,18 +665,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" | |||||
| [[package]] | [[package]] | ||||
| name = "serde" | name = "serde" | ||||
| version = "1.0.107" | |||||
| version = "1.0.110" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "eba7550f2cdf88ffc23ab0f1607133486c390a8c0f89b57e589b9654ee15e04d" | |||||
| checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" | |||||
| dependencies = [ | dependencies = [ | ||||
| "serde_derive", | "serde_derive", | ||||
| ] | ] | ||||
| [[package]] | [[package]] | ||||
| name = "serde_derive" | name = "serde_derive" | ||||
| version = "1.0.107" | |||||
| version = "1.0.110" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "10be45e22e5597d4b88afcc71f9d7bfadcd604bf0c78a3ab4582b8d2b37f39f3" | |||||
| checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" | |||||
| dependencies = [ | dependencies = [ | ||||
| "proc-macro2", | "proc-macro2", | ||||
| "quote", | "quote", | ||||
| @@ -671,9 +685,9 @@ dependencies = [ | |||||
| [[package]] | [[package]] | ||||
| name = "serde_json" | name = "serde_json" | ||||
| version = "1.0.52" | |||||
| version = "1.0.53" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd" | |||||
| checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" | |||||
| dependencies = [ | dependencies = [ | ||||
| "itoa", | "itoa", | ||||
| "ryu", | "ryu", | ||||
| @@ -16,3 +16,4 @@ chrono = "0.4.11" | |||||
| futures = "0.3.5" | futures = "0.3.5" | ||||
| toml = "0.5.6" | toml = "0.5.6" | ||||
| orion = "0.15.1" | orion = "0.15.1" | ||||
| ilmp = {path = "./ilmp"} | |||||
| @@ -1,6 +1,5 @@ | |||||
| // namespacing | // namespacing | ||||
| use crate::config::ClientConfig as Config; | 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 futures_util::io::AsyncReadExt; | use futures_util::io::AsyncReadExt; | ||||
| @@ -10,16 +9,12 @@ pub async fn client(port: u16) -> Result<()> { | |||||
| let config = Config::load()?; | let config = Config::load()?; | ||||
| let stream = TcpStream::connect(format!("127.0.0.1:{}", &port)).await?; | 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 (_read, mut write) = stream.split(); | ||||
| let join: Packet = Join::new(config.user).to_packet()?; | |||||
| join.write(&mut write).await?; | |||||
| // testing stuffs | |||||
| let message: Packet = | |||||
| Message::new("Isabelle".to_owned(), "Hello Server".to_owned()).to_packet()?; | |||||
| message.write(&mut write).await?; | |||||
| loop {} | loop {} | ||||
| } | } | ||||
| @@ -1,7 +1,6 @@ | |||||
| // modules | // modules | ||||
| mod client; | mod client; | ||||
| mod config; | mod config; | ||||
| mod packet; | |||||
| mod server; | mod server; | ||||
| // re-exports | // re-exports | ||||
| @@ -1,93 +0,0 @@ | |||||
| // namespacing | |||||
| use crate::Result; | |||||
| use async_std::net::TcpStream; | |||||
| use async_std::prelude::*; | |||||
| use futures_util::io::{ReadHalf, WriteHalf}; | |||||
| use std::convert::TryInto; | |||||
| mod join; | |||||
| pub use join::Join; | |||||
| mod message; | |||||
| pub use message::Message; | |||||
| /// structured [packet type byte][four bytes of packet length][contents of packet] | |||||
| pub struct NetworkPacket(Vec<u8>); | |||||
| impl std::convert::Into<NetworkPacket> for Packet { | |||||
| fn into(self) -> NetworkPacket { | |||||
| let mut contents: Vec<u8> = Vec::new(); | |||||
| // packet type byte | |||||
| contents.push(self.packet_type as u8); | |||||
| // write the packet length | |||||
| let contents_length = self.packet_contents.len() as u32; | |||||
| contents.extend_from_slice(&contents_length.to_le_bytes()); | |||||
| // write the rest of the contents | |||||
| contents.extend_from_slice(&self.packet_contents); | |||||
| NetworkPacket(contents) | |||||
| } | |||||
| } | |||||
| 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 | |||||
| #[derive(Debug, Clone)] | |||||
| pub struct Packet { | |||||
| pub packet_type: PacketType, | |||||
| packet_contents: Vec<u8>, | |||||
| } | |||||
| impl Packet { | |||||
| /// create a new packet | |||||
| pub fn new(packet_type: PacketType, packet_contents: Vec<u8>) -> Self { | |||||
| Self { packet_type, packet_contents } | |||||
| } | |||||
| /// read a packet from a tcpstream | |||||
| pub async fn read(stream: &mut ReadHalf<TcpStream>) -> Result<Option<Packet>> { | |||||
| let mut info_buf = [0u8; 5]; | |||||
| let check = stream.read(&mut info_buf).await?; | |||||
| if check == 0 { | |||||
| return Ok(None); | |||||
| } | |||||
| let packet_type = PacketType::from_u8(info_buf[0]).unwrap(); | |||||
| let length = u32::from_le_bytes(info_buf[1..5].try_into().unwrap()) as usize; | |||||
| let mut contents: Vec<u8> = vec![0; length]; | |||||
| stream.read(&mut contents).await?; | |||||
| Ok(Some(Packet::new(packet_type, contents))) | |||||
| } | |||||
| /// write a packet to the tcpstream | |||||
| pub async fn write(self, stream: &mut WriteHalf<TcpStream>) -> Result<()> { | |||||
| let network_packet: NetworkPacket = self.into(); | |||||
| stream.write(&network_packet.0).await?; | |||||
| Ok(()) | |||||
| } | |||||
| } | |||||
| /// represent the specific packet type | |||||
| #[derive(Debug, Clone)] | |||||
| #[repr(u8)] | |||||
| pub enum PacketType { | |||||
| Message = 0, | |||||
| Join = 1, | |||||
| } | |||||
| impl PacketType { | |||||
| /// returns the PacketType if the u8 is a valid packet type | |||||
| pub fn from_u8(packet_type: u8) -> Option<Self> { | |||||
| match packet_type { | |||||
| 0 => Some(Self::Message), | |||||
| 1 => Some(Self::Join), | |||||
| _ => None, | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,32 +0,0 @@ | |||||
| use crate::packet::{Packet, PacketType}; | |||||
| use crate::Result; | |||||
| use chrono::prelude::*; | |||||
| use serde::{Deserialize, Serialize}; | |||||
| #[derive(Deserialize, Serialize, Debug, Clone)] | |||||
| pub struct Join { | |||||
| user: String, | |||||
| timestamp: i64, | |||||
| } | |||||
| impl Join { | |||||
| pub fn new(user: String) -> Self { | |||||
| let timestamp = Utc::now().timestamp(); | |||||
| Self { user, timestamp } | |||||
| } | |||||
| } | |||||
| 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_type = PacketType::Join; | |||||
| 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,36 +0,0 @@ | |||||
| // namespacing | |||||
| use crate::packet::{Packet, PacketType}; | |||||
| use crate::Result; | |||||
| use chrono::prelude::*; | |||||
| use serde::{Deserialize, Serialize}; | |||||
| /// a Message | |||||
| #[derive(Deserialize, Serialize, Debug, Clone)] | |||||
| pub struct Message { | |||||
| user: String, | |||||
| contents: String, | |||||
| timestamp: i64, | |||||
| } | |||||
| impl Message { | |||||
| /// create a new message | |||||
| pub fn new(user: String, contents: String) -> Self { | |||||
| let timestamp = Utc::now().timestamp(); | |||||
| Self { user, contents, timestamp } | |||||
| } | |||||
| } | |||||
| 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 from_packet(packet: Packet) -> Result<Self> { | |||||
| let packet_contents = | |||||
| &String::from_utf8(packet.packet_contents).expect("could not decode as utf8"); | |||||
| let message: Message = serde_json::from_str(packet_contents)?; | |||||
| Ok(message) | |||||
| } | |||||
| } | |||||
| @@ -1,8 +1,5 @@ | |||||
| // namespacing | // namespacing | ||||
| use crate::{ | |||||
| packet::{Join, Message, Packet, PacketType, Sendable}, | |||||
| Result, | |||||
| }; | |||||
| use crate::Result; | |||||
| use async_std::{ | use async_std::{ | ||||
| net::{TcpListener, TcpStream}, | net::{TcpListener, TcpStream}, | ||||
| task, | task, | ||||
| @@ -21,7 +18,11 @@ lazy_static! { | |||||
| /// wraps the server | /// wraps the server | ||||
| pub async fn server(port: u16) -> Result<()> { | pub async fn server(port: u16) -> Result<()> { | ||||
| let listener = TcpListener::bind(format!("127.0.0.1:{}", &port)).await?; | let listener = TcpListener::bind(format!("127.0.0.1:{}", &port)).await?; | ||||
| println!("online as server at: {}:{}", listener.local_addr()?.ip(), port); | |||||
| println!( | |||||
| "online as server at: {}:{}", | |||||
| listener.local_addr()?.ip(), | |||||
| port | |||||
| ); | |||||
| let mut incoming = listener.incoming(); | let mut incoming = listener.incoming(); | ||||
| while let Some(stream) = incoming.next().await { | while let Some(stream) = incoming.next().await { | ||||
| @@ -33,7 +34,10 @@ pub async fn server(port: u16) -> Result<()> { | |||||
| let (read, write) = stream.split(); | let (read, write) = stream.split(); | ||||
| let stream_id = Uuid::new_v4(); | let stream_id = Uuid::new_v4(); | ||||
| WRITE_STREAMS.lock().expect("could not aqcuire lock").insert(stream_id.clone(), write); | |||||
| WRITE_STREAMS | |||||
| .lock() | |||||
| .expect("could not aqcuire lock") | |||||
| .insert(stream_id.clone(), write); | |||||
| task::spawn(handle_stream(read, stream_id)); | task::spawn(handle_stream(read, stream_id)); | ||||
| } | } | ||||
| @@ -41,53 +45,30 @@ pub async fn server(port: u16) -> Result<()> { | |||||
| } | } | ||||
| async fn handle_stream(mut stream: ReadHalf<TcpStream>, stream_id: Uuid) -> Result<()> { | async fn handle_stream(mut stream: ReadHalf<TcpStream>, stream_id: Uuid) -> Result<()> { | ||||
| loop { | |||||
| let packet = match Packet::read(&mut stream).await { | |||||
| Ok(packet) => packet, | |||||
| Err(err) => { | |||||
| println!("error reading packet: {:?}", err); | |||||
| return Ok(()); | |||||
| } | |||||
| }; | |||||
| let packet = if let Some(packet) = packet { | |||||
| println!("got packet"); | |||||
| packet | |||||
| } else { | |||||
| break; | |||||
| }; | |||||
| match packet.packet_type { | |||||
| PacketType::Message => { | |||||
| let msg = Message::from_packet(packet)?; | |||||
| println!("{:?}", msg); | |||||
| task::spawn(relay_packet(msg)); | |||||
| } | |||||
| PacketType::Join => { | |||||
| let join = Join::from_packet(packet)?; | |||||
| println!("{:?}", join); | |||||
| task::spawn(relay_packet(join)); | |||||
| } | |||||
| } | |||||
| println!("packet processed"); | |||||
| } | |||||
| loop {} | |||||
| println!("disconnecting"); | println!("disconnecting"); | ||||
| WRITE_STREAMS.lock().expect("failed to aqcuire lock").remove(&stream_id); | |||||
| WRITE_STREAMS | |||||
| .lock() | |||||
| .expect("failed to aqcuire lock") | |||||
| .remove(&stream_id); | |||||
| Ok(()) | Ok(()) | ||||
| } | } | ||||
| async fn relay_packet<T: Clone + Sendable>(packet: T) -> Result<()> { | |||||
| /*async fn relay_packet<T: Clone + Sendable>(packet: T) -> Result<()> { | |||||
| let mut locked_write_streams = WRITE_STREAMS.lock().expect("failed to aqcuire lock"); | let mut locked_write_streams = WRITE_STREAMS.lock().expect("failed to aqcuire lock"); | ||||
| let stream = futures::stream::iter(locked_write_streams.iter_mut()); | let stream = futures::stream::iter(locked_write_streams.iter_mut()); | ||||
| let packet = &packet; | let packet = &packet; | ||||
| stream.for_each_concurrent(None, |(_, mut stream)| async move { | stream.for_each_concurrent(None, |(_, mut stream)| async move { | ||||
| let packet = packet.clone().to_packet().expect("failed to convert to packet"); | |||||
| let packet = packet | |||||
| .clone() | |||||
| .to_packet() | |||||
| .expect("failed to convert to packet"); | |||||
| // in case any of the writes fail just ignore them | // in case any of the writes fail just ignore them | ||||
| let _ = packet.write(&mut stream); | let _ = packet.write(&mut stream); | ||||
| }); | }); | ||||
| Ok(()) | Ok(()) | ||||
| } | } | ||||
| */ | |||||