summaryrefslogtreecommitdiff
path: root/vim/bundle/slimv/swank-clojure/swank/core/server.clj
diff options
context:
space:
mode:
Diffstat (limited to 'vim/bundle/slimv/swank-clojure/swank/core/server.clj')
-rw-r--r--vim/bundle/slimv/swank-clojure/swank/core/server.clj102
1 files changed, 102 insertions, 0 deletions
diff --git a/vim/bundle/slimv/swank-clojure/swank/core/server.clj b/vim/bundle/slimv/swank-clojure/swank/core/server.clj
new file mode 100644
index 0000000..1c9f70a
--- /dev/null
+++ b/vim/bundle/slimv/swank-clojure/swank/core/server.clj
@@ -0,0 +1,102 @@
+(ns swank.core.server
+ (:use (swank util core)
+ (swank.util sys io)
+ (swank.util.concurrent thread)
+ (swank.util.net sockets)
+ (swank.core connection protocol))
+ (:import (java.io File FileReader BufferedReader InputStreamReader OutputStreamWriter)
+ (java.net Socket)))
+
+;; The swank.core.server is the layer above swank.util.net.sockets
+;; - Manages the socket server
+;; - Accepts and authenticates incoming connections
+;; - Creates swank.core.connections
+;; - Spins up new threads
+
+(defonce connections (ref []))
+
+(def slime-secret-path (str (user-home-path) File/separator ".slime-secret"))
+
+(defn- slime-secret
+ "Returns the first line from the slime-secret file, path found in
+ slime-secret-path (default: .slime-secret in the user's home
+ directory).
+
+ See also: `accept-authenticated-connection'"
+ ([] (failing-gracefully
+ (let [slime-secret-file (File. (str (user-home-path) File/separator ".slime-secret"))]
+ (when (and (.isFile slime-secret-file) (.canRead slime-secret-file))
+ (with-open [secret (BufferedReader. (FileReader. slime-secret-file))]
+ (.readLine secret)))))))
+
+(defn- accept-authenticated-connection ;; rename to authenticate-socket, takes in a connection
+ "Accepts and returns new connection if it is from an authenticated
+ machine. Otherwise, return nil.
+
+ Authentication depends on the contents of a slime-secret file on
+ both the server (swank) and the client (emacs slime). If no
+ slime-secret file is provided on the server side, all connections
+ are accepted.
+
+ See also: `slime-secret'"
+ ([#^Socket socket opts]
+ (returning [conn (make-connection socket (get opts :encoding default-encoding))]
+ (if-let [secret (slime-secret)]
+ (when-not (= (read-from-connection conn) secret)
+ (close-socket! socket))
+ conn))))
+
+(defn- make-output-redirection
+ ([conn]
+ (call-on-flush-stream
+ #(with-connection conn
+ (send-to-emacs `(:write-string ~%)))))
+ {:tag java.io.StringWriter})
+
+(defn- socket-serve [connection-serve socket opts]
+ (with-connection (accept-authenticated-connection socket opts)
+ (let [out-redir (java.io.PrintWriter. (make-output-redirection
+ *current-connection*))]
+ (binding [*out* out-redir
+ *err* out-redir]
+ (dosync (ref-set (*current-connection* :writer-redir) *out*))
+ (dosync (alter connections conj *current-connection*))
+ (connection-serve *current-connection*)))))
+
+;; Setup frontent
+(defn start-swank-socket-server!
+ "Starts and returns the socket server as a swank host. Takes an
+ optional set of options as a map:
+
+ :announce - an fn that will be called and provided with the
+ listening port of the newly established server. Default: none."
+ ([server connection-serve] (start-swank-socket-server! connection-serve {}))
+ ([server connection-serve options]
+ (start-server-socket! server connection-serve)
+ (when-let [announce (options :announce)]
+ (announce (.getLocalPort server)))
+ server))
+
+(defn setup-server
+ "The port it started on will be called as an argument to (announce-fn
+ port). A connection will then be created and (connection-serve conn)
+ will then be called."
+ [port announce-fn connection-serve opts]
+ (start-swank-socket-server!
+ (make-server-socket {:port port
+ :host (opts :host "localhost")
+ :backlog (opts :backlog 0)})
+ #(socket-serve connection-serve % opts)
+ {:announce announce-fn}))
+
+;; Announcement functions
+(defn simple-announce [port]
+ (println "Connection opened on local port " port))
+
+(defn announce-port-to-file
+ "Writes the given port number into a file."
+ ([#^String file port]
+ (with-open [out (new java.io.FileWriter file)]
+ (doto out
+ (.write (str port "\n"))
+ (.flush)))))