summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Presence/XMPPServer.hs28
-rw-r--r--Presence/main.hs63
2 files changed, 59 insertions, 32 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index 044ed9e4..4a859bc9 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -40,6 +40,33 @@ import Network.Socket
40import Data.String 40import Data.String
41import Control.Monad.Trans.Maybe 41import Control.Monad.Trans.Maybe
42import Control.Monad.IO.Class 42import Control.Monad.IO.Class
43import Control.DeepSeq
44import Control.Concurrent.STM
45
46-- | Jabber ID (JID) datatype
47data JID = JID { name :: Maybe ByteString
48 , server :: ByteString
49 , resource :: Maybe ByteString
50 }
51 deriving (Ord,Eq)
52
53instance Show JID where
54 show (JID n s r ) = L.unpack $ fmap (<++>"@") n <?++> s <++?> fmap ("/"<++>) r
55
56instance NFData JID where
57 rnf v@(JID n s r) = n `seq` s `seq` r `seq` ()
58
59jid user host rsrc = JID (Just user) host (Just rsrc)
60
61data JabberShow = Offline
62 | Away
63 | Available
64 deriving (Show,Enum,Ord,Eq,Read)
65
66data Presence = Presence JID JabberShow
67
68instance NFData Presence where
69 rnf (Presence jid stat) = rnf jid `seq` stat `seq` ()
43 70
44 71
45class XMPPSession session where 72class XMPPSession session where
@@ -48,6 +75,7 @@ class XMPPSession session where
48 setResource :: session -> ByteString -> IO () 75 setResource :: session -> ByteString -> IO ()
49 getJID :: session -> IO ByteString 76 getJID :: session -> IO ByteString
50 closeSession :: session -> IO () 77 closeSession :: session -> IO ()
78 subscribeToPresence :: session -> Maybe JID -> IO (TChan Presence)
51 79
52 80
53greet host = L.unlines 81greet host = L.unlines
diff --git a/Presence/main.hs b/Presence/main.hs
index 4168feca..78ca4363 100644
--- a/Presence/main.hs
+++ b/Presence/main.hs
@@ -37,7 +37,6 @@ import Data.Map as Map (Map)
37 37
38import Control.Concurrent.STM 38import Control.Concurrent.STM
39import Control.Concurrent (threadDelay) 39import Control.Concurrent (threadDelay)
40import Control.DeepSeq
41import Control.Monad.Trans.Maybe 40import Control.Monad.Trans.Maybe
42import Control.Monad.IO.Class 41import Control.Monad.IO.Class
43 42
@@ -48,34 +47,20 @@ import qualified Prelude
48import Prelude hiding (putStrLn) 47import Prelude hiding (putStrLn)
49 48
50 49
51-- | Jabber ID (JID) datatype
52data JID = JID { name :: Maybe ByteString
53 , server :: ByteString
54 , resource :: Maybe ByteString
55 }
56 deriving (Ord,Eq)
57
58instance Show JID where
59 show (JID n s r ) = L.unpack $ fmap (<++>"@") n <?++> s <++?> fmap ("/"<++>) r
60
61instance NFData JID where
62 rnf v@(JID n s r) = n `seq` s `seq` r `seq` ()
63
64jid user host rsrc = JID (Just user) host (Just rsrc)
65
66data UnixSession = UnixSession { 50data UnixSession = UnixSession {
67 unix_uid :: (IORef (Maybe UserID)), 51 unix_uid :: (IORef (Maybe UserID)),
68 unix_resource :: (IORef (Maybe L.ByteString)) 52 unix_resource :: (IORef (Maybe L.ByteString)),
53 presence_state :: PresenceState
69} 54}
70 55
71instance XMPPSession UnixSession where 56instance XMPPSession UnixSession where
72 data XMPPClass UnixSession = UnixSessions 57 data XMPPClass UnixSession = UnixSessions PresenceState
73 newSession _ sock handle = do 58 newSession (UnixSessions state) sock handle = do
74 muid <- getLocalPeerCred sock 59 muid <- getLocalPeerCred sock
75 L.putStrLn $ "SESSION: open " <++> bshow muid 60 L.putStrLn $ "SESSION: open " <++> bshow muid
76 uid_ref <- newIORef muid 61 uid_ref <- newIORef muid
77 res_ref <- newIORef Nothing 62 res_ref <- newIORef Nothing
78 return $ UnixSession uid_ref res_ref 63 return $ UnixSession uid_ref res_ref state
79 setResource s resource = do 64 setResource s resource = do
80 writeIORef (unix_resource s) (Just resource) 65 writeIORef (unix_resource s) (Just resource)
81 L.putStrLn $ "SESSION: resource " <++> resource 66 L.putStrLn $ "SESSION: resource " <++> resource
@@ -97,17 +82,31 @@ instance XMPPSession UnixSession where
97 L.putStrLn $ "SESSION: jid " <++> jid 82 L.putStrLn $ "SESSION: jid " <++> jid
98 return jid 83 return jid
99 closeSession _ = L.putStrLn "SESSION: close" 84 closeSession _ = L.putStrLn "SESSION: close"
100 85 subscribeToPresence session Nothing = do
101data JabberShow = Offline 86 let tmvar = greedySubscriber (presence_state session)
102 | Away 87 chan <- atomically $
103 | Available 88 (do (cnt,chan) <- takeTMVar tmvar
104 deriving (Show,Enum,Ord,Eq,Read) 89 putTMVar tmvar (cnt+1,chan)
105 90 return chan )
106data Presence = Presence JID JabberShow 91 `orElse`
107type MaybePresence = Maybe Presence 92 (do chan <- newTChan
108 93 putTMVar tmvar (1,chan)
109instance NFData Presence where 94 return chan )
110 rnf (Presence jid stat) = rnf jid `seq` stat `seq` () 95 return chan
96 subscribeToPresence session (Just jid) = do
97 let tvar = subscriberMap (presence_state session)
98 atomically $ do
99 subs <- readTVar tvar
100 let mbchan = Map.lookup jid subs
101 (chan,subs') <-
102 do case mbchan of
103 Nothing -> do
104 newchan <- newTChan
105 return (newchan, Map.insert jid (1,newchan) subs)
106 Just (cnt,chan) -> do
107 return (chan, Map.insert jid (cnt+1,chan) subs)
108 writeTVar tvar subs'
109 return chan
111 110
112matchResource tty jid = maybe Away (avail . (==tty)) $ resource jid 111matchResource tty jid = maybe Away (avail . (==tty)) $ resource jid
113 where 112 where
@@ -196,7 +195,7 @@ start = do
196 utmp_file 195 utmp_file
197 dologin 196 dologin
198#endif 197#endif
199 sock <- listenForXmppClients UnixSessions 5222 HNil 198 sock <- listenForXmppClients (UnixSessions tracked) 5222 HNil
200 199
201 threadDelay 1000 -- wait a moment to obtain current tty 200 threadDelay 1000 -- wait a moment to obtain current tty
202 dologin () 201 dologin ()