summaryrefslogtreecommitdiff
path: root/OnionRouter.hs
diff options
context:
space:
mode:
Diffstat (limited to 'OnionRouter.hs')
-rw-r--r--OnionRouter.hs31
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 #-}
3module OnionRouter where 4module OnionRouter where
4 5
5import Control.Concurrent.Lifted.Instrument 6import Control.Concurrent.Lifted.Instrument
@@ -15,6 +16,7 @@ import Network.Tox.Onion.Transport
15import qualified Network.Tox.TCP as TCP 16import qualified Network.Tox.TCP as TCP
16import qualified TCPProber as TCP 17import qualified TCPProber as TCP
17 18
19import Control.Arrow
18import Control.Concurrent.STM 20import Control.Concurrent.STM
19import Control.Concurrent.STM.TArray 21import Control.Concurrent.STM.TArray
20import Control.Monad 22import 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.
325selectTrampolines :: Show ni => OnionRouter -> TrampolineSet ni -> IO [ni] 331selectTrampolines :: OnionRouter -> IO (Either [TCP.NodeInfo] [NodeInfo])
326selectTrampolines or tset = do 332selectTrampolines 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
397handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do 410handleEvent 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 []