diff options
-rw-r--r-- | Presence/XMPPServer.hs | 5 | ||||
-rw-r--r-- | xmppServer.hs | 54 |
2 files changed, 47 insertions, 12 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs index 0103ba46..e66eea70 100644 --- a/Presence/XMPPServer.hs +++ b/Presence/XMPPServer.hs | |||
@@ -183,6 +183,7 @@ data XMPPServerParameters = | |||
183 | , xmppTellClientNameOfPeer :: ConnectionKey -> IO Text | 183 | , xmppTellClientNameOfPeer :: ConnectionKey -> IO Text |
184 | , xmppDeliverMessage :: (IO ()) -> Stanza -> IO () | 184 | , xmppDeliverMessage :: (IO ()) -> Stanza -> IO () |
185 | , xmppInformClientPresence :: ConnectionKey -> Stanza -> IO () | 185 | , xmppInformClientPresence :: ConnectionKey -> Stanza -> IO () |
186 | , xmppAnswerProbe :: ConnectionKey -> Stanza -> TChan Stanza -> IO () | ||
186 | } | 187 | } |
187 | 188 | ||
188 | 189 | ||
@@ -1569,6 +1570,10 @@ monitor sv params xmpp = do | |||
1569 | guard . not . null . mapMaybe (msgBody . snd) $ msgLangMap (stanzaType stanza) | 1570 | guard . not . null . mapMaybe (msgBody . snd) $ msgLangMap (stanzaType stanza) |
1570 | stanzaId stanza | 1571 | stanzaId stanza |
1571 | _ -> return () | 1572 | _ -> return () |
1573 | NetworkOrigin k@(PeerKey {}) replyto -> | ||
1574 | case stanzaType stanza of | ||
1575 | PresenceRequestStatus {} -> do | ||
1576 | xmppAnswerProbe xmpp k stanza replyto | ||
1572 | _ -> return () | 1577 | _ -> return () |
1573 | let deliver replyto = do | 1578 | let deliver replyto = do |
1574 | -- TODO: Issuing RecipientUnavailable for all errors is a presence leak | 1579 | -- TODO: Issuing RecipientUnavailable for all errors is a presence leak |
diff --git a/xmppServer.hs b/xmppServer.hs index a30d15d0..27ae7941 100644 --- a/xmppServer.hs +++ b/xmppServer.hs | |||
@@ -30,7 +30,7 @@ import Control.Exception ({-evaluate,-}handle,SomeException(..),bracketOnError,E | |||
30 | import System.Posix.User (getUserEntryForID,userName) | 30 | import System.Posix.User (getUserEntryForID,userName) |
31 | import qualified Data.ByteString.Lazy.Char8 as L | 31 | import qualified Data.ByteString.Lazy.Char8 as L |
32 | import qualified ConfigFiles | 32 | import qualified ConfigFiles |
33 | import Data.Maybe (listToMaybe,mapMaybe) | 33 | import Data.Maybe (maybeToList,listToMaybe,mapMaybe) |
34 | 34 | ||
35 | import TraversableT | 35 | import TraversableT |
36 | import UTmp (ProcessID,users) | 36 | import UTmp (ProcessID,users) |
@@ -77,6 +77,7 @@ data ClientState = ClientState | |||
77 | { clientResource :: Text | 77 | { clientResource :: Text |
78 | , clientUser :: Text | 78 | , clientUser :: Text |
79 | , clientPid :: Maybe ProcessID | 79 | , clientPid :: Maybe ProcessID |
80 | , clientStatus :: TVar (Maybe Stanza) | ||
80 | } | 81 | } |
81 | 82 | ||
82 | 83 | ||
@@ -155,9 +156,11 @@ chooseResourceName state k addr desired = do | |||
155 | muid <- getLocalPeerCred' addr | 156 | muid <- getLocalPeerCred' addr |
156 | (mtty,pid) <- getTTYandPID muid | 157 | (mtty,pid) <- getTTYandPID muid |
157 | user <- getJabberUserForId muid | 158 | user <- getJabberUserForId muid |
159 | status <- atomically $ newTVar Nothing | ||
158 | let client = ClientState { clientResource = maybe "fallback" id mtty | 160 | let client = ClientState { clientResource = maybe "fallback" id mtty |
159 | , clientUser = user | 161 | , clientUser = user |
160 | , clientPid = pid } | 162 | , clientPid = pid |
163 | , clientStatus = status } | ||
161 | 164 | ||
162 | atomically $ do | 165 | atomically $ do |
163 | modifyTVar' (clients state) $ Map.insert k client | 166 | modifyTVar' (clients state) $ Map.insert k client |
@@ -325,6 +328,16 @@ rewriteJIDForClient laddr jid = do | |||
325 | else peerKeyToResolvedName (PeerKey addr) | 328 | else peerKeyToResolvedName (PeerKey addr) |
326 | return (mine,(n,h',r)) | 329 | return (mine,(n,h',r)) |
327 | 330 | ||
331 | addrTextToKey h = do | ||
332 | maddr <- parseAddress (strip_brackets h) | ||
333 | return (fmap PeerKey maddr) | ||
334 | |||
335 | guardPortStrippedAddress h laddr = do | ||
336 | maddr <- fmap (fmap (`withPort` 0)) $ parseAddress (strip_brackets h) | ||
337 | let laddr' = laddr `withPort` 0 | ||
338 | return $ maddr >>= guard . (==laddr') | ||
339 | |||
340 | |||
328 | -- | Accepts a textual representation of a domainname | 341 | -- | Accepts a textual representation of a domainname |
329 | -- JID suitable for client connections, and returns the | 342 | -- JID suitable for client connections, and returns the |
330 | -- coresponding ipv6 address JID suitable for peers paired | 343 | -- coresponding ipv6 address JID suitable for peers paired |
@@ -393,6 +406,30 @@ deliverMessage state fail msg = | |||
393 | sendModifiedStanzaToClient dup | 406 | sendModifiedStanzaToClient dup |
394 | chan | 407 | chan |
395 | 408 | ||
409 | informClientPresence state k stanza = do | ||
410 | dup <- cloneStanza stanza | ||
411 | atomically $ do | ||
412 | mb <- fmap (Map.lookup k) $ readTVar (clients state) | ||
413 | flip (maybe $ return ()) mb $ \cstate -> do | ||
414 | writeTVar (clientStatus cstate) $ Just dup | ||
415 | |||
416 | answerProbe state k stanza chan = do | ||
417 | ktc <- atomically $ readTVar (keyToChan state) | ||
418 | replies <- runTraversableT $ do | ||
419 | let liftMaybe = liftT . maybeToList | ||
420 | liftIOMaybe = liftMT . fmap maybeToList | ||
421 | to <- liftMaybe $ stanzaTo stanza | ||
422 | conn <- liftMaybe $ Map.lookup k ktc | ||
423 | let (mu,h,_) = splitJID to -- TODO: currently resource-id is ignored on presence | ||
424 | -- probes. Is this correct? Check the spec. | ||
425 | cbu <- lift . atomically $ readTVar (clientsByUser state) | ||
426 | lpres <- liftMaybe $ Map.lookup u cbu | ||
427 | clientState <- liftT $ Map.elems (networkClients lpres) | ||
428 | mstanza <- lift $ atomically (readTVar (clientStatus clientState)) | ||
429 | liftMaybe mstanza | ||
430 | forM_ replies $ \reply -> do | ||
431 | sendModifiedStanzaToPeer reply chan | ||
432 | -- TODO: if null replies, send offline message | ||
396 | 433 | ||
397 | main = runResourceT $ do | 434 | main = runResourceT $ do |
398 | state <- liftIO . atomically $ do | 435 | state <- liftIO . atomically $ do |
@@ -425,16 +462,9 @@ main = runResourceT $ do | |||
425 | , xmppRosterSolicited = rosterGetSolicited state | 462 | , xmppRosterSolicited = rosterGetSolicited state |
426 | , xmppRosterOthers = rosterGetOthers state | 463 | , xmppRosterOthers = rosterGetOthers state |
427 | , xmppSubscribeToRoster = \k -> return () | 464 | , xmppSubscribeToRoster = \k -> return () |
428 | -- , xmppLookupClientJID = \k -> return $ "nobody@" <> hostname <> "/tty666" | 465 | , xmppDeliverMessage = deliverMessage state |
429 | , {- xmppDeliverMessage = \fail msg -> do | 466 | , xmppInformClientPresence = informClientPresence state |
430 | let msgs = msgLangMap (stanzaType msg) | 467 | , xmppAnswerProbe = answerProbe state |
431 | body = fmap (maybe "" id . msgBody . snd) $ take 1 msgs | ||
432 | when (not $ null body) $ do | ||
433 | Text.putStrLn $ "MESSAGE " <> head body | ||
434 | return () | ||
435 | -} | ||
436 | xmppDeliverMessage = deliverMessage state | ||
437 | , xmppInformClientPresence = \k stanza -> return () | ||
438 | } | 468 | } |
439 | liftIO $ do | 469 | liftIO $ do |
440 | atomically $ putTMVar (server state) sv | 470 | atomically $ putTMVar (server state) sv |