1use std::fmt::Debug;
4use std::io;
5use std::io::{Cursor, Read};
6use std::marker::PhantomData;
7
8use byteorder::ReadBytesExt;
9use bytes::Buf;
10use bytes::BufMut;
11use bytes::Bytes;
12use bytes::BytesMut;
13
14use super::varint::BufMutExt;
15use super::varint::ReadExt;
16
17#[derive(Clone, Debug, PartialEq)]
19pub enum VoicePacket<Dst: VoicePacketDst> {
20 Ping {
22 timestamp: u64,
25 },
26 Audio {
28 _dst: PhantomData<Dst>,
30 target: u8,
34 session_id: Dst::SessionId,
36 seq_num: u64,
40 payload: VoicePacketPayload,
42 position_info: Option<Bytes>,
48 },
49}
50
51#[derive(Clone, Debug, PartialEq)]
53#[non_exhaustive]
54pub enum VoicePacketPayload {
55 CeltAlpha(Vec<Bytes>),
57 CeltBeta(Vec<Bytes>),
59 Speex(Vec<Bytes>),
61 Opus(Bytes, bool),
63}
64
65#[derive(Debug, Default)]
70pub struct VoiceCodec<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> {
71 _encode_dst: PhantomData<EncodeDst>,
72 _decode_dst: PhantomData<DecodeDst>,
73}
74pub type ServerVoiceCodec = VoiceCodec<Clientbound, Serverbound>;
76pub type ClientVoiceCodec = VoiceCodec<Serverbound, Clientbound>;
78
79impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> VoiceCodec<EncodeDst, DecodeDst> {
80 pub fn new() -> Self {
82 Default::default()
83 }
84}
85
86#[derive(Clone, Debug, Default, PartialEq)]
88pub struct Serverbound;
89#[derive(Clone, Debug, Default, PartialEq)]
91pub struct Clientbound;
92
93mod private {
94 pub trait Sealed {}
95 impl Sealed for super::Serverbound {}
96 impl Sealed for super::Clientbound {}
97}
98
99pub trait VoicePacketDst: private::Sealed + Default + PartialEq {
103 type SessionId: Debug + Clone + PartialEq;
105 fn read_session_id<T: Read + Sized>(buf: &mut T) -> Result<Self::SessionId, io::Error>;
107 fn write_session_id(buf: &mut BytesMut, session_id: Self::SessionId);
109}
110
111impl VoicePacketDst for Serverbound {
112 type SessionId = ();
113
114 fn read_session_id<T: Read + Sized>(_buf: &mut T) -> Result<Self::SessionId, io::Error> {
115 Ok(())
116 }
117
118 fn write_session_id(_buf: &mut BytesMut, _session_id: Self::SessionId) {}
119}
120
121impl VoicePacketDst for Clientbound {
122 type SessionId = u32;
123
124 fn read_session_id<T: Read + Sized>(buf: &mut T) -> Result<Self::SessionId, io::Error> {
125 Ok(buf.read_varint()? as u32)
126 }
127
128 fn write_session_id(buf: &mut BytesMut, session_id: Self::SessionId) {
129 buf.put_varint(u64::from(session_id))
130 }
131}
132
133impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> VoiceCodec<EncodeDst, DecodeDst> {
134 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<VoicePacket<DecodeDst>>, io::Error> {
136 let mut buf = Cursor::new(&src);
137 let header = buf.read_u8()?;
138 let kind = header >> 5;
139 let target = header & 0b11111;
140 let result = if kind == 1 {
141 let timestamp = buf.read_varint()?;
142 src.advance(src.len());
143 VoicePacket::Ping { timestamp }
144 } else {
145 let session_id = DecodeDst::read_session_id(&mut buf)?;
146 let seq_num = buf.read_varint()?;
147 let payload = match kind {
148 0 | 2 | 3 => {
149 let mut frames = Vec::new();
150 let position = buf.position();
151 src.advance(position as usize);
152 loop {
153 if src.is_empty() {
154 return Err(io::ErrorKind::UnexpectedEof.into());
155 }
156 let header = src[0];
157 src.advance(1);
158
159 let len = (header & !0x80) as usize;
160 if src.len() < len {
161 return Err(io::ErrorKind::UnexpectedEof.into());
162 }
163 frames.push(src.split_to(len).freeze());
164 if header & 0x80 != 0x80 {
165 break;
166 }
167 }
168 match kind {
169 0 => VoicePacketPayload::CeltAlpha(frames),
170 2 => VoicePacketPayload::Speex(frames),
171 3 => VoicePacketPayload::CeltBeta(frames),
172 _ => panic!(),
173 }
174 }
175 4 => {
176 let header = buf.read_varint()?;
177 let position = buf.position();
178 src.advance(position as usize);
179 let termination_bit = header & 0x2000 == 0x2000;
180 let len = (header & !0x2000) as usize;
181 if src.len() < len {
182 return Err(io::ErrorKind::UnexpectedEof.into());
183 }
184 let frame = src.split_to(len).freeze();
185 VoicePacketPayload::Opus(frame, termination_bit)
186 }
187 _ => {
188 return Err(io::Error::new(
189 io::ErrorKind::InvalidData,
190 "unknown voice packet type",
191 ));
192 }
193 };
194 let position_info = if src.is_empty() {
195 None
196 } else {
197 Some(src.split().freeze())
198 };
199 VoicePacket::Audio {
200 _dst: PhantomData,
201 target,
202 session_id,
203 seq_num,
204 payload,
205 position_info,
206 }
207 };
208 Ok(Some(result))
209 }
210}
211
212#[cfg(feature = "tokio-codec")]
213impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> tokio_util::codec::Decoder
214 for VoiceCodec<EncodeDst, DecodeDst>
215{
216 type Item = VoicePacket<DecodeDst>;
217 type Error = io::Error; fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
220 self.decode(src)
221 }
222}
223
224#[cfg(feature = "asynchronous-codec")]
225impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> asynchronous_codec::Decoder
226 for VoiceCodec<EncodeDst, DecodeDst>
227{
228 type Item = VoicePacket<DecodeDst>;
229 type Error = io::Error; fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
232 self.decode(src)
233 }
234}
235
236impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> VoiceCodec<EncodeDst, DecodeDst> {
237 fn encode(
238 &mut self,
239 item: VoicePacket<EncodeDst>,
240 dst: &mut BytesMut,
241 ) -> Result<(), io::Error> {
242 match item {
243 VoicePacket::Ping { timestamp } => {
244 dst.reserve(11);
245 dst.put_u8(0x20);
246 dst.put_varint(timestamp);
247 }
248 VoicePacket::Audio {
249 _dst,
250 target,
251 session_id,
252 seq_num,
253 payload,
254 position_info,
255 } => {
256 let kind = match payload {
257 VoicePacketPayload::CeltAlpha(_) => 0,
258 VoicePacketPayload::Speex(_) => 2,
259 VoicePacketPayload::CeltBeta(_) => 3,
260 VoicePacketPayload::Opus(_, _) => 4,
261 };
262 dst.reserve(1 + 10 + 10 );
263 dst.put_u8(kind << 5 | target & 0b11111);
264 EncodeDst::write_session_id(dst, session_id);
265 dst.put_varint(seq_num);
266 match payload {
267 VoicePacketPayload::CeltAlpha(frames)
268 | VoicePacketPayload::Speex(frames)
269 | VoicePacketPayload::CeltBeta(frames) => {
270 dst.reserve(frames.iter().map(|frame| 1 + frame.len()).sum());
271 let mut iter = frames.iter().peekable();
272 while let Some(frame) = iter.next() {
273 let continuation = iter.peek().map(|_| 0x80).unwrap_or(0);
274 dst.put_u8(continuation | (frame.len() as u8));
275 dst.put(frame.as_ref());
276 }
277 }
278 VoicePacketPayload::Opus(frame, termination_bit) => {
279 dst.reserve(10 + frame.len());
280 let term_bit = if termination_bit { 0x2000 } else { 0 };
281 dst.put_varint(term_bit | (frame.len() as u64));
282 dst.put(frame);
283 }
284 };
285 if let Some(bytes) = position_info {
286 dst.extend_from_slice(&bytes);
287 }
288 }
289 }
290 Ok(())
291 }
292}
293
294#[cfg(feature = "tokio-codec")]
295impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst>
296 tokio_util::codec::Encoder<VoicePacket<EncodeDst>> for VoiceCodec<EncodeDst, DecodeDst>
297{
298 type Error = io::Error; fn encode(
301 &mut self,
302 item: VoicePacket<EncodeDst>,
303 dst: &mut BytesMut,
304 ) -> Result<(), Self::Error> {
305 self.encode(item, dst)
306 }
307}
308
309#[cfg(feature = "asynchronous-codec")]
310impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> asynchronous_codec::Encoder
311 for VoiceCodec<EncodeDst, DecodeDst>
312{
313 type Item = VoicePacket<EncodeDst>;
314 type Error = io::Error; fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
317 self.encode(item, dst)
318 }
319}