pub mod consts;
#[cfg(feature = "client_base")]
pub mod client;
#[cfg(feature = "server")]
pub mod server;
use std::
{
io::Error,
net::SocketAddr,
};
use tokio::net::UdpSocket;
use wincode::{ SchemaRead, SchemaWrite };
#[cfg(not(feature = "server"))]
use std::time::Duration;
use crate::
{
crypto,
consts::SharedKeys,
};
#[cfg(feature = "client_base")]
use crate::network::voice::client::options;
#[cfg(not(feature = "server"))]
use crate::options as chat_options;
#[derive(SchemaRead, SchemaWrite)]
pub enum VoicePacketCode
{
Hello
{
token: [u8; 32], },
HelloAck,
Audio
{
data: Vec<u8>, username: Option<String>, },
Ping
{
timestamp: u128, },
Pong
{
target_id: usize, timestamp: u128, },
}
#[derive(SchemaRead, SchemaWrite)]
pub struct VoicePacket {
pub id: usize, pub code: VoicePacketCode, pub seq: usize, }
pub async fn send (
socket: &UdpSocket,
id: usize,
code: VoicePacketCode,
#[cfg(feature = "server")] addr: &SocketAddr,
#[cfg(feature = "server")] recipient_id: &usize,
keys: &SharedKeys
) -> Result<usize, Error>
{
let mut packet = VoicePacket
{
id,
code,
seq: 0,
};
#[cfg(feature = "server")]
{
if let Some(mut conn) = server::CONNECTIONS.get_mut(recipient_id) &&
let Some(conn) = conn.0.as_mut()
{
packet.seq = conn.server_seq() + 1;
*conn.server_seq_mut() = packet.seq;
}
}
#[cfg(feature = "client_base")]
{
packet.seq = options::get_seq() + 1;
options::set_seq(packet.seq);
}
let packet_bytes = wincode::serialize(&packet).expect("Encoding packet failed");
#[cfg(feature = "server")]
let encrypted_bytes: Vec<u8>;
#[cfg(not(feature = "server"))]
let mut encrypted_bytes: Vec<u8>;
encrypted_bytes = crypto::encrypt_packet::< { consts::GRID_WIDTH }, { consts::GRID_HEIGHT } >(&packet_bytes, keys);
#[cfg(feature = "client_base")]
{
encrypted_bytes.splice(0..0, id.to_be_bytes());
}
#[cfg(feature = "server")]
{
socket.send_to(&encrypted_bytes, addr).await
}
#[cfg(not(feature = "server"))]
{
socket.send(&encrypted_bytes).await
}
}
pub async fn receive(socket: &UdpSocket) -> Option<(VoicePacket, SocketAddr)> {
let mut buffer = [0u8; 2048];
loop {
#[cfg(feature = "client_base")]
if !options::get_use_voice() { break None; }
let (len, addr) =
{
#[cfg(feature = "server")]
{
match socket.recv_from(&mut buffer).await
{
Ok(result) => result,
Err(_) => continue
}
}
#[cfg(not(feature = "server"))]
{
match tokio::time::timeout(Duration::from_millis(consts::RECV_TIMEOUT), socket.recv_from(&mut buffer)).await
{
Ok(Ok(result)) => result,
_ => continue
}
}
};
let buffer_offset: usize;
#[cfg(feature = "server")]
let sender_id: usize;
let keys =
{
#[cfg(feature = "server")]
{
if len <= 8 { continue; }
let id = match buffer[..8].try_into()
{
Ok(id_be_bytes) => usize::from_be_bytes(id_be_bytes),
Err(_) => continue
};
buffer_offset = 8;
sender_id = id;
match server::find_key(&id)
{
Some(k) => k,
None => continue
}
}
#[cfg(not(feature = "server"))]
{
buffer_offset = 0;
chat_options::get_keys().unwrap()
}
};
let decrypted_bytes = match crypto::decrypt_packet::<{ consts::GRID_WIDTH }, { consts::GRID_HEIGHT }>
(buffer[buffer_offset..len].to_vec(), &keys)
{
Some(d) => d,
None => continue
};
let packet = match wincode::deserialize::<VoicePacket>(&decrypted_bytes)
{
Ok(packet) => packet,
Err(_) => continue
};
#[cfg(feature = "server")]
if packet.id != sender_id { continue; }
return Some((packet, addr))
}
}