use parking_lot::Mutex;
use std::{
net::SocketAddr,
sync::Arc,
};
use naia_shared::IdentityToken;
use naia_shared::transport::local::{LocalTransportHub, ServerRecvError, ServerSendError};
#[doc(hidden)]
pub struct ServerAuthIo {
hub: LocalTransportHub,
buffer: [u8; 1472],
}
impl ServerAuthIo {
#[doc(hidden)]
pub fn new(hub: LocalTransportHub) -> Self {
Self {
hub,
buffer: [0; 1472],
}
}
fn receive(&mut self) -> Result<Option<(SocketAddr, &[u8])>, ServerRecvError> {
if let Some((client_addr, request_bytes)) = self.hub.try_recv_auth_request() {
let request = naia_shared::transport::bytes_to_request(&request_bytes);
if let Some(auth_header) = request.headers().get("Authorization") {
let auth_str = auth_header.to_str().unwrap();
let auth_bytes = base64::decode(auth_str).unwrap();
let len = auth_bytes.len();
self.buffer[0..len].copy_from_slice(&auth_bytes);
Ok(Some((client_addr, &self.buffer[..len])))
} else {
Ok(None)
}
} else {
Ok(None)
}
}
fn accept(
&mut self,
address: &SocketAddr,
identity_token: &IdentityToken,
) -> Result<(), ServerSendError> {
let response_body = format!("{}\r\n{}", identity_token, self.hub.server_addr());
let response = http::Response::builder()
.status(200)
.body(response_body.into_bytes())
.unwrap();
let response_bytes = naia_shared::transport::response_to_bytes(response);
self.hub
.send_auth_response(address, response_bytes)
.map_err(|_| ServerSendError)?;
Ok(())
}
fn reject(&mut self, address: &SocketAddr) -> Result<(), ServerSendError> {
let response = http::Response::builder()
.status(401)
.body(Vec::new())
.unwrap();
let response_bytes = naia_shared::transport::response_to_bytes(response);
self.hub
.send_auth_response(address, response_bytes)
.map_err(|_| ServerSendError)?;
Ok(())
}
}
#[doc(hidden)]
#[derive(Clone)]
pub struct LocalServerAuthSender {
auth_io: Arc<Mutex<ServerAuthIo>>,
}
impl LocalServerAuthSender {
#[doc(hidden)]
pub fn new(auth_io: Arc<Mutex<ServerAuthIo>>) -> Self {
Self { auth_io }
}
#[doc(hidden)]
pub fn accept(
&self,
address: &SocketAddr,
identity_token: &IdentityToken,
) -> Result<(), ServerSendError> {
self.auth_io.lock().accept(address, identity_token)
}
#[doc(hidden)]
pub fn reject(&self, address: &SocketAddr) -> Result<(), ServerSendError> {
self.auth_io.lock().reject(address)
}
}
#[doc(hidden)]
#[derive(Clone)]
pub struct LocalServerAuthReceiver {
auth_io: Arc<Mutex<ServerAuthIo>>,
buffer: Box<[u8]>,
}
impl LocalServerAuthReceiver {
#[doc(hidden)]
pub fn new(auth_io: Arc<Mutex<ServerAuthIo>>) -> Self {
Self {
auth_io,
buffer: Box::new([0; 1472]),
}
}
#[doc(hidden)]
pub fn receive(&mut self) -> Result<Option<(SocketAddr, &[u8])>, ServerRecvError> {
let mut guard = self.auth_io.lock();
match guard.receive() {
Ok(option) => match option {
Some((addr, buffer)) => {
self.buffer = buffer.into();
Ok(Some((addr, &self.buffer)))
}
None => Ok(None),
},
Err(err) => Err(err),
}
}
}