use std::{collections::HashMap, net::SocketAddr};
use log::warn;
use naia_shared::{
handshake::HandshakeHeader, BitReader, BitWriter, IdentityToken, PacketType, Serde, SerdeErr,
StandardHeader,
};
use crate::{
handshake::{HandshakeAction, Handshaker},
UserKey,
};
pub struct HandshakeManager {
authenticated_and_identified_users: HashMap<SocketAddr, UserKey>,
authenticated_unidentified_users: HashMap<IdentityToken, UserKey>,
identity_token_map: HashMap<UserKey, IdentityToken>,
}
impl Handshaker for HandshakeManager {
fn authenticate_user(&mut self, identity_token: &IdentityToken, user_key: &UserKey) {
self.authenticated_unidentified_users
.insert(identity_token.clone(), *user_key);
self.identity_token_map
.insert(*user_key, identity_token.clone());
}
fn delete_user(&mut self, user_key: &UserKey, address_opt: Option<SocketAddr>) {
if let Some(identity_token) = self.identity_token_map.remove(user_key) {
self.authenticated_unidentified_users
.remove(&identity_token);
}
if let Some(address) = address_opt {
self.authenticated_and_identified_users.remove(&address);
}
}
fn maintain_handshake(
&mut self,
address: &SocketAddr,
reader: &mut BitReader,
has_connection: bool,
) -> Result<HandshakeAction, SerdeErr> {
let handshake_header = HandshakeHeader::de(reader)?;
match handshake_header {
HandshakeHeader::ClientIdentifyRequest => {
if let Ok(id_token) = self.recv_identify_request(reader) {
if let Some(user_key) = self.authenticated_unidentified_users.remove(&id_token)
{
if self.identity_token_map.remove(&user_key).is_none() {
panic!("Server Error: Identity Token not found for user_key: {:?}. Shouldn't be possible.", user_key);
}
self.authenticated_and_identified_users
.insert(*address, user_key);
} else {
return Ok(HandshakeAction::None);
}
let identify_response = Self::write_identity_response().to_packet();
return Ok(HandshakeAction::SendPacket(identify_response));
} else {
return Ok(HandshakeAction::None);
}
}
HandshakeHeader::ClientConnectRequest => {
let writer = self.write_connect_response();
let packet = writer.to_packet();
if has_connection {
return Ok(HandshakeAction::SendPacket(packet));
} else {
let Some(user_key) = self.authenticated_and_identified_users.get(address)
else {
warn!("Server Error: User not authenticated for: {:?}", address);
return Ok(HandshakeAction::None);
};
return Ok(HandshakeAction::FinalizeConnection(*user_key, packet));
}
}
HandshakeHeader::Disconnect => {
if self.verify_disconnect_request(address, reader) {
let user_key = *self
.authenticated_and_identified_users
.get(address)
.expect("Server Error: User not authenticated for disconnect request. Shouldn't be possible.");
return Ok(HandshakeAction::DisconnectUser(user_key));
} else {
return Ok(HandshakeAction::None);
}
}
_ => {
warn!(
"Server Error: Unexpected handshake header: {:?} from {}",
handshake_header, address
);
return Ok(HandshakeAction::None);
}
}
}
}
impl HandshakeManager {
pub fn new() -> Self {
Self {
authenticated_and_identified_users: HashMap::new(),
authenticated_unidentified_users: HashMap::new(),
identity_token_map: HashMap::new(),
}
}
fn recv_identify_request(&mut self, reader: &mut BitReader) -> Result<IdentityToken, SerdeErr> {
IdentityToken::de(reader)
}
fn write_identity_response() -> BitWriter {
let mut writer = BitWriter::new();
StandardHeader::new(PacketType::Handshake, 0, 0, 0).ser(&mut writer);
HandshakeHeader::ServerIdentifyResponse.ser(&mut writer);
writer
}
fn write_connect_response(&self) -> BitWriter {
let mut writer = BitWriter::new();
StandardHeader::new(PacketType::Handshake, 0, 0, 0).ser(&mut writer);
HandshakeHeader::ServerConnectResponse.ser(&mut writer);
writer
}
fn verify_disconnect_request(
&mut self,
_address: &SocketAddr,
_reader: &mut BitReader,
) -> bool {
todo!()
}
}