Permalink
Browse files

Support outbound masking

  • Loading branch information...
1 parent 75a53f1 commit 655cf1e26a4d6f4a44ee8e92f0d84ab7daca7a07 @ahyatt committed May 23, 2012
Showing with 57 additions and 36 deletions.
  1. +17 −11 websocket-test.el
  2. +40 −25 websocket.el
View
@@ -171,17 +171,23 @@
(ert-deftest websocket-encode-frame ()
;; We've tested websocket-read-frame, now we can use that to help
;; test websocket-encode-frame.
- (should (equal
- websocket-test-hello
- (websocket-encode-frame
- (make-websocket-frame :opcode 'text :payload "Hello" :completep t))))
- (dolist (len '(200 70000))
- (let ((long-string (make-string len ?x)))
- (should (equal long-string
- (websocket-frame-payload
- (websocket-read-frame
- (websocket-encode-frame
- (make-websocket-frame :opcode 'text :payload long-string))))))))
+ (let ((websocket-mask-frames nil))
+ (should (equal
+ websocket-test-hello
+ (websocket-encode-frame
+ (make-websocket-frame :opcode 'text :payload "Hello" :completep t))))
+ (dolist (len '(200 70000))
+ (let ((long-string (make-string len ?x)))
+ (should (equal long-string
+ (websocket-frame-payload
+ (websocket-read-frame
+ (websocket-encode-frame
+ (make-websocket-frame :opcode 'text :payload long-string)))))))))
+ (let ((websocket-mask-frames t))
+ (flet ((websocket-genbytes (n) (substring websocket-test-masked-hello 2 6)))
+ (should (equal websocket-test-masked-hello
+ (websocket-encode-frame
+ (make-websocket-frame :opcode 'text :payload "Hello" :completep t))))))
(should-not
(websocket-frame-completep
(websocket-read-frame
View
@@ -52,16 +52,21 @@ URL of the connection.")
"If true, we require the correct Sec-WebSocket-Accept header
as part of the connection handshake.")
-(defun websocket-genbytes ()
- "Generate bytes used at the end of the handshake."
- (let ((s " "))
- (dotimes (i 16)
+(defvar websocket-mask-frames t
+ "If true, we mask frames as defined in the spec. This is
+recommended to be true, and some servers will refuse to
+communicate with unmasked clients.")
+
+(defun websocket-genbytes (nbytes)
+ "Generate NBYTES random bytes."
+ (let ((s (make-string nbytes ?\s)))
+ (dotimes (i nbytes)
(aset s i (random 256)))
s))
(defun websocket-genkey ()
"Generate a key suitable for the websocket handshake."
- (base64-encode-string (websocket-genbytes)))
+ (base64-encode-string (websocket-genbytes 16)))
(defun websocket-calculate-accept (key)
"Calculate the expect value of the accept header.
@@ -159,26 +164,36 @@ Otherwise we throw the error `websocket-incomplete-frame'."
(let* ((opcode (websocket-frame-opcode frame))
(payload (websocket-frame-payload frame))
(fin (websocket-frame-completep frame))
- (payloadp (memq opcode '(continuation text binary))))
- (concat (unibyte-string (logior
- (cond ((eq opcode 'continuation) 0)
- ((eq opcode 'text) 1)
- ((eq opcode 'binary 2))
- ((eq opcode 'close 8))
- ((eq opcode 'ping 9))
- ((eq opcode 'pong 10)))
- (if fin 128 0)))
- (when payloadp
- (cond ((< (length payload) 126) nil)
- ((< (length payload) 65536) (unibyte-string 126))
- (t (unibyte-string 127))))
- (when payloadp
- (websocket-to-bytes (length payload)
- (cond ((< (length payload) 126) 1)
- ((< (length payload) 65536) 2)
- ((t 8)))))
- (when payloadp
- payload))))
+ (payloadp (memq opcode '(continuation text binary)))
+ (mask-key (when websocket-mask-frames (websocket-genbytes 4))))
+ (apply 'unibyte-string
+ (append (list
+ (logior (cond ((eq opcode 'continuation) 0)
+ ((eq opcode 'text) 1)
+ ((eq opcode 'binary 2))
+ ((eq opcode 'close 8))
+ ((eq opcode 'ping 9))
+ ((eq opcode 'pong 10)))
+ (if fin 128 0)))
+ (when payloadp
+ (list
+ (logior
+ (if websocket-mask-frames 128 0)
+ (cond ((< (length payload) 126) (length payload))
+ ((< (length payload) 65536) 126)
+ (t 127)))))
+ (when (and payloadp (>= (length payload) 126))
+ (append (websocket-to-bytes (length payload)
+ (cond ((< (length payload) 126) 1)
+ ((< (length payload) 65536) 2)
+ (t 8))) nil))
+ (when websocket-mask-frames
+ (append mask-key nil))
+ (when payloadp
+ (append (if websocket-mask-frames
+ (websocket-mask mask-key payload)
+ payload)
+ nil))))))
(defun websocket-read-frame (s)
"Read a frame and return a `websocket-frame' struct with the contents.

0 comments on commit 655cf1e

Please sign in to comment.