summaryrefslogtreecommitdiff
path: root/Mainline.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Mainline.hs')
-rw-r--r--Mainline.hs41
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 #-}
9module Mainline where 10module Mainline where
@@ -382,12 +383,13 @@ is4mapped ip
382 | otherwise = False 383 | otherwise = False
383 384
384prefer4or6 :: NodeInfo -> Maybe WantIP -> WantIP 385prefer4or6 :: NodeInfo -> Maybe WantIP -> WantIP
385prefer4or6 addr iptyp = fromMaybe unspecified iptyp 386prefer4or6 addr iptyp = fromMaybe (ipFamily $ nodeIP addr) iptyp
386 where 387
387 unspecified = case nodeIP addr of 388ipFamily :: IP -> WantIP
388 IPv4 _ -> Want_IP4 389ipFamily 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
392findNodeH :: Routing -> NodeInfo -> FindNode -> IO NodeFound 394findNodeH :: Routing -> NodeInfo -> FindNode -> IO NodeFound
393findNodeH routing addr (FindNode node iptyp) = do 395findNodeH 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
454getPeersH :: Routing -> SwarmsDatabase -> NodeInfo -> GetPeers -> IO GotPeers 455getPeersH :: Routing -> SwarmsDatabase -> NodeInfo -> GetPeers -> IO GotPeers
455getPeersH routing (SwarmsDatabase peers toks _) naddr (GetPeers ih iptyp) = do 456getPeersH 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.