eschulte pushed a commit to branch master in repository elpa. commit b1b6d5cec88858bf4fad516f01b36d97e7b26245 Author: Eric Schulte <schulte.e...@gmail.com> Date: Tue Jan 7 12:32:42 2014 -0700
implemented ws-web-socket-frame to send replies something is not quite right however as the browser (Firefox doesn't like the replies and complains the connection is closing) --- examples/9-web-socket.el | 20 ++++++++++++++++---- web-server.el | 21 +++++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/examples/9-web-socket.el b/examples/9-web-socket.el index 1ad9276..1a2e4fb 100644 --- a/examples/9-web-socket.el +++ b/examples/9-web-socket.el @@ -1,6 +1,6 @@ ;;; web-sockets.el --- communicate via web-sockets -(defvar web-socket-port 8888) +(defvar web-socket-port 7777) (defvar web-socket-page (format "<html> @@ -27,10 +27,22 @@ function close(){ ws.close(); }; </body> </html>" web-socket-port)) +(defvar my-connection nil) + (defun web-socket-server (request) (with-slots (process headers) request - (ws-web-socket-connect request 'ws-web-socket-send) - (ws-response-header process 200 '("Content-type" . "text/html")) - (process-send-string process web-socket-page))) + ;; if a web-socket request, then connect and keep open + (if (ws-web-socket-connect request + (lambda (proc string) + (message "received:%S" string) + (let ((reply (ws-web-socket-frame (concat "echo: " string)))) + (message "sending:%S" reply) + (process-send-string proc reply) + (sit-for 5)) + :keep-alive)) + (prog1 :keep-alive (setq my-connection process)) + ;; otherwise send the index page + (ws-response-header process 200 '("Content-type" . "text/html")) + (process-send-string process web-socket-page)))) (ws-start '(((:GET . ".*") . web-socket-server)) web-socket-port) diff --git a/web-server.el b/web-server.el index b0cbfa6..35c09bf 100644 --- a/web-server.el +++ b/web-server.el @@ -339,7 +339,7 @@ received and parsed from the network." process (list :message (make-instance 'ws-message :handler handler :process process))) (set-process-filter process 'ws-web-socket-filter) - (throw 'close-connection :keep-alive)))) + process))) (defun ws-web-socket-filter (process string) (let ((message (plist-get (process-plist process) :message))) @@ -445,15 +445,28 @@ See RFC6455." ;; wipe the message state and call the handler (let ((it data)) (setq data "" active nil pending "" new nil) - (funcall handler it)) + (funcall handler process it)) ;; add any remaining un-parsed network data to pending (when (< (+ index pl) (length pending)) (setq pending (substring pending (+ index pl))))))) ;; possibly re-parse any pending input (when (new message) (ws-web-socket-parse-messages message))))) -(defun ws-web-socket-send (string) - (message "TODO: send %S" string)) +(defun ws-web-socket-frame (string &optional opcode) + "Frame STRING for web socket communication." + (let* ((fin 1) ;; set to 0 if not final frame + (len (length string)) + (pl (cond ((< len 126) len) + ((< len (expt 2 16)) 126) + (t (ws-error process "TODO: messages of length %d" len)))) + (opcode (ecase (or opcode :TEXT) (:TEXT 1) (:BINARY 2)))) + ;; for now we won't do any masking, as it isn't required. We'll + ;; also leave the rsv{1,2,3} flags all set to 0. + (format "%c%c%s%s" + (logior (lsh fin 7) opcode) + pl + (if (= pl 126) (logand (lsh v -8) 255) "") + string))) ;;; Convenience functions to write responses