Add essential packets
This commit is contained in:
parent
286ace55b4
commit
7458eac931
6 changed files with 190 additions and 55 deletions
|
|
@ -4,13 +4,15 @@ use hex::ToHex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
|
use crate::macros::id_alias;
|
||||||
|
|
||||||
// TODO Use base64 representation instead
|
// TODO Use base64 representation instead
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
||||||
pub struct Id(#[serde(with = "hex")] [u8; 32]);
|
struct Id(#[serde(with = "hex")] [u8; 32]);
|
||||||
|
|
||||||
impl Id {
|
impl Id {
|
||||||
pub fn of(str: &str) -> Self {
|
fn of(str: &str) -> Self {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(str);
|
hasher.update(str);
|
||||||
Self(hasher.finalize().into())
|
Self(hasher.finalize().into())
|
||||||
|
|
@ -22,3 +24,8 @@ impl fmt::Display for Id {
|
||||||
write!(f, "{}", self.0.encode_hex::<String>())
|
write!(f, "{}", self.0.encode_hex::<String>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent misuse of one id as another by only making the aliases public.
|
||||||
|
id_alias!(MessageId);
|
||||||
|
id_alias!(SessionId);
|
||||||
|
id_alias!(Identity);
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,9 @@
|
||||||
mod id;
|
mod id;
|
||||||
mod macros;
|
mod macros;
|
||||||
mod message;
|
mod message;
|
||||||
|
pub mod packets;
|
||||||
use serde::{Deserialize, Serialize};
|
mod user;
|
||||||
|
|
||||||
pub use self::id::*;
|
pub use self::id::*;
|
||||||
use self::macros::packets;
|
|
||||||
pub use self::message::*;
|
pub use self::message::*;
|
||||||
|
pub use self::user::*;
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
pub struct HelloCmd {
|
|
||||||
pub id: Id,
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
#[serde(tag = "type")]
|
|
||||||
pub enum HelloRpl {
|
|
||||||
Success { id: Id },
|
|
||||||
InvalidName { reason: String },
|
|
||||||
NameAlreadyUsed,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a Cmd enum for all commands and a Rpl enum for all replies, as well as
|
|
||||||
// TryFrom impls for the individual command and reply structs.
|
|
||||||
packets! {
|
|
||||||
Hello(HelloCmd, HelloRpl),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
#[serde(tag = "type")]
|
|
||||||
pub enum Packet {
|
|
||||||
Cmd {
|
|
||||||
id: u64,
|
|
||||||
#[serde(flatten)]
|
|
||||||
cmd: Cmd,
|
|
||||||
},
|
|
||||||
Rpl {
|
|
||||||
id: u64,
|
|
||||||
#[serde(flatten)]
|
|
||||||
rpl: Rpl,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,36 @@
|
||||||
|
// Use `pub(crate) use <macro_name>` to make a macro importable from elsewhere.
|
||||||
|
// See https://stackoverflow.com/a/31749071
|
||||||
|
|
||||||
|
macro_rules! id_alias {
|
||||||
|
($name:ident) => {
|
||||||
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
||||||
|
pub struct $name(Id);
|
||||||
|
|
||||||
|
impl $name {
|
||||||
|
pub fn of(str: &str) -> Self {
|
||||||
|
Self(Id::of(str))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for $name {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use id_alias;
|
||||||
|
|
||||||
macro_rules! packets {
|
macro_rules! packets {
|
||||||
( $( $name:ident($cmd:ident, $rpl:ident), )* ) => {
|
(
|
||||||
|
$( cmd $cmdName:ident($cmd:ident, $rpl:ident), )* // Commands with reply
|
||||||
|
$( ntf $ntfName:ident($ntf:ident), )* // Notifications
|
||||||
|
) => {
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(tag = "name", content = "data")]
|
#[serde(tag = "name", content = "data")]
|
||||||
pub enum Cmd {
|
pub enum Cmd {
|
||||||
$( $name($cmd), )*
|
$( $cmdName($cmd), )*
|
||||||
}
|
}
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
|
@ -11,7 +38,7 @@ macro_rules! packets {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
fn try_from(cmd: Cmd) -> Result<Self, Self::Error> {
|
fn try_from(cmd: Cmd) -> Result<Self, Self::Error> {
|
||||||
match cmd {
|
match cmd {
|
||||||
Cmd::$name(val) => Ok(val),
|
Cmd::$cmdName(val) => Ok(val),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +48,7 @@ macro_rules! packets {
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(tag = "name", content = "data")]
|
#[serde(tag = "name", content = "data")]
|
||||||
pub enum Rpl {
|
pub enum Rpl {
|
||||||
$( $name($rpl), )*
|
$( $cmdName($rpl), )*
|
||||||
}
|
}
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
|
@ -29,7 +56,25 @@ macro_rules! packets {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
fn try_from(rpl: Rpl) -> Result<Self, Self::Error> {
|
fn try_from(rpl: Rpl) -> Result<Self, Self::Error> {
|
||||||
match rpl {
|
match rpl {
|
||||||
Rpl::$name(val) => Ok(val),
|
Rpl::$cmdName(val) => Ok(val),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "name", content = "data")]
|
||||||
|
pub enum Ntf {
|
||||||
|
$( $ntfName($ntf), )*
|
||||||
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
impl std::convert::TryFrom<Ntf> for $ntf {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(ntf: Ntf) -> Result<Self, Self::Error> {
|
||||||
|
match ntf {
|
||||||
|
Ntf::$ntfName(val) => Ok(val),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +83,4 @@ macro_rules! packets {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make macro importable from elsewhere
|
|
||||||
// See https://stackoverflow.com/a/31749071
|
|
||||||
pub(crate) use packets;
|
pub(crate) use packets;
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Id;
|
use crate::{ Identity, MessageId};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
pub pred: Option<Id>,
|
pub pred: Option<MessageId>,
|
||||||
pub parent: Option<Id>,
|
pub parent: Option<MessageId>,
|
||||||
pub identity: Id,
|
pub identity: Identity,
|
||||||
pub nick: String,
|
pub nick: String,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Message {
|
impl Message {
|
||||||
pub fn id(&self) -> Id {
|
pub fn id(&self) -> MessageId {
|
||||||
let pred = match self.pred {
|
let pred = match self.pred {
|
||||||
Some(id) => format!("{id}"),
|
Some(id) => format!("{id}"),
|
||||||
None => "none".to_string(),
|
None => "none".to_string(),
|
||||||
|
|
@ -22,9 +22,9 @@ impl Message {
|
||||||
None => "none".to_string(),
|
None => "none".to_string(),
|
||||||
};
|
};
|
||||||
let identity = self.identity;
|
let identity = self.identity;
|
||||||
let nick = Id::of(&self.nick);
|
let nick = MessageId::of(&self.nick);
|
||||||
let content = Id::of(&self.content);
|
let content = MessageId::of(&self.content);
|
||||||
let str = format!("message {pred} {parent} {identity} {nick} {content}");
|
let str = format!("message {pred} {parent} {identity} {nick} {content}");
|
||||||
Id::of(&str)
|
MessageId::of(&str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
110
cove-core/src/packets.rs
Normal file
110
cove-core/src/packets.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::macros::packets;
|
||||||
|
use crate::{Message, MessageId, User};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct HelloCmd {
|
||||||
|
pub nick: String,
|
||||||
|
pub identity: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum HelloRpl {
|
||||||
|
Success {
|
||||||
|
you: User,
|
||||||
|
others: Vec<User>,
|
||||||
|
last_message: MessageId,
|
||||||
|
},
|
||||||
|
NickTooLong,
|
||||||
|
IdentityTooLong,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct NickCmd {
|
||||||
|
pub nick: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum NickRpl {
|
||||||
|
Success { you: User },
|
||||||
|
NickTooLong,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct SendCmd {
|
||||||
|
pub parent: Option<MessageId>,
|
||||||
|
pub nick: Option<String>,
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum SendRpl {
|
||||||
|
Success { message: Message },
|
||||||
|
NickTooLong,
|
||||||
|
ContentTooLong,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct WhoCmd;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct WhoRpl {
|
||||||
|
you: User,
|
||||||
|
others: Vec<User>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct JoinNtf {
|
||||||
|
user: User,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct NickNtf {
|
||||||
|
user: User,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct PartNtf {
|
||||||
|
user: User,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct SendNtf {
|
||||||
|
message: Message,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a Cmd enum for all commands, a Rpl enum for all replies and a Ntf enum
|
||||||
|
// for all notifications, as well as TryFrom impls for the individual structs.
|
||||||
|
packets! {
|
||||||
|
cmd Hello(HelloCmd, HelloRpl),
|
||||||
|
cmd Nick(NickCmd, NickRpl),
|
||||||
|
cmd Send(SendCmd, SendRpl),
|
||||||
|
cmd Who(WhoCmd, WhoRpl),
|
||||||
|
ntf Join(JoinNtf),
|
||||||
|
ntf Nick(NickNtf),
|
||||||
|
ntf Part(PartNtf),
|
||||||
|
ntf Send(SendNtf),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum Packet {
|
||||||
|
Cmd {
|
||||||
|
id: u64,
|
||||||
|
#[serde(flatten)]
|
||||||
|
cmd: Cmd,
|
||||||
|
},
|
||||||
|
Rpl {
|
||||||
|
id: u64,
|
||||||
|
#[serde(flatten)]
|
||||||
|
rpl: Rpl,
|
||||||
|
},
|
||||||
|
Ntf {
|
||||||
|
#[serde(flatten)]
|
||||||
|
ntf: Ntf,
|
||||||
|
},
|
||||||
|
}
|
||||||
10
cove-core/src/user.rs
Normal file
10
cove-core/src/user.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{Identity, SessionId};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct User {
|
||||||
|
nick: String,
|
||||||
|
identity: Identity,
|
||||||
|
sid: SessionId,
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue