From 825c04d22b081fc26c5b49b4dbf77db7a28533fd Mon Sep 17 00:00:00 2001 From: jake Date: Mon, 4 Nov 2019 20:33:51 -0800 Subject: [PATCH] ship init --- src/ship/ship.rs | 96 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 12 deletions(-) diff --git a/src/ship/ship.rs b/src/ship/ship.rs index b1d813f..e9045b0 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -1,49 +1,105 @@ -use libpso::PacketParseError; +use std::collections::HashMap; +use rand::Rng; + +use libpso::packet::ship::*; +use libpso::packet::login::{Login, LoginResponse, AccountStatus, Session}; +use libpso::{PacketParseError, PSOPacket}; +use libpso::crypto::bb::PSOBBCipher; + +use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY}; use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId}; + use crate::entity::gateway::EntityGateway; +use crate::entity::account::{UserAccount, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; +use crate::entity::character::Character; +use crate::login::login::get_login_status; -pub const SHIP_PORT: u16 = 12345; +pub const SHIP_PORT: u16 = 23423; #[derive(Debug)] pub enum ShipError { - + ClientNotFound(ClientId), } #[derive(Debug)] pub enum RecvShipPacket { - + Login(Login), } impl RecvServerPacket for RecvShipPacket { fn from_bytes(data: &[u8]) -> Result { - Err(PacketParseError::WrongPacketForServerType) + match u16::from_le_bytes([data[2], data[3]]) { + 0x93 => Ok(RecvShipPacket::Login(Login::from_bytes(data)?)), + _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]))) + } } } #[derive(Debug)] pub enum SendShipPacket { - - + ShipWelcome(ShipWelcome), + LoginResponse(LoginResponse), + ShipBlockList(ShipBlockList), } impl SendServerPacket for SendShipPacket { fn as_bytes(&self) -> Vec { - Vec::new() + match self { + SendShipPacket::ShipWelcome(pkt) => pkt.as_bytes(), + SendShipPacket::LoginResponse(pkt) => pkt.as_bytes(), + SendShipPacket::ShipBlockList(pkt) => pkt.as_bytes(), + } + } +} + + +struct ClientState { + user: Option, + characters: Option<[Option; 4]>, + session: Session, +} + +impl ClientState { + fn new() -> ClientState { + ClientState { + user: None, + characters: None, + session: Session::new() + } } } pub struct ShipServerState { entity_gateway: EG, + clients: HashMap } impl ShipServerState { pub fn new(entity_gateway: EG) -> ShipServerState { ShipServerState { - entity_gateway: entity_gateway + entity_gateway: entity_gateway, + clients: HashMap::new(), } } + + fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, ShipError> { + let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; + Ok(match get_login_status(&self.entity_gateway, pkt) { + Ok(user) => { + let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); + response.guildcard = user.guildcard.map_or(24, |gc| gc) as u32; + response.team_id = user.team_id.map_or(31, |ti| ti) as u32; + client.user = Some(user); + client.session = pkt.session; + vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(3))] + }, + Err(err) => { + vec![SendShipPacket::LoginResponse(LoginResponse::by_status(err, Session::new()))] + } + }) + } } @@ -53,11 +109,27 @@ impl ServerState for ShipServerState { type PacketError = ShipError; fn on_connect(&mut self, id: ClientId) -> Vec> { - Vec::new() + self.clients.insert(id, ClientState::new()); + + 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[..]); + + vec![OnConnect::Packet(SendShipPacket::ShipWelcome(ShipWelcome::new(server_key, client_key))), + OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)), + Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key)))) + ] } fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket) -> Result>, ShipError> { - Ok(Box::new(Vec::new().into_iter())) + Ok(match pkt { + RecvShipPacket::Login(login) => { + Box::new(self.validate_login(id, login)?.into_iter().map(move |pkt| (id, pkt))) + }, + }) } -} \ No newline at end of file +}