1use std::io;
4use std::io::Cursor;
5use std::marker::PhantomData;
6
7use bytes::Buf;
8use bytes::BufMut;
9use bytes::Bytes;
10use bytes::BytesMut;
11use protobuf::Error as ProtobufError;
12use protobuf::Message;
13
14use crate::voice::Clientbound;
15use crate::voice::Serverbound;
16use crate::voice::VoiceCodec;
17use crate::voice::VoicePacket;
18use crate::voice::VoicePacketDst;
19
20#[allow(renamed_and_removed_lints)] #[allow(missing_docs)] pub mod msgs {
24 pub mod id {
26 pub use super::super::generated_id::*;
27 }
28
29 include!(concat!(env!("OUT_DIR"), "/proto/mod.rs"));
30}
31
32#[derive(Clone, Debug, PartialEq)]
34pub struct RawControlPacket {
35 pub id: u16,
39 pub bytes: Bytes,
41}
42
43#[derive(Debug)]
45pub struct RawControlCodec;
46
47impl RawControlCodec {
48 pub fn new() -> Self {
50 Default::default()
51 }
52}
53
54impl Default for RawControlCodec {
55 fn default() -> Self {
56 RawControlCodec
57 }
58}
59
60impl RawControlCodec {
61 fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<RawControlPacket>, io::Error> {
62 let buf_len = buf.len();
63 if buf_len >= 6 {
64 let mut buf = Cursor::new(buf);
65 let id = buf.get_u16();
66 let len = buf.get_u32() as usize;
67 if len > 0x7f_ffff {
68 Err(io::Error::new(io::ErrorKind::Other, "packet too long"))
69 } else if buf_len >= 6 + len {
70 let mut bytes = buf.into_inner().split_to(6 + len);
71 bytes.advance(6);
72 let bytes = bytes.freeze();
73 Ok(Some(RawControlPacket { id, bytes }))
74 } else {
75 Ok(None)
76 }
77 } else {
78 Ok(None)
79 }
80 }
81}
82
83#[cfg(feature = "tokio-codec")]
84impl tokio_util::codec::Decoder for RawControlCodec {
85 type Item = RawControlPacket;
86 type Error = io::Error;
87
88 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
89 self.decode(src)
90 }
91}
92
93#[cfg(feature = "asynchronous-codec")]
94impl asynchronous_codec::Decoder for RawControlCodec {
95 type Item = RawControlPacket;
96 type Error = io::Error;
97
98 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
99 self.decode(src)
100 }
101}
102
103impl RawControlCodec {
104 fn encode(&mut self, item: RawControlPacket, dst: &mut BytesMut) -> Result<(), io::Error> {
105 let id = item.id;
106 let bytes = &item.bytes;
107 let len = bytes.len();
108 dst.reserve(6 + len);
109 dst.put_u16(id);
110 dst.put_u32(len as u32);
111 dst.put_slice(bytes);
112 Ok(())
113 }
114}
115
116#[cfg(feature = "tokio-codec")]
117impl tokio_util::codec::Encoder<RawControlPacket> for RawControlCodec {
118 type Error = io::Error;
119
120 fn encode(&mut self, item: RawControlPacket, dst: &mut BytesMut) -> Result<(), io::Error> {
121 self.encode(item, dst)
122 }
123}
124
125#[cfg(feature = "asynchronous-codec")]
126impl asynchronous_codec::Encoder for RawControlCodec {
127 type Item = RawControlPacket;
128 type Error = io::Error;
129
130 fn encode(&mut self, item: RawControlPacket, dst: &mut BytesMut) -> Result<(), io::Error> {
131 self.encode(item, dst)
132 }
133}
134
135#[derive(Debug)]
141pub struct ControlCodec<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> {
142 inner: RawControlCodec,
143 _encode_dst: PhantomData<EncodeDst>,
144 _decode_dst: PhantomData<DecodeDst>,
145}
146pub type ServerControlCodec = ControlCodec<Clientbound, Serverbound>;
148pub type ClientControlCodec = ControlCodec<Serverbound, Clientbound>;
150
151impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> ControlCodec<EncodeDst, DecodeDst> {
152 pub fn new() -> Self {
154 Default::default()
155 }
156}
157
158impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> Default
159 for ControlCodec<EncodeDst, DecodeDst>
160{
161 fn default() -> Self {
162 ControlCodec {
163 inner: RawControlCodec::default(),
164 _encode_dst: PhantomData,
165 _decode_dst: PhantomData,
166 }
167 }
168}
169
170impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> ControlCodec<EncodeDst, DecodeDst> {
171 fn decode(
172 &mut self,
173 src: &mut BytesMut,
174 ) -> Result<Option<ControlPacket<DecodeDst>>, io::Error> {
175 Ok(if let Some(raw_packet) = self.inner.decode(src)? {
176 Some(raw_packet.try_into()?)
177 } else {
178 None
179 })
180 }
181}
182
183#[cfg(feature = "tokio-codec")]
184impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> tokio_util::codec::Decoder
185 for ControlCodec<EncodeDst, DecodeDst>
186{
187 type Item = ControlPacket<DecodeDst>;
188 type Error = io::Error;
189
190 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
191 self.decode(src)
192 }
193}
194
195#[cfg(feature = "asynchronous-codec")]
196impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> asynchronous_codec::Decoder
197 for ControlCodec<EncodeDst, DecodeDst>
198{
199 type Item = ControlPacket<DecodeDst>;
200 type Error = io::Error;
201
202 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
203 self.decode(src)
204 }
205}
206
207#[cfg(feature = "tokio-codec")]
208impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst>
209 tokio_util::codec::Encoder<ControlPacket<EncodeDst>> for ControlCodec<EncodeDst, DecodeDst>
210{
211 type Error = io::Error;
212
213 fn encode(
214 &mut self,
215 item: ControlPacket<EncodeDst>,
216 dst: &mut BytesMut,
217 ) -> Result<(), Self::Error> {
218 self.inner.encode(item.into(), dst)
219 }
220}
221
222#[cfg(feature = "asynchronous-codec")]
223impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> asynchronous_codec::Encoder
224 for ControlCodec<EncodeDst, DecodeDst>
225{
226 type Item = ControlPacket<EncodeDst>;
227 type Error = io::Error;
228
229 fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
230 self.inner.encode(item.into(), dst)
231 }
232}
233
234macro_rules! define_packet_mappings {
236 ( @def $id:expr, $name:ident) => {
237 #[allow(dead_code)]
238 #[allow(non_upper_case_globals)]
239 pub const $name: u16 = $id;
240 };
241 ( @rec $id:expr, $(#[$attr:meta])* $head:ident ) => {
242 $(#[$attr])*
243 define_packet_mappings!(@def $id, $head);
244 };
245 ( @rec $id:expr, $(#[$attr:meta])* $head:ident, $( $(#[$attr_tail:meta])* $tail:ident ),* ) => {
246 $(#[$attr])*
247 define_packet_mappings!(@def $id, $head);
248 define_packet_mappings!(@rec $id + 1, $($(#[$attr_tail])* $tail),*);
249 };
250 ( $( $(#[$attrs:meta])* $names:ident ),* ) => {
251 define_packet_mappings!(@rec 0, $($(#[$attrs])* $names),*);
252 };
253}
254
255macro_rules! define_packet_from {
257 ( $Dst:ident UDPTunnel($type:ty) ) => {
258 impl<$Dst: VoicePacketDst> From<VoicePacket<Dst>> for RawControlPacket {
259 fn from(msg: VoicePacket<Dst>) -> Self {
260 let mut buf = BytesMut::new();
261
262 cfg_if::cfg_if! {
263 if #[cfg(feature = "asynchronous-codec")] {
264 use asynchronous_codec::Encoder as _;
265 } else {
266 use tokio_util::codec::Encoder as _;
267 }
268 }
269
270 VoiceCodec::<Dst, Dst>::default()
271 .encode(msg, &mut buf)
272 .expect("VoiceEncoder is infallible");
273
274 Self {
275 id: msgs::id::UDPTunnel,
276 bytes: buf.freeze(),
277 }
278 }
279 }
280 impl<$Dst: VoicePacketDst> TryFrom<RawControlPacket> for VoicePacket<$Dst> {
281 type Error = io::Error;
282
283 fn try_from(packet: RawControlPacket) -> Result<Self, Self::Error> {
284 if packet.id == msgs::id::UDPTunnel {
285 packet.bytes.try_into()
286 } else {
287 Err(io::Error::new(
288 io::ErrorKind::Other,
289 concat!("expected packet of type ", stringify!(UDPTunnel)),
290 ))
291 }
292 }
293 }
294 impl<$Dst: VoicePacketDst> TryFrom<Bytes> for VoicePacket<$Dst> {
295 type Error = io::Error;
296
297 fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
298 cfg_if::cfg_if! {
299 if #[cfg(feature = "asynchronous-codec")] {
300 use asynchronous_codec::Decoder as _;
301 } else {
302 use tokio_util::codec::Decoder as _;
303 }
304 }
305
306 VoiceCodec::<$Dst, $Dst>::default()
307 .decode(&mut BytesMut::from(bytes.as_ref()))
308 .map(|it| it.expect("VoiceCodec is stateless"))
309 }
310 }
311 impl<$Dst: VoicePacketDst> From<$type> for ControlPacket<$Dst> {
312 fn from(inner: $type) -> Self {
313 ControlPacket::UDPTunnel(Box::new(inner))
314 }
315 }
316 };
317 ( $Dst:ident $name:ident($type:ty) ) => {
318 impl<$Dst: VoicePacketDst> From<$type> for ControlPacket<$Dst> {
319 fn from(inner: $type) -> Self {
320 ControlPacket::$name(Box::new(inner))
321 }
322 }
323 impl From<$type> for RawControlPacket {
324 fn from(msg: $type) -> Self {
325 Self {
326 id: self::msgs::id::$name,
327 bytes: msg.write_to_bytes().unwrap().into(),
328 }
329 }
330 }
331 impl TryFrom<RawControlPacket> for $type {
332 type Error = ProtobufError;
333
334 fn try_from(packet: RawControlPacket) -> Result<Self, Self::Error> {
335 if packet.id == msgs::id::$name {
336 Self::try_from(packet.bytes)
337 } else {
338 Err(io::Error::new(
339 io::ErrorKind::Other,
340 concat!("expected packet of type ", stringify!($name)),
341 ).into())
342 }
343 }
344 }
345 impl TryFrom<&[u8]> for $type {
346 type Error = ProtobufError;
347
348 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
349 Message::parse_from_bytes(bytes)
350 }
351 }
352 impl TryFrom<Bytes> for $type {
353 type Error = ProtobufError;
354
355 fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
356 bytes.as_ref().try_into()
357 }
358 }
359 };
360}
361
362macro_rules! define_packet_enum {
364 ( $Dst:ident $( $(#[$attr:meta])* $name:ident($type:ty) ),* ) => {
365 #[derive(Debug, Clone, PartialEq)]
367 #[allow(clippy::large_enum_variant)]
368 #[non_exhaustive]
369 pub enum ControlPacket<$Dst: VoicePacketDst> {
370 $(
371 #[allow(missing_docs)]
372 $(#[$attr])*
373 $name(Box<$type>),
374 )*
375 Other(RawControlPacket),
377 }
378 impl<Dst: VoicePacketDst> TryFrom<RawControlPacket> for ControlPacket<$Dst> {
379 type Error = ProtobufError;
380
381 fn try_from(packet: RawControlPacket) -> Result<Self, Self::Error> {
382 Ok(match packet.id {
383 $(
384 $(#[$attr])*
385 msgs::id::$name => {
386 ControlPacket::$name(Box::new(packet.bytes.try_into()?))
387 }
388 )*
389 _ => ControlPacket::Other(packet),
390 })
391 }
392 }
393 impl<Dst: VoicePacketDst> From<ControlPacket<$Dst>> for RawControlPacket {
394 fn from(packet: ControlPacket<$Dst>) -> Self {
395 match packet {
396 $(
397 $(#[$attr])*
398 ControlPacket::$name(inner) => (*inner).into(),
399 )*
400 ControlPacket::Other(inner) => inner,
401 }
402 }
403 }
404 impl<Dst: VoicePacketDst> ControlPacket<$Dst> {
405 pub fn name(&self) -> &'static str {
407 match self {
408 $(
409 $(#[$attr])*
410 ControlPacket::$name(_) => stringify!($name),
411 )*
412 ControlPacket::Other(_) => "unknown",
413 }
414 }
415 }
416 };
417}
418
419macro_rules! define_packets {
420 ( < $Dst:ident > $( $(#[$attr:meta])* $name:ident($type:ty), )* ) => {
421 #[allow(missing_docs)]
422 mod generated_id {
423 define_packet_mappings!($($(#[$attr])* $name),*);
424 }
425 define_packet_enum!($Dst $($(#[$attr])* $name($type)),*);
426 $(
427 $(#[$attr])*
428 define_packet_from!($Dst $name($type));
429 )*
430 };
431}
432
433define_packets![
434 <Dst>
435 Version(msgs::Version),
436 UDPTunnel(VoicePacket<Dst>),
437 Authenticate(msgs::Authenticate),
438 Ping(msgs::Ping),
439 Reject(msgs::Reject),
440 ServerSync(msgs::ServerSync),
441 ChannelRemove(msgs::ChannelRemove),
442 ChannelState(msgs::ChannelState),
443 UserRemove(msgs::UserRemove),
444 UserState(msgs::UserState),
445 BanList(msgs::BanList),
446 TextMessage(msgs::TextMessage),
447 PermissionDenied(msgs::PermissionDenied),
448 ACL(msgs::ACL),
449 QueryUsers(msgs::QueryUsers),
450 CryptSetup(msgs::CryptSetup),
451 ContextActionModify(msgs::ContextActionModify),
452 ContextAction(msgs::ContextAction),
453 UserList(msgs::UserList),
454 VoiceTarget(msgs::VoiceTarget),
455 PermissionQuery(msgs::PermissionQuery),
456 CodecVersion(msgs::CodecVersion),
457 UserStats(msgs::UserStats),
458 RequestBlob(msgs::RequestBlob),
459 ServerConfig(msgs::ServerConfig),
460 SuggestConfig(msgs::SuggestConfig),
461 #[cfg(feature = "webrtc-extensions")]
462 WebRTC(msgs::WebRTC),
463 #[cfg(feature = "webrtc-extensions")]
464 IceCandidate(msgs::IceCandidate),
465 #[cfg(feature = "webrtc-extensions")]
466 TalkingState(msgs::TalkingState),
467];