1use byteorder::ReadBytesExt;
4use bytes::Buf;
5use bytes::BufMut;
6use bytes::Bytes;
7use bytes::BytesMut;
8use std::fmt::Debug;
9use std::io;
10use std::io::{Cursor, Read};
11use std::marker::PhantomData;
12use tokio_util::codec::Decoder;
13use tokio_util::codec::Encoder;
14
15use super::varint::BufMutExt;
16use super::varint::ReadExt;
17
18#[derive(Clone, Debug, PartialEq)]
20pub enum VoicePacket<Dst: VoicePacketDst> {
21 Ping {
23 timestamp: u64,
26 },
27 Audio {
29 _dst: PhantomData<Dst>,
31 target: u8,
35 session_id: Dst::SessionId,
37 seq_num: u64,
41 payload: VoicePacketPayload,
43 position_info: Option<Bytes>,
49 },
50}
51
52#[derive(Clone, Debug, PartialEq)]
54#[non_exhaustive]
55pub enum VoicePacketPayload {
56 CeltAlpha(Vec<Bytes>),
58 CeltBeta(Vec<Bytes>),
60 Speex(Vec<Bytes>),
62 Opus(Bytes, bool),
64}
65
66#[derive(Debug, Default)]
71pub struct VoiceCodec<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> {
72 _encode_dst: PhantomData<EncodeDst>,
73 _decode_dst: PhantomData<DecodeDst>,
74}
75pub type ServerVoiceCodec = VoiceCodec<Clientbound, Serverbound>;
77pub type ClientVoiceCodec = VoiceCodec<Serverbound, Clientbound>;
79
80impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> VoiceCodec<EncodeDst, DecodeDst> {
81 pub fn new() -> Self {
83 Default::default()
84 }
85}
86
87#[derive(Clone, Debug, Default, PartialEq)]
89pub struct Serverbound;
90#[derive(Clone, Debug, Default, PartialEq)]
92pub struct Clientbound;
93
94mod private {
95 pub trait Sealed {}
96 impl Sealed for super::Serverbound {}
97 impl Sealed for super::Clientbound {}
98}
99
100pub trait VoicePacketDst: private::Sealed + Default + PartialEq {
104 type SessionId: Debug + Clone + PartialEq;
106 fn read_session_id<T: Read + Sized>(buf: &mut T) -> Result<Self::SessionId, io::Error>;
108 fn write_session_id(buf: &mut BytesMut, session_id: Self::SessionId);
110}
111
112impl VoicePacketDst for Serverbound {
113 type SessionId = ();
114
115 fn read_session_id<T: Read + Sized>(_buf: &mut T) -> Result<Self::SessionId, io::Error> {
116 Ok(())
117 }
118
119 fn write_session_id(_buf: &mut BytesMut, _session_id: Self::SessionId) {}
120}
121
122impl VoicePacketDst for Clientbound {
123 type SessionId = u32;
124
125 fn read_session_id<T: Read + Sized>(buf: &mut T) -> Result<Self::SessionId, io::Error> {
126 Ok(buf.read_varint()? as u32)
127 }
128
129 fn write_session_id(buf: &mut BytesMut, session_id: Self::SessionId) {
130 buf.put_varint(u64::from(session_id))
131 }
132}
133
134impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> Decoder
135 for VoiceCodec<EncodeDst, DecodeDst>
136{
137 type Item = VoicePacket<DecodeDst>;
138 type Error = io::Error;
139
140 fn decode(&mut self, buf_mut: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
142 let mut buf = Cursor::new(&buf_mut);
143 let header = buf.read_u8()?;
144 let kind = header >> 5;
145 let target = header & 0b11111;
146 let result = if kind == 1 {
147 let timestamp = buf.read_varint()?;
148 buf_mut.advance(buf_mut.len());
149 VoicePacket::Ping { timestamp }
150 } else {
151 let session_id = DecodeDst::read_session_id(&mut buf)?;
152 let seq_num = buf.read_varint()?;
153 let payload = match kind {
154 0 | 2 | 3 => {
155 let mut frames = Vec::new();
156 let position = buf.position();
157 buf_mut.advance(position as usize);
158 loop {
159 if buf_mut.is_empty() {
160 return Err(io::ErrorKind::UnexpectedEof.into());
161 }
162 let header = buf_mut[0];
163 buf_mut.advance(1);
164
165 let len = (header & !0x80) as usize;
166 if buf_mut.len() < len {
167 return Err(io::ErrorKind::UnexpectedEof.into());
168 }
169 frames.push(buf_mut.split_to(len).freeze());
170 if header & 0x80 != 0x80 {
171 break;
172 }
173 }
174 match kind {
175 0 => VoicePacketPayload::CeltAlpha(frames),
176 2 => VoicePacketPayload::Speex(frames),
177 3 => VoicePacketPayload::CeltBeta(frames),
178 _ => panic!(),
179 }
180 }
181 4 => {
182 let header = buf.read_varint()?;
183 let position = buf.position();
184 buf_mut.advance(position as usize);
185 let termination_bit = header & 0x2000 == 0x2000;
186 let len = (header & !0x2000) as usize;
187 if buf_mut.len() < len {
188 return Err(io::ErrorKind::UnexpectedEof.into());
189 }
190 let frame = buf_mut.split_to(len).freeze();
191 VoicePacketPayload::Opus(frame, termination_bit)
192 }
193 _ => {
194 return Err(io::Error::new(
195 io::ErrorKind::InvalidData,
196 "unknown voice packet type",
197 ));
198 }
199 };
200 let position_info = if buf_mut.is_empty() {
201 None
202 } else {
203 Some(buf_mut.split().freeze())
204 };
205 VoicePacket::Audio {
206 _dst: PhantomData,
207 target,
208 session_id,
209 seq_num,
210 payload,
211 position_info,
212 }
213 };
214 Ok(Some(result))
215 }
216}
217
218impl<EncodeDst: VoicePacketDst, DecodeDst: VoicePacketDst> Encoder<VoicePacket<EncodeDst>>
219 for VoiceCodec<EncodeDst, DecodeDst>
220{
221 type Error = io::Error; fn encode(
224 &mut self,
225 item: VoicePacket<EncodeDst>,
226 dst: &mut BytesMut,
227 ) -> Result<(), Self::Error> {
228 match item {
229 VoicePacket::Ping { timestamp } => {
230 dst.reserve(11);
231 dst.put_u8(0x20);
232 dst.put_varint(timestamp);
233 }
234 VoicePacket::Audio {
235 _dst,
236 target,
237 session_id,
238 seq_num,
239 payload,
240 position_info,
241 } => {
242 let kind = match payload {
243 VoicePacketPayload::CeltAlpha(_) => 0,
244 VoicePacketPayload::Speex(_) => 2,
245 VoicePacketPayload::CeltBeta(_) => 3,
246 VoicePacketPayload::Opus(_, _) => 4,
247 };
248 dst.reserve(1 + 10 + 10 );
249 dst.put_u8(kind << 5 | target & 0b11111);
250 EncodeDst::write_session_id(dst, session_id);
251 dst.put_varint(seq_num);
252 match payload {
253 VoicePacketPayload::CeltAlpha(frames)
254 | VoicePacketPayload::Speex(frames)
255 | VoicePacketPayload::CeltBeta(frames) => {
256 dst.reserve(frames.iter().map(|frame| 1 + frame.len()).sum());
257 let mut iter = frames.iter().peekable();
258 while let Some(frame) = iter.next() {
259 let continuation = iter.peek().map(|_| 0x80).unwrap_or(0);
260 dst.put_u8(continuation | (frame.len() as u8));
261 dst.put(frame.as_ref());
262 }
263 }
264 VoicePacketPayload::Opus(frame, termination_bit) => {
265 dst.reserve(10 + frame.len());
266 let term_bit = if termination_bit { 0x2000 } else { 0 };
267 dst.put_varint(term_bit | (frame.len() as u64));
268 dst.put(frame);
269 }
270 };
271 if let Some(bytes) = position_info {
272 dst.extend_from_slice(&bytes);
273 }
274 }
275 }
276 Ok(())
277 }
278}