diff options
author | joe <joe@jerkface.net> | 2013-06-18 16:24:24 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2013-06-18 16:24:24 -0400 |
commit | 4d477d8559f35d897e16e1144bcf80902ac6d307 (patch) | |
tree | 03ead2887fae9f7e04f188b10e0fff15b5ff6bdc /Presence | |
parent | 946440e0ac31e8cb6b2fe873f27627d6d5fbd23f (diff) |
Subscriber channels.
Diffstat (limited to 'Presence')
-rw-r--r-- | Presence/main.hs | 81 |
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 | |||
32 | import System.Posix.User | 32 | import System.Posix.User |
33 | import qualified Data.Set as Set | 33 | import qualified Data.Set as Set |
34 | import Data.Set as Set (Set,(\\)) | 34 | import Data.Set as Set (Set,(\\)) |
35 | import Control.Concurrent.MVar.Strict | 35 | import qualified Data.Map as Map |
36 | import Data.Map as Map (Map) | ||
37 | import Control.Concurrent.MVar -- .Strict | ||
36 | import Control.Concurrent (threadDelay) | 38 | import Control.Concurrent (threadDelay) |
39 | import Control.Concurrent.Chan | ||
37 | import Control.DeepSeq | 40 | import Control.DeepSeq |
38 | import Debug.Trace | 41 | import Control.Monad.Trans.Maybe |
42 | -- import Control.Monad.Trans.Class | ||
43 | import Control.Monad.IO.Class | ||
44 | -- import Debug.Trace | ||
39 | 45 | ||
40 | import ByteStringOperators | 46 | import ByteStringOperators |
41 | import qualified Data.ByteString.Lazy.Char8 as L | 47 | import 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 | ||
97 | track_login :: MVar (ByteString,Set JID) -> t -> IO () | 103 | data JabberShow = Offline |
98 | track_login tracked e = do | 104 | | Away |
105 | | Available | ||
106 | deriving (Show,Enum,Ord,Eq,Read) | ||
107 | |||
108 | data Presence = Presence JID JabberShow | ||
109 | type MaybePresence = Maybe Presence | ||
110 | |||
111 | instance NFData Presence where | ||
112 | rnf (Presence jid stat) = rnf jid `seq` stat `seq` () | ||
113 | |||
114 | matchResource tty jid = maybe Away (avail . (==tty)) $ resource jid | ||
115 | where | ||
116 | avail True = Available | ||
117 | avail False = Away | ||
118 | |||
119 | sendPresence chan jid status = | ||
120 | (liftIO . writeChan chan . Just . Presence jid $ status) :: MaybeT IO () | ||
121 | |||
122 | lookupT jid subscribers = MaybeT . return $ Map.lookup jid subscribers | ||
123 | |||
124 | update_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 | |||
132 | track_login :: MVar (ByteString,Set JID,Map JID (Chan MaybePresence)) -> t -> IO () | ||
133 | track_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." | 152 | on_chvt mvar vtnum = do |
118 | Just False -> putStrLn $ bshow jid <++> " Away." | ||
119 | Nothing -> trace "Unexpected lack of resource" $ return () | ||
120 | |||
121 | on_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 | ||
133 | start :: IO () | 160 | start :: IO () |
134 | start = do | 161 | start = 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 |