use anyhow::bail; use bytes::{Buf, BufMut, BytesMut}; use prost::Message; use tokio_util::codec::{Decoder, Encoder}; use crate::MumbleMessage; use crate::proto::{Authenticate, Version, Ping, CryptSetup, CodecVersion, ChannelState, PermissionQuery, UserState, ServerSync, ServerConfig, UdpTunnel, UserRemove}; pub struct MumbleTcpCodec {} impl MumbleTcpCodec { pub fn new() -> Self { Self {} } } impl Decoder for MumbleTcpCodec { type Item = MumbleMessage; type Error = anyhow::Error; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { if src.len() < 6 { return Ok(None); } let (message_type, rest) = src.split_at(2); let (message_length, rest) = rest.split_at(4); let message_type = u16::from_be_bytes(message_type.try_into()?) as usize; let message_length = u32::from_be_bytes(message_length.try_into()?) as usize; if message_length+6 > src.len() { src.reserve(message_length+6-src.len()); return Ok(None); } let (message_data, _) = rest.split_at(message_length); let mut mumble_message: Option = None; match message_type { 0 => { mumble_message = Some(MumbleMessage::Version { data: Version::decode(message_data)? }); } 1 => { mumble_message = Some(MumbleMessage::UDPTunnel { data: UdpTunnel::decode(message_data)? }); } 3 => { mumble_message = Some(MumbleMessage::Ping { data: Ping::decode(message_data)? }); }, 5 => { mumble_message = Some(MumbleMessage::ServerSync { data: ServerSync::decode(message_data)? }); } 7 => { mumble_message = Some(MumbleMessage::ChannelState { data: ChannelState::decode(message_data)? }); } 8 => { mumble_message = Some(MumbleMessage::UserRemove { data: UserRemove::decode(message_data)? }); } 9 => { mumble_message = Some(MumbleMessage::UserState { data: UserState::decode(message_data)? }); }, 15 => { mumble_message = Some(MumbleMessage::CryptSetup { data: CryptSetup::decode(message_data)? }); } 20 => { mumble_message = Some(MumbleMessage::PermissionQuery {data: PermissionQuery::decode(message_data)?}); } 21 => { mumble_message = Some(MumbleMessage::CodecVersion {data: CodecVersion::decode(message_data)?}); }, 24 => { mumble_message = Some(MumbleMessage::ServerConfig {data: ServerConfig::decode(message_data)?}); } _ => { eprintln!("Unknown message type {:?}", message_type); } } src.advance(message_length+6); Ok(mumble_message) } } impl Encoder for MumbleTcpCodec { type Error = anyhow::Error; fn encode(&mut self, item: MumbleMessage, dst: &mut BytesMut) -> Result<(), Self::Error> { let mut message = BytesMut::new(); match item { MumbleMessage::Version { data } => { Version::encode(&data, &mut message)?; dst.put_u16(0); } MumbleMessage::Authenticate { data } => { Authenticate::encode(&data, &mut message)?; dst.put_u16(2); }, MumbleMessage::Ping { data } => { Ping::encode(&data, &mut message)?; dst.put_u16(3); } _ => { bail!("Could not encode unknown message") } } dst.put_u32(message.len() as u32); dst.extend_from_slice(&message); Ok(()) } }