accept-string
(inflight-input nil))
-(defvar websocket-version "1.1"
+(defvar websocket-version "1.2"
"Version numbers of this version of websocket.el.")
(defvar websocket-debug nil
"The websocket GUID as defined in RFC 6455.
Do not change unless the RFC changes.")
-(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.")
-
(defvar websocket-callback-debug-on-error nil
"If true, when an error happens in a client callback, invoke the debugger.
Having this on can cause issues with missing frames if the debugger is
(when (< (length s) n)
(throw 'websocket-incomplete-frame nil)))
-(defun websocket-encode-frame (frame)
- "Encode the FRAME struct to the binary representation."
+(defun websocket-encode-frame (frame should-mask)
+ "Encode the FRAME struct to the binary representation.
+We mask the frame or not, depending on SHOULD-MASK."
(let* ((opcode (websocket-frame-opcode frame))
(payload (websocket-frame-payload frame))
(fin (websocket-frame-completep frame))
(payloadp (memq opcode '(continuation text binary)))
- (mask-key (when websocket-mask-frames (websocket-genbytes 4))))
+ (mask-key (when should-mask (websocket-genbytes 4))))
(apply 'unibyte-string
(append (list
(logior (cond ((eq opcode 'continuation) 0)
(when payloadp
(list
(logior
- (if websocket-mask-frames 128 0)
+ (if should-mask 128 0)
(cond ((< (length payload) 126) (length payload))
((< (length payload) 65536) 126)
(t 127)))))
(cond ((< (length payload) 126) 1)
((< (length payload) 65536) 2)
(t 8))) nil))
- (when (and payloadp websocket-mask-frames)
+ (when (and payloadp should-mask)
(append mask-key nil))
(when payloadp
- (append (if websocket-mask-frames
- (websocket-mask mask-key payload)
+ (append (if should-mask (websocket-mask mask-key payload)
payload)
nil))))))
(unless (websocket-openp websocket)
(signal 'websocket-closed frame))
(process-send-string (websocket-conn websocket)
- (websocket-encode-frame frame)))
+ ;; We mask only when we're a client, following the spec.
+ (websocket-encode-frame frame (not (websocket-server-p websocket)))))
(defun websocket-openp (websocket)
"Check WEBSOCKET and return non-nil if it is open, and either
(defun websocket-close (websocket)
"Close WEBSOCKET and erase all the old websocket data."
(websocket-debug websocket "Closing websocket")
+ (websocket-try-callback 'websocket-on-close 'on-close websocket)
(when (websocket-openp websocket)
(websocket-send websocket
(make-websocket-frame :opcode 'close
conn
(lambda (process change)
(let ((websocket (process-get process :websocket)))
- (websocket-debug websocket
- "State change to %s" change)
- (unless (eq 'closed (websocket-ready-state websocket))
+ (websocket-debug websocket "State change to %s" change)
+ (when (and
+ (member (process-status process) '(closed failed exit signal))
+ (not (eq 'closed (websocket-ready-state websocket))))
(websocket-try-callback 'websocket-on-close 'on-close websocket)))))
(set-process-query-on-exit-flag conn nil)
(process-send-string conn
:server-conn server
:conn client
:url client
+ :server-p t
:on-open (or (process-get server :on-open) 'identity)
:on-message (or (process-get server :on-message) (lambda (_ws _frame)))
:on-close (lexical-let ((user-method
(lambda (process change)
(let ((websocket (process-get process :websocket)))
(websocket-debug websocket "State change to %s" change)
- (unless (eq 'closed (websocket-ready-state websocket))
+ (when (and
+ (member (process-status process) '(closed failed exit signal))
+ (not (eq 'closed (websocket-ready-state websocket))))
(websocket-try-callback 'websocket-on-close 'on-close websocket)))))))
(defun websocket-create-headers (url key protocol extensions)