use crate::proto::*;
use crate::MumbleMessage;
use anyhow::bail;
use bytes::{Buf, BufMut, BytesMut};
use prost::Message;
use tokio_util::codec::{Decoder, Encoder};
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<Option<Self::Item>, 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<MumbleMessage> = 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)?,
});
}
2 => {
bail!("The server should never send Authenticate")
}
3 => {
mumble_message = Some(MumbleMessage::Ping {
data: Ping::decode(message_data)?,
});
}
4 => {
mumble_message = Some(MumbleMessage::Reject {
data: Reject::decode(message_data)?,
});
}
5 => {
mumble_message = Some(MumbleMessage::ServerSync {
data: ServerSync::decode(message_data)?,
});
}
6 => {
mumble_message = Some(MumbleMessage::ChannelRemove {
data: ChannelRemove::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)?,
});
}
10 => {
mumble_message = Some(MumbleMessage::BanList {
data: BanList::decode(message_data)?,
});
}
11 => {
mumble_message = Some(MumbleMessage::TextMessage {
data: TextMessage::decode(message_data)?,
});
}
12 => {
mumble_message = Some(MumbleMessage::PermissionDenied {
data: PermissionDenied::decode(message_data)?,
});
}
13 => {
mumble_message = Some(MumbleMessage::Acl {
data: Acl::decode(message_data)?,
});
}
14 => {
mumble_message = Some(MumbleMessage::QueryUsers {
data: QueryUsers::decode(message_data)?,
});
}
15 => {
mumble_message = Some(MumbleMessage::CryptSetup {
data: CryptSetup::decode(message_data)?,
});
}
16 => {
mumble_message = Some(MumbleMessage::ContextActionModify {
data: ContextActionModify::decode(message_data)?,
});
}
17 => {
mumble_message = Some(MumbleMessage::ContextAction {
data: ContextAction::decode(message_data)?,
});
}
18 => {
mumble_message = Some(MumbleMessage::UserList {
data: UserList::decode(message_data)?,
});
}
19 => {
mumble_message = Some(MumbleMessage::VoiceTarget {
data: VoiceTarget::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)?,
});
}
22 => {
mumble_message = Some(MumbleMessage::UserStats {
data: UserStats::decode(message_data)?,
});
}
23 => {
mumble_message = Some(MumbleMessage::RequestBlob {
data: RequestBlob::decode(message_data)?,
});
}
24 => {
mumble_message = Some(MumbleMessage::ServerConfig {
data: ServerConfig::decode(message_data)?,
});
}
25 => {
mumble_message = Some(MumbleMessage::SuggestConfig {
data: SuggestConfig::decode(message_data)?,
});
}
_ => {
eprintln!("Unknown message type {:?}", message_type);
}
}
src.advance(message_length + 6);
Ok(mumble_message)
}
}
impl Encoder<MumbleMessage> 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(())
}
}