summaryrefslogtreecommitdiff
path: root/Mainline.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-07-15 00:38:41 -0400
committerjoe <joe@jerkface.net>2017-07-15 00:39:04 -0400
commitfd000ff5586ebda9e3a85e44be634a2570360335 (patch)
tree15192bd0767ee1b2668d1becba1aacb633d2c10a /Mainline.hs
parent9d5b5512ce3b5b885c0e331d6fcefa0b9d3fc42b (diff)
Implemented BEP 32 (IPv6 extensions) for get-peers.
Diffstat (limited to 'Mainline.hs')
-rw-r--r--Mainline.hs55
1 files changed, 21 insertions, 34 deletions
diff --git a/Mainline.hs b/Mainline.hs
index 12d1540b..e3a48976 100644
--- a/Mainline.hs
+++ b/Mainline.hs
@@ -23,6 +23,7 @@ import qualified Data.ByteArray as BA
23import qualified Data.ByteString as B 23import qualified Data.ByteString as B
24 ;import Data.ByteString (ByteString) 24 ;import Data.ByteString (ByteString)
25import Data.ByteString.Lazy (toStrict) 25import Data.ByteString.Lazy (toStrict)
26import Data.Coerce
26import Data.Data 27import Data.Data
27import Data.Default 28import Data.Default
28import Data.Hashable 29import Data.Hashable
@@ -413,13 +414,13 @@ instance BEncode GetPeers where
413 fromBEncode = fromDict $ GetPeers <$>! info_hash_key <*>? want_key 414 fromBEncode = fromDict $ GetPeers <$>! info_hash_key <*>? want_key
414 415
415 416
416type PeerList = Either [NodeInfo] [PeerAddr]
417
418data GotPeers = GotPeers 417data GotPeers = GotPeers
419 { -- | If the queried node has no peers for the infohash, returned 418 { -- | If the queried node has no peers for the infohash, returned
420 -- the K nodes in the queried nodes routing table closest to the 419 -- the K nodes in the queried nodes routing table closest to the
421 -- infohash supplied in the query. 420 -- infohash supplied in the query.
422 peers :: PeerList 421 peers :: [PeerAddr]
422
423 , nodes :: NodeFound
423 424
424 -- | The token value is a required argument for a future 425 -- | The token value is a required argument for a future
425 -- announce_peer query. 426 -- announce_peer query.
@@ -431,34 +432,22 @@ nodeIsIPv6 (NodeInfo _ (IPv6 _) _) = True
431nodeIsIPv6 _ = False 432nodeIsIPv6 _ = False
432 433
433instance BEncode GotPeers where 434instance BEncode GotPeers where
434 toBEncode GotPeers {..} = toDict $ 435 toBEncode GotPeers { nodes = NodeFound ns4 ns6, ..} = toDict $
435 case peers of 436 nodes_key .=? (if null ns4 then Nothing
436 Left ns 437 else Just $ S.runPut (mapM_ putNodeInfo4 ns4))
437 | let (ns6,ns4) = partition nodeIsIPv6 ns 438 .: nodes6_key .=? (if null ns6 then Nothing
438 -> 439 else Just $ S.runPut (mapM_ putNodeInfo4 ns6))
439 nodes_key .=? (if null ns4 then Nothing 440 .: token_key .=! grantedToken
440 else Just $ S.runPut (mapM_ putNodeInfo4 ns4)) 441 .: peers_key .=! map S.encode peers -- TODO: Spec says we shouldn't mix ip4/ip6 here.
441 .: nodes6_key .=? (if null ns6 then Nothing 442 -- (We could filter in MethodHandler.)
442 else Just $ S.runPut (mapM_ putNodeInfo4 ns6)) 443 .: endDict
443 .: token_key .=! grantedToken
444 .: endDict
445 Right ps ->
446 token_key .=! grantedToken
447 .: peers_key .=! map S.encode ps -- TODO: Spec says we shouldn't mix ip4/ip6 here.
448 -- (We could filter in MethodHandler.)
449 .: endDict
450 444
451 fromBEncode = fromDict $ do 445 fromBEncode = fromDict $ do
452 mns4 <- optional (binary getNodeInfo4 nodes_key) -- "nodes" 446 ns4 <- fromMaybe [] <$> optional (binary getNodeInfo4 nodes_key) -- "nodes"
453 mns6 <- optional (binary getNodeInfo6 nodes6_key) -- "nodes6" 447 ns6 <- fromMaybe [] <$> optional (binary getNodeInfo6 nodes6_key) -- "nodes6"
454 let mns = ((++) <$> mns4 <*> mns6) 448 tok <- field (req token_key) -- "token"
455 <|> mns4 449 ps <- fromMaybe [] <$> optional (field (req peers_key) >>= decodePeers) -- "values"
456 <|> mns6 450 pure $ GotPeers ps (NodeFound ns4 ns6) tok
457 tok <- field (req token_key) -- "token"
458 mps <- optional (field (req peers_key) >>= decodePeers) -- "values"
459 case (Right <$> mps) <|> (Left <$> mns) of
460 Nothing -> fail "get_peers: neihter peers nor nodes key is valid"
461 Just xs -> pure $ GotPeers xs tok
462 where 451 where
463 decodePeers = either fail pure . mapM S.decode 452 decodePeers = either fail pure . mapM S.decode
464 453
@@ -466,15 +455,13 @@ getPeersH :: Routing -> SwarmsDatabase -> NodeInfo -> GetPeers -> IO GotPeers
466getPeersH routing (SwarmsDatabase peers toks _) naddr (GetPeers ih iptyp) = do 455getPeersH routing (SwarmsDatabase peers toks _) naddr (GetPeers ih iptyp) = do
467 ps <- do 456 ps <- do
468 tm <- getTimestamp 457 tm <- getTimestamp
469 ps <- atomically $ do 458 atomically $ do
470 (ps,store') <- Peers.freshPeers ih tm <$> readTVar peers 459 (ps,store') <- Peers.freshPeers ih tm <$> readTVar peers
471 writeTVar peers store' 460 writeTVar peers store'
472 return ps 461 return ps
473 if null ps
474 then Left <$> error "TODO: getClosest ih"
475 else return (Right ps)
476 tok <- grantToken toks naddr 462 tok <- grantToken toks naddr
477 return $ GotPeers ps tok 463 ns <- findNodeH routing naddr (FindNode (coerce ih) iptyp)
464 return $ GotPeers ps ns tok
478 465
479-- | Announce that the peer, controlling the querying node, is 466-- | Announce that the peer, controlling the querying node, is
480-- downloading a torrent on a port. 467-- downloading a torrent on a port.