128 lines
4.0 KiB
Rust
128 lines
4.0 KiB
Rust
use libpso::crypto::{PSOCipher, NullCipher};
|
|
use libpso::{PSOPacket, PacketParseError};
|
|
|
|
use crate::common::serverstate::{ServerState, SendServerPacket, RecvServerPacket, OnConnect, ClientId};
|
|
use crate::common::network::{recv_packet, PacketNetworkError};
|
|
|
|
use std::net;
|
|
use std::io::{Read, Write};
|
|
use mio::tcp::TcpStream;
|
|
use mio::{Poll, Events, Token, Ready, PollOpt};
|
|
use mio_extras::channel::Sender;
|
|
|
|
pub struct Client<S, R> {
|
|
pub id: ClientId,
|
|
running: bool,
|
|
pub socket: mio::tcp::TcpStream,
|
|
cipher_in: Box<dyn PSOCipher + Send>,
|
|
cipher_out: Box<dyn PSOCipher + Send>,
|
|
recv_buffer: Vec<u8>,
|
|
incoming_data: Vec<u8>,
|
|
send_buffer: Vec<u8>,
|
|
_s: std::marker::PhantomData<S>,
|
|
_r: std::marker::PhantomData<R>,
|
|
}
|
|
|
|
impl<S, R> Client<S, R> where
|
|
S: SendServerPacket + std::fmt::Debug,
|
|
R: RecvServerPacket + std::fmt::Debug,
|
|
{
|
|
pub fn new(id: ClientId, socket: mio::tcp::TcpStream) -> Client<S, R>
|
|
{
|
|
Client {
|
|
id: id,
|
|
running: true,
|
|
socket: socket,
|
|
cipher_in: Box::new(NullCipher {}),
|
|
cipher_out: Box::new(NullCipher {}),
|
|
recv_buffer: Vec::with_capacity(32),
|
|
incoming_data: Vec::new(),
|
|
send_buffer: Vec::new(),
|
|
_s: std::marker::PhantomData,
|
|
_r: std::marker::PhantomData,
|
|
}
|
|
}
|
|
|
|
pub fn set_cipher(&mut self, cin: Box<dyn PSOCipher + Send>, out: Box<dyn PSOCipher + Send>) {
|
|
self.cipher_in = cin;
|
|
self.cipher_out = out;
|
|
}
|
|
|
|
pub fn send_data(&mut self) {
|
|
if self.send_buffer.len() == 0 {
|
|
return;
|
|
}
|
|
match self.socket.write(&self.send_buffer) {
|
|
Ok(len) => {
|
|
if len == 0 {
|
|
self.running = false;
|
|
}
|
|
self.send_buffer.drain(..len);
|
|
},
|
|
Err(err) => {
|
|
println!("[client] error sending data to {:?}: {:?}", self.socket, err);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn read_data_into_buffer(&mut self) -> Result<(), PacketNetworkError> {
|
|
let mut new_data = [0u8; 0x8000];
|
|
let len = self.socket.read(&mut new_data)?;
|
|
if len == 0 {
|
|
return Err(PacketNetworkError::ClientDisconnected);
|
|
}
|
|
|
|
self.recv_buffer.extend_from_slice(&mut new_data[..len]);
|
|
|
|
let block_chunk_len = self.recv_buffer.len() / self.cipher_in.block_size() * self.cipher_in.block_size();
|
|
let buf = self.recv_buffer.drain(..block_chunk_len).collect();
|
|
let mut dec_buf = self.cipher_in.decrypt(&buf)?;
|
|
self.incoming_data.append(&mut dec_buf);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn read_pkts(&mut self) -> Result<Vec<R>, PacketNetworkError> {
|
|
self.read_data_into_buffer()?;
|
|
let mut result = Vec::new();
|
|
|
|
loop {
|
|
if self.incoming_data.len() < 2 {
|
|
break;
|
|
}
|
|
let pkt_size = u16::from_le_bytes([self.incoming_data[0], self.incoming_data[1]]) as usize;
|
|
let mut pkt_len = pkt_size;
|
|
while pkt_len % self.cipher_in.block_size() != 0 {
|
|
pkt_len += 1;
|
|
}
|
|
|
|
if pkt_len > self.incoming_data.len() {
|
|
break;
|
|
}
|
|
|
|
let pkt_data = self.incoming_data.drain(..pkt_len).collect::<Vec<_>>();
|
|
|
|
println!("[recv: buf] {:?}", pkt_data);
|
|
let pkt = R::from_bytes(&pkt_data[..pkt_size])
|
|
.map_err(|err| -> PacketNetworkError { err.into() })?;
|
|
|
|
println!("[recv] {:?}", pkt);
|
|
result.push(pkt);
|
|
}
|
|
Ok(result)
|
|
}
|
|
|
|
pub fn send_pkt(&mut self, pkt: S) {
|
|
println!("[send] {:?}", pkt);
|
|
let buf = pkt.as_bytes();
|
|
if buf.len() < 1024*2 {
|
|
println!("[send: buf] {:?}", buf);
|
|
}
|
|
else {
|
|
println!("[send: buf] [...large buffer...]");
|
|
}
|
|
let mut cbuf = self.cipher_out.encrypt(&buf).unwrap();
|
|
self.send_buffer.append(&mut cbuf);
|
|
self.send_data();
|
|
}
|
|
}
|