diff options
author | joe <joe@jerkface.net> | 2013-07-09 20:19:31 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2013-07-09 20:19:31 -0400 |
commit | 9585ab81bdd91310fe49b36ca8d29135bd4a68b3 (patch) | |
tree | dec4b3b7d2c250ca146bae13a5d89c852528edc8 /Presence | |
parent | 2c27bf56a880341b63df0533441341e72e215a19 (diff) |
Auto-reply approval to remote peer in case a requested subscription
is already established.
Diffstat (limited to 'Presence')
-rw-r--r-- | Presence/XMPP.hs | 83 | ||||
-rw-r--r-- | Presence/XMPPTypes.hs | 10 | ||||
-rw-r--r-- | Presence/main.hs | 5 |
3 files changed, 59 insertions, 39 deletions
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs index ce1ea7c5..e4f60712 100644 --- a/Presence/XMPP.hs +++ b/Presence/XMPP.hs | |||
@@ -684,12 +684,11 @@ handlePresenceProbe session stanza = do | |||
684 | subs <- getSubscribers (peerSessionFactory session) user | 684 | subs <- getSubscribers (peerSessionFactory session) user |
685 | liftIO $ L.putStrLn $ "subscribers for "<++>bshow user<++>": " <++>bshow subs | 685 | liftIO $ L.putStrLn $ "subscribers for "<++>bshow user<++>": " <++>bshow subs |
686 | forM_ subs $ \jidstr -> do | 686 | forM_ subs $ \jidstr -> do |
687 | handle (\(IOError _ _ _ _ _ _) -> return ()) $ do | 687 | handleIO_ (return ()) $ do |
688 | -- handle (\(SomeException _) -> return ()) $ do | ||
689 | L.putStrLn $ "parsing " <++>jidstr | 688 | L.putStrLn $ "parsing " <++>jidstr |
690 | sub <- parseHostNameJID jidstr | 689 | sub <- parseHostNameJID jidstr |
691 | putStrLn $ "comparing " ++show (peer sub , peerAddress session) | 690 | putStrLn $ "comparing " ++show (peer sub , peerAddress session) |
692 | when (peer sub == peerAddress session) $ do | 691 | when (peer sub == discardPort (peerAddress session)) $ do |
693 | ps <- userStatus session user | 692 | ps <- userStatus session user |
694 | mapM_ (announcePresence session) ps | 693 | mapM_ (announcePresence session) ps |
695 | return () | 694 | return () |
@@ -776,10 +775,10 @@ peerRequestsSubsription session stanza = do | |||
776 | if elem fromjid subs | 775 | if elem fromjid subs |
777 | then do | 776 | then do |
778 | liftIO . L.putStrLn $ bshow fromjid <++> " already subscribed to " <++> user | 777 | liftIO . L.putStrLn $ bshow fromjid <++> " already subscribed to " <++> user |
779 | -- if already subscribed | 778 | -- if already subscribed, reply |
780 | -- reply | 779 | liftIO $ sendPeerMessage session (Approval tojid fromjid) |
781 | return () | ||
782 | else | 780 | else |
781 | -- TODO | ||
783 | -- if no client: | 782 | -- if no client: |
784 | -- add pending | 783 | -- add pending |
785 | -- else: | 784 | -- else: |
@@ -846,25 +845,25 @@ fromPeer session = doNestingXML $ do | |||
846 | 845 | ||
847 | 846 | ||
848 | 847 | ||
849 | data OutBoundMessage = OutBoundPresence Presence | ||
850 | | PresenceProbe JID JID | ||
851 | | Solicitation JID JID | ||
852 | | Approval JID JID | ||
853 | deriving Prelude.Show | ||
854 | |||
855 | newServerConnections = newTVar Map.empty | 848 | newServerConnections = newTVar Map.empty |
856 | 849 | ||
857 | data CachedMessages = CachedMessages | 850 | data CachedMessages = CachedMessages |
858 | { presences :: Map JID JabberShow | 851 | { presences :: Map JID JabberShow |
859 | , probes :: Map JID (Set (Bool,JID)) | 852 | , probes :: Map JID (Set (Bool,JID)) -- False means solicitation rather than probe |
853 | , approvals :: Map JID (Set JID) | ||
860 | } | 854 | } |
855 | newCache = CachedMessages Map.empty Map.empty Map.empty | ||
861 | 856 | ||
862 | connect_to_server chan peer = (>> return ()) . runMaybeT $ do | 857 | connect_to_server chan peer = (>> return ()) . runMaybeT $ do |
863 | let port = 5269 :: Int | 858 | let port = 5269 :: Int |
864 | -- We'll cache Presence notifications until the socket | 859 | -- We'll cache Presence notifications until the socket |
865 | -- is ready. | 860 | -- is ready. |
866 | cached <- liftIO $ newIORef (CachedMessages Map.empty Map.empty) | 861 | cached <- liftIO $ newIORef newCache |
867 | 862 | ||
863 | let mmInsert val key mm = Map.alter f key mm | ||
864 | where | ||
865 | f Nothing = Just $ Set.singleton val | ||
866 | f (Just set) = Just $ Set.insert val set | ||
868 | let cacheCmd (OutBoundPresence (Presence jid Offline)) cached = do | 867 | let cacheCmd (OutBoundPresence (Presence jid Offline)) cached = do |
869 | cache <- readIORef cached | 868 | cache <- readIORef cached |
870 | writeIORef cached (cache { presences=Map.delete jid . presences $ cache }) | 869 | writeIORef cached (cache { presences=Map.delete jid . presences $ cache }) |
@@ -873,13 +872,16 @@ connect_to_server chan peer = (>> return ()) . runMaybeT $ do | |||
873 | writeIORef cached (cache { presences=Map.insert jid st . presences $ cache }) | 872 | writeIORef cached (cache { presences=Map.insert jid st . presences $ cache }) |
874 | cacheCmd (PresenceProbe from to) cached = do | 873 | cacheCmd (PresenceProbe from to) cached = do |
875 | cache <- readIORef cached | 874 | cache <- readIORef cached |
876 | let probes' = Map.adjust (Set.insert (True,from)) to $ probes cache | 875 | let probes' = mmInsert (True,from) to $ probes cache |
877 | writeIORef cached (cache { probes=probes' }) | 876 | writeIORef cached (cache { probes=probes' }) |
878 | cacheCmd (Solicitation from to) cached = do | 877 | cacheCmd (Solicitation from to) cached = do |
879 | cache <- readIORef cached | 878 | cache <- readIORef cached |
880 | let probes' = Map.adjust (Set.insert (False,from)) to $ probes cache | 879 | let probes' = mmInsert (False,from) to $ probes cache |
881 | writeIORef cached (cache { probes=probes' }) | 880 | writeIORef cached (cache { probes=probes' }) |
882 | cacheCmd (Approval from to) cached = return () -- Subscription approvals are not cached. | 881 | cacheCmd (Approval from to) cached = do |
882 | cache <- readIORef cached | ||
883 | let approvals' = mmInsert from to $ approvals cache | ||
884 | writeIORef cached (cache { approvals=approvals' }) | ||
883 | 885 | ||
884 | fix $ \sendmsgs -> do | 886 | fix $ \sendmsgs -> do |
885 | connected <- liftIO . async $ connect' (peerAddr peer) port | 887 | connected <- liftIO . async $ connect' (peerAddr peer) port |
@@ -898,7 +900,7 @@ connect_to_server chan peer = (>> return ()) . runMaybeT $ do | |||
898 | hSetBuffering h NoBuffering | 900 | hSetBuffering h NoBuffering |
899 | cache <- readIORef $ cached | 901 | cache <- readIORef $ cached |
900 | -- hint garbage collector: we're done with this... | 902 | -- hint garbage collector: we're done with this... |
901 | writeIORef cached (CachedMessages Map.empty Map.empty) | 903 | writeIORef cached newCache |
902 | return (cache,packetSink h) | 904 | return (cache,packetSink h) |
903 | MaybeT $ handleOutgoingToPeer (restrictSocket sock) cache chan snk | 905 | MaybeT $ handleOutgoingToPeer (restrictSocket sock) cache chan snk |
904 | 906 | ||
@@ -920,7 +922,7 @@ goodbyePeer = | |||
920 | , EventEndDocument | 922 | , EventEndDocument |
921 | ] | 923 | ] |
922 | 924 | ||
923 | presenceProbe sock fromjid tojid typ = do | 925 | presenceStanza sock fromjid tojid typ = do |
924 | addr <- getSocketName sock | 926 | addr <- getSocketName sock |
925 | let jidstr jid = toStrict . L.decodeUtf8 | 927 | let jidstr jid = toStrict . L.decodeUtf8 |
926 | $ name jid <$++> "@" | 928 | $ name jid <$++> "@" |
@@ -963,28 +965,31 @@ toPeer sock cache chan fail = do | |||
963 | checkConnection cmd = do | 965 | checkConnection cmd = do |
964 | liftIO $ catch (getPeerName sock >> return ()) | 966 | liftIO $ catch (getPeerName sock >> return ()) |
965 | (\_ -> fail . Just $ cmd) | 967 | (\_ -> fail . Just $ cmd) |
966 | sendPresence presence = do | 968 | sendOrFail getXML cmd = do |
967 | r <- lift $ xmlifyPresenceForPeer sock presence | ||
968 | {- | ||
969 | liftIO $ do | ||
970 | p' <- catch (fmap (Just . RemotePeer) $ getPeerName sock) | ||
971 | (\_ -> (fail . Just . OutBoundPresence $ presence) >> return Nothing) | ||
972 | L.putStrLn $ "sending Presence to " <++?> fmap showPeer p' | ||
973 | -} | ||
974 | let cmd = OutBoundPresence presence | ||
975 | checkConnection cmd | 969 | checkConnection cmd |
970 | r <- liftIO $ getXML | ||
971 | -- handleIO (\e -> putStrLn ("ERROR: "++show e) >> return []) getXML | ||
976 | yieldOr r (fail . Just $ cmd) | 972 | yieldOr r (fail . Just $ cmd) |
977 | prettyPrint ">P: " r | 973 | prettyPrint ">P: " r |
978 | sendProbe' from to typ = do | 974 | sendPresence presence = |
979 | r <- liftIO $ presenceProbe sock from to typ | 975 | sendOrFail (xmlifyPresenceForPeer sock presence) |
980 | let cmd = PresenceProbe from to | 976 | (OutBoundPresence presence) |
981 | checkConnection cmd | 977 | sendProbe from to = |
982 | yieldOr r (fail . Just $ cmd) | 978 | sendOrFail (presenceStanza sock from to "probe") |
983 | prettyPrint ">P: " r | 979 | (PresenceProbe from to) |
984 | sendProbe from to = sendProbe' from to "probe" | 980 | sendSolicitation from to = |
985 | sendSolicitation from to = sendProbe' from to "subscribe" | 981 | sendOrFail (presenceStanza sock from to "subscribe") |
982 | (Solicitation from to) | ||
983 | sendApproval from to = | ||
984 | sendOrFail (presenceStanza sock from to "subscribed") | ||
985 | (Approval from to) | ||
986 | |||
986 | 987 | ||
987 | send greetPeer | 988 | send greetPeer |
989 | forM_ (Map.assocs . approvals $ cache) $ \(to,froms) -> do | ||
990 | forM_ (Set.toList froms) $ \from -> do | ||
991 | liftIO $ L.putStrLn "sending cached approval..." | ||
992 | sendApproval from to | ||
988 | forM_ (Map.assocs . presences $ cache) $ \(jid,st) -> do | 993 | forM_ (Map.assocs . presences $ cache) $ \(jid,st) -> do |
989 | sendPresence (Presence jid st) | 994 | sendPresence (Presence jid st) |
990 | forM_ (Map.assocs . probes $ cache) $ \(to,froms) -> do | 995 | forM_ (Map.assocs . probes $ cache) $ \(to,froms) -> do |
@@ -1010,8 +1015,7 @@ toPeer sock cache chan fail = do | |||
1010 | sendSolicitation from to | 1015 | sendSolicitation from to |
1011 | Approval from to -> do | 1016 | Approval from to -> do |
1012 | liftIO . L.putStrLn $ "sending approval "<++>bshow (from,to) | 1017 | liftIO . L.putStrLn $ "sending approval "<++>bshow (from,to) |
1013 | r <- liftIO $ presenceProbe sock from to "subscribed" | 1018 | sendApproval from to |
1014 | send r | ||
1015 | loop | 1019 | loop |
1016 | send goodbyePeer | 1020 | send goodbyePeer |
1017 | 1021 | ||
@@ -1075,7 +1079,8 @@ connect' addr port = do | |||
1075 | 1079 | ||
1076 | 1080 | ||
1077 | sendMessage :: TVar (Map Peer (TChan OutBoundMessage, ThreadId)) -> OutBoundMessage -> Peer -> IO () | 1081 | sendMessage :: TVar (Map Peer (TChan OutBoundMessage, ThreadId)) -> OutBoundMessage -> Peer -> IO () |
1078 | sendMessage cons msg peer = do | 1082 | sendMessage cons msg peer0 = do |
1083 | let peer = discardPort peer0 | ||
1079 | found <- atomically $ do | 1084 | found <- atomically $ do |
1080 | consmap <- readTVar cons | 1085 | consmap <- readTVar cons |
1081 | return (Map.lookup peer consmap) | 1086 | return (Map.lookup peer consmap) |
diff --git a/Presence/XMPPTypes.hs b/Presence/XMPPTypes.hs index 2bad795a..275f644e 100644 --- a/Presence/XMPPTypes.hs +++ b/Presence/XMPPTypes.hs | |||
@@ -55,6 +55,7 @@ class JabberPeerSession session where | |||
55 | userStatus :: session -> ByteString -> IO [Presence] | 55 | userStatus :: session -> ByteString -> IO [Presence] |
56 | announcePresence :: session -> Presence -> IO () | 56 | announcePresence :: session -> Presence -> IO () |
57 | peerSessionFactory :: session -> XMPPPeerClass session | 57 | peerSessionFactory :: session -> XMPPPeerClass session |
58 | sendPeerMessage :: session -> OutBoundMessage -> IO () | ||
58 | getBuddies :: XMPPPeerClass session -> ByteString -> IO [ByteString] | 59 | getBuddies :: XMPPPeerClass session -> ByteString -> IO [ByteString] |
59 | getSubscribers :: XMPPPeerClass session -> ByteString -> IO [ByteString] | 60 | getSubscribers :: XMPPPeerClass session -> ByteString -> IO [ByteString] |
60 | 61 | ||
@@ -122,6 +123,9 @@ showPeer (RemotePeer addr@(SockAddrInet6 _ _ _ _)) = pack $ stripColon (Prelude. | |||
122 | is_remote (RemotePeer _) = True | 123 | is_remote (RemotePeer _) = True |
123 | is_remote _ = False | 124 | is_remote _ = False |
124 | 125 | ||
126 | discardPort (RemotePeer addr) = RemotePeer (withoutPort addr) | ||
127 | discardPort x = x | ||
128 | |||
125 | parseHostNameJID :: ByteString -> IO JID | 129 | parseHostNameJID :: ByteString -> IO JID |
126 | parseHostNameJID jid = do | 130 | parseHostNameJID jid = do |
127 | let (name,peer_string,rsc) = splitJID jid | 131 | let (name,peer_string,rsc) = splitJID jid |
@@ -188,3 +192,9 @@ withPort (SockAddrInet6 _ a b c) port = SockAddrInet6 (toEnum port) a b c | |||
188 | 192 | ||
189 | withoutPort = (`withPort` 0) | 193 | withoutPort = (`withPort` 0) |
190 | 194 | ||
195 | data OutBoundMessage = OutBoundPresence Presence | ||
196 | | PresenceProbe JID JID | ||
197 | | Solicitation JID JID | ||
198 | | Approval JID JID | ||
199 | deriving Prelude.Show | ||
200 | |||
diff --git a/Presence/main.hs b/Presence/main.hs index 036d7237..303c4b05 100644 --- a/Presence/main.hs +++ b/Presence/main.hs | |||
@@ -287,6 +287,11 @@ instance JabberPeerSession PeerSession where | |||
287 | Offline -> MM.deleteElemIf u match jids | 287 | Offline -> MM.deleteElemIf u match jids |
288 | stat -> maybe jids (\r -> MM.insert u (r,stat) jids) rsc | 288 | stat -> maybe jids (\r -> MM.insert u (r,stat) jids) rsc |
289 | 289 | ||
290 | sendPeerMessage session msg = do | ||
291 | let cons = outGoingConnections . peer_global $ session | ||
292 | putStrLn $ "sendPeerMessage " <++> bshow msg <++> " --> "<++>bshow (peer_name session) | ||
293 | sendMessage cons msg (peer_name session) | ||
294 | |||
290 | getBuddies _ user = ConfigFiles.getBuddies user | 295 | getBuddies _ user = ConfigFiles.getBuddies user |
291 | getSubscribers _ user = ConfigFiles.getSubscribers user | 296 | getSubscribers _ user = ConfigFiles.getSubscribers user |
292 | 297 | ||