diff options
Diffstat (limited to 'Mainline.hs')
-rw-r--r-- | Mainline.hs | 41 |
1 files changed, 24 insertions, 17 deletions
diff --git a/Mainline.hs b/Mainline.hs index e3a48976..19646aeb 100644 --- a/Mainline.hs +++ b/Mainline.hs | |||
@@ -4,6 +4,7 @@ | |||
4 | {-# LANGUAGE DeriveTraversable #-} | 4 | {-# LANGUAGE DeriveTraversable #-} |
5 | {-# LANGUAGE FlexibleInstances #-} | 5 | {-# LANGUAGE FlexibleInstances #-} |
6 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | 6 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} |
7 | {-# LANGUAGE LambdaCase #-} | ||
7 | {-# LANGUAGE PatternSynonyms #-} | 8 | {-# LANGUAGE PatternSynonyms #-} |
8 | {-# LANGUAGE StandaloneDeriving #-} | 9 | {-# LANGUAGE StandaloneDeriving #-} |
9 | module Mainline where | 10 | module Mainline where |
@@ -382,12 +383,13 @@ is4mapped ip | |||
382 | | otherwise = False | 383 | | otherwise = False |
383 | 384 | ||
384 | prefer4or6 :: NodeInfo -> Maybe WantIP -> WantIP | 385 | prefer4or6 :: NodeInfo -> Maybe WantIP -> WantIP |
385 | prefer4or6 addr iptyp = fromMaybe unspecified iptyp | 386 | prefer4or6 addr iptyp = fromMaybe (ipFamily $ nodeIP addr) iptyp |
386 | where | 387 | |
387 | unspecified = case nodeIP addr of | 388 | ipFamily :: IP -> WantIP |
388 | IPv4 _ -> Want_IP4 | 389 | ipFamily ip = case ip of |
389 | IPv6 a | is4mapped a -> Want_IP4 | 390 | IPv4 _ -> Want_IP4 |
390 | | otherwise -> Want_IP6 | 391 | IPv6 a | is4mapped a -> Want_IP4 |
392 | | otherwise -> Want_IP6 | ||
391 | 393 | ||
392 | findNodeH :: Routing -> NodeInfo -> FindNode -> IO NodeFound | 394 | findNodeH :: Routing -> NodeInfo -> FindNode -> IO NodeFound |
393 | findNodeH routing addr (FindNode node iptyp) = do | 395 | findNodeH routing addr (FindNode node iptyp) = do |
@@ -438,8 +440,7 @@ instance BEncode GotPeers where | |||
438 | .: nodes6_key .=? (if null ns6 then Nothing | 440 | .: nodes6_key .=? (if null ns6 then Nothing |
439 | else Just $ S.runPut (mapM_ putNodeInfo4 ns6)) | 441 | else Just $ S.runPut (mapM_ putNodeInfo4 ns6)) |
440 | .: token_key .=! grantedToken | 442 | .: token_key .=! grantedToken |
441 | .: peers_key .=! map S.encode peers -- TODO: Spec says we shouldn't mix ip4/ip6 here. | 443 | .: peers_key .=! map S.encode peers |
442 | -- (We could filter in MethodHandler.) | ||
443 | .: endDict | 444 | .: endDict |
444 | 445 | ||
445 | fromBEncode = fromDict $ do | 446 | fromBEncode = fromDict $ do |
@@ -453,15 +454,21 @@ instance BEncode GotPeers where | |||
453 | 454 | ||
454 | getPeersH :: Routing -> SwarmsDatabase -> NodeInfo -> GetPeers -> IO GotPeers | 455 | getPeersH :: Routing -> SwarmsDatabase -> NodeInfo -> GetPeers -> IO GotPeers |
455 | getPeersH routing (SwarmsDatabase peers toks _) naddr (GetPeers ih iptyp) = do | 456 | getPeersH routing (SwarmsDatabase peers toks _) naddr (GetPeers ih iptyp) = do |
456 | ps <- do | 457 | ps <- do |
457 | tm <- getTimestamp | 458 | tm <- getTimestamp |
458 | atomically $ do | 459 | atomically $ do |
459 | (ps,store') <- Peers.freshPeers ih tm <$> readTVar peers | 460 | (ps,store') <- Peers.freshPeers ih tm <$> readTVar peers |
460 | writeTVar peers store' | 461 | writeTVar peers store' |
461 | return ps | 462 | return ps |
462 | tok <- grantToken toks naddr | 463 | -- Filter peer results to only a single address family, IPv4 or IPv6, as |
463 | ns <- findNodeH routing naddr (FindNode (coerce ih) iptyp) | 464 | -- per BEP 32. |
464 | return $ GotPeers ps ns tok | 465 | let notboth = iptyp >>= \case Want_Both -> Nothing |
466 | specific -> Just specific | ||
467 | selected = prefer4or6 naddr notboth | ||
468 | ps' = filter ( (== selected) . ipFamily . peerHost ) ps | ||
469 | tok <- grantToken toks naddr | ||
470 | ns <- findNodeH routing naddr (FindNode (coerce ih) iptyp) | ||
471 | return $ GotPeers ps' ns tok | ||
465 | 472 | ||
466 | -- | Announce that the peer, controlling the querying node, is | 473 | -- | Announce that the peer, controlling the querying node, is |
467 | -- downloading a torrent on a port. | 474 | -- downloading a torrent on a port. |