69 lines
2.1 KiB
Rust
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"))
|
|
}
|
|
}
|
|
}
|