Skip to content

Commit

Permalink
Reorganize system files.
Browse files Browse the repository at this point in the history
  • Loading branch information
fukamachi committed Aug 16, 2015
1 parent b4fd22d commit cf2ad76
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 111 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This library provides a complete implementation of the WebSocket protocols.
### Server-side with Clack

```common-lisp
(ql:quickload '(:websocket-driver :clack))
(ql:quickload '(:websocket-driver-server :clack))
(use-package :websocket-driver)
Expand All @@ -37,7 +37,7 @@ This library provides a complete implementation of the WebSocket protocols.
```common-lisp
(ql:quickload :websocket-driver-client)
(defvar *client* (wsdc:make-client "ws://localhost:5000/echo"))
(defvar *client* (wsd:make-client "ws://localhost:5000/echo"))
(as:with-event-loop ()
(wsd:start-connection *client*)
Expand Down
2 changes: 1 addition & 1 deletion run-client-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ while true; do
sleep 1
done

RESULT=$(ros -l websocket-driver.asd -l websocket-driver-client.asd -l t/client.lisp 2>/dev/null)
RESULT=$(ros -l websocket-driver-client.asd -l t/client.lisp 2>/dev/null)
echo "$RESULT"

kill "$SERVER_PID"
Expand Down
2 changes: 1 addition & 1 deletion run-tests.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh

ros -l websocket-driver.asd -l examples/echo-server.lisp &
ros -l websocket-driver-server.asd -l examples/echo-server.lisp &
SERVER_PID=$!

while true; do
Expand Down
4 changes: 3 additions & 1 deletion src/client.lisp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
(in-package :cl-user)
(defpackage websocket-driver-client
(:nicknames :wsdc)
(:use :cl)
(:import-from :websocket-driver.driver.client
#:client)
Expand All @@ -11,3 +10,6 @@
(apply #'make-instance 'client
:url url
options))

(import 'make-client :websocket-driver)
(export 'make-client :websocket-driver)
14 changes: 1 addition & 13 deletions src/driver.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
(defpackage websocket-driver
(:nicknames :wsd)
(:use :cl)
(:import-from :websocket-driver.driver.hybi
#:hybi)
(:import-from :websocket-driver.driver.base
#:driver
#:socket
Expand All @@ -29,8 +27,7 @@
#:remove-listener
#:remove-all-listeners
#:emit)
(:export #:make-server
#:websocket-p
(:export #:websocket-p

;; from driver
#:driver
Expand Down Expand Up @@ -60,15 +57,6 @@
#:emit))
(in-package :websocket-driver)

(defun make-server (env &rest options)
(let ((socket (getf env :clack.io)))
(unless socket
(error ":clack.io doesn't exist in ENV. Probably this server is not supported."))
(apply #'make-instance 'hybi
:socket socket
:headers (getf env :headers)
options)))

(defun websocket-p (env)
(let ((headers (getf env :headers)))
(and (eq (getf env :request-method) :get)
Expand Down
54 changes: 18 additions & 36 deletions src/driver/base.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
(:import-from :event-emitter
#:emit
#:event-emitter)
(:import-from :clack.socket
#:set-read-callback)
(:import-from :fast-io
#:with-fast-output
#:fast-write-sequence)
Expand Down Expand Up @@ -74,12 +72,7 @@
(send driver reason :type :close :code code
:callback
(lambda ()
(close-driver driver reason code))))

(defun close-driver (driver reason code)
(close-socket (socket driver))
(setf (ready-state driver) :closed)
(emit :close driver :code code :reason reason))
(close-connection driver reason code))))

(defmethod initialize-instance :after ((driver driver) &key)
(setf (parser driver)
Expand All @@ -94,9 +87,10 @@
(send driver payload :type :pong))
:pong-callback
(lambda (payload)
(when-let (callback (gethash payload (ping-callbacks driver)))
(remhash payload (ping-callbacks driver))
(funcall callback)))
(let ((callback (gethash payload (ping-callbacks driver))))
(when callback
(remhash payload (ping-callbacks driver))
(funcall callback))))
:close-callback
(lambda (data &key code)
(case (ready-state driver)
Expand All @@ -105,7 +99,7 @@
(send-close-frame driver data code))
;; probably the response for a 'close' frame
(otherwise
(close-driver driver data code)))
(close-connection driver data code)))
(setf (ws-stage (ws driver)) 0))
:error-callback
(lambda (code reason)
Expand All @@ -126,21 +120,7 @@
(:closing 2)
(:closed 3)))))

(defgeneric start-connection (driver)
(:method ((driver driver))
(unless (eq (ready-state driver) :connecting)
(return-from start-connection))

(let ((socket (socket driver)))
(set-read-callback socket
(lambda (data &key (start 0) end)
(parse driver data :start start :end end)))

(send-handshake-response driver
:callback
(lambda ()
(unless (eq (ready-state driver) :closed)
(open-connection driver)))))))
(defgeneric start-connection (driver))

(defgeneric parse (driver data &key start end)
(:method (driver data &key start end)
Expand Down Expand Up @@ -174,15 +154,17 @@
callback))
(send driver message :type :ping)))

(defgeneric close-connection (driver &optional reason code)
(:method ((driver driver) &optional reason code)
(declare (ignore reason code))
(unless (eq (ready-state driver) :open)
(return-from close-connection))

(setf (ready-state driver) :closed)
(emit :close driver :code nil :reason nil)
t))
(defgeneric close-connection (driver &optional reason code))

(defmethod close-connection :around ((driver driver) &optional reason code)
(case (ready-state driver)
(:connecting
(setf (ready-state driver) :closed)
(emit :close driver :code code :reason reason)
t)
(:open
(call-next-method))
(otherwise nil)))

(defgeneric open-connection (driver)
(:method ((driver driver))
Expand Down
13 changes: 10 additions & 3 deletions src/driver/client.lisp
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
(in-package :cl-user)
(defpackage websocket-driver.driver.client
(:use :cl
#:websocket-driver.driver.base)
(:import-from :websocket-driver.driver.hybi
#:generate-accept)
#:websocket-driver.driver.base
#:websocket-driver.util)
(:import-from :cl-async
#:tcp-connect)
(:import-from :event-emitter
#:emit)
(:import-from :fast-io
#:with-fast-output
#:fast-write-sequence)
Expand Down Expand Up @@ -171,3 +172,9 @@

(crlf)))
:write-cb callback)))

(defmethod close-connection ((driver client) &optional reason code)
(as:close-socket (socket driver))
(setf (ready-state driver) :closed)
(emit :close driver :code code :reason reason)
t)
53 changes: 22 additions & 31 deletions src/driver/hybi.lisp
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
(in-package :cl-user)
(defpackage websocket-driver.driver.hybi
(:use :cl
#:split-sequence
#:websocket-driver.driver.base)
#:websocket-driver.driver.base
#:websocket-driver.util)
(:import-from :event-emitter
#:emit)
(:import-from :fast-websocket
#:compose-frame
#:error-code)
(:import-from :clack.socket
#:set-read-callback
#:write-sequence-to-socket
#:write-sequence-to-socket-buffer
#:write-byte-to-socket-buffer
Expand All @@ -19,18 +20,12 @@
#:fast-write-sequence
#:fast-write-byte)
(:import-from :ironclad
#:digest-sequence
#:ascii-string-to-byte-array)
(:import-from :base64
#:usb8-array-to-base64-string)
(:import-from :trivial-utf-8
#:string-to-utf-8-bytes)
(:export #:hybi))
(in-package :websocket-driver.driver.hybi)

(defparameter +guid+
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")

(defclass hybi (driver)
((headers :initarg :headers
:initform (error ":headers is required")
Expand All @@ -40,11 +35,6 @@
:initform t
:accessor require-masking)))

(defun split-by-comma (string)
(mapl (lambda (parts)
(rplaca parts (string-trim '(#\Space) (car parts))))
(split-sequence #\, string)))

(defmethod initialize-instance :after ((driver hybi) &key)
(let ((protocols (accept-protocols driver))
(env-protocols (gethash "sec-websocket-protocol" (headers driver))))
Expand All @@ -69,17 +59,26 @@
(error "Unsupported WebSocket version: ~S" ws-version)))))
(setf (version driver) "hybi-13"))

(defmethod start-connection ((driver hybi))
(unless (eq (ready-state driver) :connecting)
(return-from start-connection))

(let ((socket (socket driver)))
(set-read-callback socket
(lambda (data &key (start 0) end)
(parse driver data :start start :end end)))

(send-handshake-response driver
:callback
(lambda ()
(unless (eq (ready-state driver) :closed)
(open-connection driver))))))

(defmethod close-connection ((driver hybi) &optional (reason "") (code (error-code :normal-closure)))
(case (ready-state driver)
(:connecting
(setf (ready-state driver) :closed)
(emit :close driver :code code :reason reason)
t)
(:open
(send driver reason :type :close :code code)
(setf (ready-state driver) :closing)
t)
(otherwise nil)))
(close-socket (socket driver))
(send driver reason :type :close :code code)
(setf (ready-state driver) :closing)
t)

(defmethod send ((driver hybi) data &key start end type code callback)
(let ((frame (compose-frame data
Expand All @@ -91,14 +90,6 @@
(write-sequence-to-socket (socket driver) frame
:callback callback)))

(defun generate-accept (key)
(declare (optimize (speed 3) (safety 0))
(type simple-string key))
(base64:usb8-array-to-base64-string
(ironclad:digest-sequence :sha1
(ironclad:ascii-string-to-byte-array
(concatenate 'string key +guid+)))))

(defmethod send-handshake-response ((driver hybi) &key callback)
(let ((socket (socket driver))
(sec-key (gethash "sec-websocket-key" (headers driver))))
Expand Down
19 changes: 19 additions & 0 deletions src/server.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(in-package :cl-user)
(defpackage websocket-driver.server
(:use :cl)
(:import-from :websocket-driver.driver.hybi
#:hybi)
(:export #:make-server))
(in-package :websocket-driver.server)

(defun make-server (env &rest options)
(let ((socket (getf env :clack.io)))
(unless socket
(error ":clack.io doesn't exist in ENV. Probably this server is not supported."))
(apply #'make-instance 'hybi
:socket socket
:headers (getf env :headers)
options)))

(import 'make-server :websocket-driver)
(export 'make-server :websocket-driver)
29 changes: 29 additions & 0 deletions src/util.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
(in-package :cl-user)
(defpackage websocket-driver.util
(:use :cl)
(:import-from :split-sequence
#:split-sequence)
(:import-from :cl-base64
#:usb8-array-to-base64-string)
(:import-from :ironclad
:digest-sequence
:ascii-string-to-byte-array)
(:export #:split-by-comma
#:generate-accept))
(in-package :websocket-driver.util)

(defparameter +guid+
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")

(defun split-by-comma (string)
(mapl (lambda (parts)
(rplaca parts (string-trim '(#\Space) (car parts))))
(split-sequence #\, string)))

(defun generate-accept (key)
(declare (optimize (speed 3) (safety 0))
(type simple-string key))
(base64:usb8-array-to-base64-string
(ironclad:digest-sequence :sha1
(ironclad:ascii-string-to-byte-array
(concatenate 'string key +guid+)))))
2 changes: 1 addition & 1 deletion t/client.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
(ql:quickload '(:uiop :websocket-driver-client) :silent t)

(defvar *client*
(wsdc:make-client "ws://localhost:5000/echo"))
(wsd:make-client "ws://localhost:5000/echo"))

(wsd:on :open *client*
(lambda ()
Expand Down
21 changes: 21 additions & 0 deletions websocket-driver-base.asd
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(in-package :cl-user)
(defpackage websocket-driver-base-asd
(:use :cl :asdf))
(in-package :websocket-driver-base-asd)

(defsystem websocket-driver-base
:version "0.2.0"
:author "Eitaro Fukamachi"
:license "BSD 2-Clause"
:depends-on (:fast-websocket
:fast-io
:event-emitter
:ironclad
:cl-base64
:split-sequence)
:components ((:module "src"
:components
((:file "driver" :depends-on ("driver/base"))
(:file "driver/base" :depends-on ("util"))
(:file "util"))))
:description "WebSocket protocol handler")
Loading

0 comments on commit cf2ad76

Please sign in to comment.