properly handle sending packets when send buffer gets filled

This commit is contained in:
Jake Probst 2019-07-18 22:25:33 -07:00
parent cec6da0d85
commit 61264d9bb1
2 changed files with 54 additions and 41 deletions

View File

@ -2,9 +2,10 @@ use libpso::crypto::{PSOCipher, NullCipher};
use libpso::{PSOPacket, PacketParseError}; use libpso::{PSOPacket, PacketParseError};
use crate::common::serverstate::{ServerState, ServerPacket, OnConnect}; use crate::common::serverstate::{ServerState, ServerPacket, OnConnect};
use crate::common::network::{send_packet, recv_packet}; use crate::common::network::{recv_packet, PacketNetworkError};
use std::net; use std::net;
use std::io::Write;
use mio::tcp::TcpStream; use mio::tcp::TcpStream;
use mio::{Poll, Events, Token, Ready, PollOpt}; use mio::{Poll, Events, Token, Ready, PollOpt};
@ -14,6 +15,7 @@ pub struct Client<P, E> {
cipher_in: Box<dyn PSOCipher>, cipher_in: Box<dyn PSOCipher>,
cipher_out: Box<dyn PSOCipher>, cipher_out: Box<dyn PSOCipher>,
state: Box<dyn ServerState<Packet = P, PacketError = E>>, state: Box<dyn ServerState<Packet = P, PacketError = E>>,
send_buffer: Vec<u8>,
} }
impl<P: ServerPacket + std::fmt::Debug, E: std::fmt::Debug> Client<P, E> { impl<P: ServerPacket + std::fmt::Debug, E: std::fmt::Debug> Client<P, E> {
@ -24,6 +26,7 @@ impl<P: ServerPacket + std::fmt::Debug, E: std::fmt::Debug> Client<P, E> {
cipher_in: Box::new(NullCipher {}), cipher_in: Box::new(NullCipher {}),
cipher_out: Box::new(NullCipher {}), cipher_out: Box::new(NullCipher {}),
state: state, state: state,
send_buffer: Vec::new(),
}; };
for task in client.state.on_connect() { for task in client.state.on_connect() {
@ -39,53 +42,73 @@ impl<P: ServerPacket + std::fmt::Debug, E: std::fmt::Debug> Client<P, E> {
client client
} }
fn send(&mut self, pkt: &dyn PSOPacket) { fn send_data(&mut self) {
match send_packet(&mut self.socket, &mut *self.cipher_out, pkt) { if self.send_buffer.len() == 0 {
Ok(_) => { return;
println!("[patch] send ({:?}): {:?}", self.socket, pkt); }
match self.socket.write(&self.send_buffer) {
Ok(len) => {
if len == 0 {
self.running = false;
}
self.send_buffer.drain(..len);
}, },
Err(err) => { Err(err) => {
println!("[patch] error sending packet to {:?}: {:?}", self.socket, err); println!("[client] error sending data to {:?}: {:?}", self.socket, err);
self.running = false;
} }
} }
} }
pub fn io_loop(mut self) { // TODO: this may need to pad to 8 bytes for bb cipher
let poll = mio::Poll::new().unwrap(); fn send(&mut self, pkt: &dyn PSOPacket) {
poll.register(&self.socket, Token(0), Ready::readable(), PollOpt::edge()).unwrap(); let buf = pkt.as_bytes();
println!("[send]: {:X?}", buf);
let mut cbuf = self.cipher_out.encrypt(&buf).unwrap();
self.send_buffer.append(&mut cbuf);
self.send_data();
}
pub fn io_loop(mut self) {
let poll = Poll::new().unwrap();
poll.register(&self.socket, Token(0), Ready::readable() | Ready::writable(), PollOpt::edge()).unwrap();
let mut events = Events::with_capacity(1024); let mut events = Events::with_capacity(1024);
loop { while self.running {
poll.poll(&mut events, None).unwrap(); poll.poll(&mut events, None).unwrap();
for event in &events{ for event in &events{
println!("event! {:?}", event);
if event.token() == Token(0) { if event.token() == Token(0) {
loop { if event.readiness().is_writable() {
let pkt = recv_packet(&mut self.socket, &mut *self.cipher_in) self.send_data();
.and_then(|pkt| { }
P::from_bytes(&pkt) if event.readiness().is_readable() {
.map_err(|err| err.into()) loop {
}); let pkt = recv_packet(&mut self.socket, &mut *self.cipher_in)
.and_then(|pkt| {
P::from_bytes(&pkt)
.map_err(|err| err.into())
});
match pkt { match pkt {
Ok(pkt) => { Ok(pkt) => {
let response = self.state.handle(&pkt); let response = self.state.handle(&pkt);
for r in response { for r in response {
self.send(&*r); self.send(&*r);
}
},
Err(err) => {
println!("error recv-ing packet with {:?}: {:?}", self.socket, err);
match err {
PacketNetworkError::ClientDisconnected => self.running = false,
_ => println!("error recv-ing packet with {:?}: {:?}", self.socket, err),
}
break;
} }
},
Err(err) => {
println!("error recv-ing packet with {:?}: {:?}", self.socket, err);
break;
} }
} }
} }
} }
} }
} }
} }
} }

View File

@ -1,7 +1,7 @@
use std::net::TcpStream; use std::io::{Read};
use std::io::{Read, Write};
use libpso::crypto::{PSOCipher, CipherError}; use libpso::crypto::{PSOCipher, CipherError};
use libpso::{PSOPacket, PacketParseError}; use libpso::PacketParseError;
#[derive(Debug)] #[derive(Debug)]
pub enum PacketNetworkError { pub enum PacketNetworkError {
@ -71,15 +71,5 @@ pub fn recv_packet<T: Read>(socket: &mut T, cipher: &mut dyn PSOCipher) -> Resul
full_buf.append(&mut dec_size_buf); full_buf.append(&mut dec_size_buf);
full_buf.append(&mut dec_data_buf); full_buf.append(&mut dec_data_buf);
//println!("[recv]: {:X?}", full_buf);
Ok(full_buf) Ok(full_buf)
} }
// TODO: this fails horribly when the send buffer is full
// if it didnt send it all make a mio poll
pub fn send_packet<T: Write>(socket: &mut T, cipher: &mut dyn PSOCipher, pkt: &dyn PSOPacket) -> Result<(), PacketNetworkError> {
let buf = pkt.as_bytes();
//println!("[send]: {:X?}", buf);
let cbuf = cipher.encrypt(&buf)?;
Ok(socket.write_all(&cbuf)?)
}