pub mod consts;
#[cfg(all(feature = "client_base"))]
pub mod client;
#[cfg(feature = "server")]
pub mod server;
use std::time::Duration;
#[cfg(target_os = "linux")]
use std::
{
mem,
os::fd::AsRawFd,
};
use tokio::net::
{
TcpStream,
tcp::OwnedWriteHalf,
};
use wincode::{ SchemaRead, SchemaWrite };
use crate::
{
consts::{ self as chat_consts, Streams },
crypto::RexPacketStream,
network::
{
self,
EncryptionMode,
SequencedPacket,
},
};
#[derive(SchemaWrite, SchemaRead, Clone)]
pub enum ScreenPacketCode
{
Video { data: Vec<u8> }, Audio { data: Vec<u8> }, Feedback { delay: u32, unsent: u32, shed: bool }, }
#[derive(SchemaWrite, SchemaRead, Clone)]
pub struct ScreenPacket {
pub code: ScreenPacketCode, pub seq: usize, }
impl SequencedPacket for ScreenPacket
{
fn seq(&self) -> usize { self.seq }
fn set_seq(&mut self, seq: usize) { self.seq = seq; }
}
#[cfg(target_os = "linux")]
pub fn tcp_backlog(stream: &TcpStream) -> Option<(u64, Duration)> {
let mut info: libc::tcp_info = unsafe { mem::zeroed() };
let mut length = mem::size_of::<libc::tcp_info>() as libc::socklen_t;
let status = unsafe
{
libc::getsockopt(stream.as_raw_fd(), libc::IPPROTO_TCP, libc::TCP_INFO, (&raw mut info).cast(), &mut length)
};
if status != 0 || (length as usize) < mem::size_of::<libc::tcp_info>() { return None; }
Some((u64::from(info.tcpi_notsent_bytes), Duration::from_micros(u64::from(info.tcpi_rtt.saturating_sub(info.tcpi_min_rtt)))))
}
#[cfg(not(target_os = "linux"))]
pub fn tcp_backlog(_stream: &TcpStream) -> Option<(u64, Duration)>
{
None
}
pub fn cap_socket_buffers(stream: &TcpStream) {
let socket = socket2::SockRef::from(stream);
socket.set_send_buffer_size(consts::SOCKET_BUFFER).ok();
socket.set_recv_buffer_size(consts::SOCKET_BUFFER).ok();
}
pub async fn send_frame (
write_stream: &mut OwnedWriteHalf,
code: ScreenPacketCode,
rex_stream: &mut RexPacketStream,
seq: Option<&mut usize>, )
{
network::send_tcp
(
write_stream,
ScreenPacket
{
code,
seq: 0,
},
EncryptionMode::Stream(rex_stream),
seq,
).await;
}
pub async fn receive_frame
(
streams: &mut Streams<'_>,
rex_stream: &mut RexPacketStream,
seq: &mut usize ) -> Option<ScreenPacketCode>
{
let read = network::read_tcp
(
streams,
EncryptionMode::Stream(rex_stream),
#[cfg(feature = "server")] true,
).await?;
match wincode::config::deserialize::<ScreenPacket, _>(&read.data, chat_consts::PACKET_CONFIG)
{
Ok(packet) =>
{
if packet.seq > *seq || *seq == 0 {
*seq = packet.seq;
} else { return None; }
Some(packet.code)
},
_ => { None } }
}