summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Presence/XMPP.hs83
-rw-r--r--Presence/XMPPTypes.hs10
-rw-r--r--Presence/main.hs5
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
849data OutBoundMessage = OutBoundPresence Presence
850 | PresenceProbe JID JID
851 | Solicitation JID JID
852 | Approval JID JID
853 deriving Prelude.Show
854
855newServerConnections = newTVar Map.empty 848newServerConnections = newTVar Map.empty
856 849
857data CachedMessages = CachedMessages 850data 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 }
855newCache = CachedMessages Map.empty Map.empty Map.empty
861 856
862connect_to_server chan peer = (>> return ()) . runMaybeT $ do 857connect_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
923presenceProbe sock fromjid tojid typ = do 925presenceStanza 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
1077sendMessage :: TVar (Map Peer (TChan OutBoundMessage, ThreadId)) -> OutBoundMessage -> Peer -> IO () 1081sendMessage :: TVar (Map Peer (TChan OutBoundMessage, ThreadId)) -> OutBoundMessage -> Peer -> IO ()
1078sendMessage cons msg peer = do 1082sendMessage 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.
122is_remote (RemotePeer _) = True 123is_remote (RemotePeer _) = True
123is_remote _ = False 124is_remote _ = False
124 125
126discardPort (RemotePeer addr) = RemotePeer (withoutPort addr)
127discardPort x = x
128
125parseHostNameJID :: ByteString -> IO JID 129parseHostNameJID :: ByteString -> IO JID
126parseHostNameJID jid = do 130parseHostNameJID 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
189withoutPort = (`withPort` 0) 193withoutPort = (`withPort` 0)
190 194
195data 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