aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/websocket.rs
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2017-03-23 17:02:52 +0100
committerAnthony Ramine <n.oxyde@gmail.com>2017-03-24 09:43:14 +0100
commit0bd54b904bf8b926afb60f4be0554bc37b30464b (patch)
tree1489467a0fd3fbf41d54fecae20398d0d1f6909f /components/script/dom/websocket.rs
parentbba0be13dd07116d02fd0f2e6d73d1ecb8e952bb (diff)
downloadservo-0bd54b904bf8b926afb60f4be0554bc37b30464b.tar.gz
servo-0bd54b904bf8b926afb60f4be0554bc37b30464b.zip
Properly follow the spec in WebSocket::Constructor
Diffstat (limited to 'components/script/dom/websocket.rs')
-rw-r--r--components/script/dom/websocket.rs158
1 files changed, 34 insertions, 124 deletions
diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs
index 296141a6c3a..a08684819e2 100644
--- a/components/script/dom/websocket.rs
+++ b/components/script/dom/websocket.rs
@@ -23,17 +23,13 @@ use dom::globalscope::GlobalScope;
use dom::messageevent::MessageEvent;
use dom::urlhelper::UrlHelper;
use dom_struct::dom_struct;
-use hyper;
-use hyper_serde::Serde;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use js::jsapi::JSAutoCompartment;
use js::jsval::UndefinedValue;
use js::typedarray::{ArrayBuffer, CreateWith};
use net_traits::{WebSocketCommunicate, WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent};
-use net_traits::CookieSource::HTTP;
-use net_traits::CoreResourceMsg::{SetCookiesForUrl, WebsocketConnect};
+use net_traits::CoreResourceMsg::WebsocketConnect;
use net_traits::MessageData;
-use net_traits::hosts::replace_hosts;
use net_traits::unwrap_websocket_protocol;
use script_runtime::CommonScriptMsg;
use script_runtime::ScriptThreadEventCategory::WebSocketEvent;
@@ -47,7 +43,6 @@ use std::thread;
use task_source::TaskSource;
use task_source::networking::NetworkingTaskSource;
use websocket::header::{Headers, WebSocketProtocol};
-use websocket::ws::util::url::parse_url;
#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
enum WebSocketRequestState {
@@ -57,75 +52,6 @@ enum WebSocketRequestState {
Closed = 3,
}
-// list of bad ports according to
-// https://fetch.spec.whatwg.org/#port-blocking
-const BLOCKED_PORTS_LIST: &'static [u16] = &[
- 1, // tcpmux
- 7, // echo
- 9, // discard
- 11, // systat
- 13, // daytime
- 15, // netstat
- 17, // qotd
- 19, // chargen
- 20, // ftp-data
- 21, // ftp
- 22, // ssh
- 23, // telnet
- 25, // smtp
- 37, // time
- 42, // name
- 43, // nicname
- 53, // domain
- 77, // priv-rjs
- 79, // finger
- 87, // ttylink
- 95, // supdup
- 101, // hostriame
- 102, // iso-tsap
- 103, // gppitnp
- 104, // acr-nema
- 109, // pop2
- 110, // pop3
- 111, // sunrpc
- 113, // auth
- 115, // sftp
- 117, // uucp-path
- 119, // nntp
- 123, // ntp
- 135, // loc-srv / epmap
- 139, // netbios
- 143, // imap2
- 179, // bgp
- 389, // ldap
- 465, // smtp+ssl
- 512, // print / exec
- 513, // login
- 514, // shell
- 515, // printer
- 526, // tempo
- 530, // courier
- 531, // chat
- 532, // netnews
- 540, // uucp
- 556, // remotefs
- 563, // nntp+ssl
- 587, // smtp
- 601, // syslog-conn
- 636, // ldap+ssl
- 993, // imap+ssl
- 995, // pop3+ssl
- 2049, // nfs
- 3659, // apple-sasl
- 4045, // lockd
- 6000, // x11
- 6665, // irc (alternate)
- 6666, // irc (alternate)
- 6667, // irc (default)
- 6668, // irc (alternate)
- 6669, // irc (alternate)
-];
-
// Close codes defined in https://tools.ietf.org/html/rfc6455#section-7.4.1
// Names are from https://github.com/mozilla/gecko-dev/blob/master/netwerk/protocol/websocket/nsIWebSocketChannel.idl
#[allow(dead_code)]
@@ -202,34 +128,36 @@ impl WebSocket {
global, WebSocketBinding::Wrap)
}
+ /// https://html.spec.whatwg.org/multipage/#dom-websocket
pub fn Constructor(global: &GlobalScope,
url: DOMString,
protocols: Option<StringOrStringSequence>)
-> Fallible<Root<WebSocket>> {
- // Step 1.
- let resource_url = try!(ServoUrl::parse(&url).map_err(|_| Error::Syntax));
- // Although we do this replace and parse operation again in the resource thread,
- // we try here to be able to immediately throw a syntax error on failure.
- let _ = try!(parse_url(&replace_hosts(&resource_url).as_url()).map_err(|_| Error::Syntax));
- // Step 2: Disallow https -> ws connections.
-
- // Step 3: Potentially block access to some ports.
- let port: u16 = resource_url.port_or_known_default().unwrap();
+ // Steps 1-2.
+ let url_record = ServoUrl::parse(&url).or(Err(Error::Syntax))?;
- if BLOCKED_PORTS_LIST.iter().any(|&p| p == port) {
- return Err(Error::Security);
+ // Step 3.
+ match url_record.scheme() {
+ "ws" | "wss" => {},
+ _ => return Err(Error::Syntax),
}
// Step 4.
- let protocols = match protocols {
- Some(StringOrStringSequence::String(string)) => vec![String::from(string)],
- Some(StringOrStringSequence::StringSequence(sequence)) => {
- sequence.into_iter().map(String::from).collect()
- },
- _ => Vec::new(),
- };
+ if url_record.fragment().is_some() {
+ return Err(Error::Syntax);
+ }
// Step 5.
+ let protocols = protocols.map_or(vec![], |p| {
+ match p {
+ StringOrStringSequence::String(string) => vec![string.into()],
+ StringOrStringSequence::StringSequence(seq) => {
+ seq.into_iter().map(String::from).collect()
+ },
+ }
+ });
+
+ // Step 6.
for (i, protocol) in protocols.iter().enumerate() {
// https://tools.ietf.org/html/rfc6455#section-4.1
// Handshake requirements, step 10
@@ -244,16 +172,12 @@ impl WebSocket {
}
}
- // Step 6: Origin.
- let origin = UrlHelper::Origin(&global.get_url()).0;
-
- // Step 7.
- let ws = WebSocket::new(global, resource_url.clone());
+ let ws = WebSocket::new(global, url_record.clone());
let address = Trusted::new(&*ws);
let connect_data = WebSocketConnectData {
- resource_url: resource_url.clone(),
- origin: origin,
+ resource_url: url_record,
+ origin: UrlHelper::Origin(&global.get_url()).0,
protocols: protocols,
};
@@ -270,6 +194,7 @@ impl WebSocket {
action_receiver: resource_action_receiver,
};
+ // Step 8.
let _ = global.core_resource_thread().send(WebsocketConnect(connect, connect_data));
*ws.sender.borrow_mut() = Some(dom_action_sender);
@@ -279,11 +204,10 @@ impl WebSocket {
thread::spawn(move || {
while let Ok(event) = dom_event_receiver.recv() {
match event {
- WebSocketNetworkEvent::ConnectionEstablished(headers, protocols) => {
+ WebSocketNetworkEvent::ConnectionEstablished(headers) => {
let open_thread = box ConnectionEstablishedTask {
address: address.clone(),
headers: headers,
- protocols: protocols,
};
task_source.queue_with_wrapper(open_thread, &wrapper).unwrap();
},
@@ -466,45 +390,31 @@ impl WebSocketMethods for WebSocket {
/// Task queued when *the WebSocket connection is established*.
+/// https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol:concept-websocket-established
struct ConnectionEstablishedTask {
address: Trusted<WebSocket>,
- protocols: Vec<String>,
headers: Headers,
}
impl Runnable for ConnectionEstablishedTask {
fn name(&self) -> &'static str { "ConnectionEstablishedTask" }
+ /// https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol:concept-websocket-established
fn handler(self: Box<Self>) {
let ws = self.address.root();
- // Step 1: Protocols.
- if !self.protocols.is_empty() && self.headers.get::<WebSocketProtocol>().is_none() {
- let task_source = ws.global().networking_task_source();
- fail_the_websocket_connection(self.address, &task_source, &ws.global().get_runnable_wrapper());
- return;
- }
-
- // Step 2.
+ // Step 1.
ws.ready_state.set(WebSocketRequestState::Open);
- // Step 3: Extensions.
- //TODO: Set extensions to extensions in use
+ // Step 2: Extensions.
+ // TODO: Set extensions to extensions in use.
- // Step 4: Protocols.
- let protocol_in_use = unwrap_websocket_protocol(self.headers.get::<WebSocketProtocol>());
- if let Some(protocol_name) = protocol_in_use {
+ // Step 3.
+ if let Some(protocol_name) = unwrap_websocket_protocol(self.headers.get::<WebSocketProtocol>()) {
*ws.protocol.borrow_mut() = protocol_name.to_owned();
};
- // Step 5: Cookies.
- if let Some(cookies) = self.headers.get::<hyper::header::SetCookie>() {
- let cookies = cookies.iter().map(|c| Serde(c.clone())).collect();
- let _ = ws.global().core_resource_thread().send(
- SetCookiesForUrl(ws.url.clone(), cookies, HTTP));
- }
-
- // Step 6.
+ // Step 4.
ws.upcast().fire_event(atom!("open"));
}
}