diff options
Diffstat (limited to 'OnionRouter.hs')
-rw-r--r-- | OnionRouter.hs | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/OnionRouter.hs b/OnionRouter.hs index 0b0b7900..bbc9ad8f 100644 --- a/OnionRouter.hs +++ b/OnionRouter.hs | |||
@@ -1,5 +1,6 @@ | |||
1 | {-# LANGUAGE LambdaCase #-} | ||
1 | {-# LANGUAGE NondecreasingIndentation #-} | 2 | {-# LANGUAGE NondecreasingIndentation #-} |
2 | {-# LANGUAGE LambdaCase #-} | 3 | {-# LANGUAGE RankNTypes #-} |
3 | module OnionRouter where | 4 | module OnionRouter where |
4 | 5 | ||
5 | import Control.Concurrent.Lifted.Instrument | 6 | import Control.Concurrent.Lifted.Instrument |
@@ -15,6 +16,7 @@ import Network.Tox.Onion.Transport | |||
15 | import qualified Network.Tox.TCP as TCP | 16 | import qualified Network.Tox.TCP as TCP |
16 | import qualified TCPProber as TCP | 17 | import qualified TCPProber as TCP |
17 | 18 | ||
19 | import Control.Arrow | ||
18 | import Control.Concurrent.STM | 20 | import Control.Concurrent.STM |
19 | import Control.Concurrent.STM.TArray | 21 | import Control.Concurrent.STM.TArray |
20 | import Control.Monad | 22 | import Control.Monad |
@@ -64,6 +66,8 @@ data OnionRouter = OnionRouter | |||
64 | , trampolinesUDP :: TrampolineSet NodeInfo | 66 | , trampolinesUDP :: TrampolineSet NodeInfo |
65 | -- | A set for TCP relays to use as trampolines when UDP is not available. | 67 | -- | A set for TCP relays to use as trampolines when UDP is not available. |
66 | , trampolinesTCP :: TrampolineSet TCP.NodeInfo | 68 | , trampolinesTCP :: TrampolineSet TCP.NodeInfo |
69 | -- | True when we need to rely on TCP relays because UDP is apparently unavailable. | ||
70 | , tcpMode :: TVar Bool | ||
67 | -- | The pseudo-random generator used to select onion routes. | 71 | -- | The pseudo-random generator used to select onion routes. |
68 | , onionDRG :: TVar ChaChaDRG | 72 | , onionDRG :: TVar ChaChaDRG |
69 | -- | Building onion routes happens in a dedicated thread. See 'forkRouteBuilder'. | 73 | -- | Building onion routes happens in a dedicated thread. See 'forkRouteBuilder'. |
@@ -184,6 +188,7 @@ newOnionRouter crypto perror = do | |||
184 | tbl | 188 | tbl |
185 | (TCP.nodeSearch prober tcp) | 189 | (TCP.nodeSearch prober tcp) |
186 | (fmap (maybe False $ const True) . TCP.tcpPing (TCP.tcpClient tcp)) | 190 | (fmap (maybe False $ const True) . TCP.tcpPing (TCP.tcpClient tcp)) |
191 | tcpmode <- newTVar False | ||
187 | let o = OnionRouter | 192 | let o = OnionRouter |
188 | { pendingRoutes = pr | 193 | { pendingRoutes = pr |
189 | , onionDRG = drg | 194 | , onionDRG = drg |
@@ -201,6 +206,7 @@ newOnionRouter crypto perror = do | |||
201 | , setNodeClass = nodeClass . TCP.udpNodeInfo | 206 | , setNodeClass = nodeClass . TCP.udpNodeInfo |
202 | , setIDs = tti | 207 | , setIDs = tti |
203 | } | 208 | } |
209 | , tcpMode = tcpmode | ||
204 | , tcpKademliaClient = tcp | 210 | , tcpKademliaClient = tcp |
205 | { TCP.tcpClient = | 211 | { TCP.tcpClient = |
206 | let c = TCP.tcpClient tcp | 212 | let c = TCP.tcpClient tcp |
@@ -322,20 +328,27 @@ randomIvalInteger (l,h) rng | |||
322 | -- | 328 | -- |
323 | -- Only the DRG random seed is updated. Hopefully another thread will change the | 329 | -- Only the DRG random seed is updated. Hopefully another thread will change the |
324 | -- trampolineNodes set so that selection can succeed. | 330 | -- trampolineNodes set so that selection can succeed. |
325 | selectTrampolines :: Show ni => OnionRouter -> TrampolineSet ni -> IO [ni] | 331 | selectTrampolines :: OnionRouter -> IO (Either [TCP.NodeInfo] [NodeInfo]) |
326 | selectTrampolines or tset = do | 332 | selectTrampolines or = do |
327 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines") | 333 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines") |
328 | atomically (selectTrampolines' (onionDRG or) tset) >>= \case | 334 | let tset :: (forall x. TrampolineSet x -> STM (Either [x] [x])) |
335 | -> STM (Either (Either [TCP.NodeInfo] [NodeInfo]) | ||
336 | (Either [TCP.NodeInfo] [NodeInfo])) | ||
337 | tset f = bool (left Right . right Right <$> f (trampolinesUDP or)) | ||
338 | (left Left . right Left <$> f (trampolinesTCP or)) | ||
339 | =<< readTVar (tcpMode or) | ||
340 | atomically (tset $ selectTrampolines' (onionDRG or)) >>= \case | ||
329 | Left ns -> do | 341 | Left ns -> do |
330 | -- atomically $ writeTChan (routeLog or) | 342 | -- atomically $ writeTChan (routeLog or) |
331 | routeLogger or $ unwords | 343 | routeLogger or $ unwords |
332 | ( "ONION Discarding insecure trampolines:" : (map show ns) ) | 344 | ( "ONION Discarding insecure trampolines:" : (either (map show) (map show) ns)) |
333 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines.sleep") | 345 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines.sleep") |
334 | case ns of | 346 | case ns of |
335 | [_,_,_] -> threadDelay 1000000 -- wait 1 second if we failed the distinct3by predicate. | 347 | Left [_,_,_] -> threadDelay 1000000 -- wait 1 second if we failed the distinct3by predicate. |
348 | Right [_,_,_] -> threadDelay 1000000 -- wait 1 second if we failed the distinct3by predicate. | ||
336 | _ -> threadDelay 5000000 -- wait 5 seconds if insufficient nodes. | 349 | _ -> threadDelay 5000000 -- wait 5 seconds if insufficient nodes. |
337 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines") | 350 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines") |
338 | selectTrampolines or tset | 351 | selectTrampolines or |
339 | Right ns -> do | 352 | Right ns -> do |
340 | myThreadId >>= flip labelThread ("OnionRouter") | 353 | myThreadId >>= flip labelThread ("OnionRouter") |
341 | return ns | 354 | return ns |
@@ -397,7 +410,7 @@ handleEvent :: (NodeId -> NodeInfo -> IO (Maybe [NodeInfo])) -> OnionRouter -> R | |||
397 | handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do | 410 | handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do |
398 | routeLogger or $ "ONION Rebuilding RouteId " ++ show rid | 411 | routeLogger or $ "ONION Rebuilding RouteId " ++ show rid |
399 | mb <- do | 412 | mb <- do |
400 | ts <- selectTrampolines or (trampolinesUDP or) | 413 | mts <- selectTrampolines or |
401 | join . atomically $ do | 414 | join . atomically $ do |
402 | drg <- readTVar (onionDRG or) | 415 | drg <- readTVar (onionDRG or) |
403 | av <- newTVar Nothing | 416 | av <- newTVar Nothing |
@@ -416,6 +429,7 @@ handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do | |||
416 | csel = shiftR sel 4 .&. 0x3 | 429 | csel = shiftR sel 4 .&. 0x3 |
417 | sendq s q ni = fmap (listToMaybe . drop (fromIntegral s)) <$> getnodes q ni | 430 | sendq s q ni = fmap (listToMaybe . drop (fromIntegral s)) <$> getnodes q ni |
418 | sendqs = do | 431 | sendqs = do |
432 | let Right ts = mts | ||
419 | forkIO $ sendq asel aq (ts !! 0) >>= atomically . writeTVar av . Just | 433 | forkIO $ sendq asel aq (ts !! 0) >>= atomically . writeTVar av . Just |
420 | forkIO $ sendq bsel bq (ts !! 1) >>= atomically . writeTVar bv . Just | 434 | forkIO $ sendq bsel bq (ts !! 1) >>= atomically . writeTVar bv . Just |
421 | forkIO $ sendq csel cq (ts !! 2) >>= atomically . writeTVar cv . Just | 435 | forkIO $ sendq csel cq (ts !! 2) >>= atomically . writeTVar cv . Just |
@@ -433,6 +447,7 @@ handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do | |||
433 | tm | 447 | tm |
434 | return $ do | 448 | return $ do |
435 | myThreadId >>= flip labelThread ("OnionRouter.sendqs") | 449 | myThreadId >>= flip labelThread ("OnionRouter.sendqs") |
450 | let Right ts = mts | ||
436 | nodes <- case ts of | 451 | nodes <- case ts of |
437 | [_,_,_] -> sendqs | 452 | [_,_,_] -> sendqs |
438 | _ -> return [] | 453 | _ -> return [] |