summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--OnionRouter.hs8
-rw-r--r--TCPProber.hs162
-rw-r--r--examples/dhtd.hs6
-rwxr-xr-xg2
-rw-r--r--src/Network/Tox.hs6
-rw-r--r--src/Network/Tox/TCP.hs52
6 files changed, 222 insertions, 14 deletions
diff --git a/OnionRouter.hs b/OnionRouter.hs
index 55ba9c28..39b3a872 100644
--- a/OnionRouter.hs
+++ b/OnionRouter.hs
@@ -12,6 +12,7 @@ import Network.QueryResponse
12import Network.Tox.NodeId 12import Network.Tox.NodeId
13import Network.Tox.Onion.Transport 13import Network.Tox.Onion.Transport
14import qualified Network.Tox.TCP as TCP 14import qualified Network.Tox.TCP as TCP
15import qualified TCPProber as TCP
15 16
16import Control.Concurrent.STM 17import Control.Concurrent.STM
17import Control.Concurrent.STM.TArray 18import Control.Concurrent.STM.TArray
@@ -83,6 +84,8 @@ data OnionRouter = OnionRouter
83 , tcpKademliaClient :: TCP.TCPClient String () Nonce8 84 , tcpKademliaClient :: TCP.TCPClient String () Nonce8
84 -- | This thread maintains the TCP relay table. 85 -- | This thread maintains the TCP relay table.
85 , tcpKademliaThread :: ThreadId 86 , tcpKademliaThread :: ThreadId
87 , tcpProber :: TCP.TCPProber
88 , tcpProberThread :: ThreadId
86 -- | Kademlia table of TCP relays. 89 -- | Kademlia table of TCP relays.
87 , tcpBucketRefresher :: BucketRefresher NodeId TCP.NodeInfo 90 , tcpBucketRefresher :: BucketRefresher NodeId TCP.NodeInfo
88 -- | Debug prints are written to this channel which is then flushed to 91 -- | Debug prints are written to this channel which is then flushed to
@@ -181,7 +184,8 @@ newOnionRouter crypto perror = do
181 tc <- newTVar 0 184 tc <- newTVar 0
182 pr <- newArray (0,11) 0 185 pr <- newArray (0,11) 0
183 rlog <- newTChan 186 rlog <- newTChan
184 refresher <- newBucketRefresher tbl (TCP.nodeSearch tcp) (fmap (maybe False $ const True) . TCP.tcpPing (TCP.tcpClient tcp)) 187 prober <- TCP.newProber
188 refresher <- newBucketRefresher tbl (TCP.nodeSearch prober tcp) (fmap (maybe False $ const True) . TCP.tcpPing (TCP.tcpClient tcp))
185 return OnionRouter 189 return OnionRouter
186 { pendingRoutes = pr 190 { pendingRoutes = pr
187 , onionDRG = drg 191 , onionDRG = drg
@@ -202,6 +206,8 @@ newOnionRouter crypto perror = do
202 , routeLog = rlog 206 , routeLog = rlog
203 , routeThread = error "forkRouteBuilder not invoked (missing onion route builder thread)." 207 , routeThread = error "forkRouteBuilder not invoked (missing onion route builder thread)."
204 , tcpKademliaThread = error "forkRouteBuilder not invoked (missing TCP bucket maintenance thread)." 208 , tcpKademliaThread = error "forkRouteBuilder not invoked (missing TCP bucket maintenance thread)."
209 , tcpProber = prober
210 , tcpProberThread = error "forkRouteBuilder not invoked (missing TCP probe thread)."
205 , routeLogger = perror 211 , routeLogger = perror
206 } 212 }
207 return or 213 return or
diff --git a/TCPProber.hs b/TCPProber.hs
new file mode 100644
index 00000000..8d468e53
--- /dev/null
+++ b/TCPProber.hs
@@ -0,0 +1,162 @@
1{-# LANGUAGE LambdaCase #-}
2module TCPProber where
3
4import Control.Concurrent
5import GHC.Conc
6
7import Control.Arrow
8import Control.Concurrent.STM
9import Control.Monad
10import Data.Function
11import Data.IP
12import Data.Maybe
13import Data.Time.Clock.POSIX
14import Network.Socket
15import System.Timeout
16
17import Crypto.Tox
18import Data.Wrapper.PSQ as PSQ
19import Network.Kademlia.Search
20import Network.Tox.NodeId
21import qualified Network.Tox.TCP as TCP
22
23resolvePort :: TCP.RelayClient -> NodeInfo -> IO (Maybe PortNumber)
24resolvePort tcp ni = do
25 got <- newTVarIO Nothing
26 cnt <- newTVarIO 0
27 let n port = TCP.NodeInfo ni port
28 forkPort port = do
29 atomically $ modifyTVar' cnt succ
30 t <- forkIO $ do
31 m <- TCP.tcpPing tcp $ n port
32 atomically $ do
33 mg <- readTVar got
34 when (isNothing mg)
35 $ forM_ m $ \_ -> writeTVar got $ Just port
36 modifyTVar' cnt pred
37 labelThread t $ "probe." ++ show port ++ "." ++ show (nodeId ni)
38 return t
39 readResult = atomically $ do
40 m <- readTVar got
41 case m of
42 Just v -> return $ Just v
43 Nothing -> readTVar cnt >>= check . (== 0) >> return Nothing
44 t443 <- forkPort 443
45 t80 <- forkPort 80
46 p <- timeout 1000000 readResult >>= \case
47 Just (Just p) -> do
48 killThread t443
49 killThread t80
50 return $ Just p
51 _ -> do
52 let uport = nodePort ni
53 tudp <- forM (guard $ uport `notElem` [443,80,3389,33445])
54 $ \() -> forkPort uport
55 t3389 <- forkPort 3389
56 t33445 <- forkPort 33445
57 p <- readResult
58 mapM_ killThread [t443,t80,t3389,t33445]
59 mapM_ killThread (tudp :: Maybe ThreadId)
60 return p
61 return p
62
63data TCPProber = TCPProber
64 { probeQueue :: TVar (PSQ' NodeId POSIXTime SockAddr{-UDP-})
65 , probeSpill :: TVar (PSQ' NodeId POSIXTime SockAddr{-UDP-})
66 , probeSpillCount :: TVar Int -- Data.HashPSQ has O(n) size, so we keep a count.
67 , probeCache :: TVar (PSQ' NodeId POSIXTime (SockAddr{-UDP-},PortNumber{-TCP-}))
68 , probeCacheCount :: TVar Int
69 }
70
71newProber :: STM TCPProber
72newProber = do
73 q <- newTVar PSQ.empty
74 spill <- newTVar PSQ.empty
75 spillcnt <- newTVar 0
76 cache <- newTVar PSQ.empty
77 cachecnt <- newTVar 0
78 return TCPProber
79 { probeQueue = q
80 , probeSpill = spill
81 , probeSpillCount = spillcnt
82 , probeCache = cache
83 , probeCacheCount = cachecnt
84 }
85
86
87enqueueProbe :: TCPProber -> NodeInfo -> IO ()
88enqueueProbe prober ni = do
89 tm <- getPOSIXTime
90 atomically $ do
91 spill <- readTVar (probeSpill prober)
92 cache <- readTVar (probeCache prober)
93 q <- readTVar (probeQueue prober)
94 let bump var x = modifyTVar' var $ insert' (nodeId ni) x tm
95 case PSQ.lookup (nodeId ni) cache of
96 Just (tm, x) -> bump (probeCache prober) x
97 Nothing | member (nodeId ni) spill -> bump (probeSpill prober) (nodeAddr ni)
98 | member (nodeId ni) q -> return ()
99 | otherwise -> bump (probeQueue prober) (nodeAddr ni)
100
101maxSpill :: Int
102maxSpill = 100
103
104maxCache :: Int
105maxCache = 50
106
107runProbeQueue :: TCPProber -> TCP.RelayClient -> Int -> IO ()
108runProbeQueue prober client maxjobs = do
109 jcnt <- newTVarIO 0
110 fix $ \loop -> do
111 (tm, mni) <- atomically $ do
112 j <- readTVar jcnt
113 check (j < maxjobs)
114 q <- readTVar $ probeQueue prober
115 case minView q of
116 Nothing -> retry
117 Just (Binding nid saddr tm,q') -> do
118 writeTVar (probeQueue prober) q'
119 return (tm, nodeInfo nid saddr)
120 forM_ mni $ \ni -> do
121 atomically $ modifyTVar' jcnt succ
122 t <- forkIO $ do
123 m <- resolvePort client ni
124 atomically $ case m of
125 Nothing -> do
126 pcnt <- readTVar (probeSpillCount prober)
127 modifyTVar' (probeSpill prober) $ insert' (nodeId ni) (nodeAddr ni) tm
128 if (pcnt == maxSpill)
129 then modifyTVar' (probeSpill prober) deleteMin
130 else modifyTVar' (probeSpillCount prober) succ
131 Just p -> do
132 ccnt <- readTVar (probeCacheCount prober)
133 modifyTVar' (probeCache prober) $ insert' (nodeId ni) (nodeAddr ni,p) tm
134 if (ccnt == maxCache)
135 then modifyTVar' (probeCache prober) deleteMin
136 else modifyTVar' (probeCacheCount prober) succ
137 atomically $ modifyTVar' jcnt pred
138 labelThread t ("probe."++show ni)
139 loop
140
141getNodes :: TCPProber -> TCP.TCPClient err () Nonce8 -> NodeId -> TCP.NodeInfo -> IO (Maybe ([TCP.NodeInfo],[TCP.NodeInfo],Maybe ()))
142getNodes prober tcp seeking dst = do
143 r <- TCP.getUDPNodes' tcp seeking (TCP.udpNodeInfo dst)
144 let tcps (ns,_,mb) = (ns',ns',mb)
145 where ns' = do
146 n <- ns
147 [ TCP.NodeInfo n 0 ]
148 fmap join $ forM r $ \(ns,gw) -> do
149 let ts = tcps ns
150 if TCP.nodeId gw == TCP.nodeId dst
151 then return $ Just ts
152 else do
153 enqueueProbe prober (TCP.udpNodeInfo dst)
154 return $ Just ts
155 return $ Just ts
156
157nodeSearch :: TCPProber -> TCP.TCPClient err () Nonce8 -> Search NodeId (IP, PortNumber) () TCP.NodeInfo TCP.NodeInfo
158nodeSearch prober tcp = Search
159 { searchSpace = TCP.tcpSpace
160 , searchNodeAddress = TCP.nodeIP &&& TCP.tcpPort
161 , searchQuery = getNodes prober tcp
162 }
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index 959383dc..1223edc8 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -97,6 +97,7 @@ import qualified Network.Tox.Onion.Transport as Tox
97import qualified Network.Tox.Onion.Handlers as Tox 97import qualified Network.Tox.Onion.Handlers as Tox
98import qualified Network.Tox.Crypto.Transport as Tox 98import qualified Network.Tox.Crypto.Transport as Tox
99import qualified Network.Tox.TCP as TCP 99import qualified Network.Tox.TCP as TCP
100import qualified TCPProber as TCP
100import Data.Typeable 101import Data.Typeable
101import Network.Tox.ContactInfo as Tox 102import Network.Tox.ContactInfo as Tox
102import OnionRouter 103import OnionRouter
@@ -1490,6 +1491,7 @@ initTox opts ssvar keysdb mbxmpp invc = case porttox opts of
1490 Want_IP4 -> toxStrap4 1491 Want_IP4 -> toxStrap4
1491 Want_IP6 -> toxStrap6 1492 Want_IP6 -> toxStrap6
1492 } 1493 }
1494 tcpprober = tcpProber $ Tox.toxOnionRoutes tox
1493 tcpclient = tcpKademliaClient $ Tox.toxOnionRoutes tox 1495 tcpclient = tcpKademliaClient $ Tox.toxOnionRoutes tox
1494 tcpRefresher = tcpBucketRefresher $ Tox.toxOnionRoutes tox 1496 tcpRefresher = tcpBucketRefresher $ Tox.toxOnionRoutes tox
1495 tcpDHT = DHT 1497 tcpDHT = DHT
@@ -1500,9 +1502,9 @@ initTox opts ssvar keysdb mbxmpp invc = case porttox opts of
1500 , pingShowResult = show 1502 , pingShowResult = show
1501 } 1503 }
1502 , dhtQuery = Map.singleton "node" DHTQuery 1504 , dhtQuery = Map.singleton "node" DHTQuery
1503 { qsearch = TCP.nodeSearch tcpclient 1505 { qsearch = TCP.nodeSearch tcpprober tcpclient
1504 , qhandler = \ni nid -> do 1506 , qhandler = \ni nid -> do
1505 ns <- R.kclosest (searchSpace $ TCP.nodeSearch tcpclient) searchK nid 1507 ns <- R.kclosest (searchSpace $ TCP.nodeSearch tcpprober tcpclient) searchK nid
1506 <$> atomically (readTVar $ refreshBuckets tcpRefresher) 1508 <$> atomically (readTVar $ refreshBuckets tcpRefresher)
1507 return (ns,ns,Just ()) 1509 return (ns,ns,Just ())
1508 , qshowR = show -- TCP.NodeInfo 1510 , qshowR = show -- TCP.NodeInfo
diff --git a/g b/g
index b5cdc09b..4ebe82ed 100755
--- a/g
+++ b/g
@@ -13,7 +13,7 @@ done
13 13
14warn="-freverse-errors -fwarn-unused-imports -Wmissing-signatures -fdefer-typed-holes" 14warn="-freverse-errors -fwarn-unused-imports -Wmissing-signatures -fdefer-typed-holes"
15exts="-XOverloadedStrings -XRecordWildCards" 15exts="-XOverloadedStrings -XRecordWildCards"
16defs="-DBENCODE_AESON -DTHREAD_DEBUG" 16defs="-DBENCODE_AESON -DTHREAD_DEBUG -UVERSION_lens"
17hidden="crypto-random crypto-api crypto-numbers cryptohash prettyclass" 17hidden="crypto-random crypto-api crypto-numbers cryptohash prettyclass"
18[ "$rootname" == "stack" ] && hidden="" 18[ "$rootname" == "stack" ] && hidden=""
19hide="" 19hide=""
diff --git a/src/Network/Tox.hs b/src/Network/Tox.hs
index ea9bbe56..d42f447d 100644
--- a/src/Network/Tox.hs
+++ b/src/Network/Tox.hs
@@ -65,6 +65,7 @@ import Network.Tox.ContactInfo
65import Text.XXD 65import Text.XXD
66import DPut 66import DPut
67import DebugTag 67import DebugTag
68import TCPProber
68import Network.Tox.Avahi 69import Network.Tox.Avahi
69import Network.Tox.Session 70import Network.Tox.Session
70import Network.Tox.Relay 71import Network.Tox.Relay
@@ -375,6 +376,10 @@ forkTox tox with_avahi = do
375 quitNC <- forkListener "toxCrypto" (toxCrypto tox) 376 quitNC <- forkListener "toxCrypto" (toxCrypto tox)
376 quitTCP <- forkListener "relay-client" (clientNet $ tcpClient $ tcpKademliaClient $ toxOnionRoutes tox) 377 quitTCP <- forkListener "relay-client" (clientNet $ tcpClient $ tcpKademliaClient $ toxOnionRoutes tox)
377 tcpKademlia <- forkPollForRefresh (tcpBucketRefresher $ toxOnionRoutes tox) 378 tcpKademlia <- forkPollForRefresh (tcpBucketRefresher $ toxOnionRoutes tox)
379 tcpprobe <- forkIO $ runProbeQueue (tcpProber $ toxOnionRoutes tox)
380 (tcpClient $ tcpKademliaClient $ toxOnionRoutes tox)
381 12
382 labelThread tcpprobe "tcp-probe"
378 quitAvahi <- if with_avahi then do 383 quitAvahi <- if with_avahi then do
379 forkPollForRefresh (DHT.refresher4 $ toxRouting tox) 384 forkPollForRefresh (DHT.refresher4 $ toxRouting tox)
380 forkPollForRefresh (DHT.refresher6 $ toxRouting tox) 385 forkPollForRefresh (DHT.refresher6 $ toxRouting tox)
@@ -392,6 +397,7 @@ forkTox tox with_avahi = do
392 quitOnion 397 quitOnion
393 quitTCP 398 quitTCP
394 killThread tcpKademlia 399 killThread tcpKademlia
400 killThread tcpprobe
395 quitToRoute 401 quitToRoute
396 quitHs 402 quitHs
397 , bootstrap (DHT.refresher4 $ toxRouting tox) 403 , bootstrap (DHT.refresher4 $ toxRouting tox)
diff --git a/src/Network/Tox/TCP.hs b/src/Network/Tox/TCP.hs
index 48059108..e3f5012b 100644
--- a/src/Network/Tox/TCP.hs
+++ b/src/Network/Tox/TCP.hs
@@ -16,6 +16,7 @@ import Data.Functor.Identity
16import Data.Hashable 16import Data.Hashable
17import qualified Data.HashMap.Strict as HashMap 17import qualified Data.HashMap.Strict as HashMap
18import Data.IP 18import Data.IP
19import Data.Maybe
19import Data.Monoid 20import Data.Monoid
20import Data.Serialize 21import Data.Serialize
21import Data.Word 22import Data.Word
@@ -24,13 +25,14 @@ import Network.Socket (SockAddr(..))
24import qualified Text.ParserCombinators.ReadP as RP 25import qualified Text.ParserCombinators.ReadP as RP
25import System.IO.Error 26import System.IO.Error
26 27
28import ControlMaybe
27import Crypto.Tox 29import Crypto.Tox
28import Data.ByteString (hPut,hGet,ByteString,length) 30import Data.ByteString (hPut,hGet,ByteString,length)
29import Data.Tox.Relay 31import Data.Tox.Relay
30import qualified Data.Word64Map 32import qualified Data.Word64Map
31import DebugTag 33import DebugTag
32import DPut 34import DPut
33import Network.Address (setPort,PortNumber) 35import Network.Address (setPort,PortNumber,localhost4,fromSockAddr)
34import Network.Kademlia.Routing 36import Network.Kademlia.Routing
35import Network.Kademlia.Search hiding (sendQuery) 37import Network.Kademlia.Search hiding (sendQuery)
36import Network.QueryResponse 38import Network.QueryResponse
@@ -116,7 +118,13 @@ tcpStream crypto = StreamHandshake
116 dput XTCP $ "TCP:" ++ show addr ++ " <-- " ++ show hello 118 dput XTCP $ "TCP:" ++ show addr ++ " <-- " ++ show hello
117 hPut h $ encode $ encryptPayload (noncef $ helloNonce hello) hello 119 hPut h $ encode $ encryptPayload (noncef $ helloNonce hello) hello
118 welcomeE <- withSize $ fmap decode . hGet h . constSize 120 welcomeE <- withSize $ fmap decode . hGet h . constSize
119 let Right welcome = welcomeE >>= \w -> decryptPayload (noncef $ welcomeNonce w) w 121 let mwelcome = welcomeE >>= \w -> decryptPayload (noncef $ welcomeNonce w) w
122 nil = SessionProtocol
123 { streamGoodbye = return ()
124 , streamDecode = return Nothing
125 , streamEncode = \y -> return ()
126 }
127 either (\_ -> return nil) id $ mwelcome <&> \welcome -> do
120 dput XTCP $ "TCP:" ++ show addr ++ " --> " ++ show welcome 128 dput XTCP $ "TCP:" ++ show addr ++ " --> " ++ show welcome
121 noncef' <- lookupNonceFunction crypto skey (sessionPublicKey $ runIdentity $ welcomeData welcome) 129 noncef' <- lookupNonceFunction crypto skey (sessionPublicKey $ runIdentity $ welcomeData welcome)
122 nsend <- newMVar (sessionBaseNonce $ runIdentity $ helloData hello) 130 nsend <- newMVar (sessionBaseNonce $ runIdentity $ helloData hello)
@@ -166,12 +174,14 @@ toxTCP crypto = tcpTransport 30 (tcpStream crypto)
166tcpSpace :: KademliaSpace NodeId NodeInfo 174tcpSpace :: KademliaSpace NodeId NodeInfo
167tcpSpace = contramap udpNodeInfo toxSpace 175tcpSpace = contramap udpNodeInfo toxSpace
168 176
177{-
169nodeSearch :: TCPClient err () Nonce8 -> Search NodeId (IP, PortNumber) () NodeInfo NodeInfo 178nodeSearch :: TCPClient err () Nonce8 -> Search NodeId (IP, PortNumber) () NodeInfo NodeInfo
170nodeSearch tcp = Search 179nodeSearch tcp = Search
171 { searchSpace = tcpSpace 180 { searchSpace = tcpSpace
172 , searchNodeAddress = nodeIP &&& tcpPort 181 , searchNodeAddress = nodeIP &&& tcpPort
173 , searchQuery = getTCPNodes tcp 182 , searchQuery = getNodes tcp
174 } 183 }
184-}
175 185
176data TCPClient err meth tid = TCPClient 186data TCPClient err meth tid = TCPClient
177 { tcpCrypto :: TransportCrypto 187 { tcpCrypto :: TransportCrypto
@@ -179,24 +189,44 @@ data TCPClient err meth tid = TCPClient
179 , tcpGetGateway :: UDP.NodeInfo -> STM (Maybe NodeInfo) 189 , tcpGetGateway :: UDP.NodeInfo -> STM (Maybe NodeInfo)
180 } 190 }
181 191
192{-
182getTCPNodes :: TCPClient err () Nonce8 -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ())) 193getTCPNodes :: TCPClient err () Nonce8 -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ()))
183getTCPNodes tcp seeking dst = do 194getTCPNodes tcp seeking dst = do
184 r <- getUDPNodes tcp seeking (udpNodeInfo dst) 195 r <- getUDPNodes' tcp seeking (udpNodeInfo dst)
185 let tcps (ns,_,mb) = (ns',ns',mb) 196 let tcps (ns,_,mb) = (ns',ns',mb)
186 where ns' = do 197 where ns' = do
187 n <- ns 198 n <- ns
188 [ NodeInfo n (fromIntegral 443) , NodeInfo n (fromIntegral 80) , NodeInfo n (UDP.nodePort n) ] 199 [ NodeInfo n (fromIntegral 443) , NodeInfo n (fromIntegral 80) , NodeInfo n (UDP.nodePort n) ]
189 return $ tcps <$> r 200 fmap join $ forM r $ \(ns,gw) -> do
201 let ts = tcps ns
202 {-
203 if nodeId gw == nodeId dst
204 then return $ Just ts
205 else do
206 forkIO $ void $ tcpPing (tcpClient tcp) dst
207 return $ Just ts
208 -}
209 forM_ ((\(xs,_,_) -> xs) ts) (forkIO . void . tcpPing (tcpClient tcp))
210 return $ Just ts
211-}
190 212
191getUDPNodes :: TCPClient err () Nonce8 -> NodeId -> UDP.NodeInfo -> IO (Maybe ([UDP.NodeInfo], [UDP.NodeInfo], Maybe ())) 213getUDPNodes :: TCPClient err () Nonce8 -> NodeId -> UDP.NodeInfo -> IO (Maybe ([UDP.NodeInfo], [UDP.NodeInfo], Maybe ()))
192getUDPNodes tcp seeking dst = do 214getUDPNodes tcp seeking dst = fmap fst <$> getUDPNodes' tcp seeking dst
193 mgateway <- atomically $ tcpGetGateway tcp dst 215
216getUDPNodes' :: TCPClient err () Nonce8 -> NodeId -> UDP.NodeInfo -> IO (Maybe (([UDP.NodeInfo], [UDP.NodeInfo], Maybe ()), NodeInfo))
217getUDPNodes' tcp seeking dst0 = do
218 mgateway <- atomically $ tcpGetGateway tcp dst0
194 fmap join $ forM mgateway $ \gateway -> do 219 fmap join $ forM mgateway $ \gateway -> do
195 (b,c,n24) <- atomically $ do 220 (b,c,n24) <- atomically $ do
196 b <- transportNewKey (tcpCrypto tcp) 221 b <- transportNewKey (tcpCrypto tcp)
197 c <- transportNewKey (tcpCrypto tcp) 222 c <- transportNewKey (tcpCrypto tcp)
198 n24 <- transportNewNonce (tcpCrypto tcp) 223 n24 <- transportNewNonce (tcpCrypto tcp)
199 return (b,c,n24) 224 return (b,c,n24)
225 let (dst,gateway') = if UDP.nodeId dst0 == nodeId gateway
226 then ( dst0 { UDP.nodeIP = fromJust $ fromSockAddr localhost4 }
227 , gateway { udpNodeInfo = (udpNodeInfo gateway)
228 { UDP.nodeIP = fromJust $ fromSockAddr localhost4 }})
229 else (dst0,gateway)
200 wrap2 <- lookupNonceFunction (tcpCrypto tcp) b (UDP.id2key $ UDP.nodeId dst) 230 wrap2 <- lookupNonceFunction (tcpCrypto tcp) b (UDP.id2key $ UDP.nodeId dst)
201 wrap1 <- lookupNonceFunction (tcpCrypto tcp) c (UDP.id2key $ nodeId gateway) 231 wrap1 <- lookupNonceFunction (tcpCrypto tcp) c (UDP.id2key $ nodeId gateway)
202 wrap0 <- lookupNonceFunction (tcpCrypto tcp) (transportSecret $ tcpCrypto tcp) (UDP.id2key $ UDP.nodeId dst) 232 wrap0 <- lookupNonceFunction (tcpCrypto tcp) (transportSecret $ tcpCrypto tcp) (UDP.id2key $ UDP.nodeId dst)
@@ -205,7 +235,7 @@ getUDPNodes tcp seeking dst = do
205 , method = () -- meth 235 , method = () -- meth
206 , wrapQuery = \n8 src gateway x -> 236 , wrapQuery = \n8 src gateway x ->
207 OnionPacket n24 $ Addressed (UDP.nodeAddr dst) 237 OnionPacket n24 $ Addressed (UDP.nodeAddr dst)
208 $ wrapOnionPure b (wrap2 n24) (nodeAddr gateway) 238 $ wrapOnionPure b (wrap2 n24) (nodeAddr gateway')
209 $ wrapOnionPure c (wrap1 n24) (UDP.nodeAddr dst) 239 $ wrapOnionPure c (wrap1 n24) (UDP.nodeAddr dst)
210 $ NotForwarded $ encryptPayload (wrap0 n24) 240 $ NotForwarded $ encryptPayload (wrap0 n24)
211 $ OnionAnnounce Asymm 241 $ OnionAnnounce Asymm
@@ -221,7 +251,7 @@ getUDPNodes tcp seeking dst = do
221 r <- sendQuery (tcpClient tcp) meth (AnnounceRequest zeros32 seeking UDP.zeroID) gateway 251 r <- sendQuery (tcpClient tcp) meth (AnnounceRequest zeros32 seeking UDP.zeroID) gateway
222 forM r $ \response -> do 252 forM r $ \response -> do
223 let (ns,_,mb) = either (const ([],[],Nothing)) (unwrapAnnounceResponse Nothing dst) $ response 253 let (ns,_,mb) = either (const ([],[],Nothing)) (unwrapAnnounceResponse Nothing dst) $ response
224 return (ns,ns, const () <$> mb) 254 return ( (ns,ns, const () <$> mb), gateway )
225 255
226 256
227handleOOB :: PublicKey -> ByteString -> NodeInfo -> NodeInfo -> IO (Maybe (RelayPacket -> RelayPacket)) 257handleOOB :: PublicKey -> ByteString -> NodeInfo -> NodeInfo -> IO (Maybe (RelayPacket -> RelayPacket))
@@ -243,7 +273,9 @@ tcpPing client dst = sendQuery client meth () dst
243 , method = () 273 , method = ()
244 } 274 }
245 275
246newClient :: TransportCrypto -> IO (Client String () Nonce8 NodeInfo RelayPacket) 276type RelayClient = Client String () Nonce8 NodeInfo RelayPacket
277
278newClient :: TransportCrypto -> IO RelayClient
247newClient crypto = do 279newClient crypto = do
248 net <- toxTCP crypto 280 net <- toxTCP crypto
249 drg <- drgNew 281 drg <- drgNew