servo: Merge #8693 - Implement unspecified websocket close code (fixes issue #8158) (from yanirs:websocket-close-unspecified-status); r=jdm
authorYanir Seroussi <yanir.seroussi@gmail.com>
Thu, 03 Dec 2015 11:26:48 +0500
changeset 337695 41ce67418034d3f5756909411403c2af6d1966da
parent 337694 a4433e435c69fa33d65f714745aa5cd650a7b172
child 337696 398c91b462525a5ceb5fe57d2dce79c5edb1aa97
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
servo: Merge #8693 - Implement unspecified websocket close code (fixes issue #8158) (from yanirs:websocket-close-unspecified-status); r=jdm Fixes #8158. Source-Repo: https://github.com/servo/servo Source-Revision: 01b4deb9d14926e5ad3ebe3e7f839affc4951a63
servo/components/script/dom/websocket.rs
--- a/servo/components/script/dom/websocket.rs
+++ b/servo/components/script/dom/websocket.rs
@@ -121,16 +121,34 @@ const BLOCKED_PORTS_LIST: &'static [u16]
     636,  // ldap+ssl
     993,  // imap+ssl
     995,  // pop3+ssl
     2049, // nfs
     4045, // lockd
     6000, // x11
 ];
 
+// 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)]
+mod close_code {
+    pub const NORMAL: u16 = 1000;
+    pub const GOING_AWAY: u16 = 1001;
+    pub const PROTOCOL_ERROR: u16 = 1002;
+    pub const UNSUPPORTED_DATATYPE: u16 = 1003;
+    pub const NO_STATUS: u16 = 1005;
+    pub const ABNORMAL: u16 = 1006;
+    pub const INVALID_PAYLOAD: u16 = 1007;
+    pub const POLICY_VIOLATION: u16 = 1008;
+    pub const TOO_LARGE: u16 = 1009;
+    pub const EXTENSION_MISSING: u16 = 1010;
+    pub const INTERNAL_ERROR: u16 = 1011;
+    pub const TLS_FAILED: u16 = 1015;
+}
+
 #[dom_struct]
 pub struct WebSocket {
     eventtarget: EventTarget,
     url: Url,
     global: GlobalField,
     ready_state: Cell<WebSocketRequestState>,
     buffered_amount: Cell<u32>,
     clearing_buffer: Cell<bool>, //Flag to tell if there is a running task to clear buffered_amount
@@ -425,18 +443,18 @@ impl WebSocketMethods for WebSocket {
                 let code: u16 = this.code.get();
                 let reason = this.reason.borrow().clone();
                 let _ = sender.lock().unwrap().send_message(&Message::close_because(code, reason));
             }
         }
 
 
         if let Some(code) = code {
-            //Check code is NOT 1000 NOR in the range of 3000-4999 (inclusive)
-            if  code != 1000 && (code < 3000 || code > 4999) {
+            //Fail if the supplied code isn't normal and isn't reserved for libraries, frameworks, and applications
+            if code != close_code::NORMAL && (code < 3000 || code > 4999) {
                 return Err(Error::InvalidAccess);
             }
         }
         if let Some(ref reason) = reason {
             if reason.0.as_bytes().len() > 123 { //reason cannot be larger than 123 bytes
                 return Err(Error::Syntax);
             }
         }
@@ -449,19 +467,17 @@ impl WebSocketMethods for WebSocket {
                 self.failed.set(true);
                 send_close(self);
                 //Note: After sending the close message, the receive loop confirms a close message from the server and
                 //      must fire a close event
             }
             WebSocketRequestState::Open => {
                 //Closing handshake not started - still in open
                 //Start the closing by setting the code and reason if they exist
-                if let Some(code) = code {
-                    self.code.set(code);
-                }
+                self.code.set(code.unwrap_or(close_code::NO_STATUS));
                 if let Some(reason) = reason {
                     *self.reason.borrow_mut() = reason.0;
                 }
                 send_close(self);
                 //Note: After sending the close message, the receive loop confirms a close message from the server and
                 //      must fire a close event
             }
         }