Skip to content

Commit 3141d31

Browse files
committed
permessage-deflate
1 parent f43e929 commit 3141d31

5 files changed

Lines changed: 45 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ utf-8 = "0.7.5"
5454
rand = "0.8.4"
5555
thiserror = "1.0.40"
5656
bytes = "1.5.0"
57+
miniz_oxide = "0.8.9"
5758

5859
# Axum integration
5960
axum-core = { version = "0.5.0", optional = true }

autobahn/Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
AUTOBAHN_TESTSUITE_DOCKER := crossbario/autobahn-testsuite:0.8.2@sha256:5d4ba3aa7d6ab2fdbf6606f3f4ecbe4b66f205ce1cbc176d6cdf650157e52242
22

33
build-server:
4-
sudo cargo build --release --example echo_server --features "upgrade"
4+
cargo build --release --example echo_server --features "upgrade"
55

66
run-server: build-server
77
echo ${PWD}
@@ -18,7 +18,7 @@ run-server: build-server
1818
../target/release/examples/echo_server
1919

2020
build-client:
21-
sudo cargo build --release --example autobahn_client --features "upgrade"
21+
cargo build --release --example autobahn_client --features "upgrade"
2222

2323
run-client: build-client
2424
echo ${PWD}
@@ -34,4 +34,4 @@ run-client: build-client
3434
sleep 5
3535
../target/release/examples/autobahn_client
3636

37-
.PHONY: build-server run-server build-client run-client
37+
.PHONY: build-server run-server build-client run-client

src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ pub enum WebSocketError {
3434
InvalidSecWebsocketVersion,
3535
#[error("Invalid value")]
3636
InvalidValue,
37+
#[error("Invalid encoding")]
38+
InvalidEncoding,
3739
#[error("Sec-WebSocket-Key header is missing")]
3840
MissingSecWebSocketKey,
3941
#[error(transparent)]

src/lib.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ use tokio::io::AsyncReadExt;
175175
use tokio::io::AsyncWrite;
176176
use tokio::io::AsyncWriteExt;
177177

178+
use miniz_oxide::{DataFormat, MZFlush};
179+
use miniz_oxide::inflate::stream::{InflateState, inflate};
180+
178181
pub use crate::close::CloseCode;
179182
pub use crate::error::WebSocketError;
180183
pub use crate::fragment::FragmentCollector;
@@ -681,7 +684,11 @@ impl ReadHalf {
681684
let rsv2 = self.buffer[0] & 0b00100000 != 0;
682685
let rsv3 = self.buffer[0] & 0b00010000 != 0;
683686

684-
if rsv1 || rsv2 || rsv3 {
687+
let mut compressed = false;
688+
689+
if rsv1 && !rsv2 && !rsv3 {
690+
compressed = true;
691+
} else if rsv1 || rsv2 || rsv3 {
685692
return Err(WebSocketError::ReservedBitsNotZero);
686693
}
687694

@@ -743,8 +750,13 @@ impl ReadHalf {
743750
}
744751

745752
// if we read too much it will stay in the buffer, for the next call to this method
746-
let payload = self.buffer.split_to(payload_len);
753+
let mut payload = self.buffer.split_to(payload_len);
754+
if compressed {
755+
payload = BytesMut::from(inflate_payload(&payload.to_vec())?.as_slice());
756+
}
757+
747758
let frame = Frame::new(fin, opcode, mask, Payload::Bytes(payload));
759+
748760
Ok(frame)
749761
}
750762
}
@@ -820,3 +832,25 @@ mod tests {
820832
assert_unsync::<WebSocket<tokio::net::TcpStream>>();
821833
};
822834
}
835+
836+
fn inflate_payload(
837+
payload: &Vec<u8>
838+
) -> Result<Vec<u8>, WebSocketError>
839+
{
840+
let max_output_size = usize::max_value();
841+
let mut out: Vec<u8> = vec![0; payload.len().saturating_mul(2).min(max_output_size)];
842+
let mut state = InflateState::new_boxed(DataFormat::Raw);
843+
844+
let payload = [payload.as_slice(), [0x00, 0x00, 0xff, 0xff].as_slice()].concat();
845+
let res = inflate(&mut state, &payload, &mut out, MZFlush::Partial);
846+
847+
match res.status {
848+
Ok(_) => {
849+
out.truncate(res.bytes_written);
850+
Ok(out)
851+
}
852+
Err(_) => {
853+
Err(WebSocketError::InvalidEncoding)
854+
}
855+
}
856+
}

0 commit comments

Comments
 (0)