diff options
Diffstat (limited to 'dht/src/Network/Tox')
-rw-r--r-- | dht/src/Network/Tox/Relay.hs | 39 | ||||
-rw-r--r-- | dht/src/Network/Tox/TCP.hs | 25 |
2 files changed, 50 insertions, 14 deletions
diff --git a/dht/src/Network/Tox/Relay.hs b/dht/src/Network/Tox/Relay.hs index 2842fcc2..2ecd7ddf 100644 --- a/dht/src/Network/Tox/Relay.hs +++ b/dht/src/Network/Tox/Relay.hs | |||
@@ -30,6 +30,8 @@ import Network.SocketLike | |||
30 | import Network.StreamServer | 30 | import Network.StreamServer |
31 | import Network.Tox.Onion.Transport hiding (encrypt,decrypt) | 31 | import Network.Tox.Onion.Transport hiding (encrypt,decrypt) |
32 | 32 | ||
33 | import DPut | ||
34 | import DebugTag | ||
33 | 35 | ||
34 | 36 | ||
35 | hGetPrefixed :: Serialize a => Handle -> IO (Either String a) | 37 | hGetPrefixed :: Serialize a => Handle -> IO (Either String a) |
@@ -43,6 +45,7 @@ hGetSized h = runGet get <$> B.hGet h len -- We treat parse-fail the same as EOF | |||
43 | where | 45 | where |
44 | ConstSize len = size :: Size x | 46 | ConstSize len = size :: Size x |
45 | 47 | ||
48 | -- This type manages ConId assignments. | ||
46 | data RelaySession = RelaySession | 49 | data RelaySession = RelaySession |
47 | { indexPool :: IntSet -- ^ Ints that are either solicited or associated. | 50 | { indexPool :: IntSet -- ^ Ints that are either solicited or associated. |
48 | , solicited :: Map PublicKey Int -- ^ Reserved ids, not yet in associated. | 51 | , solicited :: Map PublicKey Int -- ^ Reserved ids, not yet in associated. |
@@ -70,17 +73,19 @@ disconnect cons who = join $ atomically $ do | |||
70 | in IntMap.foldrWithKey notifyPeer (return ()) cs | 73 | in IntMap.foldrWithKey notifyPeer (return ()) cs |
71 | 74 | ||
72 | relaySession :: TransportCrypto | 75 | relaySession :: TransportCrypto |
76 | -> TVar (IntMap (RelayPacket -> IO ())) | ||
73 | -> TVar (Map PublicKey (RelayPacket -> IO (),TVar RelaySession)) | 77 | -> TVar (Map PublicKey (RelayPacket -> IO (),TVar RelaySession)) |
74 | -> (SockAddr -> OnionRequest N1 -> IO ()) | 78 | -> (SockAddr -> OnionRequest N1 -> IO ()) |
75 | -> sock | 79 | -> sock |
76 | -> Int | 80 | -> Int |
77 | -> Handle | 81 | -> Handle |
78 | -> IO () | 82 | -> IO () |
79 | relaySession crypto cons sendOnion _ conid h = do | 83 | relaySession crypto clients cons sendOnion _ conid h = do |
80 | -- atomically $ modifyTVar' cons $ IntMap.insert conid h | 84 | -- atomically $ modifyTVar' cons $ IntMap.insert conid h |
81 | 85 | ||
82 | -- mhello <- fmap (>>= \h -> decryptPayload (computeSharedSecret me (helloFrom h) (helloNonce h)) h) $ hGetSized h | 86 | -- mhello <- fmap (>>= \h -> decryptPayload (computeSharedSecret me (helloFrom h) (helloNonce h)) h) $ hGetSized h |
83 | 87 | ||
88 | dput XOnion $ "Relay client session conid=" ++ show conid | ||
84 | (hGetSized h >>=) $ mapM_ $ \helloE -> do | 89 | (hGetSized h >>=) $ mapM_ $ \helloE -> do |
85 | 90 | ||
86 | let me = transportSecret crypto | 91 | let me = transportSecret crypto |
@@ -88,17 +93,24 @@ relaySession crypto cons sendOnion _ conid h = do | |||
88 | 93 | ||
89 | noncef <- lookupNonceFunction crypto me them | 94 | noncef <- lookupNonceFunction crypto me them |
90 | let mhello = decryptPayload (noncef $ helloNonce helloE) helloE | 95 | let mhello = decryptPayload (noncef $ helloNonce helloE) helloE |
96 | dput XOnion $ "Relay client (conid=" ++ show conid ++ ") decrypted hello = " ++ show mhello | ||
91 | forM_ mhello $ \hello -> do | 97 | forM_ mhello $ \hello -> do |
92 | let _ = hello :: Hello Identity | 98 | let _ = hello :: Hello Identity |
93 | 99 | ||
100 | dput XOnion $ "Relay client sent hello. conid=" ++ show conid | ||
94 | (me',welcome) <- atomically $ do | 101 | (me',welcome) <- atomically $ do |
95 | skey <- transportNewKey crypto | 102 | skey <- transportNewKey crypto |
96 | dta <- HelloData (toPublic skey) <$> transportNewNonce crypto | 103 | dta <- HelloData (toPublic skey) <$> transportNewNonce crypto |
97 | w24 <- transportNewNonce crypto | 104 | w24 <- transportNewNonce crypto |
98 | return (skey, Welcome w24 $ pure dta) | 105 | return (skey, Welcome w24 $ pure dta) |
99 | 106 | ||
107 | dput XOnion $ unlines [ "Relay client to receive welcome. conid=" ++ show conid | ||
108 | , show welcome | ||
109 | ] | ||
100 | B.hPut h $ encode $ encryptPayload (noncef $ welcomeNonce welcome) welcome | 110 | B.hPut h $ encode $ encryptPayload (noncef $ welcomeNonce welcome) welcome |
101 | 111 | ||
112 | dput XOnion $ "Relay client welcome sent. conid=" ++ show conid | ||
113 | |||
102 | noncef' <- let them' = sessionPublicKey (runIdentity $ helloData hello) | 114 | noncef' <- let them' = sessionPublicKey (runIdentity $ helloData hello) |
103 | in lookupNonceFunction crypto me' them' | 115 | in lookupNonceFunction crypto me' them' |
104 | 116 | ||
@@ -133,13 +145,20 @@ relaySession crypto cons sendOnion _ conid h = do | |||
133 | 145 | ||
134 | handlePacket cons conid (helloFrom hello) crypto sendOnion sendPacket session pkt0 | 146 | handlePacket cons conid (helloFrom hello) crypto sendOnion sendPacket session pkt0 |
135 | 147 | ||
148 | atomically $ modifyTVar' clients $ IntMap.insert conid $ | ||
149 | \p -> do | ||
150 | dput XOnion $ "Sending onion reply to TCP client conid="++show conid | ||
151 | sendPacket p | ||
152 | |||
136 | flip fix (incrementNonce24 base) $ \loop n24 -> do | 153 | flip fix (incrementNonce24 base) $ \loop n24 -> do |
137 | m <- readPacket n24 | 154 | m <- readPacket n24 |
138 | forM_ m $ \p -> do | 155 | forM_ m $ \p -> do |
139 | handlePacket cons conid (helloFrom hello) crypto sendOnion sendPacket session p | 156 | handlePacket cons conid (helloFrom hello) crypto sendOnion sendPacket session p |
140 | loop (incrementNonce24 n24) | 157 | loop (incrementNonce24 n24) |
141 | `finally` | 158 | `finally` do |
159 | atomically $ modifyTVar' clients $ IntMap.delete conid | ||
142 | disconnect cons (helloFrom hello) | 160 | disconnect cons (helloFrom hello) |
161 | dput XOnion $ "Relay client session closed. conid=" ++ show conid | ||
143 | 162 | ||
144 | handlePacket :: TVar (Map PublicKey (RelayPacket -> IO (), TVar RelaySession)) | 163 | handlePacket :: TVar (Map PublicKey (RelayPacket -> IO (), TVar RelaySession)) |
145 | -> Int | 164 | -> Int |
@@ -202,6 +221,7 @@ handlePacket cons thistcp me crypto sendOnion sendToMe session = \case | |||
202 | return $ sendToThem' $ RelayData bs | 221 | return $ sendToThem' $ RelayData bs |
203 | 222 | ||
204 | OnionPacket n24 (Addressed addr req) -> do | 223 | OnionPacket n24 (Addressed addr req) -> do |
224 | dput XOnion $ "Received onion request via TCP client conid="++show thistcp | ||
205 | rpath <- atomically $ do | 225 | rpath <- atomically $ do |
206 | sym <- transportSymmetric crypto | 226 | sym <- transportSymmetric crypto |
207 | n <- transportNewNonce crypto | 227 | n <- transportNewNonce crypto |
@@ -217,19 +237,24 @@ sendTCP_ st addr x = join $ atomically | |||
217 | Nothing -> return $ return () | 237 | Nothing -> return $ return () |
218 | Just send -> return $ send $ OnionPacketResponse x | 238 | Just send -> return $ send $ OnionPacketResponse x |
219 | 239 | ||
220 | tcpRelay :: SockAddr -> (SockAddr -> OnionRequest N1 -> IO ()) -> IO (ServerHandle, Int -> OnionMessage Encrypted -> IO ()) | 240 | tcpRelay :: TransportCrypto |
221 | tcpRelay udp_addr sendOnion = do | 241 | -> SockAddr -- ^ UDP bind address (this port may be tried for TCP if hardcoded defaults dont work). |
222 | crypto <- newCrypto | 242 | -> (SockAddr -> OnionRequest N1 -> IO ()) -- ^ This callback will be used to forward onion messages over udp. |
243 | -> IO ( ServerHandle -- Handle to the Tox Tcp-Relay server. | ||
244 | , Int -> OnionMessage Encrypted -> IO () -- forward onion response to tcp client. | ||
245 | ) | ||
246 | tcpRelay crypto udp_addr sendOnion = do | ||
223 | cons <- newTVarIO Map.empty | 247 | cons <- newTVarIO Map.empty |
224 | clients <- newTVarIO IntMap.empty | 248 | clients <- newTVarIO IntMap.empty |
225 | b443 <- getBindAddress "443" True | 249 | b443 <- getBindAddress "443" True |
226 | b80 <- getBindAddress "80" True | 250 | b80 <- getBindAddress "80" True |
251 | b3389 <- getBindAddress "3389" True | ||
227 | b33445 <- getBindAddress "33445" True | 252 | b33445 <- getBindAddress "33445" True |
228 | bany <- getBindAddress "" True | 253 | bany <- getBindAddress "" True |
229 | h <- streamServer ServerConfig | 254 | h <- streamServer ServerConfig |
230 | { serverWarn = hPutStrLn stderr | 255 | { serverWarn = hPutStrLn stderr |
231 | , serverSession = relaySession crypto cons sendOnion | 256 | , serverSession = relaySession crypto clients cons sendOnion |
232 | } | 257 | } |
233 | [b443,b80,udp_addr,b33445,bany] | 258 | [b443,b80,b3389,udp_addr,b33445,bany] |
234 | return (h,sendTCP_ clients) | 259 | return (h,sendTCP_ clients) |
235 | 260 | ||
diff --git a/dht/src/Network/Tox/TCP.hs b/dht/src/Network/Tox/TCP.hs index 13da804f..ca4ca817 100644 --- a/dht/src/Network/Tox/TCP.hs +++ b/dht/src/Network/Tox/TCP.hs | |||
@@ -48,7 +48,8 @@ import Network.Tox.DHT.Handlers (toxSpace) | |||
48 | import Network.Tox.Onion.Transport hiding (encrypt,decrypt) | 48 | import Network.Tox.Onion.Transport hiding (encrypt,decrypt) |
49 | import Network.Tox.Onion.Handlers (unwrapAnnounceResponse) | 49 | import Network.Tox.Onion.Handlers (unwrapAnnounceResponse) |
50 | import qualified Network.Tox.NodeId as UDP | 50 | import qualified Network.Tox.NodeId as UDP |
51 | 51 | import Text.XXD | |
52 | import Data.Proxy | ||
52 | 53 | ||
53 | withSize :: Sized x => (Size x -> m (p x)) -> m (p x) | 54 | withSize :: Sized x => (Size x -> m (p x)) -> m (p x) |
54 | withSize f = case size of len -> f len | 55 | withSize f = case size of len -> f len |
@@ -89,14 +90,23 @@ tcpStream crypto = StreamHandshake | |||
89 | noncef <- lookupNonceFunction crypto (transportSecret crypto) (UDP.id2key $ nodeId addr) | 90 | noncef <- lookupNonceFunction crypto (transportSecret crypto) (UDP.id2key $ nodeId addr) |
90 | dput XTCP $ "TCP:" ++ show addr ++ " <-- " ++ show hello | 91 | dput XTCP $ "TCP:" ++ show addr ++ " <-- " ++ show hello |
91 | hPut h $ encode $ encryptPayload (noncef $ helloNonce hello) hello | 92 | hPut h $ encode $ encryptPayload (noncef $ helloNonce hello) hello |
92 | welcomeE <- withSize $ fmap decode . hGet h . constSize | 93 | (welcomeE, wbs) <- do |
94 | let sz0 = size | ||
95 | sz = constSize sz0 | ||
96 | bs <- hGet h sz | ||
97 | return ( fmap (`asProxyTypeOf` sz0) $ decode bs, bs ) | ||
93 | let mwelcome = welcomeE >>= \w -> decryptPayload (noncef $ welcomeNonce w) w | 98 | let mwelcome = welcomeE >>= \w -> decryptPayload (noncef $ welcomeNonce w) w |
94 | nil = SessionProtocol | 99 | nil = SessionProtocol |
95 | { streamGoodbye = return () | 100 | { streamGoodbye = return () |
96 | , streamDecode = return Nothing | 101 | , streamDecode = return Nothing |
97 | , streamEncode = \y -> dput XTCP $ "TCP nil <-- " ++ show y | 102 | , streamEncode = \y -> dput XTCP $ "TCP nil <-- " ++ show y |
98 | } | 103 | } |
99 | either (\_ -> return nil) id $ mwelcome <&> \welcome -> do | 104 | either (\e -> do |
105 | dput XTCP $ "welcome: " ++ show (Data.ByteString.length wbs) ++ " bytes." | ||
106 | forM_ (xxd2 0 wbs) $ dput XTCP | ||
107 | dput XTCP $ "TCP(fail welcome): " ++ e | ||
108 | return nil | ||
109 | ) id $ mwelcome <&> \welcome -> do | ||
100 | dput XTCP $ "TCP:" ++ show addr ++ " --> " ++ show welcome | 110 | dput XTCP $ "TCP:" ++ show addr ++ " --> " ++ show welcome |
101 | noncef' <- lookupNonceFunction crypto skey (sessionPublicKey $ runIdentity $ welcomeData welcome) | 111 | noncef' <- lookupNonceFunction crypto skey (sessionPublicKey $ runIdentity $ welcomeData welcome) |
102 | nsend <- newMVar (sessionBaseNonce $ runIdentity $ helloData hello) | 112 | nsend <- newMVar (sessionBaseNonce $ runIdentity $ helloData hello) |
@@ -118,6 +128,7 @@ tcpStream crypto = StreamHandshake | |||
118 | dput XTCP $ "TCP: Failed to decode packet." | 128 | dput XTCP $ "TCP: Failed to decode packet." |
119 | return Nothing | 129 | return Nothing |
120 | Right x -> do | 130 | Right x -> do |
131 | dput XTCP $ "TCP:"++ show addr ++ " --> packet!" | ||
121 | m24 <- timeout 1000000 (takeMVar nread) | 132 | m24 <- timeout 1000000 (takeMVar nread) |
122 | fmap join $ forM m24 $ \n24 -> do | 133 | fmap join $ forM m24 $ \n24 -> do |
123 | let r = decrypt (noncef' n24) x >>= decodePlain | 134 | let r = decrypt (noncef' n24) x >>= decodePlain |
@@ -133,16 +144,16 @@ tcpStream crypto = StreamHandshake | |||
133 | dput XTCP $ "TCP exception: " ++ show e | 144 | dput XTCP $ "TCP exception: " ++ show e |
134 | return Nothing | 145 | return Nothing |
135 | , streamEncode = \y -> do | 146 | , streamEncode = \y -> do |
136 | dput XTCP $ "TCP(acquire nonce):" ++ show addr ++ " <-- " ++ show y | 147 | -- dput XTCP $ "TCP(acquire nonce):" ++ show addr ++ " <-- " ++ show y |
137 | n24 <- takeMVar nsend | 148 | n24 <- takeMVar nsend |
138 | dput XTCP $ "TCP(got nonce):" ++ show addr ++ " <-- " ++ show y | 149 | -- dput XTCP $ "TCP(got nonce):" ++ show addr ++ " <-- " ++ show y |
139 | let bs = encode $ encrypt (noncef' n24) $ encodePlain y | 150 | let bs = encode $ encrypt (noncef' n24) $ encodePlain y |
140 | ($ h) -- bracket (takeMVar hvar) (putMVar hvar) | 151 | ($ h) -- bracket (takeMVar hvar) (putMVar hvar) |
141 | $ \h -> hPut h (encode (fromIntegral $ Data.ByteString.length bs :: Word16) <> bs) | 152 | $ \h -> hPut h (encode (fromIntegral $ Data.ByteString.length bs :: Word16) <> bs) |
142 | `catchIOError` \e -> dput XTCP $ "TCP write exception: " ++ show e | 153 | `catchIOError` \e -> dput XTCP $ "TCP write exception: " ++ show e |
143 | dput XTCP $ "TCP(incrementing nonce): " ++ show addr ++ " <-- " ++ show y | 154 | -- dput XTCP $ "TCP(incrementing nonce): " ++ show addr ++ " <-- " ++ show y |
144 | putMVar nsend (incrementNonce24 n24) | 155 | putMVar nsend (incrementNonce24 n24) |
145 | dput XTCP $ "TCP(finished): " ++ show addr ++ " <-- " ++ show y | 156 | dput XTCP $ "TCP: " ++ show addr ++ " <-- " ++ show y |
146 | } | 157 | } |
147 | , streamAddr = nodeAddr | 158 | , streamAddr = nodeAddr |
148 | } | 159 | } |