summaryrefslogtreecommitdiff
path: root/xmppServer.hs
diff options
context:
space:
mode:
Diffstat (limited to 'xmppServer.hs')
-rw-r--r--xmppServer.hs69
1 files changed, 25 insertions, 44 deletions
diff --git a/xmppServer.hs b/xmppServer.hs
index d5ad7c6a..1ab36cd6 100644
--- a/xmppServer.hs
+++ b/xmppServer.hs
@@ -37,6 +37,7 @@ import LocalPeerCred
37import XMPPServer 37import XMPPServer
38import PeerResolve 38import PeerResolve
39import ConsoleWriter 39import ConsoleWriter
40import ClientState
40 41
41type UserName = Text 42type UserName = Text
42type ResourceName = Text 43type ResourceName = Text
@@ -74,28 +75,6 @@ localJID user resource = do
74 hostname <- textHostName 75 hostname <- textHostName
75 return $ user <> "@" <> hostname <> "/" <> resource 76 return $ user <> "@" <> hostname <> "/" <> resource
76 77
77cf_available :: Int8
78cf_available = 0x1
79cf_interested :: Int8
80cf_interested = 0x2
81
82data ClientState = ClientState
83 { clientResource :: Text
84 , clientUser :: Text
85 , clientPid :: Maybe ProcessID
86 , clientStatus :: TVar (Maybe Stanza)
87 , clientFlags :: TVar Int8
88 }
89
90-- | True if the client has sent an initial presence
91clientIsAvailable c = do
92 flgs <- readTVar (clientFlags c)
93 return $ flgs .&. cf_available /= 0
94
95-- | True if the client has requested a roster
96clientIsInterested c = do
97 flgs <- readTVar (clientFlags c)
98 return $ flgs .&. cf_interested /= 0
99 78
100data LocalPresence = LocalPresence 79data LocalPresence = LocalPresence
101 { networkClients :: Map ConnectionKey ClientState 80 { networkClients :: Map ConnectionKey ClientState
@@ -130,7 +109,7 @@ pcIsEmpty pc = Map.null (networkClients pc)
130data PresenceState = PresenceState 109data PresenceState = PresenceState
131 { clients :: TVar (Map ConnectionKey ClientState) 110 { clients :: TVar (Map ConnectionKey ClientState)
132 , clientsByUser :: TVar (Map Text LocalPresence) 111 , clientsByUser :: TVar (Map Text LocalPresence)
133 , remotesByPeer :: TVar (Map (Maybe ConnectionKey) 112 , remotesByPeer :: TVar (Map ConnectionKey
134 (Map UserName 113 (Map UserName
135 RemotePresence)) 114 RemotePresence))
136 , associatedPeers :: TVar (Map SockAddr ()) 115 , associatedPeers :: TVar (Map SockAddr ())
@@ -326,13 +305,13 @@ eofConn state k = do
326 jids <- atomically $ do 305 jids <- atomically $ do
327 rbp <- readTVar (remotesByPeer state) 306 rbp <- readTVar (remotesByPeer state)
328 return $ do 307 return $ do
329 umap <- maybeToList $ Map.lookup (Just k) rbp 308 umap <- maybeToList $ Map.lookup k rbp
330 (u,rp) <- Map.toList umap 309 (u,rp) <- Map.toList umap
331 r <- Map.keys (resources rp) 310 r <- Map.keys (resources rp)
332 return $ unsplitJID (Just u, h, Just r) 311 return $ unsplitJID (Just u, h, Just r)
333 forM_ jids $ \jid -> do 312 forM_ jids $ \jid -> do
334 stanza <- makePresenceStanza "jabber:client" (Just jid) Offline 313 stanza <- makePresenceStanza "jabber:client" (Just jid) Offline
335 informPeerPresence state (Just k) stanza 314 informPeerPresence state k stanza
336 315
337{- 316{-
338rewriteJIDForClient1:: Text -> IO (Maybe ((Maybe Text,Text,Maybe Text),SockAddr)) 317rewriteJIDForClient1:: Text -> IO (Maybe ((Maybe Text,Text,Maybe Text),SockAddr))
@@ -480,10 +459,13 @@ deliverMessage state fail msg =
480 459
481 460
482setClientFlag state k flag = 461setClientFlag state k flag =
483 atomically $ do 462 atomically $ do
484 cmap <- readTVar (clients state) 463 cmap <- readTVar (clients state)
485 flip (maybe $ return ()) (Map.lookup k cmap) $ \client -> do 464 flip (maybe $ return ()) (Map.lookup k cmap) $ \client -> do
486 modifyTVar' (clientFlags client) (\flgs -> flgs .|. flag) 465 setClientFlag0 client flag
466
467setClientFlag0 client flag =
468 modifyTVar' (clientFlags client) (\flgs -> flgs .|. flag)
487 469
488informSentRoster state k = do 470informSentRoster state k = do
489 setClientFlag state k cf_interested 471 setClientFlag state k cf_interested
@@ -503,16 +485,16 @@ clientJID con client = unsplitJID ( Just $ clientUser client
503-- Note that a full JID from address will be added to the 485-- Note that a full JID from address will be added to the
504-- stanza if it is not present. 486-- stanza if it is not present.
505informClientPresence state k stanza = do 487informClientPresence state k stanza = do
506 dup <- cloneStanza stanza
507 atomically $ do
508 mb <- fmap (Map.lookup k) $ readTVar (clients state)
509 flip (maybe $ return ()) mb $ \cstate -> do
510 writeTVar (clientStatus cstate) $ Just dup
511 forClient state k (return ()) $ \client -> do 488 forClient state k (return ()) $ \client -> do
489 informClientPresence0 state (Just k) client stanza
490
491informClientPresence0 state mbk client stanza = do
492 dup <- cloneStanza stanza
493 atomically $ writeTVar (clientStatus client) $ Just dup
512 is_avail <- atomically $ clientIsAvailable client 494 is_avail <- atomically $ clientIsAvailable client
513 when (not is_avail) $ do 495 when (not is_avail) $ do
514 setClientFlag state k cf_available 496 atomically $ setClientFlag0 client cf_available
515 sendCachedPresence state k 497 maybe (return ()) (sendCachedPresence state) mbk
516 addrs <- subscribedPeers (clientUser client) 498 addrs <- subscribedPeers (clientUser client)
517 ktc <- atomically $ readTVar (keyToChan state) 499 ktc <- atomically $ readTVar (keyToChan state)
518 let connected = mapMaybe (flip Map.lookup ktc . PeerKey) addrs 500 let connected = mapMaybe (flip Map.lookup ktc . PeerKey) addrs
@@ -579,7 +561,7 @@ informPeerPresence state k stanza = do
579 is_avail <- atomically $ clientIsAvailable client 561 is_avail <- atomically $ clientIsAvailable client
580 when is_avail $ do 562 when is_avail $ do
581 putStrLn $ "reversing for client: " ++ show from 563 putStrLn $ "reversing for client: " ++ show from
582 froms <- flip (maybe $ return [from]) k . const $ do 564 froms <- do -- flip (maybe $ return [from]) k . const $ do
583 let ClientKey laddr = ck 565 let ClientKey laddr = ck
584 (_,trip) <- multiplyJIDForClient laddr from 566 (_,trip) <- multiplyJIDForClient laddr from
585 return (map unsplitJID trip) 567 return (map unsplitJID trip)
@@ -649,16 +631,15 @@ sendCachedPresence state k = do
649 jids <- configText ConfigFiles.getBuddies (clientUser client) 631 jids <- configText ConfigFiles.getBuddies (clientUser client)
650 let hosts = map ((\(_,h,_)->h) . splitJID) jids 632 let hosts = map ((\(_,h,_)->h) . splitJID) jids
651 addrs <- resolveAllPeers hosts 633 addrs <- resolveAllPeers hosts
652 let onlines = rbp `Map.intersection` (Map.insert Nothing () -- send console presences 634 let onlines = rbp `Map.intersection` Map.mapKeys PeerKey addrs
653 $ Map.mapKeys (Just . PeerKey) addrs)
654 ClientKey laddr = k 635 ClientKey laddr = k
655 mcon <- atomically $ do ktc <- readTVar (keyToChan state) 636 mcon <- atomically $ do ktc <- readTVar (keyToChan state)
656 return $ Map.lookup k ktc 637 return $ Map.lookup k ktc
657 flip (maybe $ return ()) mcon $ \con -> do 638 flip (maybe $ return ()) mcon $ \con -> do
658 me <- textHostName 639 -- me <- textHostName
659 forM_ (Map.toList onlines) $ \(pk, umap) -> do 640 forM_ (Map.toList onlines) $ \(pk, umap) -> do
660 forM_ (Map.toList umap) $ \(user,rp) -> do 641 forM_ (Map.toList umap) $ \(user,rp) -> do
661 let h = maybe me peerKeyToText pk 642 let h = peerKeyToText pk
662 forM_ (Map.toList $ resources rp) $ \(resource,stanza) -> do 643 forM_ (Map.toList $ resources rp) $ \(resource,stanza) -> do
663 let jid = unsplitJID (Just user,h,Just resource) 644 let jid = unsplitJID (Just user,h,Just resource)
664 (mine,js) <- multiplyJIDForClient laddr jid 645 (mine,js) <- multiplyJIDForClient laddr jid
@@ -1002,7 +983,7 @@ main = runResourceT $ do
1002 , xmppSubscribeToRoster = informSentRoster state 983 , xmppSubscribeToRoster = informSentRoster state
1003 , xmppDeliverMessage = deliverMessage state 984 , xmppDeliverMessage = deliverMessage state
1004 , xmppInformClientPresence = informClientPresence state 985 , xmppInformClientPresence = informClientPresence state
1005 , xmppInformPeerPresence = \k -> informPeerPresence state (Just k) 986 , xmppInformPeerPresence = informPeerPresence state
1006 , xmppAnswerProbe = \k stanza chan -> answerProbe state (stanzaTo stanza) k chan 987 , xmppAnswerProbe = \k stanza chan -> answerProbe state (stanzaTo stanza) k chan
1007 , xmppClientSubscriptionRequest = clientSubscriptionRequest state 988 , xmppClientSubscriptionRequest = clientSubscriptionRequest state
1008 , xmppPeerSubscriptionRequest = peerSubscriptionRequest state 989 , xmppPeerSubscriptionRequest = peerSubscriptionRequest state
@@ -1020,8 +1001,8 @@ main = runResourceT $ do
1020 console <- atomically $ dupTChan (cwPresenceChan $ consoleWriter state) 1001 console <- atomically $ dupTChan (cwPresenceChan $ consoleWriter state)
1021 fix $ \loop -> do 1002 fix $ \loop -> do
1022 what <- atomically 1003 what <- atomically
1023 $ orElse (do stanza <- readTChan console 1004 $ orElse (do (client,stanza) <- readTChan console
1024 return $ do informPeerPresence state Nothing stanza 1005 return $ do informClientPresence0 state Nothing client stanza
1025 loop) 1006 loop)
1026 (do readTMVar quitVar 1007 (do readTMVar quitVar
1027 return $ return ()) 1008 return $ return ())