summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2013-06-18 16:24:24 -0400
committerjoe <joe@jerkface.net>2013-06-18 16:24:24 -0400
commit4d477d8559f35d897e16e1144bcf80902ac6d307 (patch)
tree03ead2887fae9f7e04f188b10e0fff15b5ff6bdc /Presence
parent946440e0ac31e8cb6b2fe873f27627d6d5fbd23f (diff)
Subscriber channels.
Diffstat (limited to 'Presence')
-rw-r--r--Presence/main.hs81
1 files changed, 54 insertions, 27 deletions
diff --git a/Presence/main.hs b/Presence/main.hs
index cf5942df..e5d3046c 100644
--- a/Presence/main.hs
+++ b/Presence/main.hs
@@ -32,10 +32,16 @@ import LocalPeerCred
32import System.Posix.User 32import System.Posix.User
33import qualified Data.Set as Set 33import qualified Data.Set as Set
34import Data.Set as Set (Set,(\\)) 34import Data.Set as Set (Set,(\\))
35import Control.Concurrent.MVar.Strict 35import qualified Data.Map as Map
36import Data.Map as Map (Map)
37import Control.Concurrent.MVar -- .Strict
36import Control.Concurrent (threadDelay) 38import Control.Concurrent (threadDelay)
39import Control.Concurrent.Chan
37import Control.DeepSeq 40import Control.DeepSeq
38import Debug.Trace 41import Control.Monad.Trans.Maybe
42-- import Control.Monad.Trans.Class
43import Control.Monad.IO.Class
44-- import Debug.Trace
39 45
40import ByteStringOperators 46import ByteStringOperators
41import qualified Data.ByteString.Lazy.Char8 as L 47import qualified Data.ByteString.Lazy.Char8 as L
@@ -94,10 +100,39 @@ instance XMPPSession UnixSession where
94 return jid 100 return jid
95 closeSession _ = L.putStrLn "SESSION: close" 101 closeSession _ = L.putStrLn "SESSION: close"
96 102
97track_login :: MVar (ByteString,Set JID) -> t -> IO () 103data JabberShow = Offline
98track_login tracked e = do 104 | Away
105 | Available
106 deriving (Show,Enum,Ord,Eq,Read)
107
108data Presence = Presence JID JabberShow
109type MaybePresence = Maybe Presence
110
111instance NFData Presence where
112 rnf (Presence jid stat) = rnf jid `seq` stat `seq` ()
113
114matchResource tty jid = maybe Away (avail . (==tty)) $ resource jid
115 where
116 avail True = Available
117 avail False = Away
118
119sendPresence chan jid status =
120 (liftIO . writeChan chan . Just . Presence jid $ status) :: MaybeT IO ()
121
122lookupT jid subscribers = MaybeT . return $ Map.lookup jid subscribers
123
124update_presence subscribers state getStatus =
125 forM_ (Set.toList state) $ \jid -> do
126 let status = getStatus jid
127 runMaybeT $ do
128 chan <- lookupT jid subscribers
129 sendPresence chan jid status
130 putStrLn $ bshow jid <++> " " <++> bshow status
131
132track_login :: MVar (ByteString,Set JID,Map JID (Chan MaybePresence)) -> t -> IO ()
133track_login mvar e = do
99#ifndef NOUTMP 134#ifndef NOUTMP
100 us <- users 135 us <- UTmp.users
101#else 136#else
102 let us = [] 137 let us = []
103#endif 138#endif
@@ -105,34 +140,26 @@ track_login tracked e = do
105 if L.take 3 tty == "tty" 140 if L.take 3 tty == "tty"
106 then Just (jid user host tty) 141 then Just (jid user host tty)
107 else Nothing 142 else Nothing
108 ids = Set.fromList $ mapMaybe (toJabberId "localhost") us 143 jids = Set.fromList $ mapMaybe (toJabberId "localhost") us
109 (tty,state) <- modifyMVar tracked $ \(tty,st) -> 144 (tty,users,subscribers)
110 return ((tty,ids),(tty,st)) 145 <- modifyMVar mvar $ \(tty,st,xs) ->
111 let arrivals = ids \\ state 146 return ((tty,jids,xs),(tty,st,xs))
112 departures = state \\ ids 147 let arrivals = jids \\ users
113 forM_ (Set.toList departures) $ \id -> do 148 departures = users \\ jids
114 putStrLn $ bshow id <++> " Offline." 149 update_presence subscribers departures $ const Offline
115 forM_ (Set.toList arrivals) $ \jid -> do 150 update_presence subscribers arrivals $ matchResource tty
116 case fmap (==tty) $ resource jid of 151
117 Just True -> putStrLn $ bshow jid <++> " Available." 152on_chvt mvar vtnum = do
118 Just False -> putStrLn $ bshow jid <++> " Away."
119 Nothing -> trace "Unexpected lack of resource" $ return ()
120
121on_chvt tracked vtnum = do
122 let tty = L.snoc "tty" $ intToDigit (fromIntegral vtnum) 153 let tty = L.snoc "tty" $ intToDigit (fromIntegral vtnum)
123 L.putStrLn $ "VT switch: " <++> tty 154 L.putStrLn $ "VT switch: " <++> tty
124 state <- modifyMVar tracked $ \(_,us) -> do 155 (users,subscribers) <- modifyMVar mvar $ \(_,us,xs) -> do
125 return ((tty,us),us) 156 return ((tty,us,xs),(us,xs))
126 forM_ (Set.toList state) $ \jid -> do 157 update_presence subscribers users $ matchResource tty
127 case fmap (==tty) $ resource jid of
128 Just True -> putStrLn $ bshow jid <++> " Available."
129 Just False -> putStrLn $ bshow jid <++> " Away."
130 Nothing -> return ()
131 158
132 159
133start :: IO () 160start :: IO ()
134start = do 161start = do
135 tracked <- newMVar ("",Set.empty) 162 tracked <- newMVar ("",Set.empty,Map.empty)
136 let dologin e = track_login tracked e 163 let dologin e = track_login tracked e
137 dologin :: t -> IO () 164 dologin :: t -> IO ()
138 installHandler sigUSR1 (Catch (dologin (userError "signaled"))) Nothing 165 installHandler sigUSR1 (Catch (dologin (userError "signaled"))) Nothing