diff options
-rw-r--r-- | Presence/main.hs | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/Presence/main.hs b/Presence/main.hs index e5d3046c..f77e582b 100644 --- a/Presence/main.hs +++ b/Presence/main.hs | |||
@@ -34,14 +34,12 @@ import qualified Data.Set as Set | |||
34 | import Data.Set as Set (Set,(\\)) | 34 | import Data.Set as Set (Set,(\\)) |
35 | import qualified Data.Map as Map | 35 | import qualified Data.Map as Map |
36 | import Data.Map as Map (Map) | 36 | import Data.Map as Map (Map) |
37 | import Control.Concurrent.MVar -- .Strict | 37 | |
38 | import Control.Concurrent.STM | ||
38 | import Control.Concurrent (threadDelay) | 39 | import Control.Concurrent (threadDelay) |
39 | import Control.Concurrent.Chan | ||
40 | import Control.DeepSeq | 40 | import Control.DeepSeq |
41 | import Control.Monad.Trans.Maybe | 41 | import Control.Monad.Trans.Maybe |
42 | -- import Control.Monad.Trans.Class | ||
43 | import Control.Monad.IO.Class | 42 | import Control.Monad.IO.Class |
44 | -- import Debug.Trace | ||
45 | 43 | ||
46 | import ByteStringOperators | 44 | import ByteStringOperators |
47 | import qualified Data.ByteString.Lazy.Char8 as L | 45 | import qualified Data.ByteString.Lazy.Char8 as L |
@@ -117,7 +115,7 @@ matchResource tty jid = maybe Away (avail . (==tty)) $ resource jid | |||
117 | avail False = Away | 115 | avail False = Away |
118 | 116 | ||
119 | sendPresence chan jid status = | 117 | sendPresence chan jid status = |
120 | (liftIO . writeChan chan . Just . Presence jid $ status) :: MaybeT IO () | 118 | (liftIO . atomically . writeTChan chan . Presence jid $ status) :: MaybeT IO () |
121 | 119 | ||
122 | lookupT jid subscribers = MaybeT . return $ Map.lookup jid subscribers | 120 | lookupT jid subscribers = MaybeT . return $ Map.lookup jid subscribers |
123 | 121 | ||
@@ -129,8 +127,21 @@ update_presence subscribers state getStatus = | |||
129 | sendPresence chan jid status | 127 | sendPresence chan jid status |
130 | putStrLn $ bshow jid <++> " " <++> bshow status | 128 | putStrLn $ bshow jid <++> " " <++> bshow status |
131 | 129 | ||
132 | track_login :: MVar (ByteString,Set JID,Map JID (Chan MaybePresence)) -> t -> IO () | 130 | type RefCount = Int |
133 | track_login mvar e = do | 131 | |
132 | data PresenceState = PresenceState { | ||
133 | currentTTY :: TVar ByteString, | ||
134 | activeUsers :: TVar (Set JID), | ||
135 | subscriberMap :: TVar (Map JID (RefCount,TChan Presence)) | ||
136 | } | ||
137 | |||
138 | newPresenceState = atomically $ do | ||
139 | tty <- newTVar "" | ||
140 | us <- newTVar (Set.empty) | ||
141 | subs <- newTVar (Map.empty) | ||
142 | return $ PresenceState tty us subs | ||
143 | |||
144 | track_login state e = do | ||
134 | #ifndef NOUTMP | 145 | #ifndef NOUTMP |
135 | us <- UTmp.users | 146 | us <- UTmp.users |
136 | #else | 147 | #else |
@@ -140,26 +151,31 @@ track_login mvar e = do | |||
140 | if L.take 3 tty == "tty" | 151 | if L.take 3 tty == "tty" |
141 | then Just (jid user host tty) | 152 | then Just (jid user host tty) |
142 | else Nothing | 153 | else Nothing |
143 | jids = Set.fromList $ mapMaybe (toJabberId "localhost") us | 154 | new_users = Set.fromList $ mapMaybe (toJabberId "localhost") us |
144 | (tty,users,subscribers) | 155 | (tty,known_users,subs) <- atomically $ do |
145 | <- modifyMVar mvar $ \(tty,st,xs) -> | 156 | tty <- readTVar $ currentTTY state |
146 | return ((tty,jids,xs),(tty,st,xs)) | 157 | st <- flip swapTVar new_users $ activeUsers state |
147 | let arrivals = jids \\ users | 158 | xs <- readTVar $ subscriberMap state |
148 | departures = users \\ jids | 159 | return (tty,st,fmap snd xs) |
149 | update_presence subscribers departures $ const Offline | 160 | let arrivals = new_users \\ known_users |
150 | update_presence subscribers arrivals $ matchResource tty | 161 | departures = known_users \\ new_users |
151 | 162 | update_presence subs departures $ const Offline | |
152 | on_chvt mvar vtnum = do | 163 | update_presence subs arrivals $ matchResource tty |
164 | |||
165 | on_chvt state vtnum = do | ||
153 | let tty = L.snoc "tty" $ intToDigit (fromIntegral vtnum) | 166 | let tty = L.snoc "tty" $ intToDigit (fromIntegral vtnum) |
154 | L.putStrLn $ "VT switch: " <++> tty | 167 | L.putStrLn $ "VT switch: " <++> tty |
155 | (users,subscribers) <- modifyMVar mvar $ \(_,us,xs) -> do | 168 | (users,subs) <- atomically $ do |
156 | return ((tty,us,xs),(us,xs)) | 169 | us <- readTVar $ activeUsers state |
157 | update_presence subscribers users $ matchResource tty | 170 | subs <- readTVar $ subscriberMap state |
171 | writeTVar (currentTTY state) tty | ||
172 | return (us,fmap snd subs) | ||
173 | update_presence subs users $ matchResource tty | ||
158 | 174 | ||
159 | 175 | ||
160 | start :: IO () | 176 | start :: IO () |
161 | start = do | 177 | start = do |
162 | tracked <- newMVar ("",Set.empty,Map.empty) | 178 | tracked <- newPresenceState |
163 | let dologin e = track_login tracked e | 179 | let dologin e = track_login tracked e |
164 | dologin :: t -> IO () | 180 | dologin :: t -> IO () |
165 | installHandler sigUSR1 (Catch (dologin (userError "signaled"))) Nothing | 181 | installHandler sigUSR1 (Catch (dologin (userError "signaled"))) Nothing |