diff options
author | joe <joe@jerkface.net> | 2013-07-09 01:40:47 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2013-07-09 01:40:47 -0400 |
commit | 5d96f7581837e84b7e2db7f119879bc701709ddd (patch) | |
tree | 9298f1ed49e343e7767166f5abd2877eaf24e284 /Presence/XMPP.hs | |
parent | c0895f5a2e604bc4594354399498e2ebb19d8c8e (diff) |
send subscription requests to remote peers
Diffstat (limited to 'Presence/XMPP.hs')
-rw-r--r-- | Presence/XMPP.hs | 79 |
1 files changed, 53 insertions, 26 deletions
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs index a08c1a0e..735eaf3a 100644 --- a/Presence/XMPP.hs +++ b/Presence/XMPP.hs | |||
@@ -71,6 +71,7 @@ import Control.Monad as Monad | |||
71 | import Text.XML.Stream.Parse (parseBytes,content) | 71 | import Text.XML.Stream.Parse (parseBytes,content) |
72 | import Text.XML.Stream.Render | 72 | import Text.XML.Stream.Render |
73 | import Data.XML.Types as XML | 73 | import Data.XML.Types as XML |
74 | import qualified Data.Text as S (takeWhile) | ||
74 | import Data.Text.Encoding as S (decodeUtf8,encodeUtf8) | 75 | import Data.Text.Encoding as S (decodeUtf8,encodeUtf8) |
75 | import Data.Text.Lazy.Encoding as L (decodeUtf8,encodeUtf8) | 76 | import Data.Text.Lazy.Encoding as L (decodeUtf8,encodeUtf8) |
76 | import Data.Text.Lazy (toStrict) | 77 | import Data.Text.Lazy (toStrict) |
@@ -512,7 +513,7 @@ toClient session pchan cmdChan rchan = toClient' False False | |||
512 | CmdChan (Send xs) -> send xs >> loop | 513 | CmdChan (Send xs) -> send xs >> loop |
513 | CmdChan BoundToResource -> toClient' True isInterested | 514 | CmdChan BoundToResource -> toClient' True isInterested |
514 | CmdChan InterestedInRoster -> toClient' isBound True | 515 | CmdChan InterestedInRoster -> toClient' isBound True |
515 | CmdChan cmd -> liftIO (putStrLn $ "unhandled event: "++show cmd) >> loop | 516 | -- CmdChan cmd -> liftIO (putStrLn $ "unhandled event: "++show cmd) >> loop |
516 | RChan (RequestedSubscription who contact) -> do | 517 | RChan (RequestedSubscription who contact) -> do |
517 | jid <- liftIO $ getJID session | 518 | jid <- liftIO $ getJID session |
518 | when (isInterested && Just who==name jid) $ do | 519 | when (isInterested && Just who==name jid) $ do |
@@ -712,18 +713,20 @@ presenceErrorRemoteNotFound iqid from to = return | |||
712 | , EventEndElement "{stream:client}presence" | 713 | , EventEndElement "{stream:client}presence" |
713 | ] | 714 | ] |
714 | 715 | ||
716 | presenceSubscribed from = return | ||
717 | [ EventBeginElement "{stream:client}presence" | ||
718 | [ attr "from" from | ||
719 | , attr "type" "subscribed" | ||
720 | ] | ||
721 | , EventEndElement "{stream:client}presence" | ||
722 | ] | ||
723 | |||
715 | clientRequestsSubscription session cmdChan stanza = do | 724 | clientRequestsSubscription session cmdChan stanza = do |
716 | -- make bare jid | ||
717 | -- check local server and obey rules 3.1.3 of rfc 6121 | ||
718 | -- or forward to remote peer | ||
719 | -- or bail with type='error' as shown in 3.1.2 | ||
720 | -- if not bailed, | ||
721 | -- add to solicited | ||
722 | -- do roster push with subscription=none ask=subscribe | ||
723 | liftIO $ do | 725 | liftIO $ do |
724 | putStrLn $ "CLIENT PRESENCE SUBSCRIBE " ++ show stanza | 726 | putStrLn $ "CLIENT PRESENCE SUBSCRIBE " ++ show stanza |
725 | withJust (lookupAttrib "to" (tagAttrs stanza)) $ \to_str -> do | 727 | withJust (lookupAttrib "to" (tagAttrs stanza)) $ \to_str0 -> do |
726 | let from = lookupAttrib "from" (tagAttrs stanza) | 728 | let to_str = S.takeWhile (/='/') to_str0 |
729 | from = lookupAttrib "from" (tagAttrs stanza) | ||
727 | iqid = lookupAttrib "id" (tagAttrs stanza) | 730 | iqid = lookupAttrib "id" (tagAttrs stanza) |
728 | let handleError e | isDoesNotExistError e = do | 731 | let handleError e | isDoesNotExistError e = do |
729 | putStrLn $ "remote-server-not-found" | 732 | putStrLn $ "remote-server-not-found" |
@@ -732,12 +735,18 @@ clientRequestsSubscription session cmdChan stanza = do | |||
732 | handleError e = do | 735 | handleError e = do |
733 | putStrLn $ "ERROR: "++ show e | 736 | putStrLn $ "ERROR: "++ show e |
734 | handleIO handleError $ do | 737 | handleIO handleError $ do |
735 | to_jid <- parseHostNameJID (L.fromChunks [S.encodeUtf8 to_str]) | 738 | let to_str' = (L.fromChunks [S.encodeUtf8 to_str]) |
736 | addSolicited session (L.fromChunks [S.encodeUtf8 to_str]) -- jid | 739 | to_jid <- fmap bare $ parseHostNameJID to_str' |
737 | putStrLn $ "added to solicited: " ++ show to_jid | 740 | if (is_remote . peer) to_jid |
738 | -- TODO: create roster item and push to interested clients | 741 | then do |
739 | -- addSolicited should write event to a roster channel | 742 | addSolicited session to_str' to_jid |
740 | -- that toClient will be listening on. | 743 | putStrLn $ "added to solicited: " ++ show to_jid |
744 | -- TODO: notify peer. | ||
745 | else do | ||
746 | -- addLocalSubscriber session to_str | ||
747 | -- self <- getJID session | ||
748 | r <- presenceSubscribed to_str -- self | ||
749 | atomically $ writeTChan cmdChan (Send r) | ||
741 | return () | 750 | return () |
742 | 751 | ||
743 | peerRequestsSubsription session stanza = do | 752 | peerRequestsSubsription session stanza = do |
@@ -807,14 +816,16 @@ fromPeer session = doNestingXML $ do | |||
807 | 816 | ||
808 | 817 | ||
809 | 818 | ||
810 | data OutBoundMessage = OutBoundPresence Presence | PresenceProbe JID JID | 819 | data OutBoundMessage = OutBoundPresence Presence |
820 | | PresenceProbe JID JID | ||
821 | | Solicitation JID JID | ||
811 | deriving Prelude.Show | 822 | deriving Prelude.Show |
812 | 823 | ||
813 | newServerConnections = newTVar Map.empty | 824 | newServerConnections = newTVar Map.empty |
814 | 825 | ||
815 | data CachedMessages = CachedMessages | 826 | data CachedMessages = CachedMessages |
816 | { presences :: Map JID JabberShow | 827 | { presences :: Map JID JabberShow |
817 | , probes :: Map JID (Set JID) | 828 | , probes :: Map JID (Set (Bool,JID)) |
818 | } | 829 | } |
819 | 830 | ||
820 | connect_to_server chan peer = (>> return ()) . runMaybeT $ do | 831 | connect_to_server chan peer = (>> return ()) . runMaybeT $ do |
@@ -831,7 +842,11 @@ connect_to_server chan peer = (>> return ()) . runMaybeT $ do | |||
831 | writeIORef cached (cache { presences=Map.insert jid st . presences $ cache }) | 842 | writeIORef cached (cache { presences=Map.insert jid st . presences $ cache }) |
832 | cacheCmd (PresenceProbe from to) cached = do | 843 | cacheCmd (PresenceProbe from to) cached = do |
833 | cache <- readIORef cached | 844 | cache <- readIORef cached |
834 | let probes' = Map.adjust (Set.insert from) to $ probes cache | 845 | let probes' = Map.adjust (Set.insert (True,from)) to $ probes cache |
846 | writeIORef cached (cache { probes=probes' }) | ||
847 | cacheCmd (Solicitation from to) cached = do | ||
848 | cache <- readIORef cached | ||
849 | let probes' = Map.adjust (Set.insert (False,from)) to $ probes cache | ||
835 | writeIORef cached (cache { probes=probes' }) | 850 | writeIORef cached (cache { probes=probes' }) |
836 | 851 | ||
837 | fix $ \sendmsgs -> do | 852 | fix $ \sendmsgs -> do |
@@ -873,7 +888,7 @@ goodbyePeer = | |||
873 | , EventEndDocument | 888 | , EventEndDocument |
874 | ] | 889 | ] |
875 | 890 | ||
876 | presenceProbe sock fromjid tojid = do | 891 | presenceProbe sock fromjid tojid typ = do |
877 | addr <- getSocketName sock | 892 | addr <- getSocketName sock |
878 | let jidstr jid = toStrict . L.decodeUtf8 | 893 | let jidstr jid = toStrict . L.decodeUtf8 |
879 | $ name jid <$++> "@" | 894 | $ name jid <$++> "@" |
@@ -887,7 +902,7 @@ presenceProbe sock fromjid tojid = do | |||
887 | [ EventBeginElement "{jabber:server}presence" | 902 | [ EventBeginElement "{jabber:server}presence" |
888 | [ attr "from" from | 903 | [ attr "from" from |
889 | , attr "to" to | 904 | , attr "to" to |
890 | , attr "type" "probe" | 905 | , attr "type" typ |
891 | ] | 906 | ] |
892 | , EventEndElement "{jabber:server}presence" | 907 | , EventEndElement "{jabber:server}presence" |
893 | ] | 908 | ] |
@@ -928,20 +943,29 @@ toPeer sock cache chan fail = do | |||
928 | checkConnection cmd | 943 | checkConnection cmd |
929 | yieldOr r (fail . Just $ cmd) | 944 | yieldOr r (fail . Just $ cmd) |
930 | prettyPrint ">P: " r | 945 | prettyPrint ">P: " r |
931 | sendProbe from to = do | 946 | sendProbe' from to typ = do |
932 | r <- liftIO $ presenceProbe sock from to | 947 | r <- liftIO $ presenceProbe sock from to typ |
933 | let cmd = PresenceProbe from to | 948 | let cmd = PresenceProbe from to |
934 | checkConnection cmd | 949 | checkConnection cmd |
935 | yieldOr r (fail . Just $ cmd) | 950 | yieldOr r (fail . Just $ cmd) |
936 | prettyPrint ">P: " r | 951 | prettyPrint ">P: " r |
952 | sendProbe from to = sendProbe' from to "probe" | ||
953 | sendSolicitation from to = sendProbe' from to "subscribe" | ||
937 | 954 | ||
938 | send greetPeer | 955 | send greetPeer |
939 | forM_ (Map.assocs . presences $ cache) $ \(jid,st) -> do | 956 | forM_ (Map.assocs . presences $ cache) $ \(jid,st) -> do |
940 | sendPresence (Presence jid st) | 957 | sendPresence (Presence jid st) |
941 | forM_ (Map.assocs . probes $ cache) $ \(to,froms) -> do | 958 | forM_ (Map.assocs . probes $ cache) $ \(to,froms) -> do |
942 | forM_ (Set.toList froms) $ \from -> do | 959 | forM_ (Set.toList froms) $ \(got,from) -> do |
943 | liftIO $ L.putStrLn "sending cached probe..." | 960 | if got |
944 | sendProbe from to | 961 | then do |
962 | liftIO $ L.putStrLn "sending cached probe..." | ||
963 | sendProbe from to | ||
964 | else do | ||
965 | liftIO $ L.putStrLn "sending cached solicitation..." | ||
966 | sendSolicitation from to | ||
967 | |||
968 | |||
945 | fix $ \loop -> do | 969 | fix $ \loop -> do |
946 | event <- lift . atomically $ readTChan chan | 970 | event <- lift . atomically $ readTChan chan |
947 | case event of | 971 | case event of |
@@ -949,6 +973,9 @@ toPeer sock cache chan fail = do | |||
949 | PresenceProbe from to -> do | 973 | PresenceProbe from to -> do |
950 | liftIO $ L.putStrLn "sending live probe..." | 974 | liftIO $ L.putStrLn "sending live probe..." |
951 | sendProbe from to | 975 | sendProbe from to |
976 | Solicitation from to -> do | ||
977 | liftIO $ L.putStrLn "sending live solicitation..." | ||
978 | sendSolicitation from to | ||
952 | loop | 979 | loop |
953 | send goodbyePeer | 980 | send goodbyePeer |
954 | 981 | ||