129 lines
4.4 KiB
Clojure
129 lines
4.4 KiB
Clojure
(ns websockify
|
|
(:use ring.adapter.jetty)
|
|
;(:import [org.jboss.netty.handler.codec.base64 Base64])
|
|
|
|
|
|
(:import
|
|
;[java.io BufferedReader DataOutputStream]
|
|
|
|
[java.net InetSocketAddress]
|
|
[java.nio ByteBuffer]
|
|
[java.nio.channels SocketChannel]
|
|
|
|
[org.jboss.netty.channel
|
|
Channels SimpleChannelHandler ChannelPipelineFactory]
|
|
[org.jboss.netty.channel.socket.nio NioClientSocketChannelFactory]
|
|
[org.jboss.netty.bootstrap ClientBootstrap]
|
|
[java.util.concurrent Executors]
|
|
|
|
[org.eclipse.jetty.server Server]
|
|
[org.eclipse.jetty.server.nio BlockingChannelConnector]
|
|
[org.eclipse.jetty.servlet ServletContextHandler ServletHolder DefaultServlet]
|
|
[org.eclipse.jetty.websocket
|
|
WebSocket WebSocketClientFactory WebSocketClient
|
|
WebSocketServlet]))
|
|
|
|
(defonce settings (atom {}))
|
|
|
|
;; TCP / NIO
|
|
|
|
;; (defn tcp-channel [host port]
|
|
;; (try
|
|
;; (let [address (InetSocketAddress. host port)
|
|
;; channel (doto (SocketChannel/open)
|
|
;; (.connect address))]
|
|
;; channel)
|
|
;; (catch Exception e
|
|
;; (println (str "Failed to connect to'" host ":" port "':" e))
|
|
;; nil)))
|
|
|
|
;; http://docs.jboss.org/netty/3.2/guide/html/start.html#d0e51
|
|
(defn make-netty-client-handler []
|
|
(proxy [SimpleChannelHandler] []
|
|
(channelConnected [ctx e]
|
|
(println "channelConnected:" e))
|
|
(channelDisconnected [ctx e]
|
|
(println "channelDisconnected:" e))
|
|
(messageReceived [ctx e]
|
|
(println "messageReceived:" (.getMessage e)))
|
|
(exceptionCaught [ctx e]
|
|
(println "exceptionCaught:" e))))
|
|
|
|
(defn netty-client [host port]
|
|
(let [pipeline (proxy [ChannelPipelineFactory] []
|
|
(getPipeline []
|
|
(doto (Channels/pipeline)
|
|
(.addLast "handler" (make-netty-client-handler)))))
|
|
bootstrap (doto (ClientBootstrap.
|
|
(NioClientSocketChannelFactory.
|
|
(Executors/newCachedThreadPool)
|
|
(Executors/newCachedThreadPool)))
|
|
(.setPipelineFactory pipeline)
|
|
(.setOption "tcpNoDelay" true)
|
|
(.setOption "keepAlive" true))
|
|
channel-future (.connect bootstrap (InetSocketAddress. host port))
|
|
channel (.. channel-future (awaitUninterruptibly) (getChannel))]
|
|
channel))
|
|
|
|
|
|
|
|
;; WebSockets
|
|
|
|
|
|
(defonce clients (atom {}))
|
|
|
|
;; http://wiki.eclipse.org/Jetty/Feature/WebSockets
|
|
(defn make-websocket-handler []
|
|
(reify org.eclipse.jetty.websocket.WebSocket$OnTextMessage
|
|
(onOpen [this connection]
|
|
(println "Got WebSocket connection:" connection)
|
|
#_(let [target (tcp-channel "localhost" 5901)]
|
|
(swap! clients assoc this {:client connection
|
|
:target target})))
|
|
(onClose [this code message]
|
|
(println "Got WebSocket close:" code message)
|
|
(swap! clients dissoc this))
|
|
(onMessage [this data]
|
|
(println "Got WebSocket message:" data))))
|
|
|
|
(defn make-websocket-servlet []
|
|
(proxy [org.eclipse.jetty.websocket.WebSocketServlet] []
|
|
(doGet [request response]
|
|
;(println "doGet" request)
|
|
(.. (proxy-super getServletContext)
|
|
(getNamedDispatcher (proxy-super getServletName))
|
|
(forward request response)))
|
|
(doWebSocketConnect [request response]
|
|
(println "doWebSocketConnect")
|
|
(make-websocket-handler))))
|
|
|
|
(defn start-websocket-server
|
|
[& {:keys [listen-port target-host target-port web]
|
|
:or {listen-port 6080
|
|
target-host "localhost"
|
|
target-port 5900
|
|
}}]
|
|
(let [http-servlet (doto (ServletHolder. (DefaultServlet.))
|
|
(.setInitParameter "dirAllowed" "true")
|
|
(.setInitParameter "resourceBase" web))
|
|
ws-servlet (ServletHolder. (make-websocket-servlet))
|
|
context (doto (ServletContextHandler.)
|
|
(.setContextPath "/")
|
|
(.addServlet ws-servlet "/websocket"))
|
|
connector (doto (BlockingChannelConnector.)
|
|
(.setPort listen-port)
|
|
(.setMaxIdleTime Integer/MAX_VALUE))
|
|
server (doto (Server.)
|
|
(.setHandler context)
|
|
(.addConnector connector)
|
|
(.start))]
|
|
(if web
|
|
(do
|
|
(println "Serving web requests from:" web)
|
|
(.addServlet context http-servlet "/"))
|
|
(println "Not serving web requests"))
|
|
|
|
(defn stop []
|
|
(.stop server))))
|
|
|