diff options
author | joe <joe@jerkface.net> | 2014-03-06 02:22:47 -0500 |
---|---|---|
committer | joe <joe@jerkface.net> | 2014-03-06 02:22:47 -0500 |
commit | 52efeff2233c896b87effcec8641e695c7120607 (patch) | |
tree | 63a3e4f296b9dd8c96575c315a968e565b4f86c1 /xmppServer.hs | |
parent | a41ffe16f5f3237a0b16c49f743ba423b19e46d6 (diff) |
offline notifications
Diffstat (limited to 'xmppServer.hs')
-rw-r--r-- | xmppServer.hs | 68 |
1 files changed, 57 insertions, 11 deletions
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 | ||
295 | eofConn state k = atomically $ modifyTVar' (keyToChan state) $ Map.delete k | 295 | eofConn 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 | {- |
298 | rewriteJIDForClient1:: Text -> IO (Maybe ((Maybe Text,Text,Maybe Text),SockAddr)) | 315 | rewriteJIDForClient1:: 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. | ||
430 | informClientPresence state k stanza = do | 450 | informClientPresence 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 | ||
484 | answerProbe state k stanza chan = do | 519 | answerProbe 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 | ||
508 | main = runResourceT $ do | 554 | main = runResourceT $ do |
509 | state <- liftIO . atomically $ do | 555 | state <- liftIO . atomically $ do |