Jake Probst
6 years ago
5 changed files with 266 additions and 179 deletions
-
91src/common/client.rs
-
3src/common/mod.rs
-
3src/common/network.rs
-
23src/common/serverstate.rs
-
305src/patch/main.rs
@ -0,0 +1,91 @@ |
|||
use libpso::crypto::{PSOCipher, NullCipher};
|
|||
use libpso::{PSOPacket, PacketParseError};
|
|||
|
|||
use crate::common::serverstate::{ServerState, ServerPacket, OnConnect};
|
|||
use crate::common::network::{send_packet, recv_packet};
|
|||
|
|||
use std::net;
|
|||
use mio::tcp::TcpStream;
|
|||
use mio::{Poll, Events, Token, Ready, PollOpt};
|
|||
|
|||
pub struct Client<P, E> {
|
|||
running: bool,
|
|||
socket: mio::tcp::TcpStream,
|
|||
cipher_in: Box<dyn PSOCipher>,
|
|||
cipher_out: Box<dyn PSOCipher>,
|
|||
state: Box<dyn ServerState<Packet = P, PacketError = E>>,
|
|||
}
|
|||
|
|||
impl<P: ServerPacket + std::fmt::Debug, E: std::fmt::Debug> Client<P, E> {
|
|||
pub fn new(socket: net::TcpStream, state: Box<dyn ServerState<Packet = P, PacketError = E>>) -> Client<P, E> {
|
|||
let mut client = Client {
|
|||
running: true,
|
|||
socket: mio::tcp::TcpStream::from_stream(socket).expect("could not convert socket to nonblocking"),
|
|||
cipher_in: Box::new(NullCipher {}),
|
|||
cipher_out: Box::new(NullCipher {}),
|
|||
state: state,
|
|||
};
|
|||
|
|||
for task in client.state.on_connect() {
|
|||
match task {
|
|||
OnConnect::Packet(pkt) => client.send(&*pkt),
|
|||
OnConnect::Cipher((cipher_in, cipher_out)) => {
|
|||
client.cipher_in = cipher_in;
|
|||
client.cipher_out = cipher_out;
|
|||
},
|
|||
}
|
|||
}
|
|||
|
|||
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);
|
|||
},
|
|||
Err(err) => {
|
|||
println!("[patch] error sending packet to {:?}: {:?}", self.socket, err);
|
|||
self.running = false;
|
|||
}
|
|||
}
|
|||
}
|
|||
|
|||
pub fn io_loop(mut self) {
|
|||
let poll = mio::Poll::new().unwrap();
|
|||
poll.register(&self.socket, Token(0), Ready::readable(), PollOpt::edge()).unwrap();
|
|||
|
|||
|
|||
let mut events = Events::with_capacity(1024);
|
|||
loop {
|
|||
poll.poll(&mut events, None).unwrap();
|
|||
|
|||
for event in &events{
|
|||
println!("event! {:?}", event);
|
|||
if event.token() == Token(0) {
|
|||
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 {
|
|||
Ok(pkt) => {
|
|||
let response = self.state.handle(&pkt);
|
|||
for r in response {
|
|||
self.send(&*r);
|
|||
}
|
|||
},
|
|||
Err(err) => {
|
|||
println!("error recv-ing packet with {:?}: {:?}", self.socket, err);
|
|||
break;
|
|||
}
|
|||
}
|
|||
}
|
|||
}
|
|||
}
|
|||
}
|
|||
|
|||
}
|
|||
}
|
@ -1,4 +1,5 @@ |
|||
pub mod cipherkeys;
|
|||
pub mod network;
|
|||
|
|||
pub mod serverstate;
|
|||
pub mod client;
|
|||
|
@ -0,0 +1,23 @@ |
|||
use libpso::{PSOPacket, PacketParseError};
|
|||
use libpso::crypto::PSOCipher;
|
|||
|
|||
|
|||
pub enum OnConnect {
|
|||
Packet(Box<dyn PSOPacket>),
|
|||
Cipher((Box<dyn PSOCipher>, Box<dyn PSOCipher>)),
|
|||
}
|
|||
|
|||
pub trait ServerPacket: Sized {
|
|||
fn from_bytes(data: &Vec<u8>) -> Result<Self, PacketParseError>;
|
|||
}
|
|||
|
|||
pub trait ServerState {
|
|||
type Packet: ServerPacket;
|
|||
type PacketError;
|
|||
|
|||
//fn handle(&mut self, pkt: &Self::Packet) -> Result<Vec<Box<dyn PSOPacket>>, Self::PacketError>;
|
|||
fn on_connect(&mut self) -> Vec<OnConnect>;
|
|||
//fn handle(&mut self, pkt: &Self::Packet) -> Result<Box<dyn Iterator<Item = Box<dyn PSOPacket>>>, Self::PacketError>;
|
|||
fn handle(&mut self, pkt: &Self::Packet) -> Box<dyn Iterator<Item = Box<dyn PSOPacket>>>;
|
|||
}
|
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue