|
@@ -1,50 +1,84 @@ |
|
|
// namespacing |
|
|
// namespacing |
|
|
|
|
|
use crate::Result; |
|
|
|
|
|
use async_std::net::TcpStream; |
|
|
|
|
|
use async_std::prelude::*; |
|
|
use chrono::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] |
|
|
/// structured [packet type byte][four bytes of packet length][contents of packet] |
|
|
struct NetworkPacket(Vec<u8>); |
|
|
|
|
|
|
|
|
pub struct NetworkPacket(Vec<u8>); |
|
|
|
|
|
|
|
|
impl std::convert::TryInto<NetworkPacket> for Packet { |
|
|
|
|
|
type Error = Box<dyn std::error::Error>; |
|
|
|
|
|
|
|
|
|
|
|
fn try_into(self) -> crate::Result<NetworkPacket> { |
|
|
|
|
|
|
|
|
impl std::convert::Into<NetworkPacket> for Packet { |
|
|
|
|
|
fn into(self) -> NetworkPacket { |
|
|
let mut contents: Vec<u8> = Vec::new(); |
|
|
let mut contents: Vec<u8> = Vec::new(); |
|
|
|
|
|
|
|
|
// packet type byte |
|
|
// packet type byte |
|
|
contents.push(self.packet_type as u8); |
|
|
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 |
|
|
// 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<u8>, |
|
|
packet_contents: Vec<u8>, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Packet { |
|
|
|
|
|
pub fn new(packet_type: PacketType, packet_contents: Vec<u8>) -> Self { |
|
|
|
|
|
Self { |
|
|
|
|
|
packet_type, |
|
|
|
|
|
packet_contents, |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub async fn read(stream: &mut TcpStream) -> Result<Packet> { |
|
|
|
|
|
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<u8> = 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)] |
|
|
#[repr(u8)] |
|
|
enum PacketType { |
|
|
|
|
|
NewMessage = 0, |
|
|
|
|
|
|
|
|
pub enum PacketType { |
|
|
|
|
|
Message = 0, |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl PacketType { |
|
|
|
|
|
pub fn from_u8(packet_type: u8) -> Option<Self> { |
|
|
|
|
|
match packet_type { |
|
|
|
|
|
0 => Some(Self::Message), |
|
|
|
|
|
_ => None, |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#[derive(Serialize)] |
|
|
|
|
|
struct NewMessage { |
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Debug)] |
|
|
|
|
|
pub struct Message { |
|
|
user: String, |
|
|
user: String, |
|
|
contents: String, |
|
|
contents: String, |
|
|
timestamp: i64, |
|
|
timestamp: i64, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
impl NewMessage { |
|
|
|
|
|
|
|
|
impl Message { |
|
|
pub fn new(user: String, contents: String) -> Self { |
|
|
pub fn new(user: String, contents: String) -> Self { |
|
|
let timestamp = Utc::now().timestamp(); |
|
|
let timestamp = Utc::now().timestamp(); |
|
|
Self { |
|
|
Self { |
|
@@ -55,12 +89,22 @@ impl NewMessage { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
impl std::convert::TryInto<Packet> for NewMessage { |
|
|
|
|
|
|
|
|
impl std::convert::TryFrom<Packet> for Message { |
|
|
|
|
|
type Error = Box<dyn std::error::Error>; |
|
|
|
|
|
|
|
|
|
|
|
fn try_from(packet: Packet) -> crate::Result<Self> { |
|
|
|
|
|
let packet_contents = &String::from_utf8(packet.packet_contents)?; |
|
|
|
|
|
let message: Message = serde_json::from_str(packet_contents)?; |
|
|
|
|
|
Ok(message) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl std::convert::TryInto<Packet> for Message { |
|
|
type Error = Box<dyn std::error::Error>; |
|
|
type Error = Box<dyn std::error::Error>; |
|
|
|
|
|
|
|
|
fn try_into(self) -> crate::Result<Packet> { |
|
|
fn try_into(self) -> crate::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::NewMessage; |
|
|
|
|
|
|
|
|
let packet_type = PacketType::Message; |
|
|
Ok(Packet { |
|
|
Ok(Packet { |
|
|
packet_type, |
|
|
packet_type, |
|
|
packet_contents, |
|
|
packet_contents, |
|
|