refactor: migrate net operation to KCP
This commit is contained in:
@@ -1,27 +1,73 @@
|
||||
use std::{
|
||||
io::Error,
|
||||
net::SocketAddr,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use mhy_kcp::Kcp;
|
||||
use prost::Message;
|
||||
use proto::CmdID;
|
||||
use tokio::{io::AsyncWriteExt, net::TcpStream};
|
||||
use tokio::{io::AsyncWrite, net::UdpSocket, sync::Mutex};
|
||||
|
||||
use crate::util;
|
||||
|
||||
use super::{packet::CommandHandler, NetPacket};
|
||||
|
||||
struct RemoteEndPoint {
|
||||
socket: Arc<UdpSocket>,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
pub struct PlayerSession {
|
||||
pub(crate) client_socket: TcpStream,
|
||||
pub token: u32,
|
||||
kcp: Mutex<Kcp<RemoteEndPoint>>,
|
||||
start_time: u64,
|
||||
}
|
||||
|
||||
impl PlayerSession {
|
||||
pub const fn new(client_socket: TcpStream) -> Self {
|
||||
Self { client_socket }
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> Result<()> {
|
||||
loop {
|
||||
let net_packet = NetPacket::read(&mut self.client_socket).await?;
|
||||
Self::on_message(self, net_packet.cmd_type, net_packet.body).await?;
|
||||
pub fn new(socket: Arc<UdpSocket>, addr: SocketAddr, conv: u32, token: u32) -> Self {
|
||||
Self {
|
||||
token,
|
||||
kcp: Mutex::new(Kcp::new(
|
||||
conv,
|
||||
token,
|
||||
false,
|
||||
RemoteEndPoint { socket, addr },
|
||||
)),
|
||||
start_time: util::cur_timestamp_secs(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send(&mut self, body: impl Message + CmdID) -> Result<()> {
|
||||
pub async fn consume(&mut self, buffer: &[u8]) -> Result<()> {
|
||||
{
|
||||
let mut kcp = self.kcp.lock().await;
|
||||
kcp.input(buffer)?;
|
||||
kcp.async_update(self.session_time() as u32).await?;
|
||||
kcp.async_flush().await?;
|
||||
}
|
||||
|
||||
let mut packets = Vec::new();
|
||||
let mut buf = [0; 24756];
|
||||
while let Ok(length) = self.kcp.lock().await.recv(&mut buf) {
|
||||
packets.push(NetPacket::from(&buf[..length]));
|
||||
}
|
||||
|
||||
for packet in packets {
|
||||
Self::on_message(self, packet.cmd_type, packet.body).await?;
|
||||
}
|
||||
|
||||
self.kcp
|
||||
.lock()
|
||||
.await
|
||||
.async_update(self.session_time() as u32)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn send(&self, body: impl Message + CmdID) -> Result<()> {
|
||||
let mut buf = Vec::new();
|
||||
body.encode(&mut buf)?;
|
||||
|
||||
@@ -32,10 +78,46 @@ impl PlayerSession {
|
||||
}
|
||||
.into();
|
||||
|
||||
self.client_socket.write_all(&payload).await?;
|
||||
let mut kcp = self.kcp.lock().await;
|
||||
kcp.send(&payload)?;
|
||||
kcp.async_flush().await?;
|
||||
kcp.async_update(self.session_time() as u32).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn send_raw(&self, payload: NetPacket) -> Result<()> {
|
||||
let mut kcp = self.kcp.lock().await;
|
||||
let payload: Vec<u8> = payload.into();
|
||||
kcp.send(&payload)?;
|
||||
kcp.async_flush().await?;
|
||||
kcp.async_update(self.session_time() as u32).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn session_time(&self) -> u64 {
|
||||
util::cur_timestamp_secs() - self.start_time
|
||||
}
|
||||
}
|
||||
|
||||
// Auto implemented
|
||||
impl CommandHandler for PlayerSession {}
|
||||
|
||||
impl AsyncWrite for RemoteEndPoint {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, Error>> {
|
||||
self.socket.poll_send_to(cx, buf, self.addr)
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user