[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] 77/119: handle chunked receipt of web-socket messages
From: |
Eric Schulte |
Subject: |
[elpa] 77/119: handle chunked receipt of web-socket messages |
Date: |
Mon, 10 Mar 2014 16:57:42 +0000 |
eschulte pushed a commit to branch master
in repository elpa.
commit 2f71a3ceec9e518ace3e9858ec1ee54633515277
Author: Eric Schulte <address@hidden>
Date: Tue Jan 7 01:20:09 2014 -0700
handle chunked receipt of web-socket messages
---
examples/9-web-socket.el | 2 +-
web-server.el | 101 ++++++++++++++++++++++++++++-----------------
2 files changed, 64 insertions(+), 39 deletions(-)
diff --git a/examples/9-web-socket.el b/examples/9-web-socket.el
index 62e6d33..25408d6 100644
--- a/examples/9-web-socket.el
+++ b/examples/9-web-socket.el
@@ -35,7 +35,7 @@ function close(){ ws.close(); };
(cons "Sec-WebSocket-Accept"
(ws-web-socket-handshake
(cdr (assoc :SEC-WEBSOCKET-KEY headers)))))
- (set-process-plist process (list :pending ""))
+ (set-process-plist process (list :parsed "" :pending nil :active nil))
(set-process-coding-system process 'binary)
(set-process-filter process 'ws-web-socket-filter)
:keep-alive)
diff --git a/web-server.el b/web-server.el
index fad4c83..f4729e1 100644
--- a/web-server.el
+++ b/web-server.el
@@ -352,44 +352,69 @@ Return non-nil only when parsing is complete."
(defun ws-web-socket-filter (proc string)
"Web socket filter to pass whole frames to the client.
See RFC6455."
- (let ((index 0))
- (cl-flet ((bits (length)
- (apply #'append
- (mapcar (lambda (int) (int-to-bits int 8))
- (subseq string index (incf index
length))))))
- (let ((data (plist-get (process-plist proc) :pending))
- fin rsvs opcode mask pl mask-key)
- (let ((byte (bits 1)))
- (setq fin (car byte)
- rsvs (subseq byte 1 4)
- opcode (let ((it (bits-to-int (subseq byte 4))))
- (case it
- (0 :CONTINUATION)
- (1 :TEXT)
- (2 :BINARY)
- ((3 4 5 6 7) :NON-CONTROL)
- (9 :PING)
- (10 :PONG)
- ((11 12 13 14 15) :CONTROL)
- (t (ws-error proc "Web Socket Fail: bad opcode %d"
- it))))))
- (unless (cl-every #'null rsvs)
- (ws-error proc "Web Socket Fail: non-zero RSV 1 2 or 3"))
- (let ((byte (bits 1)))
- (setq mask (car byte)
- pl (bits-to-int (subseq byte 1))))
- (unless (eq mask t)
- (ws-error proc "Web Socket Fail: client must mask data"))
- (cond
- ((= pl 126) (setq pl (bits-to-int (bits 2))))
- ((= pl 127) (setq pl (bits-to-int (bits 8)))))
- (when mask (setq mask-key (subseq string index (incf index 4))))
- (setq data (concat data
- (ws/web-socket-mask
- mask-key (subseq string index (+ index pl)))))
- (if fin
- (message "received message %S" data)
- (set-process-plist proc (list :data data)))))))
+ (catch 'wait ; TODO: this needs more complete partial input handling
+ (when (plist-get (process-plist proc) :active)
+ (let ((pending (plist-get (process-plist proc) :pending)))
+ (set-process-plist proc
+ (plist-put (process-plist proc)
+ :pending (concat pending string))))
+ (throw 'wait nil))
+ ;; set to active
+ (set-process-plist proc (plist-put (process-plist proc) :active t))
+ (let ((index 0))
+ (cl-flet ((bits (length)
+ (apply #'append
+ (mapcar (lambda (int) (int-to-bits int 8))
+ (subseq string index (incf index
length))))))
+ (let ((data (plist-get (process-plist proc) :parsed))
+ fin rsvs opcode mask pl mask-key)
+ (let ((byte (bits 1)))
+ (setq fin (car byte)
+ rsvs (subseq byte 1 4)
+ opcode
+ (let ((it (bits-to-int (subseq byte 4))))
+ (case it
+ (0 :CONTINUATION)
+ (1 :TEXT)
+ (2 :BINARY)
+ ((3 4 5 6 7) :NON-CONTROL)
+ (9 :PING)
+ (10 :PONG)
+ ((11 12 13 14 15) :CONTROL)
+ ;; If an unknown opcode is received, the receiving
+ ;; endpoint MUST _Fail the WebSocket Connection_.
+ (t (ws-error proc "Web Socket Fail: bad opcode %d"
it))))))
+ (unless (cl-every #'null rsvs)
+ ;; MUST be 0 unless an extension is negotiated that defines
+ ;; meanings for non-zero values.
+ (ws-error proc "Web Socket Fail: non-zero RSV 1 2 or 3"))
+ (let ((byte (bits 1)))
+ (setq mask (car byte)
+ pl (bits-to-int (subseq byte 1))))
+ (unless (eq mask t)
+ ;; All frames sent from client to server have this bit set to 1.
+ (ws-error proc "Web Socket Fail: client must mask data"))
+ (cond
+ ((= pl 126) (setq pl (bits-to-int (bits 2))))
+ ((= pl 127) (setq pl (bits-to-int (bits 8)))))
+ (when mask (setq mask-key (subseq string index (incf index 4))))
+ (setq data (concat data
+ (ws/web-socket-mask
+ mask-key (subseq string index (+ index pl)))))
+ ;; set to inactive
+ (set-process-plist proc (plist-put (process-plist proc) :active nil))
+ (if fin
+ ;; call the web-socket handler
+ (message "received message %S" data)
+ ;; add parsed data to the process plist
+ (let ((plist (process-plist proc)))
+ (set-process-plist
+ (plist-put plist :parsed (concat (plist-get plist :parsed)
+ data))))
+ ;; possibly parse pending input
+ (when (plist-get (process-plist proc) :pending)
+ (ws-web-socket-filter
+ proc (plist-get (process-plist proc) :pending)))))))))
;;; Convenience functions to write responses
- [elpa] 66/119: notes, (continued)
- [elpa] 66/119: notes, Eric Schulte, 2014/03/10
- [elpa] 70/119: run all tests with "make check", Eric Schulte, 2014/03/10
- [elpa] 67/119: test large file upload (w/o network chunking), Eric Schulte, 2014/03/10
- [elpa] 69/119: refactoring no multiple concurrent header parsing, Eric Schulte, 2014/03/10
- [elpa] 71/119: updating notes and README text, Eric Schulte, 2014/03/10
- [elpa] 72/119: notes for running behind an Apache HTTPS proxy, Eric Schulte, 2014/03/10
- [elpa] 73/119: some more examples to implement, Eric Schulte, 2014/03/10
- [elpa] 68/119: no multiple concurrent entry of ws-parse-request, Eric Schulte, 2014/03/10
- [elpa] 76/119: and more web-socket progress, Eric Schulte, 2014/03/10
- [elpa] 74/119: beginning to implement web-socket support, Eric Schulte, 2014/03/10
- [elpa] 77/119: handle chunked receipt of web-socket messages,
Eric Schulte <=
- [elpa] 78/119: hold, Eric Schulte, 2014/03/10
- [elpa] 79/119: beginning to add convenience macro for web sockets, Eric Schulte, 2014/03/10
- [elpa] 81/119: implemented ws-web-socket-frame to send replies, Eric Schulte, 2014/03/10
- [elpa] 80/119: helpers for handling web socket connections, Eric Schulte, 2014/03/10
- [elpa] 82/119: web-sockets are working, Eric Schulte, 2014/03/10
- [elpa] 84/119: more examples, Eric Schulte, 2014/03/10
- [elpa] 85/119: renaming example files, Eric Schulte, 2014/03/10
- [elpa] 86/119: another example idea -- org export service, Eric Schulte, 2014/03/10
- [elpa] 87/119: update server stopping w/requests process field, Eric Schulte, 2014/03/10
- [elpa] 83/119: supports web sockets, Eric Schulte, 2014/03/10