summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Connection.hs53
-rw-r--r--Presence/Server.hs39
-rw-r--r--Presence/XMPPServer.hs96
3 files changed, 142 insertions, 46 deletions
diff --git a/Connection.hs b/Connection.hs
new file mode 100644
index 00000000..e3e9a8ca
--- /dev/null
+++ b/Connection.hs
@@ -0,0 +1,53 @@
1{-# LANGUAGE DeriveFunctor #-}
2module Connection where
3
4import Control.Arrow
5import Control.Concurrent.STM
6import qualified Data.Map as Map
7 ;import Data.Map (Map)
8
9import PingMachine
10
11data Status status
12 = Dormant
13 | InProgress status
14 | Established
15 deriving Functor
16
17data Policy
18 = RefusingToConnect
19 | OpenToConnect
20 | TryingToConnect
21
22data Connection status = Connection
23 { connStatus :: STM (Status status)
24 , connPolicy :: STM Policy
25 , connPingLogic :: PingMachine
26 }
27 deriving Functor
28
29data Manager status k = Manager
30 { setPolicy :: k -> Policy -> IO ()
31 , connections :: STM (Map k (Connection status))
32 , stringToKey :: String -> IO (Maybe k) -- TODO: It'd be nice for this to be pure, but
33 -- currently we do a DNS resolve.
34 , showProgress :: status -> String
35 , showKey :: k -> String
36 }
37
38addManagers :: (Ord kA, Ord kB) =>
39 Manager statusA kA
40 -> Manager statusB kB
41 -> Manager (Either statusA statusB) (Either kA kB)
42addManagers mgrA mgrB = Manager
43 { setPolicy = either (setPolicy mgrA) (setPolicy mgrB)
44 , connections = do
45 as <- Map.toList <$> connections mgrA
46 bs <- Map.toList <$> connections mgrB
47 return $ Map.fromList $ map (Left *** fmap Left) as ++ map (Right *** fmap Right) bs
48 , stringToKey = \str -> do
49 ka <- fmap Left <$> stringToKey mgrA str
50 maybe (fmap Right <$> stringToKey mgrB str) (return . Just) ka
51 , showProgress = either (showProgress mgrA) (showProgress mgrB)
52 , showKey = either (showKey mgrA) (showKey mgrB)
53 }
diff --git a/Presence/Server.hs b/Presence/Server.hs
index 46b32b81..da0a6973 100644
--- a/Presence/Server.hs
+++ b/Presence/Server.hs
@@ -20,7 +20,9 @@
20-- 20--
21-- * interface tweaks 21-- * interface tweaks
22-- 22--
23module Server where 23module Server
24 ( module Server
25 , module PingMachine ) where
24 26
25import Data.ByteString (ByteString,hGetNonBlocking) 27import Data.ByteString (ByteString,hGetNonBlocking)
26import qualified Data.ByteString.Char8 as S -- ( hPutStrLn, hPutStr, pack) 28import qualified Data.ByteString.Char8 as S -- ( hPutStrLn, hPutStr, pack)
@@ -76,6 +78,9 @@ import InterruptibleDelay
76import PingMachine 78import PingMachine
77import Network.StreamServer 79import Network.StreamServer
78import Network.SocketLike hiding (sClose) 80import Network.SocketLike hiding (sClose)
81import qualified Connection as G
82 ;import Connection (Manager (..), Policy(..))
83
79 84
80type Microseconds = Int 85type Microseconds = Int
81 86
@@ -762,3 +767,35 @@ warn str = S.hPutStrLn stderr str >> hFlush stderr
762 767
763debugNoise :: Monad m => t -> m () 768debugNoise :: Monad m => t -> m ()
764debugNoise str = return () 769debugNoise str = return ()
770
771data TCPStatus = AwaitingRead | AwaitingWrite
772
773tcpManager :: Show conkey =>
774 (conkey -> (SockAddr, ConnectionParameters conkey u, Miliseconds))
775 -> (String -> IO (Maybe conkey))
776 -> Server conkey u releaseKey x
777 -> Manager TCPStatus conkey
778tcpManager grokKey parseKey sv = Manager
779 { setPolicy = \k -> \case
780 TryingToConnect -> control sv $ case grokKey k of
781 (saddr,params,ms) -> ConnectWithEndlessRetry saddr params ms
782 OpenToConnect -> return () -- TODO
783 RefusingToConnect -> return () -- TODO
784 , connections = fmap exportConnection <$> readTVar (conmap sv)
785 , stringToKey = parseKey
786 , showProgress = \case
787 AwaitingRead -> "awaiting inbound"
788 AwaitingWrite -> "awaiting outbound"
789 , showKey = show
790 }
791
792exportConnection :: ConnectionRecord u -> G.Connection TCPStatus
793exportConnection (ConnectionRecord ckont cstate cdata) = G.Connection
794 { G.connStatus = return $ case cstate of
795 SaneConnection {} -> G.Established
796 ConnectionPair {} -> G.Established
797 ReadOnlyConnection {} -> G.InProgress AwaitingWrite
798 WriteOnlyConnection {} -> G.InProgress AwaitingRead
799 , G.connPolicy = return TryingToConnect
800 , G.connPingLogic = connPingTimer cstate
801 }
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index 3505a0a2..b23bb42e 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -8,7 +8,7 @@ module XMPPServer
8 , ConnectionKey(..) 8 , ConnectionKey(..)
9 , XMPPServerParameters(..) 9 , XMPPServerParameters(..)
10 , XMPPServer 10 , XMPPServer
11 , addPeer 11 , xmppConnections
12 , StanzaWrap(..) 12 , StanzaWrap(..)
13 , Stanza(..) 13 , Stanza(..)
14 , StanzaType(..) 14 , StanzaType(..)
@@ -81,11 +81,12 @@ import qualified Data.Map as Map
81import Data.Set (Set, (\\) ) 81import Data.Set (Set, (\\) )
82import qualified Data.Set as Set 82import qualified Data.Set as Set
83import Data.String ( IsString(..) ) 83import Data.String ( IsString(..) )
84import qualified System.Random 84import qualified System.Random
85import Data.Void (Void) 85import Data.Void (Void)
86import System.Endian (toBE32) 86import System.Endian (toBE32)
87import Control.Applicative 87import Control.Applicative
88import System.IO 88import System.IO
89import qualified Connection
89 90
90peerport :: PortNumber 91peerport :: PortNumber
91peerport = 5269 92peerport = 5269
@@ -103,7 +104,7 @@ data JabberShow = Offline
103 | Chatty 104 | Chatty
104 deriving (Show,Enum,Ord,Eq,Read) 105 deriving (Show,Enum,Ord,Eq,Read)
105 106
106data MessageThread = MessageThread { 107data MessageThread = MessageThread {
107 msgThreadParent :: Maybe Text, 108 msgThreadParent :: Maybe Text,
108 msgThreadContent :: Text 109 msgThreadContent :: Text
109 } 110 }
@@ -202,9 +203,9 @@ data XMPPServerParameters =
202 , xmppInformPeerPresence :: ConnectionKey -> Stanza -> IO () 203 , xmppInformPeerPresence :: ConnectionKey -> Stanza -> IO ()
203 , -- | Called when a remote peer requests our status. 204 , -- | Called when a remote peer requests our status.
204 xmppAnswerProbe :: ConnectionKey -> Stanza -> TChan Stanza -> IO () 205 xmppAnswerProbe :: ConnectionKey -> Stanza -> TChan Stanza -> IO ()
205 , xmppClientSubscriptionRequest :: IO () -> ConnectionKey -> Stanza -> TChan Stanza -> IO () 206 , xmppClientSubscriptionRequest :: IO () -> ConnectionKey -> Stanza -> TChan Stanza -> IO ()
206 , -- | Called when a remote peer sends subscription request. 207 , -- | Called when a remote peer sends subscription request.
207 xmppPeerSubscriptionRequest :: IO () -> ConnectionKey -> Stanza -> TChan Stanza -> IO () 208 xmppPeerSubscriptionRequest :: IO () -> ConnectionKey -> Stanza -> TChan Stanza -> IO ()
208 , xmppClientInformSubscription :: IO () -> ConnectionKey -> Stanza -> IO () 209 , xmppClientInformSubscription :: IO () -> ConnectionKey -> Stanza -> IO ()
209 , -- | Called when a remote peer informs us of our subscription status. 210 , -- | Called when a remote peer informs us of our subscription status.
210 xmppPeerInformSubscription :: IO () -> ConnectionKey -> Stanza -> IO () 211 xmppPeerInformSubscription :: IO () -> ConnectionKey -> Stanza -> IO ()
@@ -220,14 +221,14 @@ enableClientHacks "Pidgin" version replyto = do
220 wlog "Enabling hack SimulatedChatErrors for client Pidgin" 221 wlog "Enabling hack SimulatedChatErrors for client Pidgin"
221 donevar <- atomically newEmptyTMVar 222 donevar <- atomically newEmptyTMVar
222 sendReply donevar 223 sendReply donevar
223 (InternalEnableHack SimulatedChatErrors) 224 (InternalEnableHack SimulatedChatErrors)
224 [] 225 []
225 replyto 226 replyto
226enableClientHacks "irssi-xmpp" version replyto = do 227enableClientHacks "irssi-xmpp" version replyto = do
227 wlog "Enabling hack SimulatedChatErrors for client irssi-xmpp" 228 wlog "Enabling hack SimulatedChatErrors for client irssi-xmpp"
228 donevar <- atomically newEmptyTMVar 229 donevar <- atomically newEmptyTMVar
229 sendReply donevar 230 sendReply donevar
230 (InternalEnableHack SimulatedChatErrors) 231 (InternalEnableHack SimulatedChatErrors)
231 [] 232 []
232 replyto 233 replyto
233enableClientHacks _ _ _ = return () 234enableClientHacks _ _ _ = return ()
@@ -240,7 +241,7 @@ cacheMessageId id' replyto = do
240 (InternalCacheId id') 241 (InternalCacheId id')
241 [] 242 []
242 replyto 243 replyto
243 244
244 245
245-- TODO: http://xmpp.org/rfcs/rfc6120.html#rules-remote-error 246-- TODO: http://xmpp.org/rfcs/rfc6120.html#rules-remote-error
246-- client connection 247-- client connection
@@ -318,7 +319,7 @@ copyToChannel
318 (Event -> a) -> LockedChan a -> TVar (Maybe [Event]) -> ConduitM Event Event m () 319 (Event -> a) -> LockedChan a -> TVar (Maybe [Event]) -> ConduitM Event Event m ()
319copyToChannel f chan closer_stack = awaitForever copy 320copyToChannel f chan closer_stack = awaitForever copy
320 where 321 where
321 copy x = do 322 copy x = do
322 liftIO . atomically $ writeLChan chan (f x) 323 liftIO . atomically $ writeLChan chan (f x)
323 case x of 324 case x of
324 EventBeginDocument {} -> do 325 EventBeginDocument {} -> do
@@ -333,9 +334,9 @@ copyToChannel f chan closer_stack = awaitForever copy
333 334
334 335
335prettyPrint :: ByteString -> ConduitM Event Void IO () 336prettyPrint :: ByteString -> ConduitM Event Void IO ()
336prettyPrint prefix = 337prettyPrint prefix =
337 XML.renderBytes (XML.def { XML.rsPretty=True }) 338 XML.renderBytes (XML.def { XML.rsPretty=True })
338 =$= CB.lines 339 =$= CB.lines
339 =$ CL.mapM_ (wlogb . (prefix <>)) 340 =$ CL.mapM_ (wlogb . (prefix <>))
340 341
341swapNamespace :: Monad m => Text -> Text -> ConduitM Event Event m () 342swapNamespace :: Monad m => Text -> Text -> ConduitM Event Event m ()
@@ -534,7 +535,7 @@ stanzaFromList stype reply = do
534 535
535grokStanzaIQGet :: Monad m => XML.Event -> NestingXML o m (Maybe StanzaType) 536grokStanzaIQGet :: Monad m => XML.Event -> NestingXML o m (Maybe StanzaType)
536grokStanzaIQGet stanza = do 537grokStanzaIQGet stanza = do
537 mtag <- nextElement 538 mtag <- nextElement
538 flip (maybe $ return Nothing) mtag $ \tag -> do 539 flip (maybe $ return Nothing) mtag $ \tag -> do
539 case tagName tag of 540 case tagName tag of
540 "{urn:xmpp:ping}ping" -> return $ Just Ping 541 "{urn:xmpp:ping}ping" -> return $ Just Ping
@@ -564,7 +565,7 @@ parseClientVersion = parseit Nothing Nothing
564 565
565grokStanzaIQResult :: XML.Event -> NestingXML o IO (Maybe StanzaType) 566grokStanzaIQResult :: XML.Event -> NestingXML o IO (Maybe StanzaType)
566grokStanzaIQResult stanza = do 567grokStanzaIQResult stanza = do
567 mtag <- nextElement 568 mtag <- nextElement
568 flip (maybe $ return (Just Pong)) mtag $ \tag -> do 569 flip (maybe $ return (Just Pong)) mtag $ \tag -> do
569 case tagName tag of 570 case tagName tag of
570 "{jabber:iq:version}query" | nameNamespace (tagName stanza)==Just "jabber:client" 571 "{jabber:iq:version}query" | nameNamespace (tagName stanza)==Just "jabber:client"
@@ -573,7 +574,7 @@ grokStanzaIQResult stanza = do
573 574
574grokStanzaIQSet :: XML.Event -> NestingXML o IO (Maybe StanzaType) 575grokStanzaIQSet :: XML.Event -> NestingXML o IO (Maybe StanzaType)
575grokStanzaIQSet stanza = do 576grokStanzaIQSet stanza = do
576 mtag <- nextElement 577 mtag <- nextElement
577 flip (maybe $ return Nothing) mtag $ \tag -> do 578 flip (maybe $ return Nothing) mtag $ \tag -> do
578 case tagName tag of 579 case tagName tag of
579 "{urn:ietf:params:xml:ns:xmpp-bind}bind" -> do 580 "{urn:ietf:params:xml:ns:xmpp-bind}bind" -> do
@@ -689,7 +690,7 @@ parseMessage ns stanza = do
689 parseChildren (th,cmap) = do 690 parseChildren (th,cmap) = do
690 child <- nextElement 691 child <- nextElement
691 lvl <- nesting 692 lvl <- nesting
692 xmllang <- xmlLang 693 xmllang <- xmlLang
693 let lang = maybe "" id xmllang 694 let lang = maybe "" id xmllang
694 let c = maybe emptyMsg id (Map.lookup lang cmap) 695 let c = maybe emptyMsg id (Map.lookup lang cmap)
695 -- log $ " child: "<> bshow child 696 -- log $ " child: "<> bshow child
@@ -719,7 +720,7 @@ parseMessage ns stanza = do
719 Nothing -> return (th,cmap) 720 Nothing -> return (th,cmap)
720 (th,langmap) <- parseChildren ( MessageThread {msgThreadParent=Nothing, msgThreadContent=""} 721 (th,langmap) <- parseChildren ( MessageThread {msgThreadParent=Nothing, msgThreadContent=""}
721 , Map.empty ) 722 , Map.empty )
722 return Message { 723 return Message {
723 msgLangMap = Map.toList langmap, 724 msgLangMap = Map.toList langmap,
724 msgThread = if msgThreadContent th/="" then Just th else Nothing 725 msgThread = if msgThreadContent th/="" then Just th else Nothing
725 } 726 }
@@ -772,7 +773,7 @@ grokMessage ns stanzaTag = do
772 773
773grokStanza 774grokStanza
774 :: Text -> XML.Event -> NestingXML o IO (Maybe StanzaType) 775 :: Text -> XML.Event -> NestingXML o IO (Maybe StanzaType)
775grokStanza "jabber:server" stanzaTag = 776grokStanza "jabber:server" stanzaTag =
776 case () of 777 case () of
777 _ | stanzaTag `isServerIQOf` "get" -> grokStanzaIQGet stanzaTag 778 _ | stanzaTag `isServerIQOf` "get" -> grokStanzaIQGet stanzaTag
778 _ | stanzaTag `isServerIQOf` "result" -> grokStanzaIQResult stanzaTag 779 _ | stanzaTag `isServerIQOf` "result" -> grokStanzaIQResult stanzaTag
@@ -780,7 +781,7 @@ grokStanza "jabber:server" stanzaTag =
780 _ | tagName stanzaTag == "{jabber:server}message" -> grokMessage "jabber:server" stanzaTag 781 _ | tagName stanzaTag == "{jabber:server}message" -> grokMessage "jabber:server" stanzaTag
781 _ -> return $ Just Unrecognized 782 _ -> return $ Just Unrecognized
782 783
783grokStanza "jabber:client" stanzaTag = 784grokStanza "jabber:client" stanzaTag =
784 case () of 785 case () of
785 _ | stanzaTag `isClientIQOf` "get" -> grokStanzaIQGet stanzaTag 786 _ | stanzaTag `isClientIQOf` "get" -> grokStanzaIQGet stanzaTag
786 _ | stanzaTag `isClientIQOf` "set" -> grokStanzaIQSet stanzaTag 787 _ | stanzaTag `isClientIQOf` "set" -> grokStanzaIQSet stanzaTag
@@ -812,7 +813,7 @@ makeMessage namespace from to bod =
812 , msgSubject = Nothing } 813 , msgSubject = Nothing }
813 814
814makeInformSubscription :: Text -> Text -> Text -> Bool -> IO Stanza 815makeInformSubscription :: Text -> Text -> Text -> Bool -> IO Stanza
815makeInformSubscription namespace from to approved = 816makeInformSubscription namespace from to approved =
816 stanzaFromList (PresenceInformSubscription approved) 817 stanzaFromList (PresenceInformSubscription approved)
817 $ [ EventBeginElement (mkname namespace "presence") 818 $ [ EventBeginElement (mkname namespace "presence")
818 [ attr "from" from 819 [ attr "from" from
@@ -843,16 +844,16 @@ makePresenceStanza namespace mjid pstat = do
843 shw Away = ["away"] 844 shw Away = ["away"]
844 shw DoNotDisturb = ["dnd"] 845 shw DoNotDisturb = ["dnd"]
845 shw _ = [] 846 shw _ = []
846 jabberShow stat = 847 jabberShow stat =
847 [ EventBeginElement "{jabber:client}show" [] 848 [ EventBeginElement "{jabber:client}show" []
848 , EventContent (ContentText stat) 849 , EventContent (ContentText stat)
849 , EventEndElement "{jabber:client}show" ] 850 , EventEndElement "{jabber:client}show" ]
850 851
851makeRosterUpdate :: Text -> Text -> [(Name, Text)] -> IO Stanza 852makeRosterUpdate :: Text -> Text -> [(Name, Text)] -> IO Stanza
852makeRosterUpdate tojid contact as = do 853makeRosterUpdate tojid contact as = do
853 let attrs = map (uncurry attr) as 854 let attrs = map (uncurry attr) as
854 stanzaFromList Unrecognized 855 stanzaFromList Unrecognized
855 [ EventBeginElement "{jabber:client}iq" 856 [ EventBeginElement "{jabber:client}iq"
856 [ attr "to" tojid 857 [ attr "to" tojid
857 , attr "id" "someid" 858 , attr "id" "someid"
858 , attr "type" "set" 859 , attr "type" "set"
@@ -932,7 +933,7 @@ xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do
932 } 933 }
933 ioWriteChan stanzas s 934 ioWriteChan stanzas s
934 you <- liftIO tellyourname 935 you <- liftIO tellyourname
935 flip (maybe $ unrecog) dispatch $ \dispatch -> 936 flip (maybe $ unrecog) dispatch $ \dispatch ->
936 case dispatch of 937 case dispatch of
937 -- Checking that the to-address matches this server. 938 -- Checking that the to-address matches this server.
938 -- Otherwise it could be a client-to-client ping or a 939 -- Otherwise it could be a client-to-client ping or a
@@ -969,7 +970,7 @@ xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do
969 awaitCloser stanza_lvl 970 awaitCloser stanza_lvl
970 liftIO . atomically $ writeTVar clsrs Nothing 971 liftIO . atomically $ writeTVar clsrs Nothing
971 loop 972 loop
972 973
973 974
974while :: IO Bool -> IO a -> IO [a] 975while :: IO Bool -> IO a -> IO [a]
975while cond body = do 976while cond body = do
@@ -1033,7 +1034,7 @@ data XMPPState
1033 deriving (Eq,Ord) 1034 deriving (Eq,Ord)
1034 1035
1035makePing :: Text -> Maybe Text -> Text -> Text -> [XML.Event] 1036makePing :: Text -> Maybe Text -> Text -> Text -> [XML.Event]
1036makePing namespace mid to from = 1037makePing namespace mid to from =
1037 [ EventBeginElement (mkname namespace "iq") 1038 [ EventBeginElement (mkname namespace "iq")
1038 $ (case mid of 1039 $ (case mid of
1039 Just c -> (("id",[ContentText c]):) 1040 Just c -> (("id",[ContentText c]):)
@@ -1073,7 +1074,7 @@ iq_bind_reply mid jid =
1073iq_session_reply :: Maybe Text -> Text -> [XML.Event] 1074iq_session_reply :: Maybe Text -> Text -> [XML.Event]
1074iq_session_reply mid host = 1075iq_session_reply mid host =
1075 -- Note: similar to Pong 1076 -- Note: similar to Pong
1076 [ EventBeginElement "{jabber:client}iq" 1077 [ EventBeginElement "{jabber:client}iq"
1077 (consid mid [("from",[ContentText host]) 1078 (consid mid [("from",[ContentText host])
1078 ,("type",[ContentText "result"]) 1079 ,("type",[ContentText "result"])
1079 ]) 1080 ])
@@ -1082,12 +1083,12 @@ iq_session_reply mid host =
1082 1083
1083iq_service_unavailable :: Maybe Text -> Text -> XML.Name -> [XML.Event] 1084iq_service_unavailable :: Maybe Text -> Text -> XML.Name -> [XML.Event]
1084iq_service_unavailable mid host {- mjid -} req = 1085iq_service_unavailable mid host {- mjid -} req =
1085 [ EventBeginElement "{jabber:client}iq" 1086 [ EventBeginElement "{jabber:client}iq"
1086 (consid mid [attr "type" "error" 1087 (consid mid [attr "type" "error"
1087 ,attr "from" host]) 1088 ,attr "from" host])
1088 , EventBeginElement req [] 1089 , EventBeginElement req []
1089 , EventEndElement req 1090 , EventEndElement req
1090 , EventBeginElement "{jabber:client}error" 1091 , EventBeginElement "{jabber:client}error"
1091 [ attr "type" "cancel" 1092 [ attr "type" "cancel"
1092 , attr "code" "503" ] 1093 , attr "code" "503" ]
1093 , EventBeginElement "{urn:ietf:params:xml:ns:xmpp-stanzas}service-unavailable" [] 1094 , EventBeginElement "{urn:ietf:params:xml:ns:xmpp-stanzas}service-unavailable" []
@@ -1139,7 +1140,7 @@ greet namespace =
1139-} 1140-}
1140 1141
1141goodbye :: [XML.Event] 1142goodbye :: [XML.Event]
1142goodbye = 1143goodbye =
1143 [ EventEndElement (streamP "stream") 1144 [ EventEndElement (streamP "stream")
1144 , EventEndDocument 1145 , EventEndDocument
1145 ] 1146 ]
@@ -1274,7 +1275,7 @@ forkConnection sv xmpp k laddr pingflag src snk stanzas = do
1274 -- TODO: Probably some stanzas should be queued or saved for re-connect. 1275 -- TODO: Probably some stanzas should be queued or saved for re-connect.
1275 mapM_ fail $ filter notError (maybeToList last ++ es') 1276 mapM_ fail $ filter notError (maybeToList last ++ es')
1276 wlog $ "end post-queue fork: " ++ show k 1277 wlog $ "end post-queue fork: " ++ show k
1277 1278
1278 output <- atomically newTChan 1279 output <- atomically newTChan
1279 hacks <- atomically $ newTVar Map.empty 1280 hacks <- atomically $ newTVar Map.empty
1280 msgids <- atomically $ newTVar [] 1281 msgids <- atomically $ newTVar []
@@ -1376,8 +1377,8 @@ data PeerState
1376peerKey :: SocketLike sock => sock -> IO (ConnectionKey,SockAddr) 1377peerKey :: SocketLike sock => sock -> IO (ConnectionKey,SockAddr)
1377peerKey sock = do 1378peerKey sock = do
1378 addr <- getSocketName sock 1379 addr <- getSocketName sock
1379 peer <- 1380 peer <-
1380 sIsConnected sock >>= \c -> 1381 sIsConnected sock >>= \c ->
1381 if c then getPeerName sock -- addr is normally socketName 1382 if c then getPeerName sock -- addr is normally socketName
1382 else return addr -- Weird hack: addr is would-be peer name 1383 else return addr -- Weird hack: addr is would-be peer name
1383 laddr <- getSocketName sock 1384 laddr <- getSocketName sock
@@ -1390,12 +1391,12 @@ clientKey sock = do
1390 return $ (ClientKey addr,paddr) 1391 return $ (ClientKey addr,paddr)
1391 1392
1392xmlifyRosterItems :: Monad m => Set Text -> Text -> Set Text -> ConduitM i Event m () 1393xmlifyRosterItems :: Monad m => Set Text -> Text -> Set Text -> ConduitM i Event m ()
1393xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set) 1394xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set)
1394 where 1395 where
1395 item jid = do yield $ EventBeginElement "{jabber:iq:roster}item" 1396 item jid = do yield $ EventBeginElement "{jabber:iq:roster}item"
1396 ([ attr "jid" jid 1397 ([ attr "jid" jid
1397 , attr "subscription" stype 1398 , attr "subscription" stype
1398 ]++if Set.member jid solicited 1399 ]++if Set.member jid solicited
1399 then [attr "ask" "subscribe"] 1400 then [attr "ask" "subscribe"]
1400 else [] ) 1401 else [] )
1401 yield $ EventEndElement "{jabber:iq:roster}item" 1402 yield $ EventEndElement "{jabber:iq:roster}item"
@@ -1430,7 +1431,7 @@ sendRoster query xmpp replyto = do
1430 (consid (stanzaId query) 1431 (consid (stanzaId query)
1431 [ attr "to" jid 1432 [ attr "to" jid
1432 , attr "type" "result" ]) 1433 , attr "type" "result" ])
1433 yield $ EventBeginElement "{jabber:iq:roster}query" [] -- todo: ver? 1434 yield $ EventBeginElement "{jabber:iq:roster}query" [] -- todo: ver?
1434 xmlifyRosterItems solicited "to" subto 1435 xmlifyRosterItems solicited "to" subto
1435 xmlifyRosterItems solicited "from" subfrom 1436 xmlifyRosterItems solicited "from" subfrom
1436 xmlifyRosterItems solicited "both" subboth 1437 xmlifyRosterItems solicited "both" subboth
@@ -1462,7 +1463,7 @@ socketFromKey sv k = do
1462 case mcd of 1463 case mcd of
1463 Nothing -> case k of 1464 Nothing -> case k of
1464 ClientKey addr -> return addr 1465 ClientKey addr -> return addr
1465 PeerKey addr -> return addr 1466 PeerKey addr -> return addr
1466 -- XXX: ? wrong address 1467 -- XXX: ? wrong address
1467 -- Shouldnt happen anyway. 1468 -- Shouldnt happen anyway.
1468 Just cd -> return $ cdata cd 1469 Just cd -> return $ cdata cd
@@ -1533,7 +1534,7 @@ xep0086 e =
1533 UnexpectedRequest -> ("wait", 400) 1534 UnexpectedRequest -> ("wait", 400)
1534 1535
1535errorText :: StanzaError -> Text 1536errorText :: StanzaError -> Text
1536errorText e = 1537errorText e =
1537 case e of 1538 case e of
1538 BadRequest -> "Bad request" 1539 BadRequest -> "Bad request"
1539 Conflict -> "Conflict" 1540 Conflict -> "Conflict"
@@ -1635,7 +1636,7 @@ monitor sv params xmpp = do
1635 quitVar <- atomically newEmptyTMVar 1636 quitVar <- atomically newEmptyTMVar
1636 fix $ \loop -> do 1637 fix $ \loop -> do
1637 action <- atomically $ foldr1 orElse 1638 action <- atomically $ foldr1 orElse
1638 [ readTChan chan >>= \((k,u),e) -> return $ do 1639 [ readTChan chan >>= \((k,u),e) -> return $ do
1639 case e of 1640 case e of
1640 Connection pingflag xsrc xsnk -> do 1641 Connection pingflag xsrc xsnk -> do
1641 wlog $ tomsg k "Connection" 1642 wlog $ tomsg k "Connection"
@@ -1665,7 +1666,7 @@ monitor sv params xmpp = do
1665 1666
1666 forkIO $ do 1667 forkIO $ do
1667 case stanzaOrigin stanza of 1668 case stanzaOrigin stanza of
1668 NetworkOrigin k@(ClientKey {}) replyto -> 1669 NetworkOrigin k@(ClientKey {}) replyto ->
1669 case stanzaType stanza of 1670 case stanzaType stanza of
1670 RequestResource wanted -> do 1671 RequestResource wanted -> do
1671 sockaddr <- socketFromKey sv k 1672 sockaddr <- socketFromKey sv k
@@ -1676,7 +1677,7 @@ monitor sv params xmpp = do
1676 let requestVersion :: Producer IO XML.Event 1677 let requestVersion :: Producer IO XML.Event
1677 requestVersion = do 1678 requestVersion = do
1678 yield $ EventBeginElement "{jabber:client}iq" 1679 yield $ EventBeginElement "{jabber:client}iq"
1679 [ attr "to" rsc 1680 [ attr "to" rsc
1680 , attr "from" hostname 1681 , attr "from" hostname
1681 , attr "type" "get" 1682 , attr "type" "get"
1682 , attr "id" "version"] 1683 , attr "id" "version"]
@@ -1780,7 +1781,7 @@ monitor sv params xmpp = do
1780 NetworkOrigin (PeerKey {}) _ -> "P" 1781 NetworkOrigin (PeerKey {}) _ -> "P"
1781 wlog "" 1782 wlog ""
1782 stanzaToConduit dup $$ prettyPrint typ 1783 stanzaToConduit dup $$ prettyPrint typ
1783 1784
1784 ] 1785 ]
1785 action 1786 action
1786 loop 1787 loop
@@ -1794,9 +1795,14 @@ data XMPPServer
1794 , _xmpp_peer_params :: ConnectionParameters ConnectionKey SockAddr 1795 , _xmpp_peer_params :: ConnectionParameters ConnectionKey SockAddr
1795 } 1796 }
1796 1797
1797addPeer :: XMPPServer -> SockAddr -> IO () 1798grokPeer :: XMPPServer -> ConnectionKey -> (SockAddr, ConnectionParameters ConnectionKey SockAddr, Miliseconds)
1798addPeer sv addr = do 1799grokPeer sv (PeerKey addr) = (addr, _xmpp_peer_params sv, 10000)
1799 control (_xmpp_sv sv) (ConnectWithEndlessRetry addr (_xmpp_peer_params sv) 10000) 1800
1801xmppConnections :: XMPPServer -> Connection.Manager TCPStatus ConnectionKey
1802xmppConnections sv = tcpManager (grokPeer sv) resolvPeer (_xmpp_sv sv)
1803 where
1804 resolvPeer :: String -> IO (Maybe ConnectionKey)
1805 resolvPeer str = fmap PeerKey <$> listToMaybe <$> resolvePeer (Text.pack str)
1800 1806
1801xmppServer :: ( MonadResource m 1807xmppServer :: ( MonadResource m
1802 , MonadIO m 1808 , MonadIO m