@ -18,6 +18,7 @@ use crate::common::serverstate::{RecvServerPacket, SendServerPacket, ServerState
pub enum PatchError {
pub enum PatchError {
NetworkError ( NetworkError ) ,
NetworkError ( NetworkError ) ,
IOError ( std ::io ::Error ) ,
IOError ( std ::io ::Error ) ,
NoSuchClient ( ClientId ) ,
}
}
impl From < NetworkError > for PatchError {
impl From < NetworkError > for PatchError {
@ -135,11 +136,10 @@ impl SendServerPacket for SendPatchPacket {
}
}
}
}
pub struct PatchServerState {
pub struct PatchServerState {
patch_file_tree : PatchFileTree ,
patch_file_tree : PatchFileTree ,
patch_file_lookup : HashMap < u32 , PatchFile > ,
patch_file_lookup : HashMap < u32 , PatchFile > ,
patch_file_info : Vec < FileInfoReply > ,
client_file_info : HashMap < ClientId , Vec < FileInfoReply > > ,
patch_motd : String ,
patch_motd : String ,
}
}
@ -148,7 +148,7 @@ impl PatchServerState {
PatchServerState {
PatchServerState {
patch_file_tree ,
patch_file_tree ,
patch_file_lookup ,
patch_file_lookup ,
patch_file_info : Vec ::new ( ) ,
client_file_info : HashMap ::new ( ) ,
patch_motd ,
patch_motd ,
}
}
}
}
@ -160,10 +160,11 @@ impl ServerState for PatchServerState {
type RecvPacket = RecvPatchPacket ;
type RecvPacket = RecvPatchPacket ;
type PacketError = PatchError ;
type PacketError = PatchError ;
async fn on_connect ( & mut self , _ id : ClientId ) -> Result < Vec < OnConnect < Self ::SendPacket > > , PatchError > {
async fn on_connect ( & mut self , id : ClientId ) -> Result < Vec < OnConnect < Self ::SendPacket > > , PatchError > {
let mut rng = rand ::thread_rng ( ) ;
let mut rng = rand ::thread_rng ( ) ;
let key_in : u32 = rng . gen ( ) ;
let key_in : u32 = rng . gen ( ) ;
let key_out : u32 = rng . gen ( ) ;
let key_out : u32 = rng . gen ( ) ;
self . client_file_info . insert ( id , Vec ::new ( ) ) ;
Ok ( vec ! [ OnConnect ::Packet ( SendPatchPacket ::PatchWelcome ( PatchWelcome ::new ( key_out , key_in ) ) ) ,
Ok ( vec ! [ OnConnect ::Packet ( SendPatchPacket ::PatchWelcome ( PatchWelcome ::new ( key_out , key_in ) ) ) ,
OnConnect ::Cipher ( ( Box ::new ( PSOPCCipher ::new ( key_in ) ) , Box ::new ( PSOPCCipher ::new ( key_out ) ) ) )
OnConnect ::Cipher ( ( Box ::new ( PSOPCCipher ::new ( key_in ) ) , Box ::new ( PSOPCCipher ::new ( key_out ) ) ) )
@ -183,26 +184,29 @@ impl ServerState for PatchServerState {
Box ::new ( p . into_iter ( ) . map ( move | pkt | ( id , pkt ) ) )
Box ::new ( p . into_iter ( ) . map ( move | pkt | ( id , pkt ) ) )
} ,
} ,
RecvPatchPacket ::FileInfoReply ( pkt ) = > {
RecvPatchPacket ::FileInfoReply ( pkt ) = > {
self . patch _file_info. push ( pkt . clone ( ) ) ;
self . client _file_info. get_mut ( & id ) . ok_or ( PatchError ::NoSuchClient ( id ) ) ? . push ( pkt . clone ( ) ) ; // it should be impossible to error here under normal conditions?
Box ::new ( None . into_iter ( ) . map ( move | pkt | ( id , pkt ) ) )
Box ::new ( None . into_iter ( ) . map ( move | pkt | ( id , pkt ) ) )
} ,
} ,
RecvPatchPacket ::FileInfoListEnd ( _pkt ) = > {
RecvPatchPacket ::FileInfoListEnd ( _pkt ) = > {
let need_update = self . patch_file_info . iter ( )
. filter ( | file_info | does_file_need_updating ( file_info , & self . patch_file_lookup ) )
let need_update = self . client_file_info . get ( & id )
. ok_or ( PatchError ::NoSuchClient ( id ) ) ?
. iter ( )
. filter ( | client_file_info | does_file_need_updating ( client_file_info , & self . patch_file_lookup ) )
. collect ::< Vec < _ > > ( ) ;
. collect ::< Vec < _ > > ( ) ;
let total_size = need_update . iter ( ) . fold ( 0 , | a , file_info | a + file_info . size ) ;
let total_size = need_update . iter ( )
. filter_map ( | client_file | self . patch_file_lookup . get ( & client_file . id ) ) // TODO: dont unwrap?
. fold ( 0 , | a , file_info | a + file_info . size ) ;
let total_files = need_update . len ( ) as u32 ;
let total_files = need_update . len ( ) as u32 ;
let p = vec ! [ SendPatchPacket ::FilesToPatchMetadata ( FilesToPatchMetadata ::new ( total_size , total_files ) ) ,
let p = vec ! [ SendPatchPacket ::FilesToPatchMetadata ( FilesToPatchMetadata ::new ( total_size , total_files ) ) ,
SendPatchPacket ::PatchStartList ( PatchStartList { } )
SendPatchPacket ::PatchStartList ( PatchStartList { } )
] ;
] ;
Box ::new ( p . into_iter ( ) . chain ( SendFileIterator ::new ( self ) ) . map ( move | pkt | ( id , pkt ) ) )
Box ::new ( p . into_iter ( ) . chain ( SendFileIterator ::new ( self , need_update ) ) . map ( move | pkt | ( id , pkt ) ) )
}
}
} )
} )
}
}
async fn on_disconnect ( & mut self , _id : ClientId ) -> Result < Vec < ( ClientId , SendPatchPacket ) > , PatchError > {
async fn on_disconnect ( & mut self , id : ClientId ) -> Result < Vec < ( ClientId , SendPatchPacket ) > , PatchError > {
self . client_file_info . remove ( & id ) ;
Ok ( Vec ::new ( ) )
Ok ( Vec ::new ( ) )
}
}
}
}
@ -279,9 +283,9 @@ fn get_checksum_and_size(path: &Path) -> Result<(u32, u32), PatchError> {
Ok ( ( crc . sum32 ( ) , size as u32 ) )
Ok ( ( crc . sum32 ( ) , size as u32 ) )
}
}
fn does_file_need_updating ( file_info : & FileInfoReply , patch_file_lookup : & HashMap < u32 , PatchFile > ) -> bool {
let patch_file = patch_file_lookup . get ( & file_info . id ) . unwrap ( ) ;
patch_file . checksum ! = file_info . checksum | | patch_file . size ! = file_info . size
fn does_file_need_updating ( client_ file_info : & FileInfoReply , patch_file_lookup : & HashMap < u32 , PatchFile > ) -> bool {
let patch_file = patch_file_lookup . get ( & client_ file_info. id ) . unwrap ( ) ;
patch_file . checksum ! = client_ file_info. checksum | | patch_file . size ! = client_ file_info. size
}
}
@ -294,9 +298,8 @@ struct SendFileIterator {
}
}
impl SendFileIterator {
impl SendFileIterator {
fn new ( state : & PatchServerState ) -> SendFileIterator {
let file_ids_to_update = state . patch_file_info . iter ( )
. filter ( | file_info | does_file_need_updating ( file_info , & state . patch_file_lookup ) )
fn new ( state : & PatchServerState , client_file_info : Vec < & FileInfoReply > ) -> SendFileIterator {
let file_ids_to_update = client_file_info . iter ( )
. map ( | k | k . id )
. map ( | k | k . id )
. collect ::< HashSet < _ > > ( ) ;
. collect ::< HashSet < _ > > ( ) ;