109 lines
No EOL
3.8 KiB
Rust
109 lines
No EOL
3.8 KiB
Rust
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<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)? });
|
|
}
|
|
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<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(())
|
|
}
|
|
} |