diff --git a/src/lib.rs b/src/lib.rs index 4ec7f70..669a9cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,9 @@ use async_std::net::TcpListener; use async_std::net::TcpStream; use async_std::prelude::*; +use std::convert::{TryFrom, TryInto}; + +use packet::{Message, Packet, PacketType}; mod packet; @@ -17,9 +20,15 @@ pub async fn server(port: u16) -> Result<()> { while let Some(stream) = incoming.next().await { let mut stream = stream?; - // handle stream println!("new stream from: {}", stream.peer_addr()?.ip()); - stream.write_all(b"hello world").await?; + // handle stream + + // testing + let packet = Packet::read(&mut stream).await?; + let message = match packet.packet_type { + PacketType::Message => Message::try_from(packet), + }; + println!("{:?}", message); } Ok(()) @@ -33,6 +42,11 @@ pub async fn client(port: u16) -> Result<()> { port ); + // testing stuffs + let message: Packet = + Message::new("Isabelle".to_owned(), "Hello Server".to_owned()).try_into()?; + message.write(&mut stream).await?; + /*let mut buf = vec![0u8; 1024]; stream.read(&mut buf).await?; println!("{}", String::from_utf8_lossy(&mut buf));*/ diff --git a/src/packet.rs b/src/packet.rs index 56ac7aa..0524dc8 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,50 +1,84 @@ // namespacing +use crate::Result; +use async_std::net::TcpStream; +use async_std::prelude::*; use chrono::prelude::*; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::convert::TryInto; /// structured [packet type byte][four bytes of packet length][contents of packet] -struct NetworkPacket(Vec); +pub struct NetworkPacket(Vec); -impl std::convert::TryInto for Packet { - type Error = Box; - - fn try_into(self) -> crate::Result { +impl std::convert::Into for Packet { + fn into(self) -> NetworkPacket { let mut contents: Vec = Vec::new(); // packet type byte contents.push(self.packet_type as u8); - // create room for the packet length - (1..5).for_each(|_| contents.push(0x00)); + // 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 - self.packet_contents - .iter() - .for_each(|byte| contents.push(*byte)); - // write the packet len bytes - let packet_length = ((self.packet_contents.len() + 5) as u32).to_le_bytes(); - (1..5).for_each(|i| contents[i] = packet_length[i - 1]); - - Ok(NetworkPacket(contents)) + contents.extend_from_slice(&self.packet_contents); + NetworkPacket(contents) } } -struct Packet { - packet_type: PacketType, +pub struct Packet { + pub packet_type: PacketType, packet_contents: Vec, } +impl Packet { + pub fn new(packet_type: PacketType, packet_contents: Vec) -> Self { + Self { + packet_type, + packet_contents, + } + } + + pub async fn read(stream: &mut TcpStream) -> Result { + let mut info_buf = [0u8; 5]; + stream.read(&mut info_buf).await?; + 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 = vec![0; length]; + stream.read(&mut contents).await?; + + Ok(Packet::new(packet_type, contents)) + } + + pub async fn write(self, stream: &mut TcpStream) -> Result<()> { + let network_packet: NetworkPacket = self.into(); + let _ = stream.write(&network_packet.0).await?; + Ok(()) + } +} + #[repr(u8)] -enum PacketType { - NewMessage = 0, +pub enum PacketType { + Message = 0, +} + +impl PacketType { + pub fn from_u8(packet_type: u8) -> Option { + match packet_type { + 0 => Some(Self::Message), + _ => None, + } + } } -#[derive(Serialize)] -struct NewMessage { +#[derive(Deserialize, Serialize, Debug)] +pub struct Message { user: String, contents: String, timestamp: i64, } -impl NewMessage { +impl Message { pub fn new(user: String, contents: String) -> Self { let timestamp = Utc::now().timestamp(); Self { @@ -55,12 +89,22 @@ impl NewMessage { } } -impl std::convert::TryInto for NewMessage { +impl std::convert::TryFrom for Message { + type Error = Box; + + fn try_from(packet: Packet) -> crate::Result { + let packet_contents = &String::from_utf8(packet.packet_contents)?; + let message: Message = serde_json::from_str(packet_contents)?; + Ok(message) + } +} + +impl std::convert::TryInto for Message { type Error = Box; fn try_into(self) -> crate::Result { let packet_contents: Vec = serde_json::to_string(&self)?.into_bytes(); - let packet_type = PacketType::NewMessage; + let packet_type = PacketType::Message; Ok(Packet { packet_type, packet_contents,