Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 8 commits
  • 17 files changed
  • 0 commit comments
  • 1 contributor
View
5 etc/log4j.properties
@@ -0,0 +1,5 @@
+log4j.appender.C = org.apache.log4j.ConsoleAppender
+log4j.appender.C.layout = org.apache.log4j.PatternLayout
+log4j.appender.C.layout.ConversionPattern = %d | %-5p | %c | %m%n
+
+log4j.rootLogger = INFO, C
View
7 etc/subrosa.clj
@@ -1,4 +1,5 @@
-{:host "localhost"
+{:port 6667
+ :host "localhost"
:network "Subrosa"
:ssl {:keystore nil
:password nil}
@@ -7,4 +8,6 @@
:directory "log"}
:catchup {:enabled? true
:max-msgs-per-room 20
- :default-playback-size 10}}}
+ :default-playback-size 10}
+ :swank {:enabled? false
+ :port 4005}}}
View
3 pkg/bin/subrosa.sh
@@ -4,6 +4,5 @@ BASEDIR="$(cd "$(dirname $0)/.." > /dev/null; pwd)"
JAVA_CMD=${JAVA_CMD:-"java"}
JAVA_OPTS=${JAVA_OPTS:-"-server"}
-SUBROSA_PORT=${SUBROSA_PORT:-"6667"}
-exec $JAVA_CMD $JAVA_OPTS -cp "$BASEDIR/etc/:$BASEDIR/lib/*" subrosa.main $SUBROSA_PORT
+exec $JAVA_CMD $JAVA_OPTS -cp "$BASEDIR/etc/:$BASEDIR/lib/*" subrosa.main
View
1 pkg/etc/log4j.properties
View
8 project.clj
@@ -5,6 +5,8 @@
"http://repository.jboss.org/nexus/content/groups/public/"}
:dependencies [[org.clojure/clojure "1.2.1"]
[org.clojure/clojure-contrib "1.2.0"]
- [org.jboss.netty/netty "3.2.1.Final"]]
- :dev-dependencies [[swank-clojure "1.2.1"]
- [lein-release "1.1.1"]])
+ [org.clojure/tools.logging "0.2.3"]
+ [log4j "1.2.16"]
+ [org.jboss.netty/netty "3.2.1.Final"]
+ [swank-clojure "1.3.2"]]
+ :dev-dependencies [[lein-tar "1.0.5"]])
View
28 src/subrosa/client.clj
@@ -93,9 +93,10 @@
(send-to-client channel 3
(format ":This server was created %s" (:started server)))
(send-to-client channel 4
- (format "%s %s mMvV bcdefFhiIklmnoPqstv"
+ (format "%s %s mMvV %s"
(hostname)
- (:version server)))
+ (:version server)
+ (apply str supported-room-modes)))
(send-to-client channel 5
(format "NETWORK=%s :are supported on this server"
(config :network))))
@@ -163,7 +164,10 @@
(defn maybe-create-room! [room-name]
(when-not (room-for-name room-name)
(db/put :room {:name room-name
- :topic nil})))
+ :topic nil
+ :mode (if (.endsWith room-name "-")
+ #{\p}
+ #{})})))
(defn maybe-delete-room! [room-name]
(when-not (seq (db/get :user-in-room :room-name room-name))
@@ -185,7 +189,6 @@
(defn remove-channel! [channel]
(let [user (user-for-channel channel)
nick (:nick user)]
- #_(println "gonna remove user:" user)
(db/delete :user (:id user))
(doseq [room-name (rooms-for-nick nick)]
(remove-nick-from-room! nick room-name))))
@@ -193,6 +196,23 @@
(defn topic-for-room [room-name]
(:topic (room-for-name room-name)))
+(defn format-mode [enable? mode]
+ (str (if enable?
+ "+"
+ "-")
+ (apply str (map str mode))))
+
+(defn mode-for-room [room-name]
+ (:mode (room-for-name room-name)))
+
+(defn set-mode-for-room! [room-name mode]
+ (let [room (room-for-name room-name)]
+ (db/put :room (assoc room
+ :mode mode))))
+
+(defn room-is-private? [room-name]
+ ((mode-for-room room-name) \p))
+
(defn nicks-in-room [room-name]
(map :user-nick (db/get :user-in-room :room-name room-name)))
View
57 src/subrosa/commands.clj
@@ -3,8 +3,10 @@
[subrosa.hooks :only [add-hook hooked? run-hook]]
[subrosa.utils :only [interleave-all]]
[subrosa.config :only [config]]
+ [subrosa.server :only [supported-room-modes]]
[clojure.string :only [join]]
[clojure.contrib.condition :only [raise]])
+ (:require [clojure.tools.logging :as log])
(:import [org.jboss.netty.channel ChannelFutureListener]))
(defn dispatch-message [message channel]
@@ -13,7 +15,7 @@
(run-hook cmd channel (or args ""))
(do
(when-not (empty? message)
- (println "Received unhandled command:" message)
+ (log/debug "Received unhandled command:" message)
(when (authenticated? channel)
(raise {:type :client-error
:code 421
@@ -266,7 +268,7 @@
(let [nick (:nick user)
user-name (:user-name user)
real-name (:real-name user)
- rooms (rooms-for-nick nick)
+ rooms (remove room-is-private? (rooms-for-nick nick))
hostname (format-hostname (:channel user))]
(send-to-client channel 311 (format "%s %s * :%s"
user-name
@@ -299,7 +301,8 @@
;; ":Users" and "Name"
(send-to-client channel 321 "Channel :Users Name")
(doseq [room-name rooms
- :when (room-for-name room-name)]
+ :when (and (room-for-name room-name)
+ (not (room-is-private? room-name)))]
(send-to-client channel 322 (format "%s %s :%s"
room-name
(count (nicks-in-room room-name))
@@ -349,8 +352,12 @@
(doseq [{:keys [nick real-name user-name] :as user} users]
(send-to-client channel 352 (format "%s %s %s %s %s H :0 %s"
(if (= room-name-for-reply "*")
- room-name-for-reply
- (first (rooms-for-nick nick)))
+ (or
+ (first
+ (remove room-is-private?
+ (rooms-for-nick nick)))
+ room-name-for-reply)
+ room-name-for-reply)
user-name
(format-hostname (:channel user))
(hostname)
@@ -456,4 +463,42 @@
:code 461
:msg "KICK :Not enough parameters"}))))
-
+(defcommand mode [channel args]
+ (let [[room-name modes params] (.split args " ")
+ user (user-for-nick room-name)
+ room (room-for-name room-name)]
+ (if (or user room)
+ (if room
+ (if-not modes
+ (send-to-client channel
+ 324
+ (format "%s %s"
+ room-name
+ (format-mode true (mode-for-room room-name))))
+ (let [first-char (.charAt modes 0)
+ enable? (not= \- first-char)
+ new-mode (set (if (#{\+ \-} first-char)
+ (rest modes)
+ (seq modes)))]
+ (if (every? supported-room-modes new-mode)
+ (dosync
+ (let [room-mode (mode-for-room room-name)]
+ (if enable?
+ (set-mode-for-room! room-name (clojure.set/union room-mode new-mode))
+ (set-mode-for-room! room-name (clojure.set/difference room-mode new-mode)))
+ (when-not (= room-mode (mode-for-room room-name))
+ (send-to-room room-name (format ":%s MODE %s %s"
+ (format-client channel)
+ room-name
+ (format-mode enable? new-mode))))))
+ (raise {:type :client-error
+ :code 472
+ :msg (format "%s :is unknown mode char to me for %s"
+ (first new-mode)
+ room-name)}))))
+ (raise {:type :client-error
+ :code 501
+ :msg ":Unknown MODE flag"}))
+ (raise {:type :client-error
+ :code 401
+ :msg (format "%s :No such nick/channel" room-name)}))))
View
8 src/subrosa/main.clj
@@ -1,8 +1,10 @@
(ns subrosa.main
(:gen-class)
- (use [subrosa.netty :only [create-server]]))
+ (:use [subrosa.config :only [config]]
+ [subrosa.netty :only [create-server]])
+ (:require [clojure.tools.logging :as log]))
-(defn -main [port]
- (let [{:keys [start-fn stop-fn]} (create-server (Integer/parseInt port))]
+(defn -main []
+ (let [{:keys [start-fn stop-fn]} (create-server (config :port))]
(start-fn)
(.addShutdownHook (Runtime/getRuntime) (Thread. stop-fn))))
View
26 src/subrosa/netty.clj
@@ -7,6 +7,7 @@
[subrosa.commands :only [dispatch-message quit]]
[subrosa.plugins :only [load-plugins]]
[clojure.stacktrace :only [root-cause]])
+ (:require [clojure.tools.logging :as log])
(:import [java.net InetSocketAddress]
[java.util.concurrent Executors]
[org.jboss.netty.bootstrap ServerBootstrap]
@@ -51,14 +52,14 @@
(let [condition (meta (root-cause evt))
chan-future-agent
(condp = (:type condition)
- :client-error (send-to-client
+ :client-error (send-to-client
+ (.getChannel evt)
+ (:code condition)
+ (:msg condition))
+ :protocol-error (send-to-client*
(.getChannel evt)
- (:code condition)
- (:msg condition))
- :protocol-error (send-to-client*
- (.getChannel evt)
- (format "ERROR %s" (:msg condition)))
- :client-disconnect nil)]
+ (format "ERROR %s" (:msg condition)))
+ :client-disconnect nil)]
(when (:disconnect condition)
(await chan-future-agent)
(when-let [chan-future @chan-future-agent]
@@ -67,8 +68,7 @@
#{java.io.IOException
java.nio.channels.ClosedChannelException
javax.net.ssl.SSLException}))
- (println up-or-down "ERROR")
- (.printStackTrace (root-cause evt)))))
+ (log/error (root-cause evt)))))
evt)
(defn connect-handler [channel-group pipeline evt]
@@ -143,16 +143,16 @@
(.setOption "child.keepAlive" true))
(load-plugins)
{:start-fn (fn []
- (println "Starting Subrosa.")
(reset-all-state!)
(->> port
InetSocketAddress.
(.bind bootstrap)
- (.add channel-group)))
+ (.add channel-group))
+ (log/info "Starting Subrosa... done."))
:stop-fn (fn []
- (println "Shutting down Subrosa.")
(doseq [channel channel-group
:when (user-for-channel channel)]
(send-to-client* channel "ERROR :Server going down"))
(-> channel-group .close .awaitUninterruptibly)
- (.releaseExternalResources channel-factory))}))
+ (.releaseExternalResources channel-factory)
+ (log/info "Stopping Subrosa... done."))}))
View
3 src/subrosa/plugins/catchup.clj
@@ -50,7 +50,8 @@
(rooms-for-nick nick)
[room])]
(doseq [room rooms]
- (if (nick-in-room? nick room)
+ (if (and (nick-in-room? nick room)
+ (not (room-is-private? room)))
(do
(send-to-client*
channel (format ":*** PRIVMSG %s :%s" room "Catchup Playback"))
View
13 src/subrosa/plugins/fs_logging.clj
@@ -21,12 +21,13 @@
(str log-dir "/" room-name "_" (format-date) ".log")))
(defn append [room-name msg]
- (send io-agent
- (fn [_]
- (io!
- (with-open [out (FileWriter. (get-log-name room-name) true)]
- (.write out (.toCharArray
- (str (format-time) " " msg "\n"))))))))
+ (when-not (room-is-private? room-name)
+ (send io-agent
+ (fn [_]
+ (io!
+ (with-open [out (FileWriter. (get-log-name room-name) true)]
+ (.write out (.toCharArray
+ (str (format-time) " " msg "\n")))))))))
(defmulti log (fn [& args] (first args)))
View
9 src/subrosa/plugins/swank.clj
@@ -0,0 +1,9 @@
+(ns subrosa.plugins.swank
+ (:use [subrosa.config :only [config]])
+ (:require [swank.swank]
+ [clojure.tools.logging :as log]))
+
+(when (config :plugins :swank :enabled?)
+ (with-out-str
+ (swank.swank/start-repl (config :plugins :swank :port)))
+ (log/info "Starting Swank... done."))
View
5 src/subrosa/server.clj
@@ -6,13 +6,16 @@
;; database schema:
;; :user => [:nick :real-name :user-name :quit-message :channel :pending?]
-;; :room => [:name :topic]
+;; :room => [:name :topic :mode]
;; :user-in-room => [:user-nick :room-name]
(defonce server {:host (config :host)
:version (str "subrosa-" (.trim (slurp "etc/version.txt")))
:started (Date.)})
+(def supported-room-modes #{\p})
+;; p -> private
+
(defn reset-all-state! []
(alter-var-root #'server assoc :started (Date.))
(dosync (ref-set db/db {}))
View
3 test/subrosa/test/connection.clj
@@ -232,11 +232,12 @@
(with-connection s2
(transmit s2 "NICK awesomedan")
(transmit s2 "USER dan2 0 * :Dan Larkin2")
+ (transmit s2 "JOIN #foo")
(transmit s2 "WHO")
(is (received?
s2 #"352 awesomedan \* dan .* .* superdan H :0 Dan Larkin"))
(is (received?
- s2 #"352 awesomedan \* dan2 .* .* awesomedan H :0 Dan Larkin2"))
+ s2 #"352 awesomedan \#foo dan2 .* .* awesomedan H :0 Dan Larkin2"))
(is (received? s2 #"315 awesomedan \* :End of WHO list")))))
(deftest who-command-for-an-empty-channel
View
11 test/subrosa/test/expect.clj
@@ -3,6 +3,7 @@
[clojure.string :only [join]]
[subrosa.netty :only [create-server]]
[subrosa.config :only [config]])
+ (:require [clojure.tools.logging :as log])
(:import [java.io BufferedReader InputStreamReader]
[javax.net.ssl X509TrustManager SSLContext]
[javax.net SocketFactory]))
@@ -14,10 +15,10 @@
(defn run-test-server [f]
(let [server (create-server *port*)]
(try
- (with-out-str ((:start-fn server)))
- (f)
- (finally
- (with-out-str ((:stop-fn server)))))))
+ (binding [log/log* (fn [& _])]
+ ((:start-fn server))
+ (f)
+ ((:stop-fn server))))))
(defn socket-read-line [in]
(try
@@ -54,7 +55,7 @@
(try
~@body
(finally
- (.close (:socket ~s))))))
+ (.close (:socket ~s))))))
(defn transmit [socket command]
(let [out (:out socket)]
View
5 test/subrosa/test/plugins/catchup.clj
@@ -11,6 +11,9 @@
(transmit s1 "USER lee 0 * :Lee Hinmanm")
(transmit s1 "JOIN #foo")
(Thread/sleep 500)
+ (transmit s1 "JOIN #bar-")
+ (Thread/sleep 500)
+ (transmit s1 "PRIVMSG #bar- :Hey, bar private chat")
(transmit s1 "PRIVMSG #foo :Hello, World!")
(transmit s1 "NOTICE #foo :Hey, it's a notice!")
(transmit s1 "PRIVMSG #foo :\u0001ACTION says hi\u0001")
@@ -25,6 +28,8 @@
(is (received? s1 #"PRIVMSG #foo :\[.*\] Hello, World!"))
(is (received? s1 #"NOTICE #foo :\[.*\] Hey, it's a notice!"))
(is (received? s1 #"PRIVMSG #foo :\u0001ACTION \[.*\] says hi\u0001"))
+ (transmit s1 "CATCHUP #bar-")
+ (is (not-received? s1 #"PRIVMSG #bar- :\[.*\] Hey, bar private chat"))
(transmit s1 "PART #foo")
(transmit s1 "QUIT"))))
View
39 test/subrosa/test/rooms.clj
@@ -353,3 +353,42 @@
(transmit s "KICK #supercool dan2")
(is (received?
s #"441 dan dan2 \#supercool :They aren't on that channel")))))
+
+(deftest private-rooms-dont-show-in-list
+ (with-connection s
+ (transmit s "NICK dan")
+ (transmit s "USER dan 0 * :Dan Larkin")
+ (transmit s "JOIN #foo")
+ (transmit s "JOIN #foo-")
+ (transmit s "LIST")
+ (is (received? s #"322 dan #foo 1 :"))
+ (is (not-received? s #"322 dan #foo- 1 :"))))
+
+(deftest private-rooms-dont-show-in-whois
+ (with-connection s
+ (transmit s "NICK dan")
+ (transmit s "USER dan 0 * :Dan Larkin")
+ (transmit s "JOIN #foo")
+ (transmit s "JOIN #foo-")
+ (transmit s "WHOIS dan")
+ (is (received? s #"311 dan dan .* \* :Dan Larkin"))
+ (is (received? s #"319 dan dan :#foo"))
+ (is (received? s #":End of WHOIS list"))))
+
+(deftest mode-tests
+ (with-connection s
+ (transmit s "NICK dan")
+ (transmit s "USER dan 0 * :Dan Larkin")
+ (transmit s "JOIN #foo")
+ (transmit s "MODE #foo")
+ (is (received? s #"324 dan #foo +"))
+ (transmit s "MODE #foo p")
+ (is (received? s #"MODE #foo \+p"))
+ (reset! (:received s) [])
+ (transmit s "MODE #foo +p")
+ (is (not-received? s #"MODE #foo \+p"))
+ (transmit s "MODE #foo -p")
+ (is (received? s #"MODE #foo \-p"))
+ (reset! (:received s) [])
+ (transmit s "MODE #foo -p")
+ (is (not-received? s #"MODE #foo \-p"))))

No commit comments for this range

Something went wrong with that request. Please try again.