summaryrefslogtreecommitdiff
path: root/Presence/XMPPServer.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2018-06-24 02:27:18 -0400
committerjoe <joe@jerkface.net>2018-06-24 03:10:43 -0400
commit55db1198b3da0c706f2b9f1ed9c8fd11fc4ae552 (patch)
treede035195ed188f8611da54e6e339d9124d2a5b3f /Presence/XMPPServer.hs
parent3054de811f4ae7659dfc4dc338aab2c3d11b5c27 (diff)
XMPP: Type-checking on various uses of SockAddr.
Diffstat (limited to 'Presence/XMPPServer.hs')
-rw-r--r--Presence/XMPPServer.hs285
1 files changed, 153 insertions, 132 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index 8d294698..1de6a26a 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -7,11 +7,17 @@
7module XMPPServer 7module XMPPServer
8 ( xmppServer 8 ( xmppServer
9 , quitXmpp 9 , quitXmpp
10 , ConnectionKey(..) 10 , ClientAddress
11 , PeerAddress
12 , Local(..)
13 , Remote(..)
11 , ConnectionData(..) 14 , ConnectionData(..)
12 , ConnectionType(..) 15 , ConnectionType(..)
13 , XMPPServerParameters(..) 16 , XMPPServerParameters(..)
14 , XMPPServer 17 , XMPPServer
18 , classifyConnection
19 , addrToPeerKey
20 , addrFromClientKey
15 , xmppConnections 21 , xmppConnections
16 , xmppEventChannel 22 , xmppEventChannel
17 , StanzaWrap(..) 23 , StanzaWrap(..)
@@ -85,7 +91,7 @@ import Data.XML.Types as XML
85import Data.Maybe 91import Data.Maybe
86import Data.Monoid ( (<>) ) 92import Data.Monoid ( (<>) )
87import Data.Text (Text) 93import Data.Text (Text)
88import qualified Data.Text as Text (pack,unpack,words,intercalate) 94import qualified Data.Text as Text (pack,unpack,words,intercalate,drop)
89import Data.Char (chr,ord) 95import Data.Char (chr,ord)
90import qualified Data.Map as Map 96import qualified Data.Map as Map
91import Data.Set (Set, (\\) ) 97import Data.Set (Set, (\\) )
@@ -167,7 +173,10 @@ data StanzaType
167 | InternalCacheId Text 173 | InternalCacheId Text
168 deriving (Show,Eq) 174 deriving (Show,Eq)
169 175
170data StanzaOrigin = LocalPeer | NetworkOrigin ConnectionKey (TChan Stanza) 176data StanzaOrigin = LocalPeer
177 | PeerOrigin PeerAddress (TChan Stanza)
178 | ClientOrigin ClientAddress (TChan Stanza)
179
171 180
172data StanzaWrap a = Stanza 181data StanzaWrap a = Stanza
173 { stanzaType :: StanzaType 182 { stanzaType :: StanzaType
@@ -182,6 +191,9 @@ data StanzaWrap a = Stanza
182 191
183type Stanza = StanzaWrap (LockedChan XML.Event) 192type Stanza = StanzaWrap (LockedChan XML.Event)
184 193
194newtype Local a = Local a deriving (Eq,Ord,Show)
195newtype Remote a = Remote a deriving (Eq,Ord,Show)
196
185data XMPPServerParameters = 197data XMPPServerParameters =
186 XMPPServerParameters 198 XMPPServerParameters
187 { -- | Called when a client requests a resource id. The first Maybe indicates 199 { -- | Called when a client requests a resource id. The first Maybe indicates
@@ -190,36 +202,35 @@ data XMPPServerParameters =
190 -- 202 --
191 -- Note: The returned domain will be discarded and replaced with the result of 203 -- Note: The returned domain will be discarded and replaced with the result of
192 -- 'xmppTellMyNameToClient'. 204 -- 'xmppTellMyNameToClient'.
193 xmppChooseResourceName :: ConnectionKey -> SockAddr -> Maybe Text -> Maybe Text -> IO Text 205 xmppChooseResourceName :: ClientAddress -> Remote SockAddr -> Maybe Text -> Maybe Text -> IO Text
194 , -- | This should indicate the server's hostname that all client's see. 206 , -- | This should indicate the server's hostname that all client's see.
195 xmppTellMyNameToClient :: ConnectionKey -> IO Text 207 xmppTellMyNameToClient :: ClientAddress -> IO Text
196 , xmppTellMyNameToPeer :: SockAddr -> IO Text 208 , xmppTellMyNameToPeer :: Local SockAddr -> IO Text
197 , xmppTellClientHisName :: ConnectionKey -> IO Text 209 , xmppTellClientHisName :: ClientAddress -> IO Text
198 , xmppTellPeerHisName :: ConnectionKey -> IO Text 210 , xmppTellPeerHisName :: PeerAddress -> IO Text
199 , xmppNewConnection :: ConnectionKey -> ConnectionData -> TChan Stanza -> IO () 211 , xmppNewConnection :: SockAddr -> ConnectionData -> TChan Stanza -> IO ()
200 , xmppEOF :: ConnectionKey -> IO () 212 , xmppEOF :: SockAddr -> ConnectionData -> IO ()
201 , xmppRosterBuddies :: ConnectionKey -> IO [Text] 213 , xmppRosterBuddies :: ClientAddress -> IO [Text]
202 , xmppRosterSubscribers :: ConnectionKey -> IO [Text] 214 , xmppRosterSubscribers :: ClientAddress -> IO [Text]
203 , xmppRosterSolicited :: ConnectionKey -> IO [Text] 215 , xmppRosterSolicited :: ClientAddress -> IO [Text]
204 , xmppRosterOthers :: ConnectionKey -> IO [Text] 216 , xmppRosterOthers :: ClientAddress -> IO [Text]
205 , -- | Called when after sending a roster to a client. Usually this means 217 , -- | Called when after sending a roster to a client. Usually this means
206 -- the client status should change from "available" to "interested". 218 -- the client status should change from "available" to "interested".
207 xmppSubscribeToRoster :: ConnectionKey -> IO () 219 xmppSubscribeToRoster :: ClientAddress -> IO ()
208 -- , xmppLookupClientJID :: ConnectionKey -> IO Text 220 -- , xmppLookupClientJID :: SockAddr -> IO Text
209 , xmppTellClientNameOfPeer :: ConnectionKey -> [Text] -> IO Text
210 , xmppDeliverMessage :: (IO ()) -> Stanza -> IO () 221 , xmppDeliverMessage :: (IO ()) -> Stanza -> IO ()
211 -- | Called whenever a local client's presence changes. 222 -- | Called whenever a local client's presence changes.
212 , xmppInformClientPresence :: ConnectionKey -> Stanza -> IO () 223 , xmppInformClientPresence :: ClientAddress -> Stanza -> IO ()
213 -- | Called whenever a remote peer's presence changes. 224 -- | Called whenever a remote peer's presence changes.
214 , xmppInformPeerPresence :: ConnectionKey -> Stanza -> IO () 225 , xmppInformPeerPresence :: PeerAddress -> Stanza -> IO ()
215 , -- | Called when a remote peer requests our status. 226 , -- | Called when a remote peer requests our status.
216 xmppAnswerProbe :: ConnectionKey -> Stanza -> TChan Stanza -> IO () 227 xmppAnswerProbe :: PeerAddress -> Stanza -> TChan Stanza -> IO ()
217 , xmppClientSubscriptionRequest :: IO () -> ConnectionKey -> Stanza -> TChan Stanza -> IO () 228 , xmppClientSubscriptionRequest :: IO () -> ClientAddress -> Stanza -> TChan Stanza -> IO ()
218 , -- | Called when a remote peer sends subscription request. 229 , -- | Called when a remote peer sends subscription request.
219 xmppPeerSubscriptionRequest :: IO () -> ConnectionKey -> Stanza -> TChan Stanza -> IO () 230 xmppPeerSubscriptionRequest :: IO () -> PeerAddress -> Stanza -> TChan Stanza -> IO ()
220 , xmppClientInformSubscription :: IO () -> ConnectionKey -> Stanza -> IO () 231 , xmppClientInformSubscription :: IO () -> ClientAddress -> Stanza -> IO ()
221 , -- | Called when a remote peer informs us of our subscription status. 232 , -- | Called when a remote peer informs us of our subscription status.
222 xmppPeerInformSubscription :: IO () -> ConnectionKey -> Stanza -> IO () 233 xmppPeerInformSubscription :: IO () -> PeerAddress -> Stanza -> IO ()
223 , xmppVerbosity :: IO Int 234 , xmppVerbosity :: IO Int
224 , xmppClientBind :: Maybe SockAddr 235 , xmppClientBind :: Maybe SockAddr
225 , xmppPeerBind :: Maybe SockAddr 236 , xmppPeerBind :: Maybe SockAddr
@@ -270,10 +281,9 @@ addrToText (addr@(SockAddrInet6 _ _ _ _)) = Text.pack $ stripColon (show addr)
270 where 281 where
271 (pre,bracket) = break (==']') s 282 (pre,bracket) = break (==']') s
272 283
273-- Shows (as Text) the IP address associated with the given ConnectionKey. 284-- Shows (as Text) the IP address associated with the given SockAddr.
274peerKeyToText :: ConnectionKey -> Text 285peerKeyToText :: PeerAddress -> Text
275peerKeyToText (PeerKey { callBackAddress=addr }) = addrToText addr 286peerKeyToText (PeerAddress addr) = addrToText addr
276peerKeyToText (ClientKey { localAddress=addr }) = "ErrorClIeNt0"
277 287
278 288
279wlog :: String -> IO () 289wlog :: String -> IO ()
@@ -895,26 +905,17 @@ makePong namespace mid to from =
895 , EventEndElement (mkname namespace "iq") 905 , EventEndElement (mkname namespace "iq")
896 ] 906 ]
897 907
908data ClientOrPeer = IsClient | IsPeer
898 909
899xmppInbound :: Server ConnectionKey ConnectionData releaseKey XML.Event 910xmppInbound :: Server SockAddr ConnectionData releaseKey XML.Event -- ^ XXX: unused
900 -> XMPPServerParameters 911 -> XMPPServerParameters -- ^ XXX: unused
901 -> ConnectionKey 912 -> (Text, IO Text, IO Text, TChan Stanza -> StanzaOrigin)
902 -> SockAddr 913 -> FlagCommand -- ^ action to check whether the connection needs a ping (XXX: unused)
903 -> FlagCommand -- ^ action to check whether the connection needs a ping
904 -> TChan Stanza -- ^ channel to announce incoming stanzas on 914 -> TChan Stanza -- ^ channel to announce incoming stanzas on
905 -> TChan Stanza -- ^ channel used to send stanzas 915 -> TChan Stanza -- ^ channel used to send stanzas
906 -> TMVar () -- ^ mvar that is filled when the connection quits 916 -> TMVar () -- ^ mvar that is filled when the connection quits
907 -> Sink XML.Event IO () 917 -> ConduitM Event o IO ()
908xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do 918xmppInbound sv xmpp (namespace,tellmyname,tellyourname,mkorigin) pingflag stanzas output donevar = doNestingXML $ do
909 let (namespace,tellmyname,tellyourname) = case k of
910 ClientKey {} -> ( "jabber:client"
911 , xmppTellMyNameToClient xmpp k
912 , xmppTellClientHisName xmpp k
913 )
914 PeerKey {} -> ( "jabber:server"
915 , xmppTellMyNameToPeer xmpp laddr
916 , xmppTellPeerHisName xmpp k
917 )
918 me <- liftIO tellmyname 919 me <- liftIO tellmyname
919 withXML $ \begindoc -> do 920 withXML $ \begindoc -> do
920 when (begindoc==EventBeginDocument) $ do 921 when (begindoc==EventBeginDocument) $ do
@@ -948,7 +949,7 @@ xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do
948 , stanzaChan = chan 949 , stanzaChan = chan
949 , stanzaClosers = clsrs 950 , stanzaClosers = clsrs
950 , stanzaInterrupt = donevar 951 , stanzaInterrupt = donevar
951 , stanzaOrigin = NetworkOrigin k output 952 , stanzaOrigin = mkorigin output
952 } 953 }
953 ioWriteChan stanzas s 954 ioWriteChan stanzas s
954 you <- liftIO tellyourname 955 you <- liftIO tellyourname
@@ -973,7 +974,7 @@ xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do
973 , stanzaChan = chan 974 , stanzaChan = chan
974 , stanzaClosers = clsrs 975 , stanzaClosers = clsrs
975 , stanzaInterrupt = donevar 976 , stanzaInterrupt = donevar
976 , stanzaOrigin = NetworkOrigin k output 977 , stanzaOrigin = mkorigin output
977 } 978 }
978#endif 979#endif
979 stype -> ioWriteChan stanzas Stanza 980 stype -> ioWriteChan stanzas Stanza
@@ -986,7 +987,7 @@ xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do
986 , stanzaChan = chan 987 , stanzaChan = chan
987 , stanzaClosers = clsrs 988 , stanzaClosers = clsrs
988 , stanzaInterrupt = donevar 989 , stanzaInterrupt = donevar
989 , stanzaOrigin = NetworkOrigin k output 990 , stanzaOrigin = mkorigin output
990 } 991 }
991 awaitCloser stanza_lvl 992 awaitCloser stanza_lvl
992 liftIO . atomically $ writeTVar clsrs Nothing 993 liftIO . atomically $ writeTVar clsrs Nothing
@@ -1244,19 +1245,23 @@ slotsToSource slots nesting lastStanza needsFlush rdone =
1244 ,readTMVar rdone >> return (return ()) 1245 ,readTMVar rdone >> return (return ())
1245 ] 1246 ]
1246 1247
1247forkConnection :: Server ConnectionKey ConnectionData releaseKey XML.Event 1248forkConnection :: Server SockAddr ConnectionData releaseKey XML.Event
1248 -> XMPPServerParameters 1249 -> XMPPServerParameters
1249 -> ConnectionKey 1250 -> SockAddr -- SockAddr (remote for peer, local for client)
1250 -> ConnectionData 1251 -> ConnectionData
1251 -> FlagCommand 1252 -> FlagCommand
1252 -> Source IO XML.Event 1253 -> Source IO XML.Event
1253 -> Sink (Flush XML.Event) IO () 1254 -> Sink (Flush XML.Event) IO ()
1254 -> TChan Stanza 1255 -> TChan Stanza
1255 -> IO (TChan Stanza) 1256 -> IO (TChan Stanza)
1256forkConnection sv xmpp k (ConnectionData laddr _) pingflag src snk stanzas = do 1257forkConnection sv xmpp saddr (ConnectionData auxAddr _) pingflag src snk stanzas = do
1257 let (namespace,tellmyname) = case k of 1258 let clientOrServer@(namespace,tellmyname,telltheirname,_) = case auxAddr of
1258 ClientKey {} -> ("jabber:client", xmppTellMyNameToClient xmpp k) 1259 Right _ -> ("jabber:client", xmppTellMyNameToClient xmpp (ClientAddress saddr)
1259 PeerKey {} -> ("jabber:server",xmppTellMyNameToPeer xmpp laddr) 1260 , xmppTellClientHisName xmpp (ClientAddress saddr)
1261 , ClientOrigin (ClientAddress saddr))
1262 Left laddr -> ("jabber:server", xmppTellMyNameToPeer xmpp laddr
1263 , xmppTellPeerHisName xmpp (PeerAddress saddr)
1264 , PeerOrigin (PeerAddress saddr))
1260 me <- tellmyname 1265 me <- tellmyname
1261 rdone <- atomically newEmptyTMVar 1266 rdone <- atomically newEmptyTMVar
1262 let isStarter (Left _) = True 1267 let isStarter (Left _) = True
@@ -1274,7 +1279,11 @@ forkConnection sv xmpp k (ConnectionData laddr _) pingflag src snk stanzas = do
1274 CL.sourceList (greet' namespace me) =$= CL.map Chunk 1279 CL.sourceList (greet' namespace me) =$= CL.map Chunk
1275 yield Flush 1280 yield Flush
1276 slot_src = slotsToSource slots nesting lastStanza needsFlush rdone 1281 slot_src = slotsToSource slots nesting lastStanza needsFlush rdone
1277 forkIO $ do myThreadId >>= flip labelThread ("post-queue."++show k) 1282 let lbl n = concat [ n
1283 , Text.unpack (Text.drop 7 namespace)
1284 , "."
1285 , show saddr ]
1286 forkIO $ do myThreadId >>= flip labelThread (lbl "post-queue.")
1278 (greet_src >> slot_src) $$ snk 1287 (greet_src >> slot_src) $$ snk
1279 last <- atomically $ readTVar lastStanza 1288 last <- atomically $ readTVar lastStanza
1280 es <- while (atomically . fmap not $ Slotted.isEmpty slots) 1289 es <- while (atomically . fmap not $ Slotted.isEmpty slots)
@@ -1298,14 +1307,14 @@ forkConnection sv xmpp k (ConnectionData laddr _) pingflag src snk stanzas = do
1298 _ -> True 1307 _ -> True
1299 -- TODO: Probably some stanzas should be queued or saved for re-connect. 1308 -- TODO: Probably some stanzas should be queued or saved for re-connect.
1300 mapM_ fail $ filter notError (maybeToList last ++ es') 1309 mapM_ fail $ filter notError (maybeToList last ++ es')
1301 wlog $ "end post-queue fork: " ++ show k 1310 wlog $ "end post-queue fork: " ++ (lbl "")
1302 1311
1303 output <- atomically newTChan 1312 output <- atomically newTChan
1304 hacks <- atomically $ newTVar Map.empty 1313 hacks <- atomically $ newTVar Map.empty
1305 msgids <- atomically $ newTVar [] 1314 msgids <- atomically $ newTVar []
1306 forkIO $ do 1315 forkIO $ do
1307 -- mapM_ (atomically . Slotted.push slots Nothing) greetPeer 1316 -- mapM_ (atomically . Slotted.push slots Nothing) greetPeer
1308 myThreadId >>= flip labelThread ("pre-queue."++show k) 1317 myThreadId >>= flip labelThread (lbl "pre-queue.")
1309 verbosity <- xmppVerbosity xmpp 1318 verbosity <- xmppVerbosity xmpp
1310 fix $ \loop -> do 1319 fix $ \loop -> do
1311 what <- atomically $ foldr1 orElse 1320 what <- atomically $ foldr1 orElse
@@ -1320,9 +1329,9 @@ forkConnection sv xmpp k (ConnectionData laddr _) pingflag src snk stanzas = do
1320 notping $ do 1329 notping $ do
1321 dup <- cloneStanza stanza 1330 dup <- cloneStanza stanza
1322 let typ = Strict8.pack $ c ++ "<-"++(concat . take 1 . words $ show (stanzaType dup))++" " 1331 let typ = Strict8.pack $ c ++ "<-"++(concat . take 1 . words $ show (stanzaType dup))++" "
1323 c = case k of 1332 c = case auxAddr of
1324 ClientKey {} -> "C" 1333 Right _ -> "C"
1325 PeerKey {} -> "P" 1334 Left _ -> "P"
1326 wlog "" 1335 wlog ""
1327 stanzaToConduit dup $$ prettyPrint typ 1336 stanzaToConduit dup $$ prettyPrint typ
1328 -- wlog $ "hacks: "++show (stanzaId stanza) 1337 -- wlog $ "hacks: "++show (stanzaId stanza)
@@ -1360,7 +1369,7 @@ forkConnection sv xmpp k (ConnectionData laddr _) pingflag src snk stanzas = do
1360 loop 1369 loop
1361 ,do pingflag >>= check 1370 ,do pingflag >>= check
1362 return $ do 1371 return $ do
1363 to <- xmppTellPeerHisName xmpp k -- addrToText (callBackAddress k) 1372 to <- telltheirname
1364 let from = me -- Look it up from Server object 1373 let from = me -- Look it up from Server object
1365 -- or pass it with Connection event. 1374 -- or pass it with Connection event.
1366 mid = Just "ping" 1375 mid = Just "ping"
@@ -1368,23 +1377,21 @@ forkConnection sv xmpp k (ConnectionData laddr _) pingflag src snk stanzas = do
1368 ping <- atomically $ wrapStanzaList ping0 1377 ping <- atomically $ wrapStanzaList ping0
1369 mapM_ (atomically . Slotted.push slots (Just $ PingSlot)) 1378 mapM_ (atomically . Slotted.push slots (Just $ PingSlot))
1370 ping 1379 ping
1371#ifdef PINGNOISE
1372 wlog "" 1380 wlog ""
1373 CL.sourceList ping0 $$ prettyPrint $ case k of 1381 CL.sourceList ping0 $$ prettyPrint $ case auxAddr of
1374 ClientKey {} -> "C<-Ping" 1382 Right _ -> "C<-Ping"
1375 PeerKey {} -> "P<-Ping " 1383 Left _ -> "P<-Ping "
1376#endif
1377 loop 1384 loop
1378 ,readTMVar rdone >> return (return ()) 1385 ,readTMVar rdone >> return (return ())
1379 ] 1386 ]
1380 what 1387 what
1381 wlog $ "end pre-queue fork: " ++ show k 1388 wlog $ "end pre-queue fork: " ++ show (lbl "")
1382 forkIO $ do 1389 forkIO $ do
1383 myThreadId >>= flip labelThread ("reader."++show k) 1390 myThreadId >>= flip labelThread (lbl "reader.")
1384 -- src $$ awaitForever (lift . putStrLn . takeWhile (/=' ') . show) 1391 -- src $$ awaitForever (lift . putStrLn . takeWhile (/=' ') . show)
1385 src $$ xmppInbound sv xmpp k laddr pingflag stanzas output rdone 1392 src $$ xmppInbound sv xmpp clientOrServer pingflag stanzas output rdone
1386 atomically $ putTMVar rdone () 1393 atomically $ putTMVar rdone ()
1387 wlog $ "end reader fork: " ++ show k 1394 wlog $ "end reader fork: " ++ lbl ""
1388 return output 1395 return output
1389 1396
1390{- 1397{-
@@ -1398,22 +1405,22 @@ data PeerState
1398 | PeerConnected (TChan Stanza) 1405 | PeerConnected (TChan Stanza)
1399-} 1406-}
1400 1407
1401peerKey :: SocketLike sock => Maybe SockAddr -> sock -> IO (ConnectionKey,ConnectionData) 1408peerKey :: SocketLike sock => Maybe SockAddr -> sock -> IO (SockAddr,ConnectionData)
1402peerKey outgoingPeerPort sock = do 1409peerKey bind_addr sock = do
1403 addr <- getSocketName sock 1410 laddr <- getSocketName sock
1404 peer <- 1411 raddr <-
1405 sIsConnected sock >>= \c -> 1412 sIsConnected sock >>= \c ->
1406 if c then getPeerName sock -- addr is normally socketName 1413 if c then getPeerName sock -- addr is normally socketName
1407 else return addr -- Weird hack: addr is would-be peer name 1414 else return laddr -- Weird hack: addr is would-be peer name
1408 laddr <- getSocketName sock 1415 -- Assume remote peers are listening on the same port that we do.
1409 let peerport = fromMaybe 5269 $ outgoingPeerPort >>= sockAddrPort 1416 let peerport = fromIntegral $ fromMaybe 5269 $ bind_addr >>= sockAddrPort
1410 return $ (PeerKey (peer `withPort` fromIntegral peerport),ConnectionData laddr XMPP) 1417 return $ (raddr `withPort` peerport,ConnectionData (Left (Local laddr)) XMPP)
1411 1418
1412clientKey :: SocketLike sock => sock -> IO (ConnectionKey,ConnectionData) 1419clientKey :: SocketLike sock => sock -> IO (SockAddr,ConnectionData)
1413clientKey sock = do 1420clientKey sock = do
1414 addr <- getSocketName sock 1421 laddr <- getSocketName sock
1415 paddr <- getPeerName sock 1422 raddr <- getPeerName sock
1416 return $ (ClientKey addr,ConnectionData paddr XMPP) 1423 return $ (laddr,ConnectionData (Right (Remote raddr)) XMPP)
1417 1424
1418xmlifyRosterItems :: Monad m => Set Text -> Text -> Set Text -> ConduitM i Event m () 1425xmlifyRosterItems :: Monad m => Set Text -> Text -> Set Text -> ConduitM i Event m ()
1419xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set) 1426xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set)
@@ -1429,14 +1436,15 @@ xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set)
1429sendRoster :: 1436sendRoster ::
1430 StanzaWrap a 1437 StanzaWrap a
1431 -> XMPPServerParameters 1438 -> XMPPServerParameters
1432 -> ConnectionKey 1439 -> ClientAddress
1433 -> TChan Stanza 1440 -> TChan Stanza
1434 -> IO () 1441 -> IO ()
1435sendRoster query xmpp clientKey replyto = do 1442sendRoster query xmpp clientKey replyto = do
1436 let k = case stanzaOrigin query of 1443 let maddr = case stanzaOrigin query of
1437 NetworkOrigin k _ -> Just k 1444 ClientOrigin addr _ -> Just addr
1438 LocalPeer -> Nothing -- local peer requested roster? 1445 PeerOrigin {} -> Nothing -- remote peer requested roster?
1439 forM_ k $ \k -> do 1446 LocalPeer -> Nothing -- local peer requested roster?
1447 forM_ maddr $ \k -> do
1440 hostname <- xmppTellMyNameToClient xmpp clientKey 1448 hostname <- xmppTellMyNameToClient xmpp clientKey
1441 let getlist f = do 1449 let getlist f = do
1442 bs <- f xmpp k 1450 bs <- f xmpp k
@@ -1445,9 +1453,7 @@ sendRoster query xmpp clientKey replyto = do
1445 subscribers <- getlist xmppRosterSubscribers 1453 subscribers <- getlist xmppRosterSubscribers
1446 solicited <- getlist xmppRosterSolicited 1454 solicited <- getlist xmppRosterSolicited
1447 subnone0 <- getlist xmppRosterOthers 1455 subnone0 <- getlist xmppRosterOthers
1448 jid <- case k of 1456 jid <- xmppTellClientHisName xmpp k -- LookupClientJID xmpp k
1449 ClientKey {} -> xmppTellClientHisName xmpp k -- LookupClientJID xmpp k
1450 PeerKey {} -> xmppTellClientNameOfPeer xmpp k (Set.toList buddies)
1451 let subnone = Set.union solicited subnone0 \\ Set.union buddies subscribers 1457 let subnone = Set.union solicited subnone0 \\ Set.union buddies subscribers
1452 let subto = buddies \\ subscribers 1458 let subto = buddies \\ subscribers
1453 let subfrom = subscribers \\ buddies 1459 let subfrom = subscribers \\ buddies
@@ -1482,17 +1488,14 @@ sendRoster query xmpp clientKey replyto = do
1482 -} 1488 -}
1483 1489
1484 1490
1485socketFromKey :: Server ConnectionKey ConnectionData releaseKey XML.Event -> ConnectionKey -> IO SockAddr 1491socketFromKey :: Server SockAddr ConnectionData releaseKey XML.Event -> ClientAddress -> IO (Remote SockAddr)
1486socketFromKey sv k = do 1492socketFromKey sv (ClientAddress addr) = do
1487 map <- atomically $ readTVar (conmap sv) 1493 map <- atomically $ readTVar (conmap sv)
1488 let mcd = Map.lookup k map 1494 let mcd = Map.lookup addr map
1495 oops = Remote addr -- No connection data, so using incorrect address.
1489 case mcd of 1496 case mcd of
1490 Nothing -> case k of 1497 Nothing -> return oops
1491 ClientKey addr -> return addr 1498 Just cd -> return $ either (const oops) id $ cdAddr $ cdata cd
1492 PeerKey addr -> return addr
1493 -- XXX: ? wrong address
1494 -- Shouldnt happen anyway.
1495 Just cd -> return $ cdAddr $ cdata cd
1496 1499
1497class StanzaFirstTag a where 1500class StanzaFirstTag a where
1498 stanzaFirstTag :: StanzaWrap a -> IO XML.Event 1501 stanzaFirstTag :: StanzaWrap a -> IO XML.Event
@@ -1652,8 +1655,8 @@ makeErrorStanza stanza = do
1652 ] 1655 ]
1653 1656
1654monitor :: 1657monitor ::
1655 Server ConnectionKey ConnectionData releaseKey XML.Event 1658 Server SockAddr ConnectionData releaseKey XML.Event
1656 -> ConnectionParameters ConnectionKey ConnectionData 1659 -> ConnectionParameters SockAddr ConnectionData
1657 -> XMPPServerParameters 1660 -> XMPPServerParameters
1658 -> IO b 1661 -> IO b
1659monitor sv params xmpp = do 1662monitor sv params xmpp = do
@@ -1662,20 +1665,25 @@ monitor sv params xmpp = do
1662 quitVar <- atomically newEmptyTMVar 1665 quitVar <- atomically newEmptyTMVar
1663 fix $ \loop -> do 1666 fix $ \loop -> do
1664 action <- atomically $ foldr1 orElse 1667 action <- atomically $ foldr1 orElse
1665 [ readTChan chan >>= \((k,u),e) -> return $ do 1668 [ readTChan chan >>= \((addr,u),e) -> return $ do
1666 case e of 1669 case e of
1667 Connection pingflag xsrc xsnk -> do 1670 Connection pingflag xsrc xsnk
1668 wlog $ tomsg k "Connection" 1671 -> do wlog $ tomsg addr "Connection"
1669 outs <- forkConnection sv xmpp k u pingflag xsrc xsnk stanzas 1672 outs <- forkConnection sv xmpp addr u pingflag xsrc xsnk stanzas
1670 xmppNewConnection xmpp k u outs 1673 xmppNewConnection xmpp addr u outs
1671 ConnectFailure addr -> return () -- wlog $ tomsg k "ConnectFailure" 1674 ConnectFailure addr
1672 EOF -> do wlog $ tomsg k "EOF" 1675 -> do return () -- wlog $ tomsg k "ConnectFailure"
1673 xmppEOF xmpp k 1676 EOF -> do wlog $ tomsg addr "EOF"
1674 HalfConnection In -> do 1677 xmppEOF xmpp addr u
1675 wlog $ tomsg k "ReadOnly" 1678 HalfConnection In
1676 control sv (Connect (callBackAddress k) params) 1679 -> do wlog $ tomsg addr "ReadOnly"
1677 HalfConnection Out -> wlog $ tomsg k "WriteOnly" 1680 case cdAddr u of
1678 RequiresPing -> return () -- wlog $ tomsg k "RequiresPing" 1681 Left (Local _) -> control sv (Connect addr params)
1682 _ -> return () -- Don't call-back client connections.
1683 HalfConnection Out
1684 -> do wlog $ tomsg addr "WriteOnly"
1685 RequiresPing
1686 -> do return () -- wlog $ tomsg k "RequiresPing"
1679 , readTChan stanzas >>= \stanza -> return $ do 1687 , readTChan stanzas >>= \stanza -> return $ do
1680 {- 1688 {-
1681 dup <- case stanzaType stanza of 1689 dup <- case stanzaType stanza of
@@ -1692,7 +1700,7 @@ monitor sv params xmpp = do
1692 1700
1693 forkIO $ do 1701 forkIO $ do
1694 case stanzaOrigin stanza of 1702 case stanzaOrigin stanza of
1695 NetworkOrigin k@(ClientKey {}) replyto -> 1703 ClientOrigin k replyto ->
1696 case stanzaType stanza of 1704 case stanzaType stanza of
1697 RequestResource clientsNameForMe wanted -> do 1705 RequestResource clientsNameForMe wanted -> do
1698 sockaddr <- socketFromKey sv k 1706 sockaddr <- socketFromKey sv k
@@ -1755,7 +1763,7 @@ monitor sv params xmpp = do
1755 guard . not . null . mapMaybe (msgBody . snd) $ msgLangMap (stanzaType stanza) 1763 guard . not . null . mapMaybe (msgBody . snd) $ msgLangMap (stanzaType stanza)
1756 stanzaId stanza 1764 stanzaId stanza
1757 _ -> return () 1765 _ -> return ()
1758 NetworkOrigin k@(PeerKey {}) replyto -> 1766 PeerOrigin k replyto ->
1759 case stanzaType stanza of 1767 case stanzaType stanza of
1760 PresenceRequestStatus {} -> do 1768 PresenceRequestStatus {} -> do
1761 xmppAnswerProbe xmpp k stanza replyto 1769 xmppAnswerProbe xmpp k stanza replyto
@@ -1785,14 +1793,13 @@ monitor sv params xmpp = do
1785 Message {} -> do 1793 Message {} -> do
1786 case stanzaOrigin stanza of 1794 case stanzaOrigin stanza of
1787 LocalPeer {} -> return () 1795 LocalPeer {} -> return ()
1788 NetworkOrigin _ replyto -> deliver replyto 1796 ClientOrigin _ replyto -> deliver replyto
1797 PeerOrigin _ replyto -> deliver replyto
1789 Error {} -> do 1798 Error {} -> do
1790 case stanzaOrigin stanza of 1799 case stanzaOrigin stanza of
1791 LocalPeer {} -> return () 1800 LocalPeer {} -> return ()
1792 NetworkOrigin k replyto -> do 1801 ClientOrigin _ replyto -> deliver replyto
1793 -- wlog $ "delivering error: " ++show (stanzaId stanza) 1802 PeerOrigin _ replyto -> deliver replyto
1794 -- wlog $ " from: " ++ show k
1795 deliver replyto
1796 _ -> return () 1803 _ -> return ()
1797 -- We need to clone in the case the stanza is passed on as for Message. 1804 -- We need to clone in the case the stanza is passed on as for Message.
1798 verbosity <- xmppVerbosity xmpp 1805 verbosity <- xmppVerbosity xmpp
@@ -1803,9 +1810,9 @@ monitor sv params xmpp = do
1803 notping $ do 1810 notping $ do
1804 let typ = Strict8.pack $ c ++ "->"++(concat . take 1 . words $ show (stanzaType stanza))++" " 1811 let typ = Strict8.pack $ c ++ "->"++(concat . take 1 . words $ show (stanzaType stanza))++" "
1805 c = case stanzaOrigin stanza of 1812 c = case stanzaOrigin stanza of
1806 LocalPeer -> "*" 1813 LocalPeer -> "*"
1807 NetworkOrigin (ClientKey {}) _ -> "C" 1814 ClientOrigin {} -> "C"
1808 NetworkOrigin (PeerKey {}) _ -> "P" 1815 PeerOrigin {} -> "P"
1809 wlog "" 1816 wlog ""
1810 stanzaToConduit dup $$ prettyPrint typ 1817 stanzaToConduit dup $$ prettyPrint typ
1811 1818
@@ -1821,27 +1828,41 @@ data ConnectionType = XMPP | Tox
1821 deriving (Eq,Ord,Enum,Show,Read) 1828 deriving (Eq,Ord,Enum,Show,Read)
1822 1829
1823data ConnectionData = ConnectionData 1830data ConnectionData = ConnectionData
1824 { cdAddr :: SockAddr 1831 { cdAddr :: Either (Local SockAddr) -- Peer connection local address
1832 (Remote SockAddr) -- Client connection remote address
1825 , cdType :: ConnectionType 1833 , cdType :: ConnectionType
1826 } 1834 }
1827 deriving (Eq,Ord,Show) 1835 deriving (Eq,Ord,Show)
1828 1836
1837addrToPeerKey :: Remote SockAddr -> PeerAddress
1838addrToPeerKey (Remote raddr) = PeerAddress raddr
1839
1840addrFromClientKey :: ClientAddress -> Local SockAddr
1841addrFromClientKey (ClientAddress laddr) = Local laddr
1842
1843classifyConnection :: SockAddr -> ConnectionData -> Either (PeerAddress, Local SockAddr)
1844 (ClientAddress, Remote SockAddr)
1845classifyConnection saddr dta = case cdAddr dta of
1846 Left laddr -> Left (PeerAddress saddr, laddr)
1847 Right raddr -> Right (ClientAddress saddr, raddr)
1848
1829data XMPPServer 1849data XMPPServer
1830 = forall releaseKey. 1850 = forall releaseKey.
1831 XMPPServer { _xmpp_sv :: Server ConnectionKey ConnectionData releaseKey XML.Event 1851 XMPPServer { _xmpp_sv :: Server SockAddr ConnectionData releaseKey XML.Event
1832 , _xmpp_peer_params :: ConnectionParameters ConnectionKey ConnectionData 1852 , _xmpp_peer_params :: ConnectionParameters SockAddr ConnectionData
1833 } 1853 }
1834 1854
1835grokPeer :: XMPPServer -> ConnectionKey -> (SockAddr, ConnectionParameters ConnectionKey ConnectionData, Miliseconds) 1855grokPeer :: XMPPServer -> SockAddr -> (SockAddr, ConnectionParameters SockAddr ConnectionData, Miliseconds)
1836grokPeer sv (PeerKey addr) = (addr, _xmpp_peer_params sv, 10000) 1856grokPeer sv addr = (addr, _xmpp_peer_params sv, 10000)
1857
1837 1858
1838xmppConnections :: XMPPServer -> IO (Connection.Manager TCPStatus Text) 1859xmppConnections :: XMPPServer -> IO (Connection.Manager TCPStatus Text)
1839xmppConnections xsv@XMPPServer{_xmpp_sv=sv} = tcpManager (grokPeer xsv) (Just . Text.pack) resolvPeer sv 1860xmppConnections xsv@XMPPServer{_xmpp_sv=sv} = tcpManager (grokPeer xsv) (Just . Text.pack) resolve sv
1840 where 1861 where
1841 resolvPeer :: Text -> IO (Maybe ConnectionKey) 1862 resolve :: Text -> IO (Maybe SockAddr)
1842 resolvPeer str = fmap PeerKey <$> listToMaybe <$> resolvePeer str 1863 resolve hostname = listToMaybe . map (\(PeerAddress addr) -> addr) <$> resolvePeer hostname
1843 1864
1844xmppEventChannel :: XMPPServer -> TChan ((ConnectionKey, ConnectionData), ConnectionEvent Event) 1865xmppEventChannel :: XMPPServer -> TChan ((SockAddr, ConnectionData), ConnectionEvent Event)
1845xmppEventChannel XMPPServer{_xmpp_sv=sv} = serverEvent sv 1866xmppEventChannel XMPPServer{_xmpp_sv=sv} = serverEvent sv
1846 1867
1847quitXmpp :: XMPPServer -> IO () 1868quitXmpp :: XMPPServer -> IO ()