Only pass the protocol in use in to establish a WS connection

This commit is contained in:
Anthony Ramine 2017-03-24 10:48:24 +01:00
parent 189b0d9094
commit a6d22b1a35
6 changed files with 23 additions and 29 deletions

1
Cargo.lock generated
View file

@ -2293,7 +2293,6 @@ dependencies = [
"selectors 0.18.0", "selectors 0.18.0",
"serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-websocket 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_atoms 0.0.1", "servo_atoms 0.0.1",
"servo_config 0.0.1", "servo_config 0.0.1",
"servo_geometry 0.0.1", "servo_geometry 0.0.1",

View file

@ -10,14 +10,13 @@ use hyper::header::{Host, SetCookie};
use net_traits::{CookieSource, MessageData, WebSocketCommunicate}; use net_traits::{CookieSource, MessageData, WebSocketCommunicate};
use net_traits::{WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent}; use net_traits::{WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent};
use net_traits::hosts::replace_hosts; use net_traits::hosts::replace_hosts;
use net_traits::unwrap_websocket_protocol;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::thread; use std::thread;
use websocket::{Client, Message}; use websocket::{Client, Message};
use websocket::header::{Headers, Origin, WebSocketProtocol}; use websocket::header::{Origin, WebSocketProtocol};
use websocket::message::Type; use websocket::message::Type;
use websocket::receiver::Receiver; use websocket::receiver::Receiver;
use websocket::result::{WebSocketError, WebSocketResult}; use websocket::result::{WebSocketError, WebSocketResult};
@ -31,7 +30,9 @@ fn establish_a_websocket_connection(resource_url: &ServoUrl,
origin: String, origin: String,
protocols: Vec<String>, protocols: Vec<String>,
cookie_jar: Arc<RwLock<CookieStorage>>) cookie_jar: Arc<RwLock<CookieStorage>>)
-> WebSocketResult<(Headers, Sender<WebSocketStream>, Receiver<WebSocketStream>)> { -> WebSocketResult<(Option<String>,
Sender<WebSocketStream>,
Receiver<WebSocketStream>)> {
// Steps 1-2 are not really applicable here, given we don't exactly go // Steps 1-2 are not really applicable here, given we don't exactly go
// through the same infrastructure as the Fetch spec. // through the same infrastructure as the Fetch spec.
@ -77,9 +78,13 @@ fn establish_a_websocket_connection(resource_url: &ServoUrl,
// Step 13 and transitive subset of step 14. // Step 13 and transitive subset of step 14.
// See step 6 of http://tools.ietf.org/html/rfc6455#section-4.1. // See step 6 of http://tools.ietf.org/html/rfc6455#section-4.1.
if let Some(protocol_name) = unwrap_websocket_protocol(response.protocol()) { let protocol_in_use = response.protocol().and_then(|header| {
if !protocols.is_empty() && !protocols.iter().any(|p| (&**p).eq_ignore_ascii_case(protocol_name)) { // https://github.com/whatwg/fetch/issues/515
return Err(WebSocketError::ProtocolError("Protocol in Use not in client-supplied protocol list")); header.first().cloned()
});
if let Some(ref protocol_name) = protocol_in_use {
if !protocols.is_empty() && !protocols.iter().any(|p| (&**p).eq_ignore_ascii_case(protocol_name)) {
return Err(WebSocketError::ProtocolError("Protocol in Use not in client-supplied protocol list"));
}; };
}; };
@ -94,9 +99,8 @@ fn establish_a_websocket_connection(resource_url: &ServoUrl,
} }
} }
let headers = response.headers.clone();
let (sender, receiver) = response.begin().split(); let (sender, receiver) = response.begin().split();
Ok((headers, sender, receiver)) Ok((protocol_in_use, sender, receiver))
} }
pub fn init(connect: WebSocketCommunicate, connect_data: WebSocketConnectData, cookie_jar: Arc<RwLock<CookieStorage>>) { pub fn init(connect: WebSocketCommunicate, connect_data: WebSocketConnectData, cookie_jar: Arc<RwLock<CookieStorage>>) {
@ -106,8 +110,8 @@ pub fn init(connect: WebSocketCommunicate, connect_data: WebSocketConnectData, c
connect_data.protocols, connect_data.protocols,
cookie_jar); cookie_jar);
let (ws_sender, mut receiver) = match channel { let (ws_sender, mut receiver) = match channel {
Ok((headers, sender, receiver)) => { Ok((protocol_in_use, sender, receiver)) => {
let _ = connect.event_sender.send(WebSocketNetworkEvent::ConnectionEstablished(headers)); let _ = connect.event_sender.send(WebSocketNetworkEvent::ConnectionEstablished { protocol_in_use });
(sender, receiver) (sender, receiver)
}, },
Err(e) => { Err(e) => {

View file

@ -348,9 +348,9 @@ pub enum WebSocketDomAction {
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub enum WebSocketNetworkEvent { pub enum WebSocketNetworkEvent {
ConnectionEstablished(#[serde(deserialize_with = "::hyper_serde::deserialize", ConnectionEstablished {
serialize_with = "::hyper_serde::serialize")] protocol_in_use: Option<String>,
header::Headers), },
MessageReceived(MessageData), MessageReceived(MessageData),
Close(Option<u16>, String), Close(Option<u16>, String),
Fail, Fail,
@ -514,11 +514,6 @@ pub fn load_whole_resource(request: RequestInit,
} }
} }
/// Defensively unwraps the protocol string from the response object's protocol
pub fn unwrap_websocket_protocol(wsp: Option<&header::WebSocketProtocol>) -> Option<&str> {
wsp.and_then(|protocol_list| protocol_list.get(0).map(|protocol| protocol.as_ref()))
}
/// An unique identifier to keep track of each load message in the resource handler /// An unique identifier to keep track of each load message in the resource handler
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
pub struct ResourceId(pub u32); pub struct ResourceId(pub u32);

View file

@ -79,8 +79,7 @@ servo_atoms = {path = "../atoms"}
servo_config = {path = "../config", features = ["servo"] } servo_config = {path = "../config", features = ["servo"] }
servo_geometry = {path = "../geometry" } servo_geometry = {path = "../geometry" }
servo_rand = {path = "../rand"} servo_rand = {path = "../rand"}
servo_url = {path = "../url", features = ["servo"] } servo_url = {path = "../url", features = ["servo"]}
servo-websocket = "0.18"
smallvec = "0.3" smallvec = "0.3"
style = {path = "../style"} style = {path = "../style"}
style_traits = {path = "../style_traits"} style_traits = {path = "../style_traits"}

View file

@ -30,7 +30,6 @@ use js::typedarray::{ArrayBuffer, CreateWith};
use net_traits::{WebSocketCommunicate, WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent}; use net_traits::{WebSocketCommunicate, WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent};
use net_traits::CoreResourceMsg::WebsocketConnect; use net_traits::CoreResourceMsg::WebsocketConnect;
use net_traits::MessageData; use net_traits::MessageData;
use net_traits::unwrap_websocket_protocol;
use script_runtime::CommonScriptMsg; use script_runtime::CommonScriptMsg;
use script_runtime::ScriptThreadEventCategory::WebSocketEvent; use script_runtime::ScriptThreadEventCategory::WebSocketEvent;
use script_thread::{Runnable, RunnableWrapper}; use script_thread::{Runnable, RunnableWrapper};
@ -42,7 +41,6 @@ use std::ptr;
use std::thread; use std::thread;
use task_source::TaskSource; use task_source::TaskSource;
use task_source::networking::NetworkingTaskSource; use task_source::networking::NetworkingTaskSource;
use websocket::header::{Headers, WebSocketProtocol};
#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)] #[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
enum WebSocketRequestState { enum WebSocketRequestState {
@ -204,10 +202,10 @@ impl WebSocket {
thread::spawn(move || { thread::spawn(move || {
while let Ok(event) = dom_event_receiver.recv() { while let Ok(event) = dom_event_receiver.recv() {
match event { match event {
WebSocketNetworkEvent::ConnectionEstablished(headers) => { WebSocketNetworkEvent::ConnectionEstablished { protocol_in_use } => {
let open_thread = box ConnectionEstablishedTask { let open_thread = box ConnectionEstablishedTask {
address: address.clone(), address: address.clone(),
headers: headers, protocol_in_use,
}; };
task_source.queue_with_wrapper(open_thread, &wrapper).unwrap(); task_source.queue_with_wrapper(open_thread, &wrapper).unwrap();
}, },
@ -393,7 +391,7 @@ impl WebSocketMethods for WebSocket {
/// https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol:concept-websocket-established /// https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol:concept-websocket-established
struct ConnectionEstablishedTask { struct ConnectionEstablishedTask {
address: Trusted<WebSocket>, address: Trusted<WebSocket>,
headers: Headers, protocol_in_use: Option<String>,
} }
impl Runnable for ConnectionEstablishedTask { impl Runnable for ConnectionEstablishedTask {
@ -410,8 +408,8 @@ impl Runnable for ConnectionEstablishedTask {
// TODO: Set extensions to extensions in use. // TODO: Set extensions to extensions in use.
// Step 3. // Step 3.
if let Some(protocol_name) = unwrap_websocket_protocol(self.headers.get::<WebSocketProtocol>()) { if let Some(protocol_name) = self.protocol_in_use {
*ws.protocol.borrow_mut() = protocol_name.to_owned(); *ws.protocol.borrow_mut() = protocol_name;
}; };
// Step 4. // Step 4.

View file

@ -98,7 +98,6 @@ extern crate tinyfiledialogs;
extern crate url; extern crate url;
extern crate uuid; extern crate uuid;
extern crate webrender_traits; extern crate webrender_traits;
extern crate websocket;
extern crate webvr_traits; extern crate webvr_traits;
extern crate xml5ever; extern crate xml5ever;