summaryrefslogtreecommitdiff
path: root/Presence/main.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Presence/main.hs')
-rw-r--r--Presence/main.hs42
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 #-}
4module Main where 5module Main where
5 6
6import System.Directory 7import 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
280data RefCountedChan = forall a. RefCountedChan (TMVar (RefCount,TChan a))
281
282subscribeToChan :: TMVar (RefCount, TChan a) -> STM (TChan a)
254subscribeToChan tmvar = 283subscribeToChan 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 )
292unsubscribeToChan :: TMVar (RefCount,TChan a) -> STM ()
293unsubscribeToChan 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
264getRefFromMap tvar key newObject copyObject = do 299getRefFromMap 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
329sendProbes state jid = do 365sendProbes state jid = do
330 L.putStrLn $ "sending probes for " <++> bshow jid 366 L.putStrLn $ "sending probes for " <++> bshow jid