multiplayer-game/src/websoket_connection.rs

69 lines
2.1 KiB
Rust

use crate::{
request::{Connection, Protocol, Request, RequestHeader},
response::Response,
};
use tokio::io::{self, AsyncWriteExt};
use tokio::net::TcpStream;
use base64::prelude::*;
use sha1::{Digest, Sha1};
pub struct WebsocketConnection {
stream: TcpStream,
}
impl WebsocketConnection {
pub async fn initialize_connection(
req: Request,
mut stream: TcpStream,
) -> tokio::io::Result<Self> {
let (mut upgrade, mut connection, mut key_exists) = (false, false, false);
let mut key_val: Box<str> = "".into();
for i in req.headers {
match i {
RequestHeader::Upgrade(upgrad) => {
if let Some(upg) = upgrad.first()
&& upg.protocol == Protocol::Websocket
{
upgrade = true;
}
}
RequestHeader::Connection(con) => {
if con == Connection::Upgrade {
connection = true;
}
}
RequestHeader::Other { name, value } => {
if name == "Sec-WebSocket-Key".into() {
key_val = value.clone();
key_exists = true;
}
}
_ => (),
}
}
if upgrade && connection && key_exists {
let magic_val = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
let mut hasher = Sha1::new();
hasher.update(key_val.as_bytes());
hasher.update(magic_val);
let result = hasher.finalize();
let result = BASE64_STANDARD.encode(result);
Response::new().with_code(200).with_header(crate::response::ResponseHeader::Location)
Ok(Self { stream })
} else {
Response::new()
.with_code(crate::response::ResponseCode::BadRequest)
.respond(&mut stream)
.await?;
stream.flush().await?;
Err(io::Error::new(io::ErrorKind::InvalidData, "Wrong request"))
}
}
}