diff options
author | Joe Crayne <joe@jerkface.net> | 2020-01-13 05:28:21 -0500 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2020-01-14 03:37:41 -0500 |
commit | b56ac5aa4a4d9c026f6aadad58daeee7729e9f4c (patch) | |
tree | db74187d2d1d4ed9255a2fd810a97e5b8f59e99f | |
parent | 8183644b29224b1f2a33b9428729744052373fb5 (diff) |
Made client's handshake to/from attributes available to xmppTellNameToClient.
-rw-r--r-- | dht/Presence/Nesting.hs | 10 | ||||
-rw-r--r-- | dht/Presence/Presence.hs | 39 | ||||
-rw-r--r-- | dht/Presence/XMPPServer.hs | 173 | ||||
-rw-r--r-- | dht/examples/dhtd.hs | 17 |
4 files changed, 160 insertions, 79 deletions
diff --git a/dht/Presence/Nesting.hs b/dht/Presence/Nesting.hs index 403d63cf..a9e550d4 100644 --- a/dht/Presence/Nesting.hs +++ b/dht/Presence/Nesting.hs | |||
@@ -24,12 +24,10 @@ doNestingXML :: Monad m => NestingXML o m r -> ConduitM Event o m r | |||
24 | doNestingXML m = | 24 | doNestingXML m = |
25 | evalStateC (XMLState 0 StrictNil) (trackNesting .| m) | 25 | evalStateC (XMLState 0 StrictNil) (trackNesting .| m) |
26 | 26 | ||
27 | startNestingXML :: Monad m => NestingXML o m r -> ConduitM Event o m (r, XMLState) | 27 | startNestingXML :: Monad m => NestingXML o m r -> ConduitM Event o m (r, NestingXML o m ()) |
28 | startNestingXML m = | 28 | startNestingXML m = do |
29 | runStateC (XMLState 0 StrictNil) (trackNesting .| m) | 29 | (r,st) <- runStateC (XMLState 0 StrictNil) (trackNesting .| m) |
30 | 30 | return (r, lift $ put st) | |
31 | finishNestingXML :: Monad m => XMLState -> NestingXML o m r -> ConduitM Event o m r | ||
32 | finishNestingXML = evalStateC | ||
33 | 31 | ||
34 | nesting :: Monad m => NestingXML o m Int | 32 | nesting :: Monad m => NestingXML o m Int |
35 | nesting = lift $ (return . nestingLevel) =<< get | 33 | nesting = lift $ (return . nestingLevel) =<< get |
diff --git a/dht/Presence/Presence.hs b/dht/Presence/Presence.hs index 866aad78..c54c3659 100644 --- a/dht/Presence/Presence.hs +++ b/dht/Presence/Presence.hs | |||
@@ -13,6 +13,7 @@ import Control.Concurrent | |||
13 | import Control.Concurrent.Lifted.Instrument | 13 | import Control.Concurrent.Lifted.Instrument |
14 | #endif | 14 | #endif |
15 | 15 | ||
16 | import Control.Arrow | ||
16 | import Control.Concurrent.STM | 17 | import Control.Concurrent.STM |
17 | import Control.Monad.Trans | 18 | import Control.Monad.Trans |
18 | import Network.Socket ( SockAddr(..) ) | 19 | import Network.Socket ( SockAddr(..) ) |
@@ -133,17 +134,21 @@ newPresenceState cw toxman sv man = atomically $ do | |||
133 | return $ st { toxManager = fmap ($ st) toxman } | 134 | return $ st { toxManager = fmap ($ st) toxman } |
134 | 135 | ||
135 | 136 | ||
136 | nameForClient :: PresenceState stat -> ClientAddress -> IO Text | 137 | nameForClient' :: PresenceState stat -> Maybe Text -> Maybe Text -> ClientAddress -> IO Text |
137 | nameForClient state k = do | 138 | nameForClient' state mbNameForMe mbTheirName k = do |
138 | mc <- atomically $ do | 139 | mc <- atomically $ do |
139 | cmap <- readTVar (clients state) | 140 | cmap <- readTVar (clients state) |
140 | return $ Map.lookup k cmap | 141 | return $ Map.lookup k cmap |
141 | case mc of | 142 | case mc of |
142 | Nothing -> textHostName | 143 | Nothing -> textHostName -- TODO: We can use mbNameForMe to initialize the clientProfile |
143 | Just client -> case clientProfile client of | 144 | Just client -> case clientProfile client of |
144 | "." -> textHostName | 145 | "." -> textHostName |
145 | profile -> return profile | 146 | profile -> return profile |
146 | 147 | ||
148 | nameForClient :: PresenceState stat -> ClientAddress -> IO Text | ||
149 | nameForClient state k = nameForClient' state Nothing Nothing k | ||
150 | |||
151 | |||
147 | presenceHooks :: PresenceState stat -> Map Text MUC | 152 | presenceHooks :: PresenceState stat -> Map Text MUC |
148 | -> Int | 153 | -> Int |
149 | -> Maybe SockAddr -- ^ client-to-server bind address | 154 | -> Maybe SockAddr -- ^ client-to-server bind address |
@@ -152,7 +157,7 @@ presenceHooks :: PresenceState stat -> Map Text MUC | |||
152 | presenceHooks state chats verbosity mclient mpeer = XMPPServerParameters | 157 | presenceHooks state chats verbosity mclient mpeer = XMPPServerParameters |
153 | { xmppChooseResourceName = chooseResourceName state | 158 | { xmppChooseResourceName = chooseResourceName state |
154 | , xmppTellClientHisName = tellClientHisName state | 159 | , xmppTellClientHisName = tellClientHisName state |
155 | , xmppTellMyNameToClient = nameForClient state | 160 | , xmppTellMyNameToClient = nameForClient' state |
156 | , xmppTellMyNameToPeer = \(Local addr) -> return $ addrToText addr | 161 | , xmppTellMyNameToPeer = \(Local addr) -> return $ addrToText addr |
157 | , xmppTellPeerHisName = return . peerKeyToText | 162 | , xmppTellPeerHisName = return . peerKeyToText |
158 | , xmppNewConnection = newConn state | 163 | , xmppNewConnection = newConn state |
@@ -726,8 +731,12 @@ deliverMessage state fail msg = | |||
726 | fromMaybe (do dput XJabber $ "Unknown peer " ++ show senderk | 731 | fromMaybe (do dput XJabber $ "Unknown peer " ++ show senderk |
727 | fail) | 732 | fail) |
728 | $ Map.lookup senderk pchans | 733 | $ Map.lookup senderk pchans |
729 | <&> \(Conn { connChan = sender_chan | 734 | <&> \Conn { connChan = sender_chan |
730 | , auxData = ConnectionData (Left laddr) ctyp cprof _ }) -> do | 735 | , auxData = ConnectionData { cdAddr = Left laddr |
736 | , cdType = ctyp | ||
737 | , cdProfile = cprof | ||
738 | } | ||
739 | } -> do | ||
731 | fromMaybe (do dput XJabber $ "Message missing \"to\" attribute." | 740 | fromMaybe (do dput XJabber $ "Message missing \"to\" attribute." |
732 | fail) | 741 | fail) |
733 | $ (stanzaTo msg) <&> \to -> do | 742 | $ (stanzaTo msg) <&> \to -> do |
@@ -916,9 +925,7 @@ informPeerPresence state k stanza = do | |||
916 | dput XJabber $ "xmppInformPeerPresence (length clients="++show (length clients)++")" | 925 | dput XJabber $ "xmppInformPeerPresence (length clients="++show (length clients)++")" |
917 | (ctyp,cprof) <- atomically $ do | 926 | (ctyp,cprof) <- atomically $ do |
918 | mconn <- Map.lookup k <$> readTVar (pkeyToChan state) | 927 | mconn <- Map.lookup k <$> readTVar (pkeyToChan state) |
919 | return $ fromMaybe (XMPP,".") $ do | 928 | return $ fromMaybe (XMPP,".") $ (cdType &&& cdProfile) . auxData <$> mconn |
920 | ConnectionData _ ctyp cprof _ <- auxData <$> mconn | ||
921 | return (ctyp,cprof) | ||
922 | forM_ clients $ \(ck,con,client) -> do | 929 | forM_ clients $ \(ck,con,client) -> do |
923 | -- (TODO: appropriately authorized clients only.) | 930 | -- (TODO: appropriately authorized clients only.) |
924 | -- For now, all "available" clients (available = sent initial presence) | 931 | -- For now, all "available" clients (available = sent initial presence) |
@@ -1263,7 +1270,11 @@ peerSubscriptionRequest state fail k stanza chan = do | |||
1263 | cmap <- readTVar (clients state) | 1270 | cmap <- readTVar (clients state) |
1264 | return (pktc,cktc,cmap) | 1271 | return (pktc,cktc,cmap) |
1265 | fromMaybe fail $ (Map.lookup k pktc) | 1272 | fromMaybe fail $ (Map.lookup k pktc) |
1266 | <&> \Conn { auxData=ConnectionData (Left laddr) ctyp profile _ } -> do | 1273 | <&> \Conn { auxData = ConnectionData { cdAddr = Left laddr |
1274 | , cdType = ctyp | ||
1275 | , cdProfile = profile | ||
1276 | } | ||
1277 | } -> do | ||
1267 | (mine,totup) <- case (ctyp,profile) of | 1278 | (mine,totup) <- case (ctyp,profile) of |
1268 | (Tox,p) -> let (u,h,r) = splitJID to | 1279 | (Tox,p) -> let (u,h,r) = splitJID to |
1269 | in return ( h == p, (u,h,r) ) | 1280 | in return ( h == p, (u,h,r) ) |
@@ -1412,8 +1423,12 @@ peerInformSubscription state fail k stanza = do | |||
1412 | cmap <- readTVar (clients state) | 1423 | cmap <- readTVar (clients state) |
1413 | return (pktc,cktc,cmap) | 1424 | return (pktc,cktc,cmap) |
1414 | fromMaybe fail $ Map.lookup k ktc | 1425 | fromMaybe fail $ Map.lookup k ktc |
1415 | <&> \(Conn { connChan=sender_chan | 1426 | <&> \Conn { connChan = sender_chan |
1416 | , auxData =ConnectionData (Left laddr) ctyp profile _ }) -> do | 1427 | , auxData = ConnectionData { cdAddr = Left laddr |
1428 | , cdType = ctyp | ||
1429 | , cdProfile = profile } | ||
1430 | } -> do | ||
1431 | |||
1417 | let man = manager state profile | 1432 | let man = manager state profile |
1418 | (from_u,from_h,_) <- case ctyp of | 1433 | (from_u,from_h,_) <- case ctyp of |
1419 | Tox -> return $ splitJID from | 1434 | Tox -> return $ splitJID from |
diff --git a/dht/Presence/XMPPServer.hs b/dht/Presence/XMPPServer.hs index 0aef1ed6..89fd76b6 100644 --- a/dht/Presence/XMPPServer.hs +++ b/dht/Presence/XMPPServer.hs | |||
@@ -129,8 +129,10 @@ data XMPPServerParameters = | |||
129 | -- | 129 | -- |
130 | -- A Left result causes an error stanza to be sent instead. | 130 | -- A Left result causes an error stanza to be sent instead. |
131 | xmppChooseResourceName :: ClientAddress -> Remote SockAddr -> Maybe Text -> Maybe Text -> IO (Either Text Text) | 131 | xmppChooseResourceName :: ClientAddress -> Remote SockAddr -> Maybe Text -> Maybe Text -> IO (Either Text Text) |
132 | , -- | This should indicate the server's hostname that all client's see. | 132 | , -- | This should indicate the server's hostname that the client will see. |
133 | xmppTellMyNameToClient :: ClientAddress -> IO Text | 133 | -- The first two arguments are the "to" and "from" attributes, |
134 | -- respectively, that the client sent in its greeting to the server. | ||
135 | xmppTellMyNameToClient :: Maybe Text -> Maybe Text -> ClientAddress -> IO Text | ||
134 | , xmppTellMyNameToPeer :: Local SockAddr -> IO Text | 136 | , xmppTellMyNameToPeer :: Local SockAddr -> IO Text |
135 | , xmppTellClientHisName :: ClientAddress -> IO Text | 137 | , xmppTellClientHisName :: ClientAddress -> IO Text |
136 | , xmppTellPeerHisName :: PeerAddress -> IO Text | 138 | , xmppTellPeerHisName :: PeerAddress -> IO Text |
@@ -476,16 +478,14 @@ C->Unrecognized </iq> | |||
476 | 478 | ||
477 | -- Sends all stanzas to announce channel except ping, for which it sends a pong | 479 | -- Sends all stanzas to announce channel except ping, for which it sends a pong |
478 | -- to the output channel. | 480 | -- to the output channel. |
479 | xmppInbound :: Maybe Text -- ^ "to" attribute sent from remote | 481 | xmppInbound :: ConnectionData |
480 | -> Maybe Text -- ^ "from" attribute sent from remote | ||
481 | -> ConnectionData | ||
482 | -> (Text, IO Text, IO Text, TChan Stanza -> StanzaOrigin) | 482 | -> (Text, IO Text, IO Text, TChan Stanza -> StanzaOrigin) |
483 | -> FlagCommand -- ^ action to check whether the connection needs a ping (XXX: unused) | 483 | -> FlagCommand -- ^ action to check whether the connection needs a ping (XXX: unused) |
484 | -> TChan Stanza -- ^ channel to announce incoming stanzas on | 484 | -> TChan Stanza -- ^ channel to announce incoming stanzas on |
485 | -> TChan Stanza -- ^ channel used to send stanzas | 485 | -> TChan Stanza -- ^ channel used to send stanzas |
486 | -> TMVar () -- ^ mvar that is filled when the connection quits | 486 | -> TMVar () -- ^ mvar that is filled when the connection quits |
487 | -> NestingXML o IO () | 487 | -> NestingXML o IO () |
488 | xmppInbound stream_name stream_remote cdta (namespace,tellmyname,tellyourname,mkorigin) pingflag stanzas output donevar = | 488 | xmppInbound cdta (namespace,tellmyname,tellyourname,mkorigin) pingflag stanzas output donevar = |
489 | fix $ \loop -> do | 489 | fix $ \loop -> do |
490 | -- liftIO . wlog $ "waiting for stanza." | 490 | -- liftIO . wlog $ "waiting for stanza." |
491 | (chan,clsrs) <- liftIO . atomically $ | 491 | (chan,clsrs) <- liftIO . atomically $ |
@@ -540,7 +540,7 @@ xmppInbound stream_name stream_remote cdta (namespace,tellmyname,tellyourname,mk | |||
540 | } | 540 | } |
541 | stype -> ioWriteChan stanzas Stanza | 541 | stype -> ioWriteChan stanzas Stanza |
542 | { stanzaType = case stype of | 542 | { stanzaType = case stype of |
543 | RequestResource _ rsc -> RequestResource stream_name rsc | 543 | RequestResource _ rsc -> RequestResource (cdTheirNameForMe cdta) rsc |
544 | _ -> stype | 544 | _ -> stype |
545 | , stanzaId = mid | 545 | , stanzaId = mid |
546 | , stanzaTo = mto | 546 | , stanzaTo = mto |
@@ -911,44 +911,81 @@ forkConnection :: Server PeerAddress ConnectionData releaseKey XML.Event | |||
911 | -> ConduitT (Flush XML.Event) Void IO () | 911 | -> ConduitT (Flush XML.Event) Void IO () |
912 | -> TChan Stanza | 912 | -> TChan Stanza |
913 | -> MVar () | 913 | -> MVar () |
914 | -> IO (TChan Stanza) | 914 | -> IO (TChan Stanza, ConnectionData) |
915 | forkConnection sv xmpp saddr cdta pingflag src snk stanzas pp_mvar = do | 915 | forkConnection sv xmpp saddr cdta0 pingflag src snk stanzas pp_mvar = do |
916 | -- client.PeerAddress {peerAddress = [::1]:5222} | 916 | -- client.PeerAddress {peerAddress = [::1]:5222} |
917 | let lbl n = concat [ n | 917 | let auxAddr = cdAddr cdta0 |
918 | , Text.unpack (Text.drop 7 namespace) -- "client" or "server" | ||
919 | , "." | ||
920 | , case cdProfile cdta of | ||
921 | _ | Right _ <- cdAddr cdta -> show saddr | ||
922 | "." -> show saddr | ||
923 | mytoxname -> show saddr {- TODO: remote tox peer name? -} ] | ||
924 | 918 | ||
925 | auxAddr = cdAddr cdta | 919 | is_client = case auxAddr of { Right _ -> True ; Left _ -> False } |
926 | 920 | ||
927 | clientOrServer@(namespace,tellmyname,telltheirname,_) = case auxAddr of | 921 | (namespace,clientOrServer0) = case auxAddr of |
928 | Right _ -> ("jabber:client", xmppTellMyNameToClient xmpp (ClientAddress $ peerAddress saddr) | 922 | Right _ -> ( "jabber:client" |
929 | , xmppTellClientHisName xmpp (ClientAddress $ peerAddress saddr) | 923 | , ( xmppTellMyNameToClient xmpp Nothing Nothing $ ClientAddress $ peerAddress saddr |
930 | , ClientOrigin (ClientAddress $ peerAddress saddr)) | 924 | , xmppTellClientHisName xmpp $ ClientAddress $ peerAddress saddr |
931 | Left laddr -> ("jabber:server", xmppTellMyNameToPeer xmpp laddr | 925 | , ClientOrigin $ ClientAddress $ peerAddress saddr ) ) |
932 | , xmppTellPeerHisName xmpp saddr | 926 | Left laddr -> ( "jabber:server" |
933 | , PeerOrigin saddr) | 927 | , ( xmppTellMyNameToPeer xmpp laddr |
928 | , xmppTellPeerHisName xmpp saddr | ||
929 | , PeerOrigin saddr) ) | ||
930 | |||
931 | updateNameField f (tmn,ttn,o) = (namespace,f tmn,ttn,o) | ||
932 | |||
933 | lbl n = concat [ n | ||
934 | , Text.unpack (Text.drop 7 namespace) -- "client" or "server" | ||
935 | , "." | ||
936 | , case cdProfile cdta0 of | ||
937 | _ | Right _ <- auxAddr -> show saddr | ||
938 | "." -> show saddr | ||
939 | mytoxname -> show saddr {- TODO: remote tox peer name? -} ] | ||
940 | |||
941 | |||
942 | realDoGreeting = await >>= \case | ||
943 | Just EventBeginDocument -> | ||
944 | nextElement >>= \case | ||
945 | Just xml -> | ||
946 | forM (elementAttrs "stream" xml) $ \stream_attrs -> do | ||
947 | -- liftIO $ dput XMisc $ "STREAM ATTRS "++show stream_attrs | ||
948 | let stream_name = lookupAttrib "to" stream_attrs | ||
949 | stream_remote = lookupAttrib "from" stream_attrs | ||
950 | -- xmpp_version = lookupAttrib "version" stream_attrs | ||
951 | liftIO $ atomically $ writeTVar (cdRemoteName cdta0) stream_remote | ||
952 | return (stream_name, stream_remote) | ||
953 | Nothing -> return Nothing | ||
954 | _ -> return Nothing | ||
955 | |||
956 | (clientOrServer@(namespace,tellmyname,telltheirname,_), (cdta, src', doGreeting)) | ||
957 | <- if is_client | ||
958 | then do | ||
959 | -- For a client, we can wait for them to greet us before we send them | ||
960 | -- any information. | ||
961 | (srcSealed,(mb,resume)) <- src $$+ startNestingXML realDoGreeting | ||
962 | let stream_name = mb >>= fst | ||
963 | stream_remote = mb >>= snd | ||
964 | cdta = cdta0 { cdTheirNameForMe = stream_name | ||
965 | , cdTheirName = stream_remote | ||
966 | } | ||
967 | newName _ = xmppTellMyNameToClient xmpp stream_name stream_remote | ||
968 | $ ClientAddress $ peerAddress saddr | ||
969 | atomically $ | ||
970 | modifyTVar' (conmap sv) $ | ||
971 | Map.adjust (\c -> c { cdata = cdta }) saddr | ||
972 | return ( updateNameField newName clientOrServer0 | ||
973 | , (cdta, unsealConduitT srcSealed, resume >> return mb) ) | ||
974 | else -- For a server, this is a no-op. | ||
975 | return ( updateNameField id clientOrServer0 | ||
976 | , (cdta0, src, realDoGreeting) ) | ||
934 | 977 | ||
935 | output <- atomically newTChan | 978 | output <- atomically newTChan |
936 | rdone <- atomically newEmptyTMVar | 979 | rdone <- atomically newEmptyTMVar |
937 | forkLabeled (lbl "xmpp-reader.") $ do | 980 | forkLabeled (lbl "xmpp-reader.") $ do |
938 | -- src $$ awaitForever (lift . putStrLn . takeWhile (/=' ') . show) | 981 | -- src $$ awaitForever (lift . putStrLn . takeWhile (/=' ') . show) |
939 | runConduit $ (.|) src $ | 982 | runConduit $ (.|) src' $ |
940 | -- :: ConduitM Event o IO () | 983 | -- :: ConduitM Event o IO () |
941 | doNestingXML $ do | 984 | doNestingXML $ do |
942 | withXML $ \begindoc -> do | 985 | doGreeting >>= \case |
943 | when (begindoc==EventBeginDocument) $ do | 986 | Just (stream_name, stream_remote) -> |
944 | whenJust nextElement $ \xml -> do | 987 | xmppInbound cdta clientOrServer pingflag stanzas output rdone |
945 | withJust (elementAttrs "stream" xml) $ \stream_attrs -> do | 988 | Nothing -> return () |
946 | -- liftIO $ dput XMisc $ "STREAM ATTRS "++show stream_attrs | ||
947 | let stream_name = lookupAttrib "to" stream_attrs | ||
948 | stream_remote = lookupAttrib "from" stream_attrs | ||
949 | -- xmpp_version = lookupAttrib "version" stream_attrs | ||
950 | liftIO $ atomically $ writeTVar (cdRemoteName cdta) stream_remote | ||
951 | xmppInbound stream_name stream_remote cdta clientOrServer pingflag stanzas output rdone | ||
952 | atomically $ putTMVar rdone () | 989 | atomically $ putTMVar rdone () |
953 | wlog $ "end reader fork: " ++ lbl "" | 990 | wlog $ "end reader fork: " ++ lbl "" |
954 | 991 | ||
@@ -1087,7 +1124,7 @@ forkConnection sv xmpp saddr cdta pingflag src snk stanzas pp_mvar = do | |||
1087 | ] | 1124 | ] |
1088 | what | 1125 | what |
1089 | wlog $ "end xmpp-pre fork: " ++ show (lbl "") | 1126 | wlog $ "end xmpp-pre fork: " ++ show (lbl "") |
1090 | return output | 1127 | return (output, cdta) |
1091 | 1128 | ||
1092 | {- | 1129 | {- |
1093 | data Peer = Peer | 1130 | data Peer = Peer |
@@ -1121,7 +1158,9 @@ peerKey bind_addr (sock,(laddr,Remote raddr)) = do | |||
1121 | , ConnectionData { cdAddr = Left laddr | 1158 | , ConnectionData { cdAddr = Left laddr |
1122 | , cdType = XMPP | 1159 | , cdType = XMPP |
1123 | , cdProfile = "." | 1160 | , cdProfile = "." |
1124 | , cdRemoteName = rname } ) | 1161 | , cdRemoteName = rname |
1162 | , cdTheirNameForMe = Nothing | ||
1163 | , cdTheirName = Nothing } ) | ||
1125 | 1164 | ||
1126 | clientKey :: SocketLike sock => (sock, (Local SockAddr,Remote SockAddr)) -> IO (PeerAddress,ConnectionData) | 1165 | clientKey :: SocketLike sock => (sock, (Local SockAddr,Remote SockAddr)) -> IO (PeerAddress,ConnectionData) |
1127 | clientKey (sock,(laddr,Remote raddr)) = do | 1166 | clientKey (sock,(laddr,Remote raddr)) = do |
@@ -1138,7 +1177,9 @@ clientKey (sock,(laddr,Remote raddr)) = do | |||
1138 | , ConnectionData { cdAddr = Right (Remote raddr) -- FIXME: This is a bad way to detect client/peer. | 1177 | , ConnectionData { cdAddr = Right (Remote raddr) -- FIXME: This is a bad way to detect client/peer. |
1139 | , cdType = XMPP | 1178 | , cdType = XMPP |
1140 | , cdProfile = "." | 1179 | , cdProfile = "." |
1141 | , cdRemoteName = rname } ) | 1180 | , cdRemoteName = rname |
1181 | , cdTheirNameForMe = Nothing | ||
1182 | , cdTheirName = Nothing } ) | ||
1142 | 1183 | ||
1143 | 1184 | ||
1144 | xmlifyRosterItems :: Monad m => Set Text -> Text -> Set Text -> ConduitM i Event m () | 1185 | xmlifyRosterItems :: Monad m => Set Text -> Text -> Set Text -> ConduitM i Event m () |
@@ -1154,17 +1195,18 @@ xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set) | |||
1154 | 1195 | ||
1155 | sendRoster :: | 1196 | sendRoster :: |
1156 | StanzaWrap a | 1197 | StanzaWrap a |
1198 | -> Server PeerAddress ConnectionData releaseKey xml | ||
1157 | -> XMPPServerParameters | 1199 | -> XMPPServerParameters |
1158 | -> ClientAddress | 1200 | -> ClientAddress |
1159 | -> TChan Stanza | 1201 | -> TChan Stanza |
1160 | -> IO () | 1202 | -> IO () |
1161 | sendRoster query xmpp clientKey replyto = do | 1203 | sendRoster query sv xmpp clientKey replyto = do |
1162 | let maddr = case stanzaOrigin query of | 1204 | let maddr = case stanzaOrigin query of |
1163 | ClientOrigin addr _ -> Just addr | 1205 | ClientOrigin addr _ -> Just addr |
1164 | PeerOrigin {} -> Nothing -- remote peer requested roster? | 1206 | PeerOrigin {} -> Nothing -- remote peer requested roster? |
1165 | LocalPeer -> Nothing -- local peer requested roster? | 1207 | LocalPeer -> Nothing -- local peer requested roster? |
1166 | forM_ maddr $ \k -> do | 1208 | forM_ maddr $ \k -> do |
1167 | hostname <- xmppTellMyNameToClient xmpp clientKey | 1209 | hostname <- svTellMyName sv xmpp clientKey |
1168 | let getlist f = do | 1210 | let getlist f = do |
1169 | bs <- f xmpp k | 1211 | bs <- f xmpp k |
1170 | return (Set.fromList bs) -- js) | 1212 | return (Set.fromList bs) -- js) |
@@ -1278,13 +1320,24 @@ makeErrorStanza' stanza err attrs = do | |||
1278 | , endTag | 1320 | , endTag |
1279 | ] | 1321 | ] |
1280 | 1322 | ||
1323 | svTellMyName :: Server PeerAddress ConnectionData releaseKey xml | ||
1324 | -> XMPPServerParameters | ||
1325 | -> ClientAddress | ||
1326 | -> IO Text | ||
1327 | svTellMyName sv xmpp k@(ClientAddress saddr) = do | ||
1328 | mc <- atomically $ | ||
1329 | fmap cdata . Map.lookup (PeerAddress saddr) <$> readTVar (conmap sv) | ||
1330 | let me = mc >>= cdTheirNameForMe | ||
1331 | them = mc >>= cdTheirName | ||
1332 | xmppTellMyNameToClient xmpp me them k | ||
1333 | |||
1281 | monitor :: | 1334 | monitor :: |
1282 | Server PeerAddress ConnectionData releaseKey XML.Event | 1335 | Server PeerAddress ConnectionData releaseKey XML.Event |
1283 | -> ConnectionParameters PeerAddress ConnectionData | 1336 | -> ConnectionParameters PeerAddress ConnectionData |
1284 | -> XMPPServerParameters | 1337 | -> XMPPServerParameters |
1285 | -> IO b | 1338 | -> IO b |
1286 | monitor sv params xmpp = do | 1339 | monitor sv params xmpp = do |
1287 | chan <- return $ serverEvent sv | 1340 | let chan = serverEvent sv |
1288 | stanzas <- atomically newTChan | 1341 | stanzas <- atomically newTChan |
1289 | quitVar <- atomically newEmptyTMVar | 1342 | quitVar <- atomically newEmptyTMVar |
1290 | pp_mvar <- newMVar () -- Lock for synchronous pretty-printing of stanzas in log. | 1343 | pp_mvar <- newMVar () -- Lock for synchronous pretty-printing of stanzas in log. |
@@ -1296,16 +1349,18 @@ monitor sv params xmpp = do | |||
1296 | case e of | 1349 | case e of |
1297 | Connection pingflag xsrc xsnk | 1350 | Connection pingflag xsrc xsnk |
1298 | -> do wlog $ tomsg addr "Connection" | 1351 | -> do wlog $ tomsg addr "Connection" |
1299 | outs <- forkConnection sv xmpp addr u pingflag xsrc xsnk stanzas pp_mvar | 1352 | (outs,u') <- forkConnection sv xmpp addr u pingflag xsrc xsnk stanzas pp_mvar |
1300 | -- /addr/ may be a peer or a client. So we'll strip off | 1353 | -- /addr/ may be a peer or a client. So we'll strip off |
1301 | -- the PeerAddress constructor before exposing it. | 1354 | -- the PeerAddress constructor before exposing it. |
1302 | xmppNewConnection xmpp (peerAddress addr) u outs | 1355 | xmppNewConnection xmpp (peerAddress addr) u' outs |
1303 | ConnectFailure addr | 1356 | ConnectFailure addr |
1304 | -> do return () -- wlog $ tomsg k "ConnectFailure" | 1357 | -> do return () -- wlog $ tomsg k "ConnectFailure" |
1305 | EOF -> do wlog $ tomsg addr "EOF" | 1358 | EOF -> do wlog $ tomsg addr "EOF" |
1306 | -- /addr/ may be a peer or a client. So we'll strip off | 1359 | -- /addr/ may be a peer or a client. So we'll strip off |
1307 | -- the PeerAddress constructor before exposing it. | 1360 | -- the PeerAddress constructor before exposing it. |
1308 | xmppEOF xmpp (peerAddress addr) u | 1361 | xmppEOF xmpp (peerAddress addr) u -- Note: cdTheirName and cdTheirNameForMe are with their |
1362 | -- default values rather than the updated versions provided | ||
1363 | -- by 'forkConnection'. | ||
1309 | HalfConnection In | 1364 | HalfConnection In |
1310 | -> do wlog $ tomsg addr "ReadOnly" | 1365 | -> do wlog $ tomsg addr "ReadOnly" |
1311 | case cdAddr u of | 1366 | case cdAddr u of |
@@ -1359,7 +1414,7 @@ monitor sv params xmpp = do | |||
1359 | $ \(k,((rkey,muckey),(replyto,r))) -> do | 1414 | $ \(k,((rkey,muckey),(replyto,r))) -> do |
1360 | (mine,ChatTransaction no cjid cnick es) <- readRoom k r | 1415 | (mine,ChatTransaction no cjid cnick es) <- readRoom k r |
1361 | return $ do | 1416 | return $ do |
1362 | me <- xmppTellMyNameToClient xmpp k | 1417 | me <- svTellMyName sv xmpp k |
1363 | dput XJabber $ "CHAT " ++ Text.unpack rkey ++ ": <" ++ Text.unpack cnick ++ "> " ++ show es | 1418 | dput XJabber $ "CHAT " ++ Text.unpack rkey ++ ": <" ++ Text.unpack cnick ++ "> " ++ show es |
1364 | forM_ es $ \case | 1419 | forM_ es $ \case |
1365 | Join | mine -> sendRoomOccupants muckey me cnick rkey r replyto | 1420 | Join | mine -> sendRoomOccupants muckey me cnick rkey r replyto |
@@ -1387,7 +1442,7 @@ monitor sv params xmpp = do | |||
1387 | else Map.insert k m' jrs | 1442 | else Map.insert k m' jrs |
1388 | writeTVar joined_rooms jrs' | 1443 | writeTVar joined_rooms jrs' |
1389 | Talk talk -> do | 1444 | Talk talk -> do |
1390 | them <- xmppTellClientHisName xmpp k | 1445 | them <- svTellMyName sv xmpp k |
1391 | stanza <- makeMessageEx "jabber:client" (roomjid muckey me rkey cnick) them GroupChatMsg talk | 1446 | stanza <- makeMessageEx "jabber:client" (roomjid muckey me rkey cnick) them GroupChatMsg talk |
1392 | ioWriteChan replyto stanza | 1447 | ioWriteChan replyto stanza |
1393 | return () | 1448 | return () |
@@ -1475,7 +1530,7 @@ applyStanza sv joined_rooms quitVar xmpp stanza = do | |||
1475 | sockaddr <- socketFromKey sv k | 1530 | sockaddr <- socketFromKey sv k |
1476 | xmppChooseResourceName xmpp k sockaddr clientsNameForMe wanted >>= \case | 1531 | xmppChooseResourceName xmpp k sockaddr clientsNameForMe wanted >>= \case |
1477 | Right rsc0 -> do | 1532 | Right rsc0 -> do |
1478 | hostname <- xmppTellMyNameToClient xmpp k | 1533 | hostname <- svTellMyName sv xmpp k |
1479 | let rsc = unsplitJID (n,hostname,r) where (n,_,r) = splitJID rsc0 | 1534 | let rsc = unsplitJID (n,hostname,r) where (n,_,r) = splitJID rsc0 |
1480 | let reply = iq_bind_reply (stanzaId stanza) rsc | 1535 | let reply = iq_bind_reply (stanzaId stanza) rsc |
1481 | sendReply quitVar SetResource reply replyto | 1536 | sendReply quitVar SetResource reply replyto |
@@ -1486,19 +1541,19 @@ applyStanza sv joined_rooms quitVar xmpp stanza = do | |||
1486 | (requestVersion rsc hostname) | 1541 | (requestVersion rsc hostname) |
1487 | >>= ioWriteChan replyto | 1542 | >>= ioWriteChan replyto |
1488 | Left err -> do | 1543 | Left err -> do |
1489 | hostname <- xmppTellMyNameToClient xmpp k | 1544 | hostname <- svTellMyName sv xmpp k |
1490 | reply <- makeErrorStanza' stanza NotAllowed [] | 1545 | reply <- makeErrorStanza' stanza NotAllowed [] |
1491 | sendReply quitVar (Error NotAuthorized (head reply)) reply replyto | 1546 | sendReply quitVar (Error NotAuthorized (head reply)) reply replyto |
1492 | SessionRequest -> do | 1547 | SessionRequest -> do |
1493 | me <- xmppTellMyNameToClient xmpp k | 1548 | me <- svTellMyName sv xmpp k |
1494 | let reply = iq_session_reply (stanzaId stanza) me | 1549 | let reply = iq_session_reply (stanzaId stanza) me |
1495 | sendReply quitVar Pong reply replyto | 1550 | sendReply quitVar Pong reply replyto |
1496 | RequestRoster -> do | 1551 | RequestRoster -> do |
1497 | sendRoster stanza xmpp k replyto | 1552 | sendRoster stanza sv xmpp k replyto |
1498 | xmppSubscribeToRoster xmpp k | 1553 | xmppSubscribeToRoster xmpp k |
1499 | PresenceStatus {} -> do | 1554 | PresenceStatus {} -> do |
1500 | let mucs = xmppGroupChat xmpp | 1555 | let mucs = xmppGroupChat xmpp |
1501 | me <- xmppTellMyNameToClient xmpp k | 1556 | me <- svTellMyName sv xmpp k |
1502 | if | Just to <- stanzaTo stanza | 1557 | if | Just to <- stanzaTo stanza |
1503 | , (Just room,h,mnick) <- splitJID to | 1558 | , (Just room,h,mnick) <- splitJID to |
1504 | , let roomjid = unsplitJID ((Just room,h,Nothing)) | 1559 | , let roomjid = unsplitJID ((Just room,h,Nothing)) |
@@ -1550,7 +1605,7 @@ applyStanza sv joined_rooms quitVar xmpp stanza = do | |||
1550 | NotifyClientVersion name version -> do | 1605 | NotifyClientVersion name version -> do |
1551 | enableClientHacks name version replyto | 1606 | enableClientHacks name version replyto |
1552 | RequestInfo mnode -> do | 1607 | RequestInfo mnode -> do |
1553 | me <- xmppTellMyNameToClient xmpp k | 1608 | me <- svTellMyName sv xmpp k |
1554 | let unavail = let query = "{http://jabber.org/protocol/disco#info}info" | 1609 | let unavail = let query = "{http://jabber.org/protocol/disco#info}info" |
1555 | reply = iq_service_unavailable (stanzaId stanza) me query | 1610 | reply = iq_service_unavailable (stanzaId stanza) me query |
1556 | in return (Error ServiceUnavailable (head reply), reply) | 1611 | in return (Error ServiceUnavailable (head reply), reply) |
@@ -1608,7 +1663,7 @@ applyStanza sv joined_rooms quitVar xmpp stanza = do | |||
1608 | sendReply quitVar rtyp reply replyto | 1663 | sendReply quitVar rtyp reply replyto |
1609 | RequestItems mnode -> do | 1664 | RequestItems mnode -> do |
1610 | -- let query = "{http://jabber.org/protocol/disco#items}query" | 1665 | -- let query = "{http://jabber.org/protocol/disco#items}query" |
1611 | me <- xmppTellMyNameToClient xmpp k | 1666 | me <- svTellMyName sv xmpp k |
1612 | let unavail = let query = "{http://jabber.org/protocol/disco#info}info" | 1667 | let unavail = let query = "{http://jabber.org/protocol/disco#info}info" |
1613 | reply = iq_service_unavailable (stanzaId stanza) me query | 1668 | reply = iq_service_unavailable (stanzaId stanza) me query |
1614 | in return (Error ServiceUnavailable (head reply), reply) | 1669 | in return (Error ServiceUnavailable (head reply), reply) |
@@ -1635,12 +1690,12 @@ applyStanza sv joined_rooms quitVar xmpp stanza = do | |||
1635 | return (Items, reply) | 1690 | return (Items, reply) |
1636 | sendReply quitVar rtyp reply replyto | 1691 | sendReply quitVar rtyp reply replyto |
1637 | UnrecognizedQuery query -> do | 1692 | UnrecognizedQuery query -> do |
1638 | me <- xmppTellMyNameToClient xmpp k | 1693 | me <- svTellMyName sv xmpp k |
1639 | let reply = iq_service_unavailable (stanzaId stanza) me query | 1694 | let reply = iq_service_unavailable (stanzaId stanza) me query |
1640 | sendReply quitVar (Error ServiceUnavailable (head reply)) reply replyto | 1695 | sendReply quitVar (Error ServiceUnavailable (head reply)) reply replyto |
1641 | Message { msgType = GroupChatMsg } -> do | 1696 | Message { msgType = GroupChatMsg } -> do |
1642 | let mucs = xmppGroupChat xmpp | 1697 | let mucs = xmppGroupChat xmpp |
1643 | me <- xmppTellMyNameToClient xmpp k | 1698 | me <- svTellMyName sv xmpp k |
1644 | if | Just to <- stanzaTo stanza | 1699 | if | Just to <- stanzaTo stanza |
1645 | , (Just room,h,mnick) <- splitJID to | 1700 | , (Just room,h,mnick) <- splitJID to |
1646 | , let roomjid = unsplitJID ((Just room,h,Nothing)) | 1701 | , let roomjid = unsplitJID ((Just room,h,Nothing)) |
@@ -1732,7 +1787,13 @@ data ConnectionData = ConnectionData | |||
1732 | 1787 | ||
1733 | -- Initially Nothing, when the remote end identifies itself by a given name, | 1788 | -- Initially Nothing, when the remote end identifies itself by a given name, |
1734 | -- the result will be stored here. | 1789 | -- the result will be stored here. |
1735 | , cdRemoteName :: TVar (Maybe Text) | 1790 | , cdRemoteName :: TVar (Maybe Text) -- This is similar to 'cdTheirName' except that |
1791 | -- it is available for remote xmpp servers and to | ||
1792 | -- the 'xmppEOF' function. | ||
1793 | , cdTheirNameForMe :: Maybe Text -- (client only) "to" attribute sent with <stream> | ||
1794 | -- Also: currently unavailable to 'xmppEOF' | ||
1795 | , cdTheirName :: Maybe Text -- (client only) "from" attribute sent with <stream> | ||
1796 | -- Also: currently unavailable to 'xmppEOF' | ||
1736 | } | 1797 | } |
1737 | 1798 | ||
1738 | addrToPeerKey :: Remote SockAddr -> PeerAddress | 1799 | addrToPeerKey :: Remote SockAddr -> PeerAddress |
diff --git a/dht/examples/dhtd.hs b/dht/examples/dhtd.hs index d7c817ca..f9dc777d 100644 --- a/dht/examples/dhtd.hs +++ b/dht/examples/dhtd.hs | |||
@@ -1366,17 +1366,24 @@ onNewToxSession runio sv ssvar invc ContactInfo{accounts} addrTox netcrypto = do | |||
1366 | 1366 | ||
1367 | uniqkey <- xor24 <$> hash24 (them netcrypto) <*> hash24 (me netcrypto) | 1367 | uniqkey <- xor24 <$> hash24 (them netcrypto) <*> hash24 (me netcrypto) |
1368 | 1368 | ||
1369 | let me_dot_tox = xmppHostname $ me netcrypto | ||
1370 | them_dot_tox = xmppHostname $ them netcrypto | ||
1371 | |||
1369 | c <- atomically $ do | 1372 | c <- atomically $ do |
1370 | mc <- Map.lookup uniqkey <$> readTVar ssvar | 1373 | mc <- Map.lookup uniqkey <$> readTVar ssvar |
1371 | case mc of | 1374 | case mc of |
1372 | Nothing -> do | 1375 | Nothing -> do |
1373 | announce <- do | 1376 | announce <- do |
1374 | v <- newTVar Nothing | 1377 | v <- newTVar $ Just them_dot_tox |
1375 | let ck = uniqueAsKey uniqkey | 1378 | let ck = uniqueAsKey uniqkey |
1376 | condta s = ConnectionData (Left (Local addrTox)) | 1379 | condta s = ConnectionData |
1377 | XMPPServer.Tox | 1380 | { cdAddr = Left (Local addrTox) |
1378 | (xmppHostname $ me s) | 1381 | , cdType = XMPPServer.Tox |
1379 | v | 1382 | , cdProfile = me_dot_tox |
1383 | , cdRemoteName = v | ||
1384 | , cdTheirNameForMe = Just me_dot_tox | ||
1385 | , cdTheirName = Just them_dot_tox | ||
1386 | } | ||
1380 | return $ \s e -> writeTChan (xmppEventChannel sv) ( (ck, condta s), e) | 1387 | return $ \s e -> writeTChan (xmppEventChannel sv) ( (ck, condta s), e) |
1381 | c <- newAggregateSession $ onStatusChange announce | 1388 | c <- newAggregateSession $ onStatusChange announce |
1382 | modifyTVar' ssvar $ Map.insert uniqkey c | 1389 | modifyTVar' ssvar $ Map.insert uniqkey c |