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 { let (mut upgrade, mut connection, mut key_exists) = (false, false, false); let mut key_val: Box = "".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")) } } }