Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ws_client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2024"

[dependencies]
ws_core = { path = "../ws_core" }
rand = "0.9.2"
base64 = "0.22.1"
sha1="0.10.6"
36 changes: 26 additions & 10 deletions ws_client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ use base64::Engine;
use base64::engine::general_purpose;
use rand::Rng;
use sha1::{Digest, Sha1};
use ws_core::write::send_client_message;

pub fn handle_server(mut stream: TcpStream) -> Result<()> {
let random_bs64_key =generate_base64_key(16);
let random_bs64_key = generate_base64_key(16);
//send a http request to the server for upgrading the protocol from normal http to websocket
stream.write_all(
format!(
"GET / HTTP/1.1\r\n
Host: 127.0.0.1:8080\r\n
"GET / HTTP/1.1\r\n\
Host: 127.0.0.1:8080\r\n\
Upgrade: websocket\r\n\
Connection: Upgrade\r\n\
Sec-WebSocket-Key: {}\r\n\
Expand All @@ -25,7 +26,7 @@ pub fn handle_server(mut stream: TcpStream) -> Result<()> {
let mut buffer = Vec::new();
let mut temp = [0u8; 1024];

//loop over all the streams and stop when we get CL RF CL RF
//loop over all the streams and stop when we get CL RF CL RF
// this makes us read all the valid stream and stops us from breaking and reading only half streamed data
loop {
let bytes_read = stream.read(&mut temp).expect("failed to read the stream");
Expand All @@ -50,7 +51,7 @@ pub fn handle_server(mut stream: TcpStream) -> Result<()> {
{
let mut server_key = String::new();

//get the server key which server sent for upgrading
//get the server key which server sent for upgrading
for line in request.lines() {
if line.starts_with("Sec-WebSocket-Accept:") {
server_key = line.split(":").nth(1).unwrap().trim().to_string();
Expand All @@ -68,10 +69,25 @@ pub fn handle_server(mut stream: TcpStream) -> Result<()> {

//match the expected key with the server key if yes then create a loop untill the connection closes
if received_key == server_key {
loop {

}
}else{
loop {
let msg = "Hello, server".as_bytes();
let fincode = 0b1000_0000;
let opcode = 0b0000_0001;

let byte1 = fincode | opcode;

let mut masking_key = [0u8; 4];
rand::rng().fill(&mut masking_key[..]);
let mut encoded_data = vec![0u8; msg.len()];

for i in 0..msg.len() {
let idx: usize = i.try_into().unwrap();
encoded_data[idx] = msg[idx] ^ masking_key[idx % 4];
}

send_client_message(&mut stream, byte1, &encoded_data, masking_key)?;
}
} else {
println!("failed to upgrade connection")
}
}
Expand All @@ -95,7 +111,7 @@ pub fn main() -> Result<()> {

// function to create a base 64 key and it is done because the server accepts 16 bytes of base 64 encoded key to upgrade the protocol
fn generate_base64_key(bytes: u8) -> String {
let mut key_bytes = vec![0u8;bytes as usize];
let mut key_bytes = vec![0u8; bytes as usize];

rand::rng().fill(&mut key_bytes[..]);

Expand Down
32 changes: 31 additions & 1 deletion ws_core/src/write.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::io::{Result, Write};
use std::net::TcpStream;

pub fn send_message(stream: &mut TcpStream, byte1:u8,payload:&[u8]) -> Result<()> {
pub fn send_server_message(stream: &mut TcpStream, byte1:u8,payload:&[u8]) -> Result<()> {
let mut frame = Vec::new();

frame.push(byte1);
Expand All @@ -22,4 +22,34 @@ pub fn send_message(stream: &mut TcpStream, byte1:u8,payload:&[u8]) -> Result<()

stream.write_all(&frame)

}

pub fn send_client_message(stream: &mut TcpStream, byte1:u8,payload:&[u8],masking_key : [u8;4]) -> Result<()> {
let mut frame = Vec::new();

frame.push(byte1);

let mask = 0b1000_0000;
let payload_len = payload.len();
let byte2 :u8;

if payload_len <126 {
byte2 = (mask | payload_len) as u8;
frame.push(byte2);
} else if payload_len <= 65535 {
byte2 = (mask | 126) as u8;
frame.push(byte2);
frame.extend_from_slice(&(payload_len as u16).to_be_bytes());
} else {
byte2 = (mask | 127) as u8;
frame.push(byte2);
frame.extend_from_slice(&(payload_len as u64).to_be_bytes());
}

frame.extend_from_slice(&masking_key);

frame.extend_from_slice(payload);

stream.write_all(&frame)

}
10 changes: 5 additions & 5 deletions ws_server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::net::{TcpListener, TcpStream};
use std::thread;

use ws_core::read::read_header;
use ws_core::write::send_message;
use ws_core::write::send_server_message;


pub fn handle_client(mut stream: TcpStream) -> Result<()> {
Expand Down Expand Up @@ -82,14 +82,14 @@ pub fn handle_client(mut stream: TcpStream) -> Result<()> {
//close frame from the client
if cont_opcode == 0b0000_1000 {
let byte1 = fin_code | 0b0000_1000;
send_message(&mut stream, byte1, &frame.decoded_data)?;
send_server_message(&mut stream, byte1, &frame.decoded_data)?;
return Ok(());
}

//ping from the client
if cont_opcode == 0b0000_1001 {
let byte1 = fin_code | 0b0000_1010;
send_message(&mut stream, byte1, &frame.decoded_data)?;
send_server_message(&mut stream, byte1, &frame.decoded_data)?;
continue;
}

Expand Down Expand Up @@ -119,14 +119,14 @@ pub fn handle_client(mut stream: TcpStream) -> Result<()> {
println!("Text recieved : {}",text);

let byte1 = fin_code | opcode;
send_message(&mut stream, byte1, text.as_bytes())?;
send_server_message(&mut stream, byte1, text.as_bytes())?;
continue;
}
} else {
println!("Recieved {} of binary message",final_message.len());

let byte1 = fin_code | opcode;
send_message(&mut stream, byte1, &final_message)?;
send_server_message(&mut stream, byte1, &final_message)?;
continue;
}
}
Expand Down