     For WebSocket, a text frame is sent to client if data is String,
     a binary frame when data is byte[] or InputStream. For for HTTP streaming
     responses, data can be one of the type defined by Ring spec")
+
   (on-receive [ch callback]
     "Sets handler (fn [message]) for notification of client WebSocket
     messages. Message ordering is guaranteed by server.
 
     The message argument could be a string or a byte[].")
+
   (on-ping [ch callback]
     "Sets handler (fn [data]) for notification of client WebSocket pings. The
     data param represents application data and will by a byte[].")
+
   (on-close [ch callback]
     "Sets handler (fn [status]) for notification of channel being closed by the
     server or client. Handler will be invoked at most once. Useful for clean-up.


(extend-type AsyncChannel
  Channel
  (open? [ch] (not (.isClosed ch)))
  (close [ch] (.serverClose ch 1000))
  (websocket? [ch] (.isWebSocket ch))
  (send!
    ([ch data] (.send ch data (not (websocket? ch))))
    ([ch data close-after-send?] (.send ch data (boolean close-after-send?))))
  (on-receive [ch callback] (.setReceiveHandler ch callback))
  (on-ping [ch callback] (.setPingHandler ch callback))
  (on-close [ch callback] (.setCloseHandler ch callback)))

;;;; WebSocket

(defn sec-websocket-accept [sec-websocket-key]
  (let [md (MessageDigest/getInstance "SHA1")

  (doseq [ch @clients]
    (swap! clients disj ch)
    (send! ch {:status  200
               :headers {\"Content-Type\" \"text/html\"}
               :body your-async-response}
             ;; false ; Uncomment to use chunk encoding for HTTP streaming
             )))

