diff options
Diffstat (limited to 'Presence')
-rw-r--r-- | Presence/XMPP.hs | 3 | ||||
-rw-r--r-- | Presence/XMPPTypes.hs | 1 | ||||
-rw-r--r-- | Presence/main.hs | 79 |
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 | ||
42 | class JabberPeerSession session where | 43 | class 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) | |||
56 | import System.Environment | 56 | import System.Environment |
57 | import qualified Text.Show.ByteString as L | 57 | import qualified Text.Show.ByteString as L |
58 | import Network.Socket (Family(AF_INET,AF_INET6)) | 58 | import Network.Socket (Family(AF_INET,AF_INET6)) |
59 | import Holumbus.Data.MultiMap as MM (MultiMap) | ||
60 | import qualified Holumbus.Data.MultiMap as MM | ||
59 | 61 | ||
60 | type RefCount = Int | 62 | type RefCount = Int |
61 | 63 | ||
64 | type JabberResource = L.ByteString | ||
65 | type JabberName = L.ByteString | ||
66 | data JabberUser = JabberUser JabberName Peer | ||
67 | deriving (Eq,Ord,Show) | ||
68 | |||
69 | splitResource :: JID -> Maybe (JabberUser,Maybe JabberResource) | ||
70 | splitResource (JID Nothing _ _ ) = Nothing | ||
71 | splitResource (JID (Just n) p r ) = Just (JabberUser n p, r) | ||
72 | |||
73 | unsplitResource (JabberUser n p) r = JID (Just n) p r | ||
74 | |||
62 | data PresenceState = PresenceState | 75 | data 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 | ||
87 | getJabberUserForId 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 | |||
74 | data ClientSession = ClientSession { | 98 | data 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 | ||
123 | data PeerSession = PeerSession { | 161 | data 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) |