diff options
author | joe <joe@jerkface.net> | 2018-06-24 02:27:18 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2018-06-24 03:10:43 -0400 |
commit | 55db1198b3da0c706f2b9f1ed9c8fd11fc4ae552 (patch) | |
tree | de035195ed188f8611da54e6e339d9124d2a5b3f /Presence/XMPPServer.hs | |
parent | 3054de811f4ae7659dfc4dc338aab2c3d11b5c27 (diff) |
XMPP: Type-checking on various uses of SockAddr.
Diffstat (limited to 'Presence/XMPPServer.hs')
-rw-r--r-- | Presence/XMPPServer.hs | 285 |
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 @@ | |||
7 | module XMPPServer | 7 | module 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 | |||
85 | import Data.Maybe | 91 | import Data.Maybe |
86 | import Data.Monoid ( (<>) ) | 92 | import Data.Monoid ( (<>) ) |
87 | import Data.Text (Text) | 93 | import Data.Text (Text) |
88 | import qualified Data.Text as Text (pack,unpack,words,intercalate) | 94 | import qualified Data.Text as Text (pack,unpack,words,intercalate,drop) |
89 | import Data.Char (chr,ord) | 95 | import Data.Char (chr,ord) |
90 | import qualified Data.Map as Map | 96 | import qualified Data.Map as Map |
91 | import Data.Set (Set, (\\) ) | 97 | import 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 | ||
170 | data StanzaOrigin = LocalPeer | NetworkOrigin ConnectionKey (TChan Stanza) | 176 | data StanzaOrigin = LocalPeer |
177 | | PeerOrigin PeerAddress (TChan Stanza) | ||
178 | | ClientOrigin ClientAddress (TChan Stanza) | ||
179 | |||
171 | 180 | ||
172 | data StanzaWrap a = Stanza | 181 | data StanzaWrap a = Stanza |
173 | { stanzaType :: StanzaType | 182 | { stanzaType :: StanzaType |
@@ -182,6 +191,9 @@ data StanzaWrap a = Stanza | |||
182 | 191 | ||
183 | type Stanza = StanzaWrap (LockedChan XML.Event) | 192 | type Stanza = StanzaWrap (LockedChan XML.Event) |
184 | 193 | ||
194 | newtype Local a = Local a deriving (Eq,Ord,Show) | ||
195 | newtype Remote a = Remote a deriving (Eq,Ord,Show) | ||
196 | |||
185 | data XMPPServerParameters = | 197 | data 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. |
274 | peerKeyToText :: ConnectionKey -> Text | 285 | peerKeyToText :: PeerAddress -> Text |
275 | peerKeyToText (PeerKey { callBackAddress=addr }) = addrToText addr | 286 | peerKeyToText (PeerAddress addr) = addrToText addr |
276 | peerKeyToText (ClientKey { localAddress=addr }) = "ErrorClIeNt0" | ||
277 | 287 | ||
278 | 288 | ||
279 | wlog :: String -> IO () | 289 | wlog :: 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 | ||
908 | data ClientOrPeer = IsClient | IsPeer | ||
898 | 909 | ||
899 | xmppInbound :: Server ConnectionKey ConnectionData releaseKey XML.Event | 910 | xmppInbound :: 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 () |
908 | xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do | 918 | xmppInbound 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 | ||
1247 | forkConnection :: Server ConnectionKey ConnectionData releaseKey XML.Event | 1248 | forkConnection :: 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) |
1256 | forkConnection sv xmpp k (ConnectionData laddr _) pingflag src snk stanzas = do | 1257 | forkConnection 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 | ||
1401 | peerKey :: SocketLike sock => Maybe SockAddr -> sock -> IO (ConnectionKey,ConnectionData) | 1408 | peerKey :: SocketLike sock => Maybe SockAddr -> sock -> IO (SockAddr,ConnectionData) |
1402 | peerKey outgoingPeerPort sock = do | 1409 | peerKey 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 | ||
1412 | clientKey :: SocketLike sock => sock -> IO (ConnectionKey,ConnectionData) | 1419 | clientKey :: SocketLike sock => sock -> IO (SockAddr,ConnectionData) |
1413 | clientKey sock = do | 1420 | clientKey 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 | ||
1418 | xmlifyRosterItems :: Monad m => Set Text -> Text -> Set Text -> ConduitM i Event m () | 1425 | xmlifyRosterItems :: Monad m => Set Text -> Text -> Set Text -> ConduitM i Event m () |
1419 | xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set) | 1426 | xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set) |
@@ -1429,14 +1436,15 @@ xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set) | |||
1429 | sendRoster :: | 1436 | sendRoster :: |
1430 | StanzaWrap a | 1437 | StanzaWrap a |
1431 | -> XMPPServerParameters | 1438 | -> XMPPServerParameters |
1432 | -> ConnectionKey | 1439 | -> ClientAddress |
1433 | -> TChan Stanza | 1440 | -> TChan Stanza |
1434 | -> IO () | 1441 | -> IO () |
1435 | sendRoster query xmpp clientKey replyto = do | 1442 | sendRoster 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 | ||
1485 | socketFromKey :: Server ConnectionKey ConnectionData releaseKey XML.Event -> ConnectionKey -> IO SockAddr | 1491 | socketFromKey :: Server SockAddr ConnectionData releaseKey XML.Event -> ClientAddress -> IO (Remote SockAddr) |
1486 | socketFromKey sv k = do | 1492 | socketFromKey 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 | ||
1497 | class StanzaFirstTag a where | 1500 | class 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 | ||
1654 | monitor :: | 1657 | monitor :: |
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 |
1659 | monitor sv params xmpp = do | 1662 | monitor 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 | ||
1823 | data ConnectionData = ConnectionData | 1830 | data 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 | ||
1837 | addrToPeerKey :: Remote SockAddr -> PeerAddress | ||
1838 | addrToPeerKey (Remote raddr) = PeerAddress raddr | ||
1839 | |||
1840 | addrFromClientKey :: ClientAddress -> Local SockAddr | ||
1841 | addrFromClientKey (ClientAddress laddr) = Local laddr | ||
1842 | |||
1843 | classifyConnection :: SockAddr -> ConnectionData -> Either (PeerAddress, Local SockAddr) | ||
1844 | (ClientAddress, Remote SockAddr) | ||
1845 | classifyConnection saddr dta = case cdAddr dta of | ||
1846 | Left laddr -> Left (PeerAddress saddr, laddr) | ||
1847 | Right raddr -> Right (ClientAddress saddr, raddr) | ||
1848 | |||
1829 | data XMPPServer | 1849 | data 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 | ||
1835 | grokPeer :: XMPPServer -> ConnectionKey -> (SockAddr, ConnectionParameters ConnectionKey ConnectionData, Miliseconds) | 1855 | grokPeer :: XMPPServer -> SockAddr -> (SockAddr, ConnectionParameters SockAddr ConnectionData, Miliseconds) |
1836 | grokPeer sv (PeerKey addr) = (addr, _xmpp_peer_params sv, 10000) | 1856 | grokPeer sv addr = (addr, _xmpp_peer_params sv, 10000) |
1857 | |||
1837 | 1858 | ||
1838 | xmppConnections :: XMPPServer -> IO (Connection.Manager TCPStatus Text) | 1859 | xmppConnections :: XMPPServer -> IO (Connection.Manager TCPStatus Text) |
1839 | xmppConnections xsv@XMPPServer{_xmpp_sv=sv} = tcpManager (grokPeer xsv) (Just . Text.pack) resolvPeer sv | 1860 | xmppConnections 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 | ||
1844 | xmppEventChannel :: XMPPServer -> TChan ((ConnectionKey, ConnectionData), ConnectionEvent Event) | 1865 | xmppEventChannel :: XMPPServer -> TChan ((SockAddr, ConnectionData), ConnectionEvent Event) |
1845 | xmppEventChannel XMPPServer{_xmpp_sv=sv} = serverEvent sv | 1866 | xmppEventChannel XMPPServer{_xmpp_sv=sv} = serverEvent sv |
1846 | 1867 | ||
1847 | quitXmpp :: XMPPServer -> IO () | 1868 | quitXmpp :: XMPPServer -> IO () |