diff options
Diffstat (limited to 'Presence/main.hs')
-rw-r--r-- | Presence/main.hs | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/Presence/main.hs b/Presence/main.hs index bf4809a8..a7ff5e5a 100644 --- a/Presence/main.hs +++ b/Presence/main.hs | |||
@@ -1,6 +1,7 @@ | |||
1 | {-# LANGUAGE CPP #-} | 1 | {-# LANGUAGE CPP #-} |
2 | {-# LANGUAGE OverloadedStrings #-} | 2 | {-# LANGUAGE OverloadedStrings #-} |
3 | {-# LANGUAGE TypeFamilies #-} | 3 | {-# LANGUAGE TypeFamilies #-} |
4 | {-# LANGUAGE ExistentialQuantification #-} | ||
4 | module Main where | 5 | module Main where |
5 | 6 | ||
6 | import System.Directory | 7 | import System.Directory |
@@ -79,6 +80,7 @@ data PresenceState = PresenceState | |||
79 | , subscriberMap :: TVar (Map JID (RefCount,TChan Presence)) -- UNUSED as yet | 80 | , subscriberMap :: TVar (Map JID (RefCount,TChan Presence)) -- UNUSED as yet |
80 | , localSubscriber :: TMVar (RefCount,TChan Presence) -- TODO: rename this, its not just locals | 81 | , localSubscriber :: TMVar (RefCount,TChan Presence) -- TODO: rename this, its not just locals |
81 | -- ... or make a seperate channel for remotes | 82 | -- ... or make a seperate channel for remotes |
83 | , rosterChannel :: TMVar (RefCount,TChan RosterEvent) | ||
82 | , remoteUsers :: TVar (Map Peer (RefCount,TVar (MultiMap JabberUser (JabberResource,JabberShow)))) | 84 | , remoteUsers :: TVar (Map Peer (RefCount,TVar (MultiMap JabberUser (JabberResource,JabberShow)))) |
83 | , outGoingConnections :: TVar (Map Peer (TChan OutBoundMessage, ThreadId)) | 85 | , outGoingConnections :: TVar (Map Peer (TChan OutBoundMessage, ThreadId)) |
84 | } | 86 | } |
@@ -99,6 +101,7 @@ data ClientSession = ClientSession { | |||
99 | localhost :: Peer, -- ByteString, | 101 | localhost :: Peer, -- ByteString, |
100 | unix_uid :: (IORef (Maybe (UserID,L.ByteString))), | 102 | unix_uid :: (IORef (Maybe (UserID,L.ByteString))), |
101 | unix_resource :: (IORef (Maybe L.ByteString)), | 103 | unix_resource :: (IORef (Maybe L.ByteString)), |
104 | chans :: TVar [RefCountedChan], | ||
102 | presence_state :: PresenceState | 105 | presence_state :: PresenceState |
103 | } | 106 | } |
104 | 107 | ||
@@ -112,7 +115,8 @@ instance JabberClientSession ClientSession where | |||
112 | L.putStrLn $ "CLIENT SESSION: open " <++> bshow muid | 115 | L.putStrLn $ "CLIENT SESSION: open " <++> bshow muid |
113 | uid_ref <- newIORef muid | 116 | uid_ref <- newIORef muid |
114 | res_ref <- newIORef Nothing | 117 | res_ref <- newIORef Nothing |
115 | return $ ClientSession (hostname state) uid_ref res_ref state | 118 | chans <- atomically $ newTVar [] |
119 | return $ ClientSession (hostname state) uid_ref res_ref chans state | ||
116 | 120 | ||
117 | setResource s resource = do | 121 | setResource s resource = do |
118 | -- TODO: handle resource = empty string | 122 | -- TODO: handle resource = empty string |
@@ -137,15 +141,30 @@ instance JabberClientSession ClientSession where | |||
137 | return (JID (Just user) host rsc) | 141 | return (JID (Just user) host rsc) |
138 | 142 | ||
139 | closeSession session = do | 143 | closeSession session = do |
144 | atomically $ do | ||
145 | cs <- readTVar (chans session) | ||
146 | forM_ cs $ \(RefCountedChan c) -> do | ||
147 | unsubscribeToChan c | ||
140 | L.putStrLn "CLIENT SESSION: close" | 148 | L.putStrLn "CLIENT SESSION: close" |
141 | 149 | ||
142 | subscribe session Nothing = do | 150 | subscribe session Nothing = do |
143 | let tmvar = localSubscriber (presence_state session) | 151 | let tmvar = localSubscriber (presence_state session) |
144 | atomically $ subscribeToChan tmvar | 152 | atomically $ do |
153 | cs <- readTVar (chans session) | ||
154 | writeTVar (chans session) (RefCountedChan tmvar:cs) | ||
155 | subscribeToChan tmvar | ||
145 | subscribe session (Just jid) = do -- UNUSED as yet | 156 | subscribe session (Just jid) = do -- UNUSED as yet |
146 | let tvar = subscriberMap (presence_state session) | 157 | let tvar = subscriberMap (presence_state session) |
147 | atomically $ subscribeToMap tvar jid | 158 | atomically $ subscribeToMap tvar jid |
148 | 159 | ||
160 | subscribeToRoster session = do | ||
161 | let rchan = rosterChannel . presence_state $ session | ||
162 | atomically $ do | ||
163 | cs <- readTVar (chans session) | ||
164 | writeTVar (chans session) (RefCountedChan rchan:cs) | ||
165 | subscribeToChan rchan | ||
166 | |||
167 | |||
149 | forCachedPresence s action = do | 168 | forCachedPresence s action = do |
150 | jid <- getJID s | 169 | jid <- getJID s |
151 | L.putStrLn $ "forCachedPresence "<++> bshow jid | 170 | L.putStrLn $ "forCachedPresence "<++> bshow jid |
@@ -171,6 +190,13 @@ instance JabberClientSession ClientSession where | |||
171 | addSolicited s jid = do | 190 | addSolicited s jid = do |
172 | user <- readIORef (unix_uid s) >>= getJabberUserForId | 191 | user <- readIORef (unix_uid s) >>= getJabberUserForId |
173 | ConfigFiles.addSolicited user jid -- (L.show jid) | 192 | ConfigFiles.addSolicited user jid -- (L.show jid) |
193 | let rchan = rosterChannel . presence_state $ s | ||
194 | atomically $ do | ||
195 | isempty <- isEmptyTMVar rchan | ||
196 | when (not isempty) $ do | ||
197 | (_,ch) <- readTMVar rchan | ||
198 | writeTChan ch (RequestedSubscription user jid) | ||
199 | |||
174 | 200 | ||
175 | getMyBuddies s = do | 201 | getMyBuddies s = do |
176 | user <- readIORef (unix_uid s) >>= getJabberUserForId | 202 | user <- readIORef (unix_uid s) >>= getJabberUserForId |
@@ -251,6 +277,9 @@ instance JabberPeerSession PeerSession where | |||
251 | getSubscribers _ user = ConfigFiles.getSubscribers user | 277 | getSubscribers _ user = ConfigFiles.getSubscribers user |
252 | 278 | ||
253 | 279 | ||
280 | data RefCountedChan = forall a. RefCountedChan (TMVar (RefCount,TChan a)) | ||
281 | |||
282 | subscribeToChan :: TMVar (RefCount, TChan a) -> STM (TChan a) | ||
254 | subscribeToChan tmvar = | 283 | subscribeToChan tmvar = |
255 | (do (cnt,chan) <- takeTMVar tmvar | 284 | (do (cnt,chan) <- takeTMVar tmvar |
256 | putTMVar tmvar (cnt+1,chan) | 285 | putTMVar tmvar (cnt+1,chan) |
@@ -260,6 +289,12 @@ subscribeToChan tmvar = | |||
260 | (do chan <- newTChan | 289 | (do chan <- newTChan |
261 | putTMVar tmvar (1,chan) | 290 | putTMVar tmvar (1,chan) |
262 | return chan ) | 291 | return chan ) |
292 | unsubscribeToChan :: TMVar (RefCount,TChan a) -> STM () | ||
293 | unsubscribeToChan tmvar = do | ||
294 | isEmpty <- isEmptyTMVar tmvar | ||
295 | when (not isEmpty) $ do | ||
296 | (cnt,chan) <- takeTMVar tmvar | ||
297 | when (cnt>1) (putTMVar tmvar (cnt-1,chan)) | ||
263 | 298 | ||
264 | getRefFromMap tvar key newObject copyObject = do | 299 | getRefFromMap tvar key newObject copyObject = do |
265 | subs <- readTVar tvar | 300 | subs <- readTVar tvar |
@@ -322,9 +357,10 @@ newPresenceState hostname = atomically $ do | |||
322 | us <- newTVar (Set.empty) | 357 | us <- newTVar (Set.empty) |
323 | subs <- newTVar (Map.empty) | 358 | subs <- newTVar (Map.empty) |
324 | locals_greedy <- newEmptyTMVar | 359 | locals_greedy <- newEmptyTMVar |
360 | rchan <- newEmptyTMVar | ||
325 | remotes <- newTVar (Map.empty) | 361 | remotes <- newTVar (Map.empty) |
326 | server_connections <- newServerConnections | 362 | server_connections <- newServerConnections |
327 | return $ PresenceState hostname tty us subs locals_greedy remotes server_connections | 363 | return $ PresenceState hostname tty us subs locals_greedy rchan remotes server_connections |
328 | 364 | ||
329 | sendProbes state jid = do | 365 | sendProbes state jid = do |
330 | L.putStrLn $ "sending probes for " <++> bshow jid | 366 | L.putStrLn $ "sending probes for " <++> bshow jid |