huddle_core/network/
protocol.rs1use serde::{Deserialize, Serialize};
10
11pub const ROOMS_TOPIC: &str = "huddle-rooms-v1";
12pub const ROOM_TOPIC_PREFIX: &str = "huddle-room-";
13
14pub fn room_topic(room_id: &str) -> String {
15 format!("{ROOM_TOPIC_PREFIX}{room_id}")
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct RoomAnnouncement {
22 pub room_id: String,
23 pub name: String,
24 pub encrypted: bool,
25 pub passphrase_salt: Option<Vec<u8>>,
28 pub member_count: u32,
29 pub creator_fingerprint: String,
30 pub announced_at: i64,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
36pub enum RoomMessage {
37 MemberAnnounce {
40 sender_fingerprint: String,
41 wrapped_session_key: Option<String>,
45 },
46 SessionKeyRequest {
49 requester_fingerprint: String,
50 },
51 Encrypted {
53 sender_fingerprint: String,
54 session_id: String,
55 ciphertext_b64: String,
57 },
58 Plain {
60 sender_fingerprint: String,
61 body: String,
62 },
63 MemberLeave {
65 sender_fingerprint: String,
66 },
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn room_announcement_round_trip() {
75 let ann = RoomAnnouncement {
76 room_id: "rid".into(),
77 name: "general".into(),
78 encrypted: true,
79 passphrase_salt: Some(vec![1, 2, 3, 4]),
80 member_count: 3,
81 creator_fingerprint: "creator-fp".into(),
82 announced_at: 100,
83 };
84 let json = serde_json::to_vec(&ann).unwrap();
85 let back: RoomAnnouncement = serde_json::from_slice(&json).unwrap();
86 assert_eq!(back.name, "general");
87 assert_eq!(back.passphrase_salt, Some(vec![1, 2, 3, 4]));
88 }
89
90 #[test]
91 fn room_message_variants_round_trip() {
92 let msgs = vec![
93 RoomMessage::MemberAnnounce {
94 sender_fingerprint: "fp".into(),
95 wrapped_session_key: Some("base64data".into()),
96 },
97 RoomMessage::Plain {
98 sender_fingerprint: "fp".into(),
99 body: "hi".into(),
100 },
101 RoomMessage::Encrypted {
102 sender_fingerprint: "fp".into(),
103 session_id: "sid".into(),
104 ciphertext_b64: "ct".into(),
105 },
106 RoomMessage::SessionKeyRequest {
107 requester_fingerprint: "fp".into(),
108 },
109 RoomMessage::MemberLeave {
110 sender_fingerprint: "fp".into(),
111 },
112 ];
113 for m in msgs {
114 let json = serde_json::to_vec(&m).unwrap();
115 let back: RoomMessage = serde_json::from_slice(&json).unwrap();
116 assert_eq!(format!("{m:?}"), format!("{back:?}"));
117 }
118 }
119
120 #[test]
121 fn room_topic_format() {
122 assert_eq!(room_topic("abc123"), "huddle-room-abc123");
123 }
124}