diff options
Diffstat (limited to 'Presence/XMPP.hs')
-rw-r--r-- | Presence/XMPP.hs | 67 |
1 files changed, 56 insertions, 11 deletions
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs index 7b01711e..1520839e 100644 --- a/Presence/XMPP.hs +++ b/Presence/XMPP.hs | |||
@@ -62,6 +62,7 @@ import Control.Exception | |||
62 | , finally | 62 | , finally |
63 | , bracketOnError ) | 63 | , bracketOnError ) |
64 | import GHC.IO.Exception (IOException(..)) | 64 | import GHC.IO.Exception (IOException(..)) |
65 | import System.IO.Error (isDoesNotExistError) | ||
65 | import Control.Monad.IO.Class | 66 | import Control.Monad.IO.Class |
66 | import Control.Monad.Trans.Class | 67 | import Control.Monad.Trans.Class |
67 | import Control.Monad.Trans.Maybe | 68 | import Control.Monad.Trans.Maybe |
@@ -93,7 +94,11 @@ import GHC.Conc | |||
93 | , ThreadId | 94 | , ThreadId |
94 | ) | 95 | ) |
95 | 96 | ||
96 | data Commands = Send [XML.Event] | QuitThread | 97 | data Commands = |
98 | Send [XML.Event] | ||
99 | | BoundToResource | ||
100 | | InterestedInRoster | ||
101 | | QuitThread | ||
97 | deriving Prelude.Show | 102 | deriving Prelude.Show |
98 | 103 | ||
99 | getNamesForPeer :: Peer -> IO [ByteString] | 104 | getNamesForPeer :: Peer -> IO [ByteString] |
@@ -260,7 +265,9 @@ handleIQSetBind session cmdChan stanza_id = do | |||
260 | L.putStrLn $ "iq-set-bind-resource " <++> rsc | 265 | L.putStrLn $ "iq-set-bind-resource " <++> rsc |
261 | setResource session rsc | 266 | setResource session rsc |
262 | jid <- getJID session | 267 | jid <- getJID session |
263 | atomically $ writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) ) | 268 | atomically $ do |
269 | writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) ) | ||
270 | writeTChan cmdChan BoundToResource | ||
264 | forCachedPresence session $ \presence -> do | 271 | forCachedPresence session $ \presence -> do |
265 | xs <- xmlifyPresenceForClient presence | 272 | xs <- xmlifyPresenceForClient presence |
266 | atomically . writeTChan cmdChan . Send $ xs | 273 | atomically . writeTChan cmdChan . Send $ xs |
@@ -410,7 +417,9 @@ handleIQGet session cmdChan tag = do | |||
410 | -- ,(Name {nameLocalName = "type", nameNamespace = Nothing, namePrefix = Nothing}, | 417 | -- ,(Name {nameLocalName = "type", nameNamespace = Nothing, namePrefix = Nothing}, |
411 | -- [ContentText "get"])] | 418 | -- [ContentText "get"])] |
412 | roster <- getRoster session stanza_id | 419 | roster <- getRoster session stanza_id |
413 | atomically . writeTChan cmdChan . Send $ roster | 420 | atomically $ do |
421 | writeTChan cmdChan InterestedInRoster | ||
422 | writeTChan cmdChan . Send $ roster | ||
414 | req -> unhandledGet req | 423 | req -> unhandledGet req |
415 | 424 | ||
416 | 425 | ||
@@ -436,15 +445,17 @@ fromClient session cmdChan = doNestingXML $ do | |||
436 | whenJust nextElement $ \stanza -> do | 445 | whenJust nextElement $ \stanza -> do |
437 | stanza_lvl <- nesting | 446 | stanza_lvl <- nesting |
438 | 447 | ||
448 | liftIO . putStrLn $ "stanza: "++show stanza | ||
449 | |||
439 | let unhandledStanza = do | 450 | let unhandledStanza = do |
440 | xs <- gatherElement stanza Seq.empty | 451 | xs <- gatherElement stanza Seq.empty |
441 | prettyPrint "unhandled-C: " (toList xs) | 452 | prettyPrint "unhandled-C: " (toList xs) |
442 | case () of | 453 | case () of |
443 | _ | stanza `isIQOf` iqTypeSet -> handleIQSet session cmdChan stanza | 454 | _ | stanza `isIQOf` iqTypeSet -> handleIQSet session cmdChan stanza |
444 | _ | stanza `isIQOf` iqTypeGet -> handleIQGet session cmdChan stanza | 455 | _ | stanza `isIQOf` iqTypeGet -> handleIQGet session cmdChan stanza |
445 | _ | stanza `isPresenceOf` presenceTypeSubscribe | 456 | _ | stanza `isClientPresenceOf` presenceTypeSubscribe |
446 | -> clientRequestsSubscription session stanza | 457 | -> clientRequestsSubscription session cmdChan stanza |
447 | _ | stanza `isPresenceOf` presenceTypeSubscribed | 458 | _ | stanza `isClientPresenceOf` presenceTypeSubscribed |
448 | -> clientApprovesSubscription session stanza | 459 | -> clientApprovesSubscription session stanza |
449 | _ | otherwise -> unhandledStanza | 460 | _ | otherwise -> unhandledStanza |
450 | 461 | ||
@@ -468,6 +479,7 @@ toClient pchan cmdChan = fix $ \loop -> do | |||
468 | case event of | 479 | case event of |
469 | Right QuitThread -> return () | 480 | Right QuitThread -> return () |
470 | Right (Send xs) -> send xs >> loop | 481 | Right (Send xs) -> send xs >> loop |
482 | Right cmd -> liftIO (putStrLn $ "unhandled event: "++show cmd) >> loop | ||
471 | Left presence -> do | 483 | Left presence -> do |
472 | xs <- liftIO $ xmlifyPresenceForClient presence | 484 | xs <- liftIO $ xmlifyPresenceForClient presence |
473 | send xs | 485 | send xs |
@@ -610,6 +622,12 @@ isPresenceOf (EventBeginElement name attrs) testType | |||
610 | = True | 622 | = True |
611 | isPresenceOf _ _ = False | 623 | isPresenceOf _ _ = False |
612 | 624 | ||
625 | isClientPresenceOf (EventBeginElement name attrs) testType | ||
626 | | name=="{jabber:client}presence" | ||
627 | && matchAttribMaybe "type" testType attrs | ||
628 | = True | ||
629 | isClientPresenceOf _ _ = False | ||
630 | |||
613 | handlePresenceProbe session stanza = do | 631 | handlePresenceProbe session stanza = do |
614 | withJust (lookupAttrib "to" (tagAttrs stanza)) $ \to -> do | 632 | withJust (lookupAttrib "to" (tagAttrs stanza)) $ \to -> do |
615 | -- withJust (lookupAttrib "from" (tagAttrs stanza)) $ \from -> do | 633 | -- withJust (lookupAttrib "from" (tagAttrs stanza)) $ \from -> do |
@@ -638,7 +656,22 @@ subscribeToPresence subscribers peer_jid user = do | |||
638 | 656 | ||
639 | bare (JID n host _) = JID n host Nothing | 657 | bare (JID n host _) = JID n host Nothing |
640 | 658 | ||
641 | clientRequestsSubscription session stanza = do | 659 | presenceErrorRemoteNotFound iqid from to = return |
660 | [ EventBeginElement "{stream:client}presence" | ||
661 | ( case iqid of { Nothing -> id; Just iqid -> ( attr "id" iqid :) } | ||
662 | $ [ attr "from" to | ||
663 | , attr "type" "error" | ||
664 | ] ) | ||
665 | , EventBeginElement "{stream:client}error" | ||
666 | [ attr "type" "modify"] | ||
667 | , EventBeginElement "{urn:ietf:params:xml:ns:xmpp-stanzas}remote-server-not-found" | ||
668 | [] | ||
669 | , EventEndElement "{urn:ietf:params:xml:ns:xmpp-stanzas}remote-server-not-found" | ||
670 | , EventEndElement "{stream:client}error" | ||
671 | , EventEndElement "{stream:client}presence" | ||
672 | ] | ||
673 | |||
674 | clientRequestsSubscription session cmdChan stanza = do | ||
642 | -- make bare jid | 675 | -- make bare jid |
643 | -- check local server and obey rules 3.1.3 of rfc 6121 | 676 | -- check local server and obey rules 3.1.3 of rfc 6121 |
644 | -- or forward to remote peer | 677 | -- or forward to remote peer |
@@ -646,10 +679,22 @@ clientRequestsSubscription session stanza = do | |||
646 | -- if not bailed, | 679 | -- if not bailed, |
647 | -- add to solicited | 680 | -- add to solicited |
648 | -- do roster push with subscription=none ask=subscribe | 681 | -- do roster push with subscription=none ask=subscribe |
649 | liftIO $ putStrLn $ "CLIENT PRESENCE SUBSCRIBE " ++ show stanza | 682 | liftIO $ do |
650 | -- add solicited | 683 | putStrLn $ "CLIENT PRESENCE SUBSCRIBE " ++ show stanza |
651 | -- notify other clients | 684 | withJust (lookupAttrib "to" (tagAttrs stanza)) $ \to_str -> do |
652 | -- notify peer | 685 | let from = lookupAttrib "from" (tagAttrs stanza) |
686 | iqid = lookupAttrib "id" (tagAttrs stanza) | ||
687 | let handleError e | isDoesNotExistError e = do | ||
688 | putStrLn $ "remote-server-not-found" | ||
689 | r <- presenceErrorRemoteNotFound iqid from to_str | ||
690 | atomically $ writeTChan cmdChan (Send r) | ||
691 | handleError e = do | ||
692 | putStrLn $ "ERROR: "++ show e | ||
693 | handleIO handleError $ do | ||
694 | to_jid <- parseHostNameJID (L.fromChunks [S.encodeUtf8 to_str]) | ||
695 | addSolicited session (L.fromChunks [S.encodeUtf8 to_str]) -- jid | ||
696 | putStrLn $ "added to solicited: " ++ show to_jid | ||
697 | -- TODO: create roster item and push to interested clients | ||
653 | return () | 698 | return () |
654 | 699 | ||
655 | peerRequestsSubsription session stanza = do | 700 | peerRequestsSubsription session stanza = do |