[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] 79/119: beginning to add convenience macro for web sockets
From: |
Eric Schulte |
Subject: |
[elpa] 79/119: beginning to add convenience macro for web sockets |
Date: |
Mon, 10 Mar 2014 16:57:43 +0000 |
eschulte pushed a commit to branch master
in repository elpa.
commit 1c09b7327fcd077f04715bc35b6583ffb8162e07
Author: Eric Schulte <address@hidden>
Date: Tue Jan 7 01:40:39 2014 -0700
beginning to add convenience macro for web sockets
---
web-server.el | 149 +++++++++++++++++++++++++++++----------------------------
1 files changed, 75 insertions(+), 74 deletions(-)
diff --git a/web-server.el b/web-server.el
index e765be9..cbb68fc 100644
--- a/web-server.el
+++ b/web-server.el
@@ -351,80 +351,81 @@ Return non-nil only when parsing is complete."
;; | Payload Data continued ... |
;; +---------------------------------------------------------------+
;;
-(defun ws-web-socket-filter (proc string)
+(defun ws-make-web-socket-filter (handler)
"Web socket filter to pass whole frames to the client.
See RFC6455."
- (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
- (funcall ws/web-socket-handler data) ; call the web-socket
handler
- ;; 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))))
- ;; add any remaining un-parsed network data to pending
- (when (< (+ index pl) (length string))
- (let ((plist (process-plist proc)))
- (set-process-plist
- (plist-put plist :pending
- (concat (substring string (+ index pl))
- (or (plist-get plist :pending) ""))))))
- ;; possibly re-parse any pending input
- (when (plist-get (process-plist proc) :pending)
- (set-process-plist (plist-put (process-plist proc) :pending nil))
- (ws-web-socket-filter
- proc (plist-get (process-plist proc) :pending)))
- nil))))))
+ (lexical-let ((my-handler handler))
+ (lambda proc string
+ (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
+ (funcall my-handler data) ; call the web-socket handler
+ ;; 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))))
+ ;; add any remaining un-parsed network data to pending
+ (when (< (+ index pl) (length string))
+ (let ((plist (process-plist proc)))
+ (set-process-plist
+ (plist-put plist :pending
+ (concat (substring string (+ index pl))
+ (or (plist-get plist :pending) ""))))))
+ ;; possibly re-parse any pending input
+ (when (plist-get (process-plist proc) :pending)
+ (set-process-plist (plist-put (process-plist proc) :pending
nil))
+ (ws-web-socket-filter
+ proc (plist-get (process-plist proc) :pending)))))))))))
(defmacro ws/web-socket-messages-do (headers variable body)
"Helper macro to set the `ws-web-socket-filter' appropriately."
@@ -437,8 +438,8 @@ See RFC6455."
(cdr (assoc :SEC-WEBSOCKET-KEY headers)))))
(set-process-plist process (list :parsed "" :pending nil :active nil))
(set-process-coding-system process 'binary)
- (lexical-let ((ws/web-socket-handler (lambda ,(list variable) ,@body)))
- (set-process-filter process 'ws-web-socket-filter))
+ (set-process-filter process (ws-make-web-socket-filter
+ (lambda ,(list variable) ,@body)))
(throw 'close-connection :keep-alive)))
(defun ws/web-socket-send (string)
- [elpa] 67/119: test large file upload (w/o network chunking), (continued)
- [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, 2014/03/10
- [elpa] 78/119: hold, Eric Schulte, 2014/03/10
- [elpa] 79/119: beginning to add convenience macro for web sockets,
Eric Schulte <=
- [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
- [elpa] 75/119: more web-socket implementation, Eric Schulte, 2014/03/10
- [elpa] 91/119: more tutorial, Eric Schulte, 2014/03/10