Переглянути джерело

working packet formatting

master
Isabelle L. 5 роки тому
джерело
коміт
76612ae685
2 змінених файлів з 85 додано та 27 видалено
  1. +16
    -2
      src/lib.rs
  2. +69
    -25
      src/packet.rs

+ 16
- 2
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));*/


+ 69
- 25
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<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();

// 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<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)]
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,
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<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>;

fn try_into(self) -> crate::Result<Packet> {
let packet_contents: Vec<u8> = serde_json::to_string(&self)?.into_bytes();
let packet_type = PacketType::NewMessage;
let packet_type = PacketType::Message;
Ok(Packet {
packet_type,
packet_contents,


Завантаження…
Відмінити
Зберегти