summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Presence/XMPPServer.hs28
-rw-r--r--xmppServer.hs68
2 files changed, 85 insertions, 11 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index af392f27..4dda1f70 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -22,6 +22,8 @@ module XMPPServer
22 , sendModifiedStanzaToClient 22 , sendModifiedStanzaToClient
23 , presenceProbe 23 , presenceProbe
24 , presenceSolicitation 24 , presenceSolicitation
25 , makePresenceStanza
26 , JabberShow(..)
25 ) where 27 ) where
26 28
27import Debug.Trace 29import Debug.Trace
@@ -746,6 +748,32 @@ grokStanza "jabber:client" stanzaTag =
746mkname :: Text -> Text -> XML.Name 748mkname :: Text -> Text -> XML.Name
747mkname namespace name = (Name name (Just namespace) Nothing) 749mkname namespace name = (Name name (Just namespace) Nothing)
748 750
751makePresenceStanza namespace mjid pstat = do
752 stanzaFromList PresenceStatus { presenceShow = pstat
753 , presencePriority = Nothing
754 , presenceStatus = []
755 }
756 $ [ EventBeginElement (mkname namespace "presence")
757 (setFrom $ typ pstat) ]
758 ++ (shw pstat >>= jabberShow) ++
759 [ EventEndElement (mkname namespace "presence")]
760 where
761 setFrom = maybe id
762 (\jid -> (attr "from" jid :) )
763 mjid
764 typ Offline = [attr "type" "unavailable"]
765 typ _ = []
766 shw ExtendedAway = ["xa"]
767 shw Chatty = ["chat"]
768 shw Away = ["away"]
769 shw DoNotDisturb = ["dnd"]
770 shw _ = []
771 jabberShow stat =
772 [ EventBeginElement "{jabber:client}show" []
773 , EventContent (ContentText stat)
774 , EventEndElement "{jabber:client}show" ]
775
776
749makePong :: Text -> Maybe Text -> Text -> Text -> [XML.Event] 777makePong :: Text -> Maybe Text -> Text -> Text -> [XML.Event]
750makePong namespace mid to from = 778makePong namespace mid to from =
751 -- Note: similar to session reply 779 -- Note: similar to session reply
diff --git a/xmppServer.hs b/xmppServer.hs
index 107054bf..699c6a7a 100644
--- a/xmppServer.hs
+++ b/xmppServer.hs
@@ -292,7 +292,24 @@ newConn state k addr outchan = do
292 when (isPeerKey k) 292 when (isPeerKey k)
293 $ sendProbesAndSolicitations state k addr outchan 293 $ sendProbesAndSolicitations state k addr outchan
294 294
295eofConn state k = atomically $ modifyTVar' (keyToChan state) $ Map.delete k 295eofConn state k = do
296 atomically $ modifyTVar' (keyToChan state) $ Map.delete k
297 case k of
298 ClientKey {} -> do
299 stanza <- makePresenceStanza "{jabber:server}" Nothing Offline
300 informClientPresence state k stanza
301 PeerKey {} -> do
302 let h = peerKeyToText k
303 jids <- atomically $ do
304 rbp <- readTVar (remotesByPeer state)
305 return $ do
306 umap <- maybeToList $ Map.lookup k rbp
307 (u,rp) <- Map.toList umap
308 r <- Map.keys (resources rp)
309 return $ unsplitJID (Just u, h, Just r)
310 forM_ jids $ \jid -> do
311 stanza <- makePresenceStanza "{jabber:client}" (Just jid) Offline
312 informPeerPresence state k stanza
296 313
297{- 314{-
298rewriteJIDForClient1:: Text -> IO (Maybe ((Maybe Text,Text,Maybe Text),SockAddr)) 315rewriteJIDForClient1:: Text -> IO (Maybe ((Maybe Text,Text,Maybe Text),SockAddr))
@@ -427,6 +444,9 @@ deliverMessage state fail msg =
427 sendModifiedStanzaToClient dup 444 sendModifiedStanzaToClient dup
428 chan 445 chan
429 446
447-- | Send presence notification to subscribed peers.
448-- Note that a full JID from address will be added to the
449-- stanza if it is not present.
430informClientPresence state k stanza = do 450informClientPresence state k stanza = do
431 dup <- cloneStanza stanza 451 dup <- cloneStanza stanza
432 atomically $ do 452 atomically $ do
@@ -461,9 +481,24 @@ informPeerPresence state k stanza = do
461 flip (maybe $ return ()) muser $ \user -> do 481 flip (maybe $ return ()) muser $ \user -> do
462 482
463 clients <- atomically $ do 483 clients <- atomically $ do
464 -- TODO: Store the stanza 484
485 -- Update remotesByPeer...
486 rbp <- readTVar (remotesByPeer state)
487 let umap = maybe Map.empty id $ Map.lookup k rbp
488 rp = case (presenceShow $ stanzaType stanza) of
489 Offline ->
490 maybe (Map.empty)
491 (Map.delete resource . resources)
492 $ Map.lookup user umap
493 _ -> maybe (Map.singleton resource ())
494 (Map.insert resource () . resources )
495 $ Map.lookup user umap
496 umap' = Map.insert user (RemotePresence rp) umap
497 writeTVar (remotesByPeer state) $ Map.insert k umap' rbp
498 -- TODO: Store or delete the stanza (remotesByPeer)
499
465 -- For now, all clients: 500 -- For now, all clients:
466 -- (TODO: interested/authorized clients only.) 501 -- (TODO: interested/auteorized clients only.)
467 ktc <- readTVar (keyToChan state) 502 ktc <- readTVar (keyToChan state)
468 runTraversableT $ do 503 runTraversableT $ do
469 (ck,client) <- liftMT $ fmap Map.toList $ readTVar (clients state) 504 (ck,client) <- liftMT $ fmap Map.toList $ readTVar (clients state)
@@ -482,15 +517,21 @@ informPeerPresence state k stanza = do
482 (connChan con) 517 (connChan con)
483 518
484answerProbe state k stanza chan = do 519answerProbe state k stanza chan = do
485 putStrLn $ "answerProbe! " ++ show (stanzaType stanza) 520 -- putStrLn $ "answerProbe! " ++ show (stanzaType stanza)
486 ktc <- atomically $ readTVar (keyToChan state) 521 ktc <- atomically $ readTVar (keyToChan state)
487 replies <- runTraversableT $ do 522 muser <- runTraversableT $ do
488 to <- liftMaybe $ stanzaTo stanza 523 to <- liftT $ stanzaTo stanza
489 conn <- liftMaybe $ Map.lookup k ktc 524 conn <- liftT $ Map.lookup k ktc
490 let (mu,h,_) = splitJID to -- TODO: currently resource-id is ignored on presence 525 let (mu,h,_) = splitJID to -- TODO: currently resource-id is ignored on presence
491 -- probes. Is this correct? Check the spec. 526 -- probes. Is this correct? Check the spec.
492 liftIOMaybe $ guardPortStrippedAddress h (auxAddr conn) 527 liftMT $ guardPortStrippedAddress h (auxAddr conn)
493 u <- liftMaybe mu 528 u <- liftT mu
529 let ch = addrToText (auxAddr conn)
530 return (u,conn,ch)
531
532 flip (maybe $ return ()) muser $ \(u,conn,ch) -> do
533
534 replies <- runTraversableT $ do
494 cbu <- lift . atomically $ readTVar (clientsByUser state) 535 cbu <- lift . atomically $ readTVar (clientsByUser state)
495 lpres <- liftMaybe $ Map.lookup u cbu 536 lpres <- liftMaybe $ Map.lookup u cbu
496 clientState <- liftT $ Map.elems (networkClients lpres) 537 clientState <- liftT $ Map.elems (networkClients lpres)
@@ -499,11 +540,16 @@ answerProbe state k stanza chan = do
499 let jid = unsplitJID (Just $ clientUser clientState 540 let jid = unsplitJID (Just $ clientUser clientState
500 , ch 541 , ch
501 ,Just $ clientResource clientState) 542 ,Just $ clientResource clientState)
502 ch = addrToText (auxAddr conn)
503 return stanza { stanzaFrom = Just jid } 543 return stanza { stanzaFrom = Just jid }
544
504 forM_ replies $ \reply -> do 545 forM_ replies $ \reply -> do
505 sendModifiedStanzaToPeer reply chan 546 sendModifiedStanzaToPeer reply chan
506 -- TODO: if null replies, send offline message 547
548 -- if no presence, send offline message
549 when (null replies) $ do
550 let jid = unsplitJID (Just u,ch,Nothing)
551 pstanza <- makePresenceStanza "{jabber:server}" (Just jid) Offline
552 atomically $ writeTChan (connChan conn) pstanza
507 553
508main = runResourceT $ do 554main = runResourceT $ do
509 state <- liftIO . atomically $ do 555 state <- liftIO . atomically $ do