WebSocketConfig extended to allow accepting unmasked client frames

This commit is contained in:
Adam Bezecny (DHL IT Services) 2020-11-26 20:51:50 +01:00
parent a7daafdfc8
commit 0121bf9682
2 changed files with 72 additions and 3 deletions

View File

@ -0,0 +1,50 @@
use std::{net::TcpListener, thread::spawn};
use tungstenite::{
handshake::server::{Request, Response},
protocol::WebSocketConfig,
server::accept_hdr_with_config,
};
fn main() {
env_logger::init();
let server = TcpListener::bind("127.0.0.1:3012").unwrap();
for stream in server.incoming() {
spawn(move || {
let callback = |req: &Request, mut response: Response| {
println!("Received a new ws handshake");
println!("The request's path is: {}", req.uri().path());
println!("The request's headers are:");
for (ref header, _value) in req.headers() {
println!("* {}", header);
}
// Let's add an additional header to our response to the client.
let headers = response.headers_mut();
headers.append("MyCustomHeader", ":)".parse().unwrap());
headers.append("SOME_TUNGSTENITE_HEADER", "header_value".parse().unwrap());
Ok(response)
};
let config = Some(WebSocketConfig {
max_send_queue: None,
max_message_size: None,
max_frame_size: None,
// This setting allows to accept client frames which are not masked
// This is not in compliance with RFC 6455 but might be handy in some
// rare cases where it is necessary to integrate with existing/legacy
// clients which are sending unmasked frames
server_allow_unmasked: Some(true),
});
let mut websocket = accept_hdr_with_config(stream.unwrap(), callback, config).unwrap();
loop {
let msg = websocket.read_message().unwrap();
if msg.is_binary() || msg.is_text() {
println!("received message {}", msg);
}
}
});
}
}

View File

@ -50,6 +50,11 @@ pub struct WebSocketConfig {
/// be reasonably big for all normal use-cases but small enough to prevent memory eating
/// by a malicious user.
pub max_frame_size: Option<usize>,
/// If set to true it will allow the websocket server to accept unmasked frames from client.
/// Even though this behaviour is not in compliance with RFC 6455 (which requires the server
/// to close the connection when unmasked frame from client is received) it might be handy in some cases
/// as there are existing applications sending unmasked client frames.
pub server_allow_unmasked: Option<bool>,
}
impl Default for WebSocketConfig {
@ -58,6 +63,7 @@ impl Default for WebSocketConfig {
max_send_queue: None,
max_message_size: Some(64 << 20),
max_frame_size: Some(16 << 20),
server_allow_unmasked: None,
}
}
}
@ -449,9 +455,22 @@ impl WebSocketContext {
} else {
// The server MUST close the connection upon receiving a
// frame that is not masked. (RFC 6455)
return Err(Error::Protocol(
"Received an unmasked frame from client".into(),
));
// The only exception here is if the user explicitly accepts given
// stream (by tungstenite::server::accept_with_config or tungstenite::server::accept_hdr_with_config)
// with WebSocketConfig.server_allow_unmasked set to Some(true)
if let Some(server_allow_unmasked_val) =
self.get_config().server_allow_unmasked
{
if server_allow_unmasked_val == false {
return Err(Error::Protocol(
"Received an unmasked frame from client".into(),
));
}
} else {
return Err(Error::Protocol(
"Received an unmasked frame from client".into(),
));
}
}
}
Role::Client => {