aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/websocket.rs
diff options
context:
space:
mode:
authorjmr0 <jrosello720@gmail.com>2015-12-03 13:58:30 -0500
committerjmr0 <jrosello720@gmail.com>2015-12-17 09:17:15 -0500
commit7d0bede8ba5a451a103cafa5ad18586f5a889b79 (patch)
tree7eb162e5ac050f46d190fec010d166095c93b06f /components/script/dom/websocket.rs
parent99fd946130c9f06433b47c7f60241d5f7ad14a5b (diff)
downloadservo-7d0bede8ba5a451a103cafa5ad18586f5a889b79.tar.gz
servo-7d0bede8ba5a451a103cafa5ad18586f5a889b79.zip
adding initial support for websocket subprotocol negotation
Diffstat (limited to 'components/script/dom/websocket.rs')
-rw-r--r--components/script/dom/websocket.rs40
1 files changed, 37 insertions, 3 deletions
diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs
index 8d7e5ebd6c6..392b8258b5c 100644
--- a/components/script/dom/websocket.rs
+++ b/components/script/dom/websocket.rs
@@ -29,6 +29,7 @@ use libc::{uint32_t, uint8_t};
use net_traits::ControlMsg::WebsocketConnect;
use net_traits::MessageData;
use net_traits::hosts::replace_hosts;
+use net_traits::unwrap_websocket_protocol;
use net_traits::{WebSocketCommunicate, WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent};
use ref_slice::ref_slice;
use script_task::ScriptTaskEventCategory::WebSocketEvent;
@@ -39,6 +40,7 @@ use std::ptr;
use std::thread;
use util::str::DOMString;
use websocket::client::request::Url;
+use websocket::header::{Headers, WebSocketProtocol};
use websocket::ws::util::url::parse_url;
#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
@@ -146,6 +148,7 @@ pub struct WebSocket {
code: Cell<u16>, //Closing code
reason: DOMRefCell<String>, //Closing reason
binary_type: Cell<BinaryType>,
+ protocol: DOMRefCell<String>, //Subprotocol selected by server
}
impl WebSocket {
@@ -164,6 +167,7 @@ impl WebSocket {
code: Cell::new(0),
reason: DOMRefCell::new("".to_owned()),
binary_type: Cell::new(BinaryType::Blob),
+ protocol: DOMRefCell::new("".to_owned()),
}
}
@@ -208,6 +212,8 @@ impl WebSocket {
return Err(Error::Syntax);
}
+ // TODO: also check that no separator characters are used
+ // https://tools.ietf.org/html/rfc6455#section-4.1
if protocol.chars().any(|c| c < '\u{0021}' || c > '\u{007E}') {
return Err(Error::Syntax);
}
@@ -220,10 +226,12 @@ impl WebSocket {
let address = Trusted::new(global.get_cx(), ws.r(), global.networking_task_source());
let origin = global.get_url().serialize();
+ let protocols: Vec<String> = protocols.iter().map(|x| String::from(x.clone())).collect();
let connect_data = WebSocketConnectData {
resource_url: resource_url.clone(),
origin: origin,
+ protocols: protocols,
};
// Create the interface for communication with the resource task
@@ -246,13 +254,14 @@ impl WebSocket {
let moved_address = address.clone();
let sender = global.networking_task_source();
-
thread::spawn(move || {
while let Ok(event) = dom_event_receiver.recv() {
match event {
- WebSocketNetworkEvent::ConnectionEstablished => {
+ WebSocketNetworkEvent::ConnectionEstablished(headers, protocols) => {
let open_task = box ConnectionEstablishedTask {
addr: moved_address.clone(),
+ headers: headers,
+ protocols: protocols,
};
sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, open_task)).unwrap();
},
@@ -358,6 +367,11 @@ impl WebSocketMethods for WebSocket {
self.binary_type.set(btype)
}
+ // https://html.spec.whatwg.org/multipage/#dom-websocket-protocol
+ fn Protocol(&self) -> DOMString {
+ DOMString::from(self.protocol.borrow().clone())
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-websocket-send
fn Send(&self, data: USVString) -> Fallible<()> {
@@ -448,22 +462,42 @@ impl WebSocketMethods for WebSocket {
/// Task queued when *the WebSocket connection is established*.
struct ConnectionEstablishedTask {
addr: Trusted<WebSocket>,
+ protocols: Vec<String>,
+ headers: Headers,
}
impl Runnable for ConnectionEstablishedTask {
fn handler(self: Box<Self>) {
let ws = self.addr.root();
+ let global = ws.global.root();
+
// Step 1: Protocols.
+ if !self.protocols.is_empty() && self.headers.get::<WebSocketProtocol>().is_none() {
+ ws.failed.set(true);
+ ws.ready_state.set(WebSocketRequestState::Closing);
+ let task = box CloseTask {
+ addr: self.addr,
+ };
+ let sender = global.r().networking_task_source();
+ sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, task)).unwrap();
+ return;
+ }
// Step 2.
ws.ready_state.set(WebSocketRequestState::Open);
// Step 3: 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 {
+ *ws.protocol.borrow_mut() = protocol_name.to_owned();
+ };
+
// Step 5: Cookies.
// Step 6.
- let global = ws.global.root();
let event = Event::new(global.r(), atom!("open"),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable);