diff --git a/other/project.clj b/other/project.clj index 210b52f..8874ec1 100644 --- a/other/project.clj +++ b/other/project.clj @@ -1,14 +1,12 @@ (defproject websockify "1.0.0-SNAPSHOT" :description "Websockify" :dependencies [[org.clojure/clojure "1.2.1"] - [aleph "0.2.0"] - [ring/ring-jetty-adapter "1.0.0-beta2"] - ;[ring-json-params "0.1.3"] - [compojure "0.6.5"] + [org.eclipse.jetty/jetty-websocket "7.5.4.v20111024"] + [org.eclipse.jetty/jetty-server "7.5.4.v20111024"] + [org.eclipse.jetty/jetty-servlet "7.5.4.v20111024"] ;[commons-codec/commons-codec "1.4"] ;[clj-base64 "0.0.0-SNAPSHOT"] - ] ; :dev-dependencies [[swank-clojure "1.3.0-SNAPSHOT"]] ) diff --git a/other/websockify.clj b/other/websockify.clj index 3fa52b6..d8cfee7 100644 --- a/other/websockify.clj +++ b/other/websockify.clj @@ -1,109 +1,69 @@ (ns websockify - (:use compojure.core, - ring.adapter.jetty, - aleph.http, - aleph.tcp, - aleph.http.core, - lamina.core) - (:require [compojure.route :as route] - [aleph.formats]) - (:import [org.jboss.netty.handler.codec.base64 Base64]) + (:use ring.adapter.jetty) + ;(:import [org.jboss.netty.handler.codec.base64 Base64]) - (:use [clojure.java.io :only (file)]) + (:import [java.net URL URI] + [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])) - (:import [java.net URL URI])) - -(def settings (atom {})) +(defonce settings (atom {})) ;; WebSockets -(def clients (atom {})) - -;(defn base64-encode -; "Encodes the data into a base64 string representation." -; [data] -; (when data -; (-> data to-channel-buffer Base64/encode -; channel-buffer->string))) -; -;(defn base64-decode -; "Decodes a base64 encoded string into bytes." -; [string] -; (when string -; (-> string string->channel-buffer Base64/decode))) +(defonce clients (atom {})) -(defn receive-client-msg [client target b64] - (if b64 - (try - (println "Client b64 data: " b64) - (let [raw (aleph.formats/base64-decode b64)] - (do - (println "Sending to target: " (pr-str (.toString raw "latin1"))) - (println "Sending to target: " (map #(mod % 256) (into-array ^char (.array raw)))) - (enqueue target (.array raw)))) - (catch Exception e (println e))) - (do - (println "Client Closed") - (swap! clients dissoc client) - (close target) - (close client)))) +(defn make-websocket-handler [] + (reify org.eclipse.jetty.websocket.WebSocket$OnTextMessage + (onOpen [this connection] + (println "Got WebSocket connection:" connection) + (swap! clients assoc this connection)) + (onClose [this code message] + (println "Got WebSocket close:" code message) + (swap! clients dissoc this)) + (onMessage [this data] + (println "Got WebSocket message:" data)))) -(defn receive-target-msg [client target raw] - (if raw - (try - (println "Target raw data: " (pr-str (aleph.formats/bytes->string raw "latin1"))) - (println "Target raw class: " (class raw)) - (println "Target raw array: " (.array raw)) - (println "Target raw data: " (map #(mod % 256) (into-array ^char (.array raw)))) - (let [b64 (aleph.formats/base64-encode raw)] - (do - (println "Sending to client: " b64) - (enqueue client b64))) - (catch Exception e (println e))) - (do - (println "Target Closed") - (swap! clients dissoc client) - (close client) - (close target)) - )) +(defn 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 ws-handler [client handshake] - (let [target-host (@settings :target-host) - target-port (@settings :target-port) - target @(tcp-client {:host target-host, :port target-port})] - (println "Connected to target") - (println "client: " (class client) ", target: " (class target)) - (receive-all client #(receive-client-msg client target %)) - (println "Started receive-client-msg") - (receive-all target #(receive-target-msg client target %)) - (println "Started receive-target-msg") - (swap! clients assoc client target))) - -;; HTTP -(defn get-routes [root] - (defroutes main-routes - (GET "*" {websocket :websocket} - (when websocket (wrap-aleph-handler ws-handler))) - - (route/files "/" - {:root root} - (route/not-found (file "www/404.html"))) - (route/not-found "

Page not found

"))) - -(defn start - "Start websockify - :listen-port - port to start server on (default 6080) - :opts - map of Noir server options" - [& {:keys [listen-port target-host target-port web opts] +(defn start-websocket-server + [& {:keys [listen-port target-host target-port web] :or {listen-port 6080 target-host "localhost" target-port 5900 - web "./" - opts {}}}] + }}] + (let [http-servlet (doto (ServletHolder. (DefaultServlet.)) + (.setInitParameter "dirAllowed" "true") + (.setInitParameter "resourceBase" web)) + ws-servlet (ServletHolder. (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)))) - (reset! settings {:target-host target-host - :target-port target-port}) - (def stop - (let [stop (start-http-server (wrap-ring-handler (get-routes web)) - {:port listen-port :websocket true})] - (fn [] (stop)))))