branch: master commit 24e896d50356e0545642dbbf6ef69d90b2e97f5a Author: Andrew Hyatt <ahy...@gmail.com> Commit: Andrew Hyatt <ahy...@gmail.com>
Update to emacs-websocket version 1.8. * websocket.el (websocket-mask): Mask multibyte characters correctly. * websocket.el (websocket-server): Don't ask to terminate the connection. * websocket-functional-test.el: Test out multibyte characters. * websocket-functional-test.el: Disable trust checking for echo server connection. --- packages/websocket/websocket-functional-test.el | 30 ++++++++++++++----------- packages/websocket/websocket.el | 24 +++++++++++++++----- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/packages/websocket/websocket-functional-test.el b/packages/websocket/websocket-functional-test.el index e447015..80eb004 100644 --- a/packages/websocket/websocket-functional-test.el +++ b/packages/websocket/websocket-functional-test.el @@ -52,8 +52,8 @@ (websocket-open "ws://127.0.0.1:9999" :on-message (lambda (_websocket frame) - (push (websocket-frame-payload frame) wstest-msgs) - (message "ws frame: %S" (websocket-frame-payload frame)) + (push (websocket-frame-text frame) wstest-msgs) + (message "ws frame: %S" (websocket-frame-text frame)) (error "Test error (expected)")) :on-close (lambda (_websocket) (setq wstest-closed t)))) @@ -67,10 +67,10 @@ (assert (null wstest-msgs)) -(websocket-send-text wstest-ws "Hi!") +(websocket-send-text wstest-ws "你好") (sleep-for 0.1) -(assert (equal (car wstest-msgs) "You said: Hi!")) +(assert (equal (car wstest-msgs) "You said: 你好")) (setf (websocket-on-error wstest-ws) (lambda (_ws _type _err))) (websocket-send-text wstest-ws "Hi after error!") (sleep-for 0.1) @@ -94,6 +94,10 @@ ;; Remote server test, with wss ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; echo.websocket.org has an untrusted certificate, for the test to +;; proceed, we need to disable trust checking. +(setq tls-checktrust nil) + (when (>= (string-to-number (substring emacs-version 0 2)) 24) (message "Testing with wss://echo.websocket.org") (when (eq system-type 'windows-nt) @@ -104,8 +108,8 @@ :on-open (lambda (_websocket) (message "Websocket opened")) :on-message (lambda (_websocket frame) - (push (websocket-frame-payload frame) wstest-msgs) - (message "ws frame: %S" (websocket-frame-payload frame))) + (push (websocket-frame-text frame) wstest-msgs) + (message "ws frame: %S" (websocket-frame-text frame))) :on-close (lambda (_websocket) (message "Websocket closed") (setq wstest-closed t))) @@ -131,24 +135,24 @@ :host 'local :on-message (lambda (ws frame) (message "Server received text!") - (websocket-send-text ws - (websocket-frame-payload frame))) + (websocket-send-text + ws (websocket-frame-text frame))) :on-open (lambda (_websocket) "Client connection opened!") :on-close (lambda (_websocket) (setq wstest-closed t))))) - (setq wstest-msgs nil wstest-ws (websocket-open "ws://localhost:9998" :on-message (lambda (_websocket frame) - (push (websocket-frame-payload frame) wstest-msgs) - (message "ws frame: %S" (websocket-frame-payload frame))))) + (message "ws frame: %S" (websocket-frame-text frame)) + (push + (websocket-frame-text frame) wstest-msgs)))) (assert (websocket-openp wstest-ws)) - (websocket-send-text wstest-ws "Hi to self!") + (websocket-send-text wstest-ws "你好") (sleep-for 0.3) - (assert (equal (car wstest-msgs) "Hi to self!")) + (assert (equal (car wstest-msgs) "你好")) (websocket-server-close server-conn)) (assert wstest-closed) (websocket-close wstest-ws) diff --git a/packages/websocket/websocket.el b/packages/websocket/websocket.el index 8db83c2..3784a30 100644 --- a/packages/websocket/websocket.el +++ b/packages/websocket/websocket.el @@ -4,7 +4,7 @@ ;; Author: Andrew Hyatt <ahy...@gmail.com> ;; Keywords: Communication, Websocket, Server -;; Version: 1.6 +;; Version: 1.8 ;; ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as @@ -279,14 +279,25 @@ many bytes were consumed from the string." (defstruct websocket-frame opcode payload length completep) +(defun websocket-frame-text (frame) + "Given FRAME, return the payload as a utf-8 encoded string." + (assert (websocket-frame-p frame)) + (decode-coding-string (websocket-frame-payload frame) 'utf-8)) + (defun websocket-mask (key data) "Using string KEY, mask string DATA according to the RFC. This is used to both mask and unmask data." - (apply - 'string - (loop for b across data - for i from 0 to (length data) - collect (logxor (websocket-get-bytes (substring key (mod i 4)) 1) b)))) + ;; If we don't make the string unibyte here, a string of bytes that should be + ;; interpreted as a unibyte string will instead be interpreted as a multibyte + ;; string of the same length (for example, 6 multibyte chars for 你好 instead + ;; of the correct 6 unibyte chars, which would convert into 2 multibyte + ;; chars). + (string-make-unibyte (apply + 'string + (loop for b across data + for i from 0 to (length data) + collect + (logxor (websocket-get-bytes (substring key (mod i 4)) 1) b))))) (defun websocket-ensure-length (s n) "Ensure the string S has at most N bytes. @@ -837,6 +848,7 @@ connection, which should be kept in order to pass to :name (format "websocket server on port %s" port) :server t :family 'ipv4 + :noquery t :filter 'websocket-server-filter :log 'websocket-server-accept :filter-multibyte nil