|
@ -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,30 +42,46 @@ impl<P: ServerPacket + std::fmt::Debug, E: std::fmt::Debug> Client<P, E> { |
|
|
client
|
|
|
client
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
fn send(&mut self, pkt: &dyn PSOPacket) {
|
|
|
|
|
|
match send_packet(&mut self.socket, &mut *self.cipher_out, pkt) {
|
|
|
|
|
|
Ok(_) => {
|
|
|
|
|
|
println!("[patch] send ({:?}): {:?}", self.socket, pkt);
|
|
|
|
|
|
|
|
|
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) => {
|
|
|
Err(err) => {
|
|
|
println!("[patch] error sending packet to {:?}: {:?}", self.socket, err);
|
|
|
|
|
|
self.running = false;
|
|
|
|
|
|
|
|
|
println!("[client] error sending data to {:?}: {:?}", self.socket, err);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
pub fn io_loop(mut self) {
|
|
|
|
|
|
let poll = mio::Poll::new().unwrap();
|
|
|
|
|
|
poll.register(&self.socket, Token(0), Ready::readable(), PollOpt::edge()).unwrap();
|
|
|
|
|
|
|
|
|
// TODO: this may need to pad to 8 bytes for bb cipher
|
|
|
|
|
|
fn send(&mut self, pkt: &dyn PSOPacket) {
|
|
|
|
|
|
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) {
|
|
|
|
|
|
if event.readiness().is_writable() {
|
|
|
|
|
|
self.send_data();
|
|
|
|
|
|
}
|
|
|
|
|
|
if event.readiness().is_readable() {
|
|
|
loop {
|
|
|
loop {
|
|
|
let pkt = recv_packet(&mut self.socket, &mut *self.cipher_in)
|
|
|
let pkt = recv_packet(&mut self.socket, &mut *self.cipher_in)
|
|
|
.and_then(|pkt| {
|
|
|
.and_then(|pkt| {
|
|
@ -79,6 +98,10 @@ impl<P: ServerPacket + std::fmt::Debug, E: std::fmt::Debug> Client<P, E> { |
|
|
},
|
|
|
},
|
|
|
Err(err) => {
|
|
|
Err(err) => {
|
|
|
println!("error recv-ing packet with {:?}: {:?}", self.socket, 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;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -86,6 +109,6 @@ impl<P: ServerPacket + std::fmt::Debug, E: std::fmt::Debug> Client<P, E> { |
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|