feat: v0.1.8
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -571,7 +571,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "room-rs"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures-channel",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "room-rs"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
authors = ["Hatter Jiang@Pixelbook <jht5945@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
30
README.md
30
README.md
@@ -25,6 +25,11 @@ Enter room:
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
```
|
||||
.enter room-id:<roomid> client-id:<clientid>
|
||||
```
|
||||
|
||||
Exit room:
|
||||
```json
|
||||
{
|
||||
@@ -32,6 +37,11 @@ Exit room:
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
```
|
||||
.exit
|
||||
```
|
||||
|
||||
Destroy room:
|
||||
```json
|
||||
{
|
||||
@@ -39,6 +49,11 @@ Destroy room:
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
```
|
||||
.destroy
|
||||
```
|
||||
|
||||
List room peers:
|
||||
```json
|
||||
{
|
||||
@@ -46,6 +61,11 @@ List room peers:
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
```
|
||||
.list-peers
|
||||
```
|
||||
|
||||
Broadcast room message:
|
||||
```json
|
||||
{
|
||||
@@ -54,6 +74,11 @@ Broadcast room message:
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
```
|
||||
.broadcast data:<message>
|
||||
```
|
||||
|
||||
Send room peer message:
|
||||
```json
|
||||
{
|
||||
@@ -63,6 +88,11 @@ Send room peer message:
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
```
|
||||
.peer peer-id:<peerclientid> data:<message>
|
||||
```
|
||||
|
||||
Test with command line:
|
||||
> WebSocket cat: https://www.npmjs.com/package/wscat
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ fn handle_text_message(handle_context: &mut HandleContext, tx: &Tx, addr: Socket
|
||||
}
|
||||
}
|
||||
|
||||
let room_message = match serde_json::from_str::<RoomMessage>(&msg) {
|
||||
let room_message = match RoomMessage::parse(&msg) {
|
||||
Ok(room_message) => room_message,
|
||||
Err(e) => {
|
||||
warning!("Parse message: from: {:?} - {:?}, failed: {}", handle_context.room_id, handle_context.client_id, e);
|
||||
|
||||
126
src/msg.rs
126
src/msg.rs
@@ -1,7 +1,9 @@
|
||||
use rust_util::XResult;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Tx, TxSendMessage};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum RoomMessageType {
|
||||
#[serde(rename = "Enter")]
|
||||
CreateOrEnter,
|
||||
@@ -39,6 +41,21 @@ pub struct RoomMessage {
|
||||
pub data: Option<String>,
|
||||
}
|
||||
|
||||
impl RoomMessage {
|
||||
pub fn parse(msg: &str) -> XResult<Self> {
|
||||
if let Ok(room_message) = serde_json::from_str::<RoomMessage>(msg) {
|
||||
return Ok(room_message);
|
||||
}
|
||||
if msg.starts_with('.') {
|
||||
let msg_parts = parse_message_parts(msg);
|
||||
if !msg_parts.is_empty() {
|
||||
return parse_message_parts_to_room_message(&msg_parts);
|
||||
}
|
||||
}
|
||||
simple_error!("Not valid room message.")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RoomMessageDown {
|
||||
@@ -138,3 +155,110 @@ impl RoomMessageDown {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_message_parts_to_room_message(msg_parts: &[String]) -> XResult<RoomMessage> {
|
||||
let room_message_type = get_room_message_type(&msg_parts[0])?;
|
||||
let mut message_id = None;
|
||||
let mut room_id = None;
|
||||
let mut client_id = None;
|
||||
let mut peer_id = None;
|
||||
let mut data = None;
|
||||
|
||||
msg_parts.iter().skip(1).for_each(|part| {
|
||||
let before_colon = part.chars().take_while(|c| *c != ':').collect::<String>();
|
||||
let after_colon = part.chars().skip_while(|c| *c != ':').skip(1).collect::<String>();
|
||||
match before_colon.as_str() {
|
||||
"message_id" | "message-id" => { message_id = Some(after_colon); }
|
||||
"room_id" | "room-id" => { room_id = Some(after_colon); }
|
||||
"client_id" | "client-id" => { client_id = Some(after_colon); }
|
||||
"peer_id" | "peer-id" => { peer_id = Some(after_colon); }
|
||||
"data" => { data = Some(after_colon); }
|
||||
_ => debugging!("Unknown key: {}", before_colon),
|
||||
}
|
||||
});
|
||||
|
||||
Ok(RoomMessage {
|
||||
r#type: room_message_type,
|
||||
message_id,
|
||||
room_id,
|
||||
client_id,
|
||||
peer_id,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_room_message_type(first_part: &str) -> XResult<RoomMessageType> {
|
||||
let room_message_type = match first_part {
|
||||
"create-or-enter" | "enter" => RoomMessageType::CreateOrEnter,
|
||||
"exit" => RoomMessageType::Exit,
|
||||
"destroy" => RoomMessageType::Destroy,
|
||||
"listpeers" | "list-peers" => RoomMessageType::ListPeers,
|
||||
"broadcast" => RoomMessageType::Broadcast,
|
||||
"peer" => RoomMessageType::Peer,
|
||||
_ => return simple_error!("Unknown message type: {}", first_part),
|
||||
};
|
||||
Ok(room_message_type)
|
||||
}
|
||||
|
||||
fn parse_message_parts(msg: &str) -> Vec<String> {
|
||||
let mut msg_parts = vec![];
|
||||
let mut in_quote = false;
|
||||
let mut is_back_slash = false;
|
||||
let mut last_part = vec![];
|
||||
for c in msg.chars().skip(1) {
|
||||
if is_back_slash {
|
||||
last_part.push(c);
|
||||
is_back_slash = false;
|
||||
continue;
|
||||
}
|
||||
match c {
|
||||
' ' if in_quote => {
|
||||
last_part.push(c);
|
||||
}
|
||||
' ' => {
|
||||
if !last_part.is_empty() {
|
||||
msg_parts.push(last_part.iter().collect::<String>());
|
||||
last_part.clear();
|
||||
}
|
||||
}
|
||||
'\\' => {
|
||||
is_back_slash = true;
|
||||
}
|
||||
'\'' => {
|
||||
in_quote = !in_quote;
|
||||
}
|
||||
_ => {
|
||||
last_part.push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
if !last_part.is_empty() {
|
||||
msg_parts.push(last_part.iter().collect::<String>());
|
||||
}
|
||||
msg_parts
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_room_message_parse() {
|
||||
let room_message = RoomMessage::parse(".enter").unwrap();
|
||||
assert_eq!(RoomMessageType::CreateOrEnter, room_message.r#type);
|
||||
assert_eq!(None, room_message.message_id);
|
||||
assert_eq!(None, room_message.room_id);
|
||||
assert_eq!(None, room_message.client_id);
|
||||
assert_eq!(None, room_message.peer_id);
|
||||
assert_eq!(None, room_message.data);
|
||||
let room_message = RoomMessage::parse(".enter message-id:123 room-id:'ROOM ID'").unwrap();
|
||||
assert_eq!(RoomMessageType::CreateOrEnter, room_message.r#type);
|
||||
assert_eq!(Some("123".to_string()), room_message.message_id);
|
||||
assert_eq!(Some("ROOM ID".to_string()), room_message.room_id);
|
||||
assert_eq!(None, room_message.client_id);
|
||||
assert_eq!(None, room_message.peer_id);
|
||||
assert_eq!(None, room_message.data);
|
||||
let room_message = RoomMessage::parse(".peer client-id:'CLIENT ID' peer_id:PEER 'data:DATA ---'").unwrap();
|
||||
assert_eq!(RoomMessageType::Peer, room_message.r#type);
|
||||
assert_eq!(None, room_message.message_id);
|
||||
assert_eq!(None, room_message.room_id);
|
||||
assert_eq!(Some("CLIENT ID".to_string()), room_message.client_id);
|
||||
assert_eq!(Some("PEER".to_string()), room_message.peer_id);
|
||||
assert_eq!(Some("DATA ---".to_string()), room_message.data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user