diff --git a/Cargo.toml b/Cargo.toml index ab361ef..5bca3f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,9 @@ edition = "2018" name = "patch" path = "src/patch/main.rs" +[[bin]] +name = "login" +path = "src/login/main.rs" [dependencies] futures-preview = "=0.3.0-alpha.16" diff --git a/src/login/main.rs b/src/login/main.rs new file mode 100644 index 0000000..9aab57e --- /dev/null +++ b/src/login/main.rs @@ -0,0 +1,110 @@ +use std::net::{TcpListener, SocketAddr, Ipv4Addr}; +use std::net; +use std::thread; + +use mio::{Events, Poll, Token, Ready, PollOpt}; +use rand::{Rng, RngCore}; + +use libpso::{PacketParseError, PSOPacket}; +use libpso::packet::login::*; +use libpso::crypto::{CipherError, PSOCipher, NullCipher}; +use libpso::crypto::bb::PSOBBCipher; + +use elseware::common::{send_packet, recv_packet, PacketNetworkError}; +use elseware::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY}; + +const LOGIN_PORT: u16 = 12000; +const CHARACTER_PORT: u16 = 12001; + + +struct Client { + running: bool, + socket: mio::tcp::TcpStream, + cipher_in: Box, + cipher_out: Box, +} + +impl Client { + fn new(socket: net::TcpStream) -> 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 {}), + } + } + + fn send(&mut self, pkt: &dyn PSOPacket) { + match send_packet(&mut self.socket, &mut *self.cipher_out, pkt) { + Ok(_) => { + println!("[login] send ({:?}): {:?}", self.socket, pkt); + }, + Err(err) => { + println!("[login] error sending packet to {:?}: {:?}", self.socket, err); + self.running = false; + } + } + } +} + +fn client_loop(mut client: Client) { + let poll = mio::Poll::new().unwrap(); + poll.register(&client.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 client.socket, &mut *client.cipher_in); + println!("{:?}", pkt); + + match pkt { + Ok(pkt) => { + //handle_packet(&mut client, pkt).expect("could not handle packet"); + println!("[login] pkt: {:?}", pkt); + }, + Err(err) => { + println!("[login] error recv-ing packet with {:?}: {:?}", client.socket, err); + break; + } + } + } + } + } + } +} + +fn new_client(socket: net::TcpStream) { + let mut client = Client::new(socket); + let mut rng = rand::thread_rng(); + + let mut server_key = [0u8; 48]; + let mut client_key = [0u8; 48]; + rng.fill(&mut server_key[..]); + rng.fill(&mut client_key[..]); + let welcome = LoginWelcome::new(server_key, client_key); + client.send(&welcome); + client.cipher_in = Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)); + client.cipher_out = Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key)); + client_loop(client); +} + +fn main() { + println!("[login] starting server"); + + let listener = TcpListener::bind(&SocketAddr::from((Ipv4Addr::new(0,0,0,0), LOGIN_PORT))).unwrap(); + + while let Ok((socket, addr)) = listener.accept() { + thread::spawn(move || { + println!("[login] accepted connection: {}", addr); + new_client(socket); + }); + } + + + println!("[login] exiting..."); +}