1use anyhow::{Error, Result, anyhow};
2use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
3use std::{io::Cursor, net::IpAddr};
4use uuid::Uuid;
5
6pub enum MessageData {
15 Broadcast { from: Uuid, data: Vec<u8> },
16 Send { from: Uuid, to: Uuid, data: Vec<u8> },
17 ClientJoined(Uuid),
18 ClientLeft(Uuid),
19}
20
21pub(crate) enum MessageDataInternal {
22 Broadcast(Uuid, Vec<u8>),
23 Send(Uuid, Uuid, Vec<u8>),
24 ServerUuid(Uuid),
25 ClientJoined(Uuid),
26 ClientLeft(Uuid),
27 PromoteToHost(Uuid, IpAddr, u16),
28 NewHost(IpAddr, u16),
29}
30
31impl From<MessageData> for MessageDataInternal {
32 fn from(value: MessageData) -> Self {
33 match value {
34 MessageData::Broadcast {
35 from: sender,
36 data: m,
37 } => MessageDataInternal::Broadcast(sender, m),
38 MessageData::Send {
39 from: sender,
40 to: dst,
41 data: m,
42 } => MessageDataInternal::Send(sender, dst, m),
43 MessageData::ClientJoined(uuid) => MessageDataInternal::ClientJoined(uuid),
44 MessageData::ClientLeft(uuid) => MessageDataInternal::ClientLeft(uuid),
45 }
46 }
47}
48
49const MESSAGE_KIND_BROADCAST: u8 = 0;
50const MESSAGE_KIND_CLIENT_JOINED: u8 = 1;
51const MESSAGE_KIND_SERVER_UUID: u8 = 2;
52const MESSAGE_KIND_SEND: u8 = 3;
53const MESSAGE_KIND_CLIENT_LEFT: u8 = 4;
54const MESSAGE_KIND_PROMOTE_TO_HOST: u8 = 5;
55const MESSAGE_KIND_NEW_HOST: u8 = 6;
56
57impl TryFrom<&[u8]> for MessageDataInternal {
58 type Error = Error;
59
60 fn try_from(value: &[u8]) -> Result<Self> {
61 if value.is_empty() {
64 return Err(anyhow!("empty message, can't deserialize"));
65 }
66 let t = value[0];
67 Ok(match t {
68 MESSAGE_KIND_BROADCAST => {
69 let mut c = Cursor::new(&value[1..17]);
70 let sender = Uuid::from_u128(c.read_u128::<BigEndian>()?);
71 let data = value[17..].to_vec();
72 MessageDataInternal::Broadcast(sender, data)
73 }
74 MESSAGE_KIND_CLIENT_JOINED => {
75 let mut c = Cursor::new(&value[1..17]);
76 let uuid = Uuid::from_u128(c.read_u128::<BigEndian>()?);
77 MessageDataInternal::ClientJoined(uuid)
78 }
79 MESSAGE_KIND_SERVER_UUID => {
80 let mut c = Cursor::new(&value[1..17]);
81 let uuid = Uuid::from_u128(c.read_u128::<BigEndian>()?);
82 MessageDataInternal::ServerUuid(uuid)
83 }
84 MESSAGE_KIND_SEND => {
85 let mut c = Cursor::new(&value[1..33]);
86 let sender = Uuid::from_u128(c.read_u128::<BigEndian>()?);
87 let dst = Uuid::from_u128(c.read_u128::<BigEndian>()?);
88 let data = value[33..].to_vec();
89 MessageDataInternal::Send(sender, dst, data)
90 }
91 MESSAGE_KIND_CLIENT_LEFT => {
92 let mut c = Cursor::new(&value[1..17]);
93 let uuid = Uuid::from_u128(c.read_u128::<BigEndian>()?);
94 MessageDataInternal::ClientLeft(uuid)
95 }
96 MESSAGE_KIND_PROMOTE_TO_HOST => {
97 let mut c = Cursor::new(&value[1..19]);
98 let uuid = Uuid::from_u128(c.read_u128::<BigEndian>()?);
99 let port = c.read_u16::<BigEndian>()?;
100 let rest = &value[19..];
101 let ip: IpAddr = if rest.len() == 16 {
102 let rest: [u8; 16] = rest.try_into()?;
103 rest.into()
104 } else {
105 let rest: [u8; 4] = rest.try_into()?;
106 rest.into()
107 };
108 MessageDataInternal::PromoteToHost(uuid, ip, port)
109 }
110 MESSAGE_KIND_NEW_HOST => {
111 let mut c = Cursor::new(&value[1..3]);
112 let port = c.read_u16::<BigEndian>()?;
113 let rest = &value[3..];
114 let ip: IpAddr = if rest.len() == 16 {
115 let rest: [u8; 16] = rest.try_into()?;
116 rest.into()
117 } else {
118 let rest: [u8; 4] = rest.try_into()?;
119 rest.into()
120 };
121 MessageDataInternal::NewHost(ip, port)
122 }
123 _ => {
124 return Err(anyhow!("message type not recognized"));
125 }
126 })
127 }
128}
129
130impl TryFrom<MessageDataInternal> for Vec<u8> {
131 type Error = Error;
132
133 fn try_from(value: MessageDataInternal) -> Result<Self> {
134 let (t, partial) = match value {
137 MessageDataInternal::Broadcast(sender, m) => {
138 let mut res: Vec<u8> = vec![0; 16];
139 let mut c = Cursor::new(&mut res);
140 c.write_u128::<BigEndian>(sender.as_u128())?;
141 res.extend_from_slice(&m);
142 (MESSAGE_KIND_BROADCAST, res)
143 }
144 MessageDataInternal::ClientJoined(uuid) => {
145 let mut res: Vec<u8> = vec![0; 16];
146 let mut c = Cursor::new(&mut res);
147 c.write_u128::<BigEndian>(uuid.as_u128())?;
148 (MESSAGE_KIND_CLIENT_JOINED, res)
149 }
150 MessageDataInternal::ServerUuid(uuid) => {
151 let mut res: Vec<u8> = vec![0; 16];
152 let mut c = Cursor::new(&mut res);
153 c.write_u128::<BigEndian>(uuid.as_u128())?;
154 (MESSAGE_KIND_SERVER_UUID, res)
155 }
156 MessageDataInternal::Send(sender, dst, m) => {
157 let mut res: Vec<u8> = vec![0; 32];
158 let mut c = Cursor::new(&mut res);
159 c.write_u128::<BigEndian>(sender.as_u128())?;
160 c.write_u128::<BigEndian>(dst.as_u128())?;
161 res.extend_from_slice(&m);
162 (MESSAGE_KIND_SEND, res)
163 }
164 MessageDataInternal::ClientLeft(uuid) => {
165 let mut res: Vec<u8> = vec![0; 16];
166 let mut c = Cursor::new(&mut res);
167 c.write_u128::<BigEndian>(uuid.as_u128())?;
168 (MESSAGE_KIND_CLIENT_LEFT, res)
169 }
170 MessageDataInternal::PromoteToHost(uuid, ip, port) => {
171 let mut res: Vec<u8> = vec![0; 18];
172 let mut c = Cursor::new(&mut res);
173 c.write_u128::<BigEndian>(uuid.as_u128())?;
174 c.write_u16::<BigEndian>(port)?;
175 match ip {
176 IpAddr::V4(v4) => res.extend_from_slice(&v4.octets()),
177 IpAddr::V6(v6) => res.extend_from_slice(&v6.octets()),
178 }
179 (MESSAGE_KIND_PROMOTE_TO_HOST, res)
180 }
181 MessageDataInternal::NewHost(ip, port) => {
182 let mut res: Vec<u8> = vec![0; 2];
183 let mut c = Cursor::new(&mut res);
184 c.write_u16::<BigEndian>(port)?;
185 match ip {
186 IpAddr::V4(v4) => res.extend_from_slice(&v4.octets()),
187 IpAddr::V6(v6) => res.extend_from_slice(&v6.octets()),
188 }
189 (MESSAGE_KIND_NEW_HOST, res)
190 }
191 };
192 let mut res: Vec<u8> = vec![t];
193 res.extend_from_slice(&partial);
194 Ok(res)
195 }
196}
197
198#[cfg(test)]
199mod test {
200 use std::string::FromUtf8Error;
201
202 use super::*;
203
204 struct Msg(String);
205
206 impl From<String> for Msg {
207 fn from(value: String) -> Self {
208 Self(value)
209 }
210 }
211
212 impl TryFrom<&[u8]> for Msg {
213 type Error = FromUtf8Error;
214
215 fn try_from(value: &[u8]) -> std::result::Result<Self, Self::Error> {
216 Ok(Msg(String::from_utf8(value.to_vec())?))
217 }
218 }
219
220 impl TryFrom<Msg> for Vec<u8> {
221 type Error = ();
222
223 fn try_from(value: Msg) -> std::result::Result<Self, Self::Error> {
224 Ok(value.0.into())
225 }
226 }
227
228 #[test]
229 fn test_in_out() {
230 in_out(MessageDataInternal::Broadcast(
231 Uuid::new_v4(),
232 "a".to_string().into(),
233 ));
234 in_out(MessageDataInternal::Send(
235 Uuid::new_v4(),
236 Uuid::new_v4(),
237 "a".to_string().into(),
238 ));
239 in_out(MessageDataInternal::ClientJoined(Uuid::new_v4()));
240 in_out(MessageDataInternal::ClientLeft(Uuid::new_v4()));
241 in_out(MessageDataInternal::ServerUuid(Uuid::new_v4()));
242 in_out(MessageDataInternal::PromoteToHost(
243 Uuid::new_v4(),
244 "127.0.0.1".parse().unwrap(),
245 444,
246 ));
247 in_out(MessageDataInternal::PromoteToHost(
248 Uuid::new_v4(),
249 "::1".parse().unwrap(),
250 444,
251 ));
252 in_out(MessageDataInternal::NewHost(
253 "127.0.0.1".parse().unwrap(),
254 444,
255 ));
256 in_out(MessageDataInternal::NewHost("::1".parse().unwrap(), 444));
257 }
258
259 fn in_out(m: MessageDataInternal) {
260 let v: Vec<u8> = m.try_into().unwrap();
261 let _m: MessageDataInternal = v.as_slice().try_into().unwrap();
262 }
263}