Skip to content

Instantly share code, notes, and snippets.

@bjering
Created August 23, 2010 13:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bjering/bd04ff4594a3f5413bf2 to your computer and use it in GitHub Desktop.
Save bjering/bd04ff4594a3f5413bf2 to your computer and use it in GitHub Desktop.
(ns chat.session
(:use
[clojure.contrib.def])
(:require
[chat.common]
[chat.session]
[chat.user])
(:import
[java.net InetSocketAddress]
[java.util.concurrent Executors]
[org.jboss.netty.bootstrap ServerBootstrap]
[org.jboss.netty.channel Channels ChannelPipelineFactory SimpleChannelHandler]
[org.jboss.netty.channel.group DefaultChannelGroup]
[org.jboss.netty.channel.socket.nio NioServerSocketChannelFactory]
[org.jboss.netty.buffer ChannelBuffers]
[org.jboss.netty.handler.codec.frame DelimiterBasedFrameDecoder Delimiters]))
;helpers
(defn encode
"Creates a buffer prepared for a Flash XMLSocket"
[str]
(ChannelBuffers/wrappedBuffer
(into-array
[(.getBytes str "UTF-8")
(byte-array [(byte 0)])])))
(def flash-policy-file
(str "<?xml version=\"1.0\"?>"
"<!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">"
"<cross-domain-policy>"
"<allow-access-from domain=\"195.198.115.136\" to-ports=\"4711\"/>"
"</cross-domain-policy>"))
(defn- login
[this user-name]
(let
[user (@chat.user/users user-name)]
(if user
(chat.common/login this user)
(str "error No such user: [" user-name "]" ))))
(defn- handle-message
[this msg]
(let
[msg-seq (.split #" " msg)
command (first msg-seq)
args (rest msg-seq)]
(cond
(= "login" command) (apply login this args)
:else (str "error Unknown Command: " command))))
(defn- session-parse
[this msg]
(cond
(.isEmpty msg) "error Empty Message"
(= '<' (get msg 0)) flash-policy-file
:else (handle-message this msg)))
(defn- receive
[this msg]
(let
[user (this :user)
reply (if user
(user :parse msg)
(session-parse this msg))]
(when reply
(do
(this :write reply)))))
(defn- write
[this msg]
(let
[netty-channel ((this :state) :netty-channel)]
(when (.isOpen netty-channel)
(.write netty-channel (encode msg)))))
(defn- disconnect
[this]
(let
[user (this :user)]
(when user
(user :send :logout))))
(defn dispatcher
[agt message & args]
(let
[this (partial dispatcher agt)]
(cond
(= message :agent) agt
(= message :state) @agt
(= message :user) (@agt :user)
(= message :receive) (apply receive this args)
(= message :write) (apply write this args)
(= message :disconnect) (apply disconnect this args)
(= message :send)
(do
(apply chat.common/send-message agt args)
this)
:else (throw (IllegalArgumentException.
(str "unknown message in [" "session" "] " message))))))
(defn- set-user
[session user]
(conj session {:user user}))
(defn- close
[session]
(let
[netty-channel (session :netty-channel)]
(when (.isOpen netty-channel)
(.close netty-channel))
(conj session {:user nil})))
(defn create
[netty-channel]
(partial dispatcher
(agent
{:netty-channel netty-channel
:user nil
:set-user set-user
:close close})))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment