branch: externals/websocket
commit 2195e1247ecb04c30321702aa5f5618a51c329c5
Merge: 03d1cca4bd 3210187c10
Author: Andrew Hyatt <[email protected]>
Commit: GitHub <[email protected]>
Merge pull request #84 from ahyatt/monnier-improvements
Cleanups of obsolete functions, stylistic improvements
---
.gitignore | 5 ++
websocket-functional-test.el | 19 +++--
websocket-test.el | 174 +++++++++++++++++++++++--------------------
websocket.el | 120 ++++++++++++++++++-----------
4 files changed, 188 insertions(+), 130 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..a6ae3c855d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.elc
+
+# ELPA-generated files.
+/websocket-autoloads.el
+/websocket-pkg.el
diff --git a/websocket-functional-test.el b/websocket-functional-test.el
index 3d13694720..c14f4ae2b5 100644
--- a/websocket-functional-test.el
+++ b/websocket-functional-test.el
@@ -27,10 +27,9 @@
;; These tests are written to test the basic connectivity and message-sending.
;; Corner-cases and error handling is tested in websocket-test.el.
-(require 'tls) ;; tests a particular bug we had on Emacs 23
+(require 'nsm)
(require 'websocket)
-(require 'cl)
-(require 'f)
+(require 'ert)
;;; Code:
@@ -50,16 +49,18 @@ written to be used widely."
"Run the main part of an ert test against WSTEST-SERVER-URL."
;; the server may have an untrusted certificate, for the test to proceed, we
;; need to disable trust checking.
- (let* ((tls-checktrust nil)
- (wstest-closed nil)
+ (let* ((nsm-trust-local-network t)
+ ;; (wstest-closed nil)
(wstest-msg)
- (wstest-server-proc)
+ ;; (wstest-server-proc)
(wstest-ws
(websocket-open
wstest-server-url
:on-message (lambda (_websocket frame)
(setq wstest-msg (websocket-frame-text frame)))
- :on-close (lambda (_websocket) (setq wstest-closed t)))))
+ :on-close (lambda (_websocket)
+ ;; (setq wstest-closed t)
+ t))))
(should (websocket-test-wait-with-timeout 2 (websocket-openp wstest-ws)))
(should (websocket-test-wait-with-timeout 2 (eq 'open
(websocket-ready-state wstest-ws))))
(should (null wstest-msg))
@@ -70,7 +71,9 @@ written to be used widely."
;; Hack because we have to be able to find the testserver.py script.
(defconst websocket-ft-testserver (format "%s/testserver.py"
(file-name-directory
- (f-this-file))))
+ (if (fboundp 'macroexp-file-name)
+ (macroexp-file-name) ;Emacs-28
+ load-file-name))))
(ert-deftest websocket-client-with-local-server ()
;; If testserver.py cannot start, this test will fail.
diff --git a/websocket-test.el b/websocket-test.el
index 35589dd0a1..d9d6976180 100644
--- a/websocket-test.el
+++ b/websocket-test.el
@@ -24,11 +24,11 @@
(require 'ert)
(require 'websocket)
-(require 's)
-(eval-when-compile (require 'cl))
+;; (require 's)
+(eval-when-compile (require 'cl-lib))
(ert-deftest websocket-genbytes-length ()
- (loop repeat 100
+ (cl-loop repeat 100
do (should (= (string-bytes (websocket-genbytes 16)) 16))))
(ert-deftest websocket-calculate-accept ()
@@ -38,18 +38,21 @@
(websocket-calculate-accept "dGhlIHNhbXBsZSBub25jZQ=="))))
(defconst websocket-test-hello "\x81\x05\x48\x65\x6c\x6c\x6f"
- "'Hello' string example, taken from the RFC.")
+ "\"Hello\" string example, taken from the RFC.")
(defconst websocket-test-masked-hello
"\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58"
- "'Hello' masked string example, taken from the RFC.")
+ "\"Hello\" masked string example, taken from the RFC.")
(ert-deftest websocket-get-bytes ()
(should (equal #x5 (websocket-get-bytes "\x5" 1)))
(should (equal #x101 (websocket-get-bytes "\x1\x1" 2)))
(should (equal #xffffff
(websocket-get-bytes "\x0\x0\x0\x0\x0\xFF\xFF\xFF" 8)))
- (should-error (websocket-get-bytes "\x0\x0\x0\x1\x0\x0\x0\x1" 8)
+ (unless (fboundp 'bindat-type)
+ (should-error (websocket-get-bytes "\x0\x0\x0\x1\x0\x0\x0\x1" 8)
+ :type 'websocket-unparseable-frame))
+ (should-error (websocket-get-bytes "\x80\x0\x0\x0\x0\x0\x0\x0" 8)
:type 'websocket-unparseable-frame)
(should-error (websocket-get-bytes "\x0\x0\x0" 3))
(should-error (websocket-get-bytes "\x0" 2) :type
'websocket-unparseable-frame))
@@ -107,7 +110,7 @@
(- (length websocket-test-masked-hello) (+ i
1)))))))
(defun websocket-test-header-with-lines (&rest lines)
- (mapconcat 'identity (append lines '("\r\n")) "\r\n"))
+ (mapconcat #'identity (append lines '("\r\n")) "\r\n"))
(ert-deftest websocket-verify-response-code ()
(should (websocket-verify-response-code "HTTP/1.1 101"))
@@ -226,7 +229,7 @@
"Sec-WebSocket-Key: key\r\n"
"Sec-WebSocket-Version: 13\r\n")))
(cl-letf (((symbol-function 'url-cookie-generate-header-lines)
- (lambda (host localpart secure) "")))
+ (lambda (_host _localpart _secure) "")))
(should (equal (concat base-headers "\r\n")
(websocket-create-headers "ws://www.example.com/path"
"key" nil nil nil)))
@@ -266,20 +269,21 @@
(websocket-create-headers "ws://www.example.com:123/path" "key" nil nil
nil)))))
(ert-deftest websocket-process-headers ()
- (cl-flet ((url-cookie-handle-set-cookie
- (text)
- (should (equal text "foo=bar;"))
- ;; test that we have set the implicit buffer variable needed
- ;; by url-cookie-handle-set-cookie
- (should (equal url-current-object
- (url-generic-parse-url
"ws://example.com/path")))))
+ (cl-letf (((symbol-function 'url-cookie-handle-set-cookie)
+ (lambda (text)
+ (should (equal text "foo=bar;"))
+ ;; test that we have set the implicit buffer variable needed
+ ;; by url-cookie-handle-set-cookie
+ (should (equal url-current-object
+ (url-generic-parse-url
"ws://example.com/path"))))))
(websocket-process-headers "ws://example.com/path"
(concat
"HTTP/1.1 101 Switching Protocols\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Set-Cookie: foo=bar;\r\n\r\n")))
- (cl-flet ((url-cookie-handle-set-cookie (text) (should nil)))
+ (cl-letf (((symbol-function 'url-cookie-handle-set-cookie)
+ (lambda (_text) (should nil))))
(websocket-process-headers "ws://example.com/path"
"HTTP/1.1 101 Switching Protocols\r\n")))
@@ -289,7 +293,7 @@
(deleted)
(websocket (websocket-inner-create
:conn t :url t
- :on-message (lambda (websocket frame)
+ :on-message (lambda (_websocket frame)
(setq
processed
(websocket-frame-payload frame)))
@@ -305,7 +309,7 @@
processed))))
(setq sent nil)
(cl-letf (((symbol-function 'websocket-send)
- (lambda (websocket content) (setq sent content))))
+ (lambda (_websocket content) (setq sent content))))
(should (equal
(make-websocket-frame :opcode 'pong :payload "data" :completep
t)
(progn
@@ -314,7 +318,7 @@
:payload "data")))
sent))))
(cl-letf (((symbol-function 'delete-process)
- (lambda (conn) (setq deleted t))))
+ (lambda (_conn) (setq deleted t))))
(should (progn
(funcall
(websocket-process-frame websocket
@@ -325,10 +329,10 @@
(let* ((error-called)
(websocket (websocket-inner-create
:conn t :url t :accept-string t
- :on-message (lambda (websocket frame)
+ :on-message (lambda (_websocket _frame)
(message "In on-message")
(error "err"))
- :on-error (lambda (ws type err)
+ :on-error (lambda (_ws type _err)
(should (eq 'on-message type))
(setq error-called t)))))
(funcall (websocket-process-frame websocket
@@ -344,9 +348,12 @@
(should (equal 70000 (websocket-get-bytes (websocket-to-bytes 70000 8) 8)))
;; Only run if the number we're testing with is not more than the system can
;; handle.
- (if (equal "1" (calc-eval (format "536870912 < %d" most-positive-fixnum)))
+ (if (and (not (fboundp 'bindat-type))
+ (equal "1" (calc-eval (format "536870912 < %d"
most-positive-fixnum))))
(should-error (websocket-to-bytes 536870912 8)
:type 'websocket-frame-too-large))
+ (should-error (websocket-to-bytes (expt 2 63) 8)
+ :type 'websocket-frame-too-large)
(should-error (websocket-to-bytes 30 3))
(should-error (websocket-to-bytes 300 1))
;; I'd like to test the error for 32-byte systems on 8-byte lengths,
@@ -368,19 +375,22 @@
(websocket-read-frame
(websocket-encode-frame
(make-websocket-frame :opcode 'text
- :payload long-string) t)))))))
+ :payload long-string)
+ t)))))))
(cl-letf (((symbol-function 'websocket-genbytes)
- (lambda (n) (substring websocket-test-masked-hello 2 6))))
+ (lambda (_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) t))))
+ :completep t)
+ t))))
(should-not
(websocket-frame-completep
(websocket-read-frame
(websocket-encode-frame (make-websocket-frame :opcode 'text
:payload "Hello"
- :completep nil) t))))
+ :completep nil)
+ t))))
(should (equal 'close (websocket-frame-opcode
(websocket-read-frame
(websocket-encode-frame
@@ -422,10 +432,10 @@
(let ((sent-frames)
(processes-deleted))
(cl-letf (((symbol-function 'websocket-send)
- (lambda (websocket frame) (push frame sent-frames)))
+ (lambda (_websocket frame) (push frame sent-frames)))
((symbol-function 'websocket-openp)
- (lambda (websocket) t))
- ((symbol-function 'kill-buffer) (lambda (buffer) t))
+ (lambda (_websocket) t))
+ ((symbol-function 'kill-buffer) (lambda (_buffer) t))
((symbol-function 'delete-process)
(lambda (proc) (add-to-list 'processes-deleted proc))))
(websocket-close (websocket-inner-create
@@ -447,7 +457,7 @@
'open))
(setq open-callback-called t)
(error "Ignore me!"))
- :on-error (lambda (ws type err))))
+ :on-error (lambda (_ws _type _err) nil)))
(processed-frames)
(frame1 (make-websocket-frame :opcode 'text :payload "foo" :completep
t
:length 9))
@@ -458,12 +468,11 @@
(websocket-encode-frame frame1 t)
(websocket-encode-frame frame2 t))))
(cl-letf (((symbol-function 'websocket-process-frame)
- (lambda (websocket frame)
- (lexical-let ((frame frame))
- (lambda () (push frame processed-frames)))))
+ (lambda (_websocket frame)
+ (lambda () (push frame processed-frames))))
((symbol-function 'websocket-verify-headers)
- (lambda (websocket output) t))
- ((symbol-function 'websocket-close) (lambda (websocket) t)))
+ (lambda (_websocket _output) t))
+ ((symbol-function 'websocket-close) (lambda (_websocket) t)))
(websocket-outer-filter fake-ws "HTTP/1.1 101 Switching Protocols\r\n")
(websocket-outer-filter fake-ws "Sec-")
(should (eq (websocket-ready-state fake-ws) 'connecting))
@@ -477,10 +486,10 @@
(websocket-outer-filter fake-ws (substring websocket-frames 2))
(should (equal (list frame2 frame1) processed-frames))
(should-not (websocket-inflight-input fake-ws)))
- (cl-letf (((symbol-function 'websocket-close) (lambda (websocket) t)))
+ (cl-letf (((symbol-function 'websocket-close) (lambda (_websocket) t)))
(let ((on-error-called))
(setf (websocket-ready-state fake-ws) 'connecting)
- (setf (websocket-on-open fake-ws) (lambda (ws &rest _) t))
+ (setf (websocket-on-open fake-ws) (lambda (_ws &rest _) t))
(setf (websocket-on-error fake-ws)
(lambda (_ type err)
(should (eq type 'on-open))
@@ -494,15 +503,15 @@
(websocket-closed-calledp)
(fake-ws (websocket-inner-create
:conn t :url t :accept-string t
- :on-open (lambda (websocket)
+ :on-open (lambda (_websocket)
(setq on-open-calledp t)))))
(cl-letf (((symbol-function 'websocket-verify-response-code)
- (lambda (output) t))
+ (lambda (_output) t))
((symbol-function 'websocket-verify-headers)
- (lambda (websocket output) (error "Bad headers!")))
+ (lambda (_websocket _output) (error "Bad headers!")))
((symbol-function 'websocket-close)
- (lambda (websocket) (setq websocket-closed-calledp t))))
- (condition-case err
+ (lambda (_websocket) (setq websocket-closed-calledp t))))
+ (condition-case nil
(progn (websocket-outer-filter fake-ws "HTTP/1.1 101\r\n\r\n")
(error "Should have thrown an error!"))
(error
@@ -510,14 +519,15 @@
(should websocket-closed-calledp))))))
(ert-deftest websocket-outer-filter-fragmented-header ()
- (let* ((on-open-calledp)
- (websocket-closed-calledp)
+ (let* (;; (on-open-calledp)
+ ;; (websocket-closed-calledp)
(fake-ws (websocket-inner-create
:protocols '("websocket")
:conn t :url t :accept-string "17hG/VoPPd14L9xPSI7LtEr7PQc="
- :on-open (lambda (websocket)
- (setq on-open-calledp t)))))
- (cl-letf (((symbol-function 'websocket-close) (lambda (websocket) t)))
+ :on-open (lambda (_websocket)
+ ;; (setq on-open-calledp t)
+ t))))
+ (cl-letf (((symbol-function 'websocket-close) (lambda (_websocket) t)))
(websocket-outer-filter fake-ws "HTTP/1.1 101 Web Socket Protocol
Handsh")
(websocket-outer-filter fake-ws "ake\r\nConnection: Upgrade\r\n")
(websocket-outer-filter fake-ws "Upgrade: websocket\r\n")
@@ -526,7 +536,7 @@
(ert-deftest websocket-send-text ()
(cl-letf (((symbol-function 'websocket-send)
- (lambda (ws frame)
+ (lambda (_ws frame)
(should (equal
(websocket-frame-payload frame)
"\344\275\240\345\245\275")))))
@@ -534,9 +544,9 @@
(ert-deftest websocket-send ()
(let ((ws (websocket-inner-create :conn t :url t :accept-string t)))
- (cl-letf (((symbol-function 'websocket-ensure-connected) (lambda
(websocket) t))
- ((symbol-function 'websocket-openp) (lambda (websocket) t))
- ((symbol-function 'process-send-string) (lambda (conn string)
t)))
+ (cl-letf (((symbol-function 'websocket-ensure-connected) (lambda
(_websocket) t))
+ ((symbol-function 'websocket-openp) (lambda (_websocket) t))
+ ((symbol-function 'process-send-string) (lambda (_conn _string)
t)))
;; Just make sure there is no error.
(websocket-send ws (make-websocket-frame :opcode 'ping
:completep t)))
@@ -554,17 +564,17 @@
(ert-deftest websocket-ensure-handshake ()
(let ((sent-string nil))
(cl-letf (((symbol-function 'process-send-string)
- (lambda (proc string) (setq sent-string string)))
+ (lambda (_proc string) (setq sent-string string)))
((symbol-function 'process-get)
- (lambda (proc sym)
+ (lambda (_proc _sym)
(websocket-inner-create
:conn t :url t :accept-string "key")))
((symbol-function 'process-status)
- (lambda (proc) 'run)))
+ (lambda (_proc) 'run)))
(websocket-ensure-handshake "ws://example.com?query=1"
'conn 'key nil
nil nil nil)
- (should (s-starts-with-p "GET /?query=1 HTTP/1.1\r\n" sent-string)))))
+ (should (string-prefix-p "GET /?query=1 HTTP/1.1\r\n" sent-string)))))
(ert-deftest websocket-verify-client-headers ()
(let* ((http "HTTP/1.1")
@@ -580,20 +590,22 @@
(should (equal
'(:key "key" :protocols ("protocol") :extensions ("foo" "bar;
baz=2"))
(websocket-verify-client-headers
- (mapconcat 'identity (append (list http "" protocol extensions1
extensions2)
- all-required-headers) "\r\n"))))
+ (mapconcat #'identity (append (list http "" protocol extensions1
extensions2)
+ all-required-headers)
+ "\r\n"))))
(should (websocket-verify-client-headers
- (mapconcat 'identity
- (mapcar 'upcase
+ (mapconcat #'identity
+ (mapcar #'upcase
(append (list http "" protocol extensions1
extensions2)
- all-required-headers)) "\r\n")))
+ all-required-headers))
+ "\r\n")))
(dolist (header all-required-headers)
(should-not (websocket-verify-client-headers
- (mapconcat 'identity (append (list http "")
+ (mapconcat #'identity (append (list http "")
(remove header
all-required-headers))
"\r\n"))))
(should-not (websocket-verify-client-headers
- (mapconcat 'identity (append (list "HTTP/1.0" "")
all-required-headers)
+ (mapconcat #'identity (append (list "HTTP/1.0" "")
all-required-headers)
"\r\n")))))
(ert-deftest websocket-intersect ()
@@ -627,18 +639,20 @@
(should (string-match "Sec-Websocket-Extensions: seb\r\n" output)))))
(ert-deftest websocket-server-filter ()
- (let ((on-open-called)
+ (let (;; (on-open-called)
(ws (websocket-inner-create :conn t :url t :accept-string "key"
- :on-open (lambda (ws) (setq on-open-called
t))))
+ :on-open (lambda (_ws)
+ ;; (setq on-open-called t)
+ t)))
(closed)
(response)
(processed))
- (cl-letf (((symbol-function 'process-send-string) (lambda (p text) (setq
response text)))
- ((symbol-function 'websocket-close) (lambda (ws) (setq closed
t)))
- ((symbol-function 'process-get) (lambda (process sym) ws)))
+ (cl-letf (((symbol-function 'process-send-string) (lambda (_p text) (setq
response text)))
+ ((symbol-function 'websocket-close) (lambda (_ws) (setq closed
t)))
+ ((symbol-function 'process-get) (lambda (_process _sym) ws)))
;; Bad request, in two parts
(cl-letf (((symbol-function 'websocket-verify-client-headers)
- (lambda (text) nil)))
+ (lambda (_text) nil)))
(websocket-server-filter nil "HTTP/1.0 GET /foo \r\n")
(should-not closed)
(websocket-server-filter nil "\r\n")
@@ -649,12 +663,12 @@
response nil)
(setf (websocket-inflight-input ws) nil)
(cl-letf (((symbol-function 'websocket-verify-client-headers)
- (lambda (text) t))
+ (lambda (_text) t))
((symbol-function 'websocket-get-server-response)
- (lambda (ws protocols extensions)
+ (lambda (_ws _protocols _extensions)
"response"))
((symbol-function 'websocket-process-input-on-open-ws)
- (lambda (ws text)
+ (lambda (_ws text)
(setq processed t)
(should
(equal text websocket-test-hello)))))
@@ -725,16 +739,18 @@
(should (eq 'conn-a (websocket-conn (car websocket-server-websockets))))))
(ert-deftest websocket-default-error-handler ()
- (cl-letf (((symbol-function 'try-error)
- (lambda (callback-type err expected-message)
- (cl-flet ((display-warning
- (type message &optional level buffer-name)
+ ;; `cl-flet' creates a function definition for the current lexical
+ ;; scope, whereas `cl-letf' overrides a global binding, like
+ ;; a dynamically-scoped definition.
+ (cl-flet ((try-error (callback-type err expected-message)
+ (cl-letf (((symbol-function 'display-warning)
+ (lambda (type message &optional level _buffer-name)
(should (eq type 'websocket))
(should (eq level :error))
- (should (string= message expected-message))))
- (websocket-default-error-handler nil
- callback-type
- err)))))
+ (should (string= message expected-message)))))
+ (websocket-default-error-handler nil
+ callback-type
+ err))))
(try-error
'on-message
'(end-of-buffer)
diff --git a/websocket.el b/websocket.el
index afa17c4b85..b572b19300 100644
--- a/websocket.el
+++ b/websocket.el
@@ -189,13 +189,21 @@ This is based on the KEY from the Sec-WebSocket-Key
header."
(base64-encode-string
(sha1 (concat key websocket-guid) nil nil t)))
+(defmacro websocket--if-when-compile (cond then else)
+ (declare (debug t) (indent 2))
+ (if (eval cond t) then else))
+
(defun websocket-get-bytes (s n)
"From string S, retrieve the value of N bytes.
Return the value as an unsigned integer. The value N must be a
power of 2, up to 8.
-We support getting frames up to 536870911 bytes (2^29 - 1),
-approximately 537M long."
+In Emacs<28, we support getting frames only up to 536870911 bytes (2^29 - 1),
+approximately 537M long.
+
+This is only used in situations where `bindat-type' is not available."
+ (unless (memq n '(1 2 4 8))
+ (error "websocket-get-bytes: Unknown N: %S" n))
(if (= n 8)
(let* ((32-bit-parts
(bindat-get-field (bindat-unpack '((:val vec 2 u32)) s) :val))
@@ -224,33 +232,39 @@ approximately 537M long."
:val)))
(defun websocket-to-bytes (val nbytes)
- "Encode the integer VAL in NBYTES of data.
+ "Encode the unsigned integer VAL in NBYTES of data.
NBYTES much be a power of 2, up to 8.
-This supports encoding values up to 536870911 bytes (2^29 - 1),
-approximately 537M long."
- (when (and (< nbytes 8)
- (> val (expt 2 (* 8 nbytes))))
+In Emacs<28, this supports encoding values only up to 536870911 bytes
+\(2^29 - 1), approximately 537M long."
+ (unless (memq nbytes '(1 2 4 8))
+ (error "websocket-to-bytes: Unknown NBYTES: %S" nbytes))
+ (unless (= 0 (ash val (- (* 8 nbytes))))
;; not a user-facing error, this must be caused from an error in
;; this library
(error "websocket-to-bytes: Value %d could not be expressed in %d bytes"
val nbytes))
- (if (= nbytes 8)
+ (websocket--if-when-compile (fboundp 'bindat-type)
(progn
- (let* ((hi-32bits (ash val -32))
- ;; This is just VAL on systems that don't have >= 32 bits.
- (low-32bits (- val (ash hi-32bits 32))))
- (when (or (> hi-32bits 0) (> (ash low-32bits -29) 0))
+ (if (and (= nbytes 8) (> (ash val -63) 0))
(signal 'websocket-frame-too-large (list val)))
- (bindat-pack `((:val vec 2 u32))
- `((:val . [,hi-32bits ,low-32bits])))))
- (bindat-pack
- `((:val ,(cond ((= nbytes 1) 'u8)
- ((= nbytes 2) 'u16)
- ((= nbytes 4) 'u32)
- ;; Library error, not system error
- (t (error "websocket-to-bytes: Unknown NBYTES: %S"
nbytes)))))
- `((:val . ,val)))))
+ (bindat-pack (bindat-type uint (* 8 nbytes)) val))
+ (if (= nbytes 8)
+ (progn
+ (let* ((hi-32bits (ash val -32))
+ ;; This is just VAL on systems that don't have >= 32 bits.
+ (low-32bits (- val (ash hi-32bits 32))))
+ (when (or (> hi-32bits 0) (> (ash low-32bits -29) 0))
+ (signal 'websocket-frame-too-large (list val)))
+ (bindat-pack `((:val vec 2 u32))
+ `((:val . [,hi-32bits ,low-32bits])))))
+ (bindat-pack
+ `((:val ,(cond ((= nbytes 1) 'u8)
+ ((= nbytes 2) 'u16)
+ ((= nbytes 4) 'u32)
+ ;; Library error, not system error
+ (t (error "websocket-to-bytes: Unknown NBYTES: %S"
nbytes)))))
+ `((:val . ,val))))))
(defun websocket-get-opcode (s)
"Retrieve the opcode from first byte of string S."
@@ -268,14 +282,29 @@ approximately 537M long."
We start at position 0, and return a cons of the payload length and how
many bytes were consumed from the string."
(websocket-ensure-length s 1)
- (let* ((initial-val (logand 127 (aref s 0))))
- (cond ((= initial-val 127)
- (websocket-ensure-length s 9)
- (cons (websocket-get-bytes (substring s 1) 8) 9))
- ((= initial-val 126)
- (websocket-ensure-length s 3)
- (cons (websocket-get-bytes (substring s 1) 2) 3))
- (t (cons initial-val 1)))))
+ (websocket--if-when-compile (fboundp 'bindat-type)
+ (bindat-unpack
+ (bindat-type
+ (len1-raw u8)
+ (len1 unit (logand 127 len1-raw))
+ (len2len unit (pcase len1 (127 8) (126 2) (_ 0)))
+ (len2 uint (progn
+ (websocket-ensure-length s (1+ len2len))
+ (* 8 len2len)))
+ :unpack-val (cons (if (< len1 126) len1
+ (if (and (= len2len 8) (> (ash len2 -63) 0))
+ (signal 'websocket-unparseable-frame (list
"MSB must be 0 for 64-bit length"))
+ len2))
+ (1+ len2len)))
+ s)
+ (let* ((initial-val (logand 127 (aref s 0))))
+ (cond ((= initial-val 127)
+ (websocket-ensure-length s 9)
+ (cons (websocket-get-bytes (substring s 1) 8) 9))
+ ((= initial-val 126)
+ (websocket-ensure-length s 3)
+ (cons (websocket-get-bytes (substring s 1) 2) 3))
+ (t (cons initial-val 1))))))
(cl-defstruct websocket-frame opcode payload length completep)
@@ -330,9 +359,11 @@ We mask the frame or not, depending on SHOULD-MASK."
(when (and payloadp (>= (length payload) 126))
(append (websocket-to-bytes
(length payload)
- (cond ((< (length payload) 126) 1)
+ (cond ((< (length payload) 126)
+ 1) ;FIXME: 0? Impossible?
((< (length payload) 65536) 2)
- (t 8))) nil))
+ (t 8)))
+ nil))
(when (and payloadp should-mask)
(append mask-key nil))
(when payloadp
@@ -695,7 +726,7 @@ to the websocket protocol.
:on-close on-close
:on-error on-error
:protocols protocols
- :extensions (mapcar 'car extensions)
+ :extensions (mapcar #'car extensions)
:accept-string
(websocket-calculate-accept key))))
(unless conn (error "Could not establish the websocket connection to %s"
url))
@@ -744,11 +775,12 @@ to the websocket protocol.
(defun websocket-process-headers (url headers)
"On opening URL, process the HEADERS sent from the server."
- (when (string-match "Set-Cookie: \(.*\)\r\n" headers)
- ;; The url-current-object is assumed to be set by
- ;; url-cookie-handle-set-cookie.
- (let ((url-current-object (url-generic-parse-url url)))
- (url-cookie-handle-set-cookie (match-string 1 headers)))))
+ (when (string-match "Set-Cookie: \\(.*\\)\r\n" headers)
+ (let ((cookie (match-string 1 headers))
+ ;; The url-current-object is assumed to be set by
+ ;; url-cookie-handle-set-cookie.
+ (url-current-object (url-generic-parse-url url)))
+ (url-cookie-handle-set-cookie cookie))))
(defun websocket-outer-filter (websocket output)
"Filter the WEBSOCKET server's OUTPUT.
@@ -854,8 +886,8 @@ connection, which should be kept in order to pass to
:server t
:family 'ipv4
:noquery t
- :filter 'websocket-server-filter
- :log 'websocket-server-accept
+ :filter #'websocket-server-filter
+ :log #'websocket-server-accept
:filter-multibyte nil
:plist plist
:host (plist-get plist :host)
@@ -893,7 +925,7 @@ connection, which should be kept in order to pass to
:on-error (or (process-get server :on-error)
'websocket-default-error-handler)
:protocols (process-get server :protocol)
- :extensions (mapcar 'car (process-get server :extensions)))))
+ :extensions (mapcar #'car (process-get server :extensions)))))
(unless (member ws websocket-server-websockets)
(push ws websocket-server-websockets))
(process-put client :websocket ws)
@@ -939,7 +971,7 @@ All these parameters are defined as in `websocket-open'."
(car ext)
(when (cdr ext) "; ")
(when (cdr ext)
- (mapconcat 'identity (cdr ext) "; "))))
+ (mapconcat #'identity (cdr ext) "; "))))
extensions ", "))))
host-port
key
@@ -965,7 +997,8 @@ All these parameters are defined as in `websocket-open'."
(concat
(mapconcat
(lambda (protocol) (format "Sec-WebSocket-Protocol: %s"
- protocol)) protocols separator)
+ protocol))
+ protocols separator)
separator)))
(let ((extensions (websocket-intersect
client-extensions
@@ -974,7 +1007,8 @@ All these parameters are defined as in `websocket-open'."
(concat
(mapconcat
(lambda (extension) (format "Sec-Websocket-Extensions: %s"
- extension)) extensions separator)
+ extension))
+ extensions separator)
separator)))
separator)))