diff options
Diffstat (limited to 'OnionRouter.hs')
-rw-r--r-- | OnionRouter.hs | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/OnionRouter.hs b/OnionRouter.hs index e3c32fbe..b11a0bf6 100644 --- a/OnionRouter.hs +++ b/OnionRouter.hs | |||
@@ -72,7 +72,7 @@ data OnionRouter = OnionRouter | |||
72 | -- | Each of the 12 routes has a version number here that is set larger | 72 | -- | Each of the 12 routes has a version number here that is set larger |
73 | -- than the 'routeVersion' set in 'routeMap' when the route should be | 73 | -- than the 'routeVersion' set in 'routeMap' when the route should be |
74 | -- discarded and replaced with a fresh one. | 74 | -- discarded and replaced with a fresh one. |
75 | , pendingRoutes :: IntMap (TVar Int) | 75 | , pendingRoutes :: TArray Int Int |
76 | -- | Debug prints are written to this channel which is then flushed to | 76 | -- | Debug prints are written to this channel which is then flushed to |
77 | -- 'routeLogger'. | 77 | -- 'routeLogger'. |
78 | , routeLog :: TChan String | 78 | , routeLog :: TChan String |
@@ -134,7 +134,7 @@ gotTimeout rr = rr | |||
134 | { timeoutCount = succ $ timeoutCount rr | 134 | { timeoutCount = succ $ timeoutCount rr |
135 | } | 135 | } |
136 | 136 | ||
137 | data RouteEvent = BuildRoute RouteId | 137 | newtype RouteEvent = BuildRoute RouteId |
138 | 138 | ||
139 | newOnionRouter :: (String -> IO ()) -> IO OnionRouter | 139 | newOnionRouter :: (String -> IO ()) -> IO OnionRouter |
140 | newOnionRouter perror = do | 140 | newOnionRouter perror = do |
@@ -148,10 +148,10 @@ newOnionRouter perror = do | |||
148 | tn <- newTVar IntMap.empty | 148 | tn <- newTVar IntMap.empty |
149 | ti <- newTVar HashMap.empty | 149 | ti <- newTVar HashMap.empty |
150 | tc <- newTVar 0 | 150 | tc <- newTVar 0 |
151 | vs <- sequence $ replicate 12 (newTVar 0) | 151 | pr <- newArray (0,11) 0 |
152 | rlog <- newTChan | 152 | rlog <- newTChan |
153 | return OnionRouter | 153 | return OnionRouter |
154 | { pendingRoutes = IntMap.fromList $ zip [0..11] vs | 154 | { pendingRoutes = pr |
155 | , onionDRG = drg | 155 | , onionDRG = drg |
156 | , pendingQueries = pq | 156 | , pendingQueries = pq |
157 | , routeMap = rm | 157 | , routeMap = rm |
@@ -170,17 +170,19 @@ forkRouteBuilder or getnodes = do | |||
170 | me <- myThreadId | 170 | me <- myThreadId |
171 | labelThread me "OnionRouter" | 171 | labelThread me "OnionRouter" |
172 | forever $ do | 172 | forever $ do |
173 | let checkRebuild rid want_build stm = flip orElse stm $ do | 173 | let checkRebuild :: Int -> Int -> STM RouteEvent |
174 | wanted_ver <- readTVar want_build | 174 | checkRebuild rid wanted_ver = do |
175 | current_ver <- fmap routeVersion <$> readArray (routeMap or) rid | 175 | current_ver <- fmap routeVersion <$> readArray (routeMap or) rid |
176 | writeTChan (routeLog or) $ "ONION checkRebuild "++show(current_ver,wanted_ver) | 176 | writeTChan (routeLog or) $ "ONION checkRebuild "++show(current_ver,wanted_ver) |
177 | check $ maybe True (< wanted_ver) current_ver | 177 | check $ maybe True (< wanted_ver) current_ver |
178 | return $ BuildRoute $ RouteId rid | 178 | return $ BuildRoute $ RouteId rid |
179 | io <- atomically $ | 179 | io <- atomically $ {-# SCC "forkRouteBuilder.log" #-} |
180 | (readTChan (routeLog or) >>= return . routeLogger or) | 180 | (readTChan (routeLog or) >>= return . routeLogger or) |
181 | `orElse` | 181 | `orElse` {-# SCC "forkRouteBuilder.checkRebuild" #-} |
182 | (IntMap.foldrWithKey checkRebuild retry (pendingRoutes or) | 182 | (let stms = map (\rid -> checkRebuild rid =<< readArray (pendingRoutes or) rid) |
183 | >>= return . handleEvent getnodes or { routeThread = me }) | 183 | [0..11] |
184 | in do event <- foldr1 orElse stms | ||
185 | return $ handleEvent getnodes or { routeThread = me } event) | ||
184 | io | 186 | io |
185 | return or { routeThread = tid } | 187 | return or { routeThread = tid } |
186 | 188 | ||
@@ -240,7 +242,9 @@ selectTrampolines or = do | |||
240 | routeLogger or $ unwords | 242 | routeLogger or $ unwords |
241 | ( "ONION Discarding insecure trampolines:" : (map (show . nodeAddr) ns) ) | 243 | ( "ONION Discarding insecure trampolines:" : (map (show . nodeAddr) ns) ) |
242 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines.sleep") | 244 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines.sleep") |
243 | threadDelay 1000000 | 245 | case ns of |
246 | [_,_,_] -> threadDelay 1000000 -- wait 1 second if we failed the distinct3by predicate. | ||
247 | _ -> threadDelay 5000000 -- wait 5 seconds if insufficient nodes. | ||
244 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines") | 248 | myThreadId >>= flip labelThread ("OnionRouter.selectTrampolines") |
245 | selectTrampolines or | 249 | selectTrampolines or |
246 | Right ns -> do | 250 | Right ns -> do |
@@ -347,7 +351,7 @@ handleEvent getnodes or e@(BuildRoute (RouteId rid)) = do | |||
347 | (freshRoute now r) | 351 | (freshRoute now r) |
348 | rid | 352 | rid |
349 | v <- routeVersion . fromJust <$> readArray (routeMap or) rid | 353 | v <- routeVersion . fromJust <$> readArray (routeMap or) rid |
350 | writeTVar (pendingRoutes or IntMap.! rid) v | 354 | writeArray (pendingRoutes or) rid v |
351 | ) | 355 | ) |
352 | mb | 356 | mb |
353 | case mb of | 357 | case mb of |
@@ -390,7 +394,7 @@ hookQueries or t8 tmethods = TransactionMethods | |||
390 | { dispatchRegister = \mvar od d -> {-# SCC "hookQ.dispatchRegister" #-} do -- :: MVar x -> d -> STM (tid, d) | 394 | { dispatchRegister = \mvar od d -> {-# SCC "hookQ.dispatchRegister" #-} do -- :: MVar x -> d -> STM (tid, d) |
391 | let ni = onionNodeInfo od | 395 | let ni = onionNodeInfo od |
392 | rid@(RouteId ridn) = fromMaybe (routeId (nodeId ni)) $ onionRouteSpec od | 396 | rid@(RouteId ridn) = fromMaybe (routeId (nodeId ni)) $ onionRouteSpec od |
393 | wanted <- {-# SCC "hookQ.wanted" #-} (readTVar (pendingRoutes or IntMap.! ridn)) | 397 | wanted <- {-# SCC "hookQ.wanted" #-} (readArray (pendingRoutes or) ridn) |
394 | mr <- {-# SCC "hookQ.mr_action" #-} (readArray (routeMap or) ridn) | 398 | mr <- {-# SCC "hookQ.mr_action" #-} (readArray (routeMap or) ridn) |
395 | -- Block query until a route is ready. | 399 | -- Block query until a route is ready. |
396 | check $ fromMaybe False $ do | 400 | check $ fromMaybe False $ do |
@@ -431,7 +435,7 @@ hookQueries or t8 tmethods = TransactionMethods | |||
431 | mrr <- readArray (routeMap or) rid | 435 | mrr <- readArray (routeMap or) rid |
432 | forM_ mrr $ \rr -> do | 436 | forM_ mrr $ \rr -> do |
433 | when (routeVersion rr == pendingVersion pq) $ do | 437 | when (routeVersion rr == pendingVersion pq) $ do |
434 | let expireRoute = modifyTVar' (pendingRoutes or IntMap.! rid) expire | 438 | let expireRoute = modifyArray (pendingRoutes or) expire rid |
435 | expire ver | ver <= succ (pendingVersion pq) = succ (pendingVersion pq) | 439 | expire ver | ver <= succ (pendingVersion pq) = succ (pendingVersion pq) |
436 | | otherwise = ver | 440 | | otherwise = ver |
437 | modifyArray (routeMap or) (fmap gotTimeout) rid | 441 | modifyArray (routeMap or) (fmap gotTimeout) rid |