use std::net::{UdpSocket, ToSocketAddrs};
use std::error::Error;
use std::sync::{Arc, Mutex};
use crate::kcp::Kcp;
use bytes::{Bytes, Buf};
use crate::kcp::kcp_config::KcpConfig;
use crate::kcp::Error as KCPError;
pub struct KcpClient{
udp_client:Arc<UdpSocket>,
kcp:Mutex<Kcp>
}
impl KcpClient{
pub fn connect<A:ToSocketAddrs>(addr:A,config:KcpConfig)->Result<KcpClient,Box<dyn Error>>{
let udp_client=Arc::new(UdpSocket::bind("0.0.0.0:0")?);
udp_client.connect(addr)?;
let mut kcp=Kcp::new(0,udp_client.clone());
config.apply_config(&mut kcp);
let kcp=Mutex::new(kcp);
Ok(KcpClient{
udp_client,
kcp
})
}
pub fn init_conv(&self) ->Result<u32,Box<dyn Error+'_>> {
if self.check_conv(){
return Err("conv already set".into());
}
if self.udp_client.send(&[1, 2, 3, 4])? != 4 {
return Err("not send data".into());
}
let mut conv_data = [0; 8];
let len=self.udp_client.recv(&mut conv_data)?;
if len !=8{
return Err("recv data err".into());
}
let mut read=Bytes::from(conv_data.to_vec());
read.get_u32_le();
let conv=read.get_u32_le();
self.set_conv(conv)?;
Ok(conv)
}
pub fn set_conv(&self, conv:u32) ->Result<(),Box<dyn Error+'_>> {
let mut kcp = self.kcp.lock()?;
if kcp.conv()!=0{
return Err("conv already set".into());
}
kcp.set_conv(conv);
Ok(())
}
pub fn check_conv(&self) ->bool{
let res = self.kcp.lock();
if let Ok(kcp)=res {
if kcp.conv() != 0 {
true
} else {
false
}
}else { false }
}
pub fn recv(&self)->Result<Bytes,Box<dyn Error+'_>>{
loop {
let res:Option<Bytes>= {
let mut kcp = self.kcp.lock()?;
let res = kcp.peeksize();
if let Ok(len)=res {
let mut buffer = vec![0; len];
kcp.recv(&mut buffer)?;
Some(Bytes::from(buffer))
}else{
None
}
};
return match res {
Some(res)=>Ok(res),
None=>{
let mut buffer = [0; 4096];
let len = self.udp_client.recv(&mut buffer)?;
let mut kcp = self.kcp.lock()?;
kcp.input(&buffer[..len])?;
let len = kcp.peeksize()?;
return if len > 0 {
let mut buffer = vec![0; len];
kcp.recv(&mut buffer)?;
Ok(Bytes::from(buffer))
} else {
Err(KCPError::RecvQueueEmpty.into())
}
}
};
}
}
#[inline]
fn current() -> u32 {
let time =chrono::Local::now().timestamp_millis() & 0xffffffff;
time as u32
}
pub fn update(&self)->Result<(),Box<dyn Error+'_>>{
let mut kcp= self.kcp.lock()?;
kcp.update(Self::current())?;
Ok(())
}
pub fn send(&self,data:&[u8])->Result<usize,Box<dyn Error+'_>>{
let mut kcp= self.kcp.lock()?;
Ok(kcp.send(data)?)
}
}