summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
Diffstat (limited to 'Presence')
-rw-r--r--Presence/XMPP.hs3
-rw-r--r--Presence/XMPPTypes.hs1
-rw-r--r--Presence/main.hs79
3 files changed, 65 insertions, 18 deletions
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs
index c81ed8c7..fd29473e 100644
--- a/Presence/XMPP.hs
+++ b/Presence/XMPP.hs
@@ -249,6 +249,9 @@ handleIQSetBind session cmdChan stanza_id = do
249 setResource session (L.fromChunks [S.encodeUtf8 rsc]) 249 setResource session (L.fromChunks [S.encodeUtf8 rsc])
250 jid <- getJID session 250 jid <- getJID session
251 atomically $ writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) ) 251 atomically $ writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) )
252 forCachedPresence session $ \presence -> do
253 xs <- xmlifyPresenceForClient presence
254 atomically . writeTChan cmdChan . Send $ xs
252 _ -> unhandledBind 255 _ -> unhandledBind
253 256
254 257
diff --git a/Presence/XMPPTypes.hs b/Presence/XMPPTypes.hs
index 6e054708..6fc3e2ec 100644
--- a/Presence/XMPPTypes.hs
+++ b/Presence/XMPPTypes.hs
@@ -38,6 +38,7 @@ class JabberClientSession session where
38 getJID :: session -> IO JID 38 getJID :: session -> IO JID
39 closeSession :: session -> IO () 39 closeSession :: session -> IO ()
40 subscribe :: session -> Maybe JID -> IO (TChan Presence) 40 subscribe :: session -> Maybe JID -> IO (TChan Presence)
41 forCachedPresence :: session -> (Presence -> IO ()) -> IO ()
41 42
42class JabberPeerSession session where 43class JabberPeerSession session where
43 data XMPPPeerClass session 44 data XMPPPeerClass session
diff --git a/Presence/main.hs b/Presence/main.hs
index 7a0ee2b4..6721db86 100644
--- a/Presence/main.hs
+++ b/Presence/main.hs
@@ -56,9 +56,22 @@ import Prelude hiding (putStrLn)
56import System.Environment 56import System.Environment
57import qualified Text.Show.ByteString as L 57import qualified Text.Show.ByteString as L
58import Network.Socket (Family(AF_INET,AF_INET6)) 58import Network.Socket (Family(AF_INET,AF_INET6))
59import Holumbus.Data.MultiMap as MM (MultiMap)
60import qualified Holumbus.Data.MultiMap as MM
59 61
60type RefCount = Int 62type RefCount = Int
61 63
64type JabberResource = L.ByteString
65type JabberName = L.ByteString
66data JabberUser = JabberUser JabberName Peer
67 deriving (Eq,Ord,Show)
68
69splitResource :: JID -> Maybe (JabberUser,Maybe JabberResource)
70splitResource (JID Nothing _ _ ) = Nothing
71splitResource (JID (Just n) p r ) = Just (JabberUser n p, r)
72
73unsplitResource (JabberUser n p) r = JID (Just n) p r
74
62data PresenceState = PresenceState 75data PresenceState = PresenceState
63 { hostname :: Peer -- ByteString, TODO: remove this, its always LocalHost now 76 { hostname :: Peer -- ByteString, TODO: remove this, its always LocalHost now
64 , currentTTY :: TVar ByteString 77 , currentTTY :: TVar ByteString
@@ -66,11 +79,22 @@ data PresenceState = PresenceState
66 , subscriberMap :: TVar (Map JID (RefCount,TChan Presence)) -- UNUSED as yet 79 , subscriberMap :: TVar (Map JID (RefCount,TChan Presence)) -- UNUSED as yet
67 , localSubscriber :: TMVar (RefCount,TChan Presence) -- TODO: rename this, its not just locals 80 , localSubscriber :: TMVar (RefCount,TChan Presence) -- TODO: rename this, its not just locals
68 -- ... or make a seperate channel for remotes 81 -- ... or make a seperate channel for remotes
69 , remoteUsers :: TVar (Map Peer (RefCount,TVar (Set JID))) 82 , remoteUsers :: TVar (Map Peer (RefCount,TVar (MultiMap JabberUser (JabberResource,JabberShow))))
70 , outGoingConnections :: TVar (Map Peer (TChan OutBoundMessage, ThreadId)) 83 , outGoingConnections :: TVar (Map Peer (TChan OutBoundMessage, ThreadId))
71 } 84 }
72 85
73 86
87getJabberUserForId muid =
88 maybe (return "nobody")
89 (\uid ->
90 handle (\(SomeException _) ->
91 return . L.append "uid." . L.pack . show $ uid)
92 $ do
93 user <- fmap userName $ getUserEntryForID uid
94 return (L.pack user)
95 )
96 muid
97
74data ClientSession = ClientSession { 98data ClientSession = ClientSession {
75 localhost :: Peer, -- ByteString, 99 localhost :: Peer, -- ByteString,
76 unix_uid :: (IORef (Maybe UserID)), 100 unix_uid :: (IORef (Maybe UserID)),
@@ -95,15 +119,8 @@ instance JabberClientSession ClientSession where
95 getJID s = do 119 getJID s = do
96 let host = localhost s 120 let host = localhost s
97 muid <- readIORef (unix_uid s) 121 muid <- readIORef (unix_uid s)
98 user <- maybe (return "nobody") 122 user <- getJabberUserForId muid
99 (\uid -> 123
100 handle (\(SomeException _) ->
101 return . L.append "uid." . L.pack . show $ uid)
102 $ do
103 user <- fmap userName $ getUserEntryForID uid
104 return (L.pack user)
105 )
106 muid
107 rsc <- readIORef (unix_resource s) 124 rsc <- readIORef (unix_resource s)
108 -- let jid = user <++> "@" <++> host <++?> "/" <++$> rsc 125 -- let jid = user <++> "@" <++> host <++?> "/" <++$> rsc
109 L.putStrLn $ "CLIENT SESSION: jid " <++> L.show (JID (Just user) host rsc) 126 L.putStrLn $ "CLIENT SESSION: jid " <++> L.show (JID (Just user) host rsc)
@@ -119,9 +136,30 @@ instance JabberClientSession ClientSession where
119 let tvar = subscriberMap (presence_state session) 136 let tvar = subscriberMap (presence_state session)
120 atomically $ subscribeToMap tvar jid 137 atomically $ subscribeToMap tvar jid
121 138
139 forCachedPresence s action = do
140 jid <- getJID s
141 L.putStrLn $ "forCachedPresence "<++> bshow jid
142 withJust (name jid) $ \user -> do
143 let parseHostNameJID' str = do
144 handle (\(SomeException _) -> return Nothing)
145 (fmap Just . parseHostNameJID $ str)
146 buddies <- do
147 buddies <- ConfigFiles.getBuddies user
148 fmap catMaybes (mapM parseHostNameJID' buddies)
149 remotes <- readTVarIO . remoteUsers . presence_state $ s
150 forM_ buddies $ \buddy -> do
151 L.putStrLn $ "forCachedPresence buddy = "<++> bshow buddy
152 let mjids = fmap snd $ Map.lookup (peer buddy) remotes
153 jids <- maybe (return MM.empty) readTVarIO mjids
154 L.putStrLn $ "forCachedPresence jids = "<++> bshow jids
155 withJust (splitResource buddy) $ \(buddyU,_) -> do
156 forM_ (Set.toList . MM.lookup buddyU $ jids) $ \(rsc,status) -> do
157 let p = Presence buddy status
158 L.putStrLn $ "cached presence: " <++> bshow p
159 action p
122 160
123data PeerSession = PeerSession { 161data PeerSession = PeerSession {
124 announced :: TVar (Set JID), 162 announced :: TVar (MultiMap JabberUser (JabberResource,JabberShow)),
125 peer_name :: Peer, 163 peer_name :: Peer,
126 peer_global :: PresenceState 164 peer_global :: PresenceState
127} 165}
@@ -132,7 +170,7 @@ instance JabberPeerSession PeerSession where
132 me <- fmap (RemotePeer . withoutPort) (getPeerName sock) 170 me <- fmap (RemotePeer . withoutPort) (getPeerName sock)
133 L.putStrLn $ "PEER SESSION: open "<++>showPeer me 171 L.putStrLn $ "PEER SESSION: open "<++>showPeer me
134 let remotes = remoteUsers state 172 let remotes = remoteUsers state
135 jids <- atomically $ getRefFromMap remotes me (newTVar Set.empty) return 173 jids <- atomically $ getRefFromMap remotes me (newTVar MM.empty) return
136 return $ PeerSession jids me state 174 return $ PeerSession jids me state
137 175
138 closePeerSession session = do 176 closePeerSession session = do
@@ -140,8 +178,10 @@ instance JabberPeerSession PeerSession where
140 let offline jid = Presence jid Offline 178 let offline jid = Presence jid Offline
141 unrefFromMap (remoteUsers . peer_global $ session) (peer_name session) 179 unrefFromMap (remoteUsers . peer_global $ session) (peer_name session)
142 $ do 180 $ do
143 js <- fmap Set.toList (readTVarIO . announced $ session) 181 js <- fmap (MM.toAscList) (readTVarIO . announced $ session)
144 forM_ js $ announcePresence session . offline 182 forM_ js $ \(u,rs) -> do
183 forM_ (Set.toList rs) $ \(rsc,_) -> do
184 announcePresence session . offline $ unsplitResource u (Just rsc)
145 185
146 peerSessionFactory session = PeerSessions (peer_global session) 186 peerSessionFactory session = PeerSessions (peer_global session)
147 187
@@ -167,10 +207,12 @@ instance JabberPeerSession PeerSession where
167 update_presence (Just greedy) (fmap snd subs) (Set.singleton jid) (const status) 207 update_presence (Just greedy) (fmap snd subs) (Set.singleton jid) (const status)
168 liftIO . atomically $ do 208 liftIO . atomically $ do
169 jids <- readTVar . announced $ session 209 jids <- readTVar . announced $ session
210 withJust (splitResource jid) $ \(u,rsc) -> do
211 let match (r',_) = (rsc==Nothing || Just r'==rsc)
170 writeTVar (announced session) 212 writeTVar (announced session)
171 $ case status of 213 $ case status of
172 Offline -> Set.delete jid jids 214 Offline -> MM.deleteElemIf u match jids
173 _ -> Set.insert jid jids 215 stat -> maybe jids (\r -> MM.insert u (r,stat) jids) rsc
174 216
175 getBuddies _ user = ConfigFiles.getBuddies user 217 getBuddies _ user = ConfigFiles.getBuddies user
176 getSubscribers _ user = ConfigFiles.getSubscribers user 218 getSubscribers _ user = ConfigFiles.getSubscribers user
@@ -259,8 +301,9 @@ sendProbes state jid = do
259 remotes <- readTVarIO (remoteUsers state) 301 remotes <- readTVarIO (remoteUsers state)
260 forM_ buddies $ \buddy -> do 302 forM_ buddies $ \buddy -> do
261 let mjids = fmap snd $ Map.lookup (peer buddy) remotes 303 let mjids = fmap snd $ Map.lookup (peer buddy) remotes
262 jids <- maybe (return Set.empty) readTVarIO mjids 304 jids <- maybe (return MM.empty) readTVarIO mjids
263 let noinfo = Set.notMember buddy jids 305 withJust (splitResource buddy) $ \(buddyU,_) -> do
306 let noinfo = not (MM.member buddyU jids)
264 when noinfo $ do 307 when noinfo $ do
265 L.putStrLn $ "sendMessage " <++> bshow (PresenceProbe jid buddy) 308 L.putStrLn $ "sendMessage " <++> bshow (PresenceProbe jid buddy)
266 sendMessage (outGoingConnections state) (PresenceProbe jid buddy) (peer buddy) 309 sendMessage (outGoingConnections state) (PresenceProbe jid buddy) (peer buddy)