Skip to content

Commit

Permalink
move websocket codes to example
Browse files Browse the repository at this point in the history
  • Loading branch information
hatoo committed Oct 30, 2024
1 parent 25b6198 commit 24f8f1a
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 90 deletions.
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ keywords = ["http", "proxy", "http-proxy"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
websocket = ["dep:winnow"]

[dependencies]
tokio = { version = "1.39.3", features = [
"macros",
Expand Down Expand Up @@ -46,7 +43,7 @@ clap = { version = "4.5.16", features = ["derive"] }
rcgen = { version = "0.13.1", features = ["x509-parser"] }
reqwest = { version = "0.12.7", features = ["native-tls-alpn"] }
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
winnow = "0.6.20"

[[example]]
name = "websocket"
required-features = ["websocket"]
86 changes: 82 additions & 4 deletions examples/websocket.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use std::path::PathBuf;

use clap::{Args, Parser};
use http_mitm_proxy::{
default_client::{websocket, Upgraded},
DefaultClient, MitmProxy,
};
use http_mitm_proxy::{default_client::Upgraded, DefaultClient, MitmProxy};
use moka::sync::Cache;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tracing_subscriber::EnvFilter;
Expand Down Expand Up @@ -191,3 +188,84 @@ async fn main() {

server.await;
}

pub mod websocket {
/*
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
Frame format:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
*/

use winnow::{
binary::{be_u16, be_u64, u8},
prelude::*,
token::take,
};

pub struct Frame {
pub b0: u8,
pub b1: u8,
pub payload_len: usize,
pub masking_key: Option<[u8; 4]>,
pub payload_data: Vec<u8>,
}

pub fn frame(input: &mut &[u8]) -> PResult<Frame> {
let b0 = u8(input)?;
let b1 = u8(input)?;

let payload_len = match b1 & 0b0111_1111 {
126 => {
let len = be_u16(input)?;
len as usize
}
127 => {
let len = be_u64(input)?;
len as usize
}
len => len as usize,
};

let mask = b1 & 0b1000_0000 != 0;
let masking_key = if mask {
Some([u8(input)?, u8(input)?, u8(input)?, u8(input)?])
} else {
None
};

let mut payload_data = take(payload_len).parse_next(input)?.to_vec();

if let Some(mask) = masking_key {
for (i, byte) in payload_data.iter_mut().enumerate() {
*byte ^= mask[i % 4];
}
}

Ok(Frame {
b0,
b1,
payload_len,
masking_key,
payload_data,
})
}
}
82 changes: 0 additions & 82 deletions src/default_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,85 +249,3 @@ fn remove_authority<B>(req: &mut Request<B>) {
parts.authority = None;
*req.uri_mut() = Uri::from_parts(parts).unwrap();
}

#[cfg(feature = "websocket")]
pub mod websocket {
/*
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
Frame format:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
*/

use winnow::{
binary::{be_u16, be_u64, u8},
prelude::*,
token::take,
};

pub struct Frame {
pub b0: u8,
pub b1: u8,
pub payload_len: usize,
pub masking_key: Option<[u8; 4]>,
pub payload_data: Vec<u8>,
}

pub fn frame(input: &mut &[u8]) -> PResult<Frame> {
let b0 = u8(input)?;
let b1 = u8(input)?;

let payload_len = match b1 & 0b0111_1111 {
126 => {
let len = be_u16(input)?;
len as usize
}
127 => {
let len = be_u64(input)?;
len as usize
}
len => len as usize,
};

let mask = b1 & 0b1000_0000 != 0;
let masking_key = if mask {
Some([u8(input)?, u8(input)?, u8(input)?, u8(input)?])
} else {
None
};

let mut payload_data = take(payload_len).parse_next(input)?.to_vec();

if let Some(mask) = masking_key {
for (i, byte) in payload_data.iter_mut().enumerate() {
*byte ^= mask[i % 4];
}
}

Ok(Frame {
b0,
b1,
payload_len,
masking_key,
payload_data,
})
}
}

0 comments on commit 24f8f1a

Please sign in to comment.