summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
Diffstat (limited to 'Presence')
-rw-r--r--Presence/XMPP.hs27
-rw-r--r--Presence/XMPPTypes.hs6
-rw-r--r--Presence/main.hs56
3 files changed, 69 insertions, 20 deletions
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs
index 173e7cdf..7d69e126 100644
--- a/Presence/XMPP.hs
+++ b/Presence/XMPP.hs
@@ -535,7 +535,7 @@ toClient session pchan cmdChan rchan = toClient' False False
535 , attr "type" "subscribed" 535 , attr "type" "subscribed"
536 ] 536 ]
537 , EventEndElement "{jabber:client}presence" ] 537 , EventEndElement "{jabber:client}presence" ]
538 let f True = "from" 538 let f True = "both"
539 f False = "to" 539 f False = "to"
540 subscription <- fmap f (liftIO $ isSubscribed session contact) 540 subscription <- fmap f (liftIO $ isSubscribed session contact)
541 r <- liftIO . handleIO (\e -> putStrLn ("Roster NewBuddy error: "++show e) >> return []) $ do 541 r <- liftIO . handleIO (\e -> putStrLn ("Roster NewBuddy error: "++show e) >> return []) $ do
@@ -544,7 +544,24 @@ toClient session pchan cmdChan rchan = toClient' False False
544 [attr "subscription" subscription] 544 [attr "subscription" subscription]
545 send r 545 send r
546 loop 546 loop
547 RChan (PendingBuddy who contact) -> do 547 RChan (NewSubscriber who contact) -> do
548 liftIO . putStrLn $ "Roster push: NewSubscriber "++show (isInterested,who,contact)
549 (jid,me) <- liftIO $ do
550 jid <- getJID session
551 me <- asHostNameJID jid
552 return (jid,me)
553 withJust me $ \me -> do
554 when (isInterested && Just who==name jid) $ do
555 let f True = "both"
556 f False = "from"
557 subscription <- fmap f (liftIO $ isBuddy session contact)
558 r <- liftIO . handleIO (\e -> putStrLn ("Roster NewSubscriber error: "++show e) >> return []) $ do
559 rosterPush jid
560 (toStrict . L.decodeUtf8 $ contact)
561 [attr "subscription" subscription]
562 send r
563 loop
564 RChan (PendingSubscriber who contact) -> do
548 liftIO . putStrLn $ "Roster: Pending buddy "++show (isInterested,who,contact) 565 liftIO . putStrLn $ "Roster: Pending buddy "++show (isInterested,who,contact)
549 (jid,me) <- liftIO $ do 566 (jid,me) <- liftIO $ do
550 jid <- getJID session 567 jid <- getJID session
@@ -726,7 +743,8 @@ handlePresenceProbe session stanza = do
726 putStrLn $ "comparing " ++show (peer sub , peerAddress session) 743 putStrLn $ "comparing " ++show (peer sub , peerAddress session)
727 when (peer sub == discardPort (peerAddress session)) $ do 744 when (peer sub == discardPort (peerAddress session)) $ do
728 ps <- userStatus session user 745 ps <- userStatus session user
729 mapM_ (announcePresence session) ps 746 -- todo: Consider making this a directed presence
747 mapM_ (sendPeerMessage session . OutBoundPresence) ps
730 return () 748 return ()
731 749
732subscribeToPresence subscribers peer_jid user = do 750subscribeToPresence subscribers peer_jid user = do
@@ -826,7 +844,8 @@ peerRequestsSubsription session stanza = do
826 liftIO $ do 844 liftIO $ do
827 sendPeerMessage session (Approval tojid fromjid) 845 sendPeerMessage session (Approval tojid fromjid)
828 ps <- userStatus session user 846 ps <- userStatus session user
829 mapM_ (announcePresence session) ps 847 -- todo: consider making this a directed presence
848 mapM_ (sendPeerMessage session . OutBoundPresence) ps
830 else 849 else
831 liftIO $ processRequest session user fromjid 850 liftIO $ processRequest session user fromjid
832 851
diff --git a/Presence/XMPPTypes.hs b/Presence/XMPPTypes.hs
index 6d00d509..0e98a77b 100644
--- a/Presence/XMPPTypes.hs
+++ b/Presence/XMPPTypes.hs
@@ -57,6 +57,7 @@ class JabberClientSession session where
57 getMySolicited :: session -> IO [ByteString] 57 getMySolicited :: session -> IO [ByteString]
58 addSolicited :: session -> ByteString -> JID -> IO () 58 addSolicited :: session -> ByteString -> JID -> IO ()
59 isSubscribed :: session -> ByteString -> IO Bool 59 isSubscribed :: session -> ByteString -> IO Bool
60 isBuddy :: session -> ByteString -> IO Bool
60 approveSubscriber :: session -> ByteString -> IO () 61 approveSubscriber :: session -> ByteString -> IO ()
61 62
62class JabberPeerSession session where 63class JabberPeerSession session where
@@ -94,7 +95,10 @@ data RosterEvent = RequestedSubscription
94 | NewBuddy 95 | NewBuddy
95 {- user: -} ByteString 96 {- user: -} ByteString
96 {- contact: -} ByteString 97 {- contact: -} ByteString
97 | PendingBuddy 98 | PendingSubscriber
99 {- user: -} ByteString
100 {- contact: -} ByteString
101 | NewSubscriber
98 {- user: -} ByteString 102 {- user: -} ByteString
99 {- contact: -} ByteString 103 {- contact: -} ByteString
100 deriving Prelude.Show 104 deriving Prelude.Show
diff --git a/Presence/main.hs b/Presence/main.hs
index 5cccffea..702b98d5 100644
--- a/Presence/main.hs
+++ b/Presence/main.hs
@@ -222,7 +222,7 @@ instance JabberClientSession ClientSession where
222 else return Nothing 222 else return Nothing
223 atomically $ do 223 atomically $ do
224 whenJust getRChan $ \rchan -> do 224 whenJust getRChan $ \rchan -> do
225 forM_ pending (writeTChan rchan . PendingBuddy user) 225 forM_ pending (writeTChan rchan . PendingSubscriber user)
226 226
227 addSolicited s jid_str jid = do 227 addSolicited s jid_str jid = do
228 me <- getJID s 228 me <- getJID s
@@ -264,6 +264,16 @@ instance JabberClientSession ClientSession where
264 msubs <- mapM (cmpJID cjid) subs 264 msubs <- mapM (cmpJID cjid) subs
265 return (Nothing `elem` msubs) 265 return (Nothing `elem` msubs)
266 266
267 isBuddy s contact = do
268 handleIO (\e -> return False) $ do
269 user <- readIORef (unix_uid s) >>= getJabberUserForId
270 subs <- ConfigFiles.getBuddies user
271 putStrLn $ "isBuddy parsing: "<++>contact
272 cjid <- parseHostNameJID contact
273 msubs <- mapM (cmpJID cjid) subs
274 return (Nothing `elem` msubs)
275
276
267 approveSubscriber s contact = do 277 approveSubscriber s contact = do
268 user <- readIORef (unix_uid s) >>= getJabberUserForId 278 user <- readIORef (unix_uid s) >>= getJabberUserForId
269 cjid <- parseHostNameJID contact 279 cjid <- parseHostNameJID contact
@@ -271,16 +281,40 @@ instance JabberClientSession ClientSession where
271 addRawJid ConfigFiles.modifySubscribers user contact -- add subscribers 281 addRawJid ConfigFiles.modifySubscribers user contact -- add subscribers
272 rmjid ConfigFiles.modifyPending user cjid 282 rmjid ConfigFiles.modifyPending user cjid
273 rmjid ConfigFiles.modifyOthers user cjid 283 rmjid ConfigFiles.modifyOthers user cjid
274 -- TODO 284
275 -- roster push (to other clients, or do we include the approver?) 285 -- roster push
286 let rchan = rosterChannel . presence_state $ s
287 atomically $ do
288 isempty <- isEmptyTMVar rchan
289 when (not isempty) $ do
290 (_,ch) <- readTMVar rchan
291 writeTChan ch (NewSubscriber user contact)
292
293 -- notify peer
276 sendMessage (outGoingConnections . presence_state $ s) 294 sendMessage (outGoingConnections . presence_state $ s)
277 (Approval (JID (Just user) LocalHost Nothing) 295 (Approval (JID (Just user) LocalHost Nothing)
278 cjid) 296 cjid)
279 (peer cjid) 297 (peer cjid)
298 presence <- getUserStatus (presence_state s) user
299 let cons = outGoingConnections . presence_state $ s
300 forM_ presence $ \p -> sendMessage cons (OutBoundPresence p) (peer cjid)
301 return ()
280 302
281 303
282tupleToJID (user,tty,pid) = jid user LocalHost tty 304tupleToJID (user,tty,pid) = jid user LocalHost tty
283 305
306getUserStatus state user = do
307 (tty,users) <- atomically $ do
308 tty <- readTVar $ currentTTY state
309 users <- readTVar $ activeUsers state
310 return (tty,users)
311 let jids = Set.filter (\(name,tty,pid) -> name ==user) users
312 ps = map (\jid -> Presence (tupleToJID jid) (matchResource' tty jid)) . Set.toList $ jids
313 if null ps
314 then return [Presence (JID { name=Just user, peer=LocalHost, resource=Nothing }) Offline]
315 else return ps
316
317
284data PeerSession = PeerSession { 318data PeerSession = PeerSession {
285 announced :: TVar (MultiMap JabberUser (JabberResource,JabberShow)), 319 announced :: TVar (MultiMap JabberUser (JabberResource,JabberShow)),
286 peer_name :: Peer, 320 peer_name :: Peer,
@@ -310,18 +344,10 @@ instance JabberPeerSession PeerSession where
310 344
311 peerAddress session = peer_name session 345 peerAddress session = peer_name session
312 346
313 userStatus session user = do 347 userStatus session user = getUserStatus (peer_global session) user
314 let state = peer_global session
315 (tty,users) <- atomically $ do
316 tty <- readTVar $ currentTTY state
317 users <- readTVar $ activeUsers state
318 return (tty,users)
319 let jids = Set.filter (\(name,tty,pid) -> name ==user) users
320 ps = map (\jid -> Presence (tupleToJID jid) (matchResource' tty jid)) . Set.toList $ jids
321 if null ps
322 then return [Presence (JID { name=Just user, peer=LocalHost, resource=Nothing }) Offline]
323 else return ps
324 348
349 -- This should be used on inbound presence to inform clients.
350 -- For outbound, use sendPeerMessage and OutBoundPresence.
325 announcePresence session (Presence jid status) = do 351 announcePresence session (Presence jid status) = do
326 (greedy,subs) <- atomically $ do 352 (greedy,subs) <- atomically $ do
327 subs <- readTVar $ subscriberMap (peer_global session) 353 subs <- readTVar $ subscriberMap (peer_global session)
@@ -384,7 +410,7 @@ instance JabberPeerSession PeerSession where
384 isempty <- isEmptyTMVar rchan 410 isempty <- isEmptyTMVar rchan
385 when (not isempty) $ do 411 when (not isempty) $ do
386 (_,ch) <- readTMVar rchan 412 (_,ch) <- readTMVar rchan
387 writeTChan ch (PendingBuddy user buddy) 413 writeTChan ch (PendingSubscriber user buddy)
388 414
389 415
390data RefCountedChan = forall a. RefCountedChan (TMVar (RefCount,TChan a)) 416data RefCountedChan = forall a. RefCountedChan (TMVar (RefCount,TChan a))