diff options
author | joe <joe@jerkface.net> | 2017-07-08 22:10:40 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-07-08 22:10:40 -0400 |
commit | 8fe93b8e1d1d968bdf0b8a35335b060d92a9d7d7 (patch) | |
tree | 6e9a4b35f11de5ad0e4f422e0a6d268b5270befd /src/Network/BitTorrent | |
parent | f75d515bc0100e5ca372d592aa2f5f4ff2fc858c (diff) |
WIP: Tox encryption.
Diffstat (limited to 'src/Network/BitTorrent')
-rw-r--r-- | src/Network/BitTorrent/DHT.hs | 6 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Query.hs | 103 |
2 files changed, 81 insertions, 28 deletions
diff --git a/src/Network/BitTorrent/DHT.hs b/src/Network/BitTorrent/DHT.hs index fa8071d5..2535c05c 100644 --- a/src/Network/BitTorrent/DHT.hs +++ b/src/Network/BitTorrent/DHT.hs | |||
@@ -234,7 +234,7 @@ bootstrap :: forall raw dht u ip. | |||
234 | , Show u | 234 | , Show u |
235 | , Default u | 235 | , Default u |
236 | , Serialize u | 236 | , Serialize u |
237 | ) => Maybe BS.ByteString -> [NodeAddr ip] -> DHT raw dht u ip () | 237 | ) => Maybe BS.ByteString -> [PacketDestination dht] -> DHT raw dht u ip () |
238 | bootstrap mbs startNodes = do | 238 | bootstrap mbs startNodes = do |
239 | restored <- | 239 | restored <- |
240 | case decode <$> mbs of | 240 | case decode <$> mbs of |
@@ -250,7 +250,7 @@ bootstrap mbs startNodes = do | |||
250 | return ( ns :: [NodeInfo dht ip u] ) | 250 | return ( ns :: [NodeInfo dht ip u] ) |
251 | input_nodes <- (restored ++) . T.toList <$> getTable | 251 | input_nodes <- (restored ++) . T.toList <$> getTable |
252 | -- Step 1: Use iterative searches to flesh out the table.. | 252 | -- Step 1: Use iterative searches to flesh out the table.. |
253 | do let knowns = map (map $ nodeAddr . fst) input_nodes | 253 | do let knowns = map (map $ fst) input_nodes |
254 | -- Below, we reverse the nodes since the table serialization puts the | 254 | -- Below, we reverse the nodes since the table serialization puts the |
255 | -- nearest nodes last and we want to choose a similar node id to bootstrap | 255 | -- nearest nodes last and we want to choose a similar node id to bootstrap |
256 | -- faster. | 256 | -- faster. |
@@ -265,7 +265,7 @@ bootstrap mbs startNodes = do | |||
265 | when (null ns) $ do | 265 | when (null ns) $ do |
266 | -- TODO filter duplicated in startNodes list | 266 | -- TODO filter duplicated in startNodes list |
267 | -- TODO retransmissions for startNodes | 267 | -- TODO retransmissions for startNodes |
268 | (aliveNodes,_) <- unzip <$> queryParallel (pingQ <$> startNodes) | 268 | (aliveNodes,_) <- unzip <$> queryParallel (coldPingQ <$> startNodes) |
269 | _ <- searchAll $ take 2 aliveNodes | 269 | _ <- searchAll $ take 2 aliveNodes |
270 | return () | 270 | return () |
271 | -- Step 2: Repeatedly refresh incomplete buckets until the table is full. | 271 | -- Step 2: Repeatedly refresh incomplete buckets until the table is full. |
diff --git a/src/Network/BitTorrent/DHT/Query.hs b/src/Network/BitTorrent/DHT/Query.hs index 77fede94..60b772b3 100644 --- a/src/Network/BitTorrent/DHT/Query.hs +++ b/src/Network/BitTorrent/DHT/Query.hs | |||
@@ -35,6 +35,7 @@ module Network.BitTorrent.DHT.Query | |||
35 | -- single response. | 35 | -- single response. |
36 | , Iteration | 36 | , Iteration |
37 | , pingQ | 37 | , pingQ |
38 | , coldPingQ | ||
38 | , findNodeQ | 39 | , findNodeQ |
39 | , getPeersQ | 40 | , getPeersQ |
40 | , announceQ | 41 | , announceQ |
@@ -316,44 +317,72 @@ pingQ :: forall raw dht u ip. | |||
316 | , FiniteBits (NodeId dht) | 317 | , FiniteBits (NodeId dht) |
317 | , Show (NodeId dht) | 318 | , Show (NodeId dht) |
318 | , Show (QueryMethod dht) | 319 | , Show (QueryMethod dht) |
319 | ) => NodeAddr ip -> DHT raw dht u ip (NodeInfo dht ip u , Maybe ReflectedIP) | 320 | ) => NodeInfo dht ip u -> DHT raw dht u ip (NodeInfo dht ip u , Maybe ReflectedIP) |
320 | pingQ addr = do | 321 | pingQ ni = do |
321 | let ping = DHT.pingMessage (Proxy :: Proxy dht) | 322 | let ping = DHT.pingMessage (Proxy :: Proxy dht) |
322 | (nid, pong, mip) <- queryNode' addr ping | 323 | (nid, pong, mip) <- queryNode' ni ping |
323 | let _ = pong `asTypeOf` ping | 324 | let _ = pong `asTypeOf` ping |
324 | -- (nid, PingPayload{}, mip) <- queryNode' addr PingPayload {isPong=False, pingId=pid} | 325 | -- (nid, PingPayload{}, mip) <- queryNode' addr PingPayload {isPong=False, pingId=pid} |
325 | return (NodeInfo nid addr def, mip) | 326 | return (NodeInfo nid (nodeAddr ni) def, mip) |
327 | |||
328 | -- | The most basic query. May be used to check if the given node is | ||
329 | -- alive or get its 'NodeId'. | ||
330 | coldPingQ :: forall raw dht u ip. | ||
331 | ( DHT.Kademlia dht | ||
332 | , Address ip | ||
333 | , KRPC dht (Query dht (Ping dht)) (Response dht (Ping dht)) | ||
334 | , Default u | ||
335 | , Show u | ||
336 | , Ord (TransactionID dht) | ||
337 | , Serialize (TransactionID dht) | ||
338 | , WireFormat raw dht | ||
339 | , SerializableTo raw (Response dht (Ping dht)) | ||
340 | , SerializableTo raw (Query dht (Ping dht)) | ||
341 | , Ord (NodeId dht) | ||
342 | , FiniteBits (NodeId dht) | ||
343 | , Show (NodeId dht) | ||
344 | , Show (QueryMethod dht) | ||
345 | ) => PacketDestination dht -> DHT raw dht u ip (NodeInfo dht ip u , Maybe ReflectedIP) | ||
346 | coldPingQ dest = do | ||
347 | let ping = DHT.pingMessage (Proxy :: Proxy dht) | ||
348 | naddr <- maybe (throwIO $ QueryFailed ProtocolError "unable to construct NodeAddr from PacketDestination") | ||
349 | return | ||
350 | $ fromAddr dest | ||
351 | (nid, pong, mip) <- coldQueryNode' naddr dest ping | ||
352 | let _ = pong `asTypeOf` ping | ||
353 | -- (nid, PingPayload{}, mip) <- queryNode' addr PingPayload {isPong=False, pingId=pid} | ||
354 | return (NodeInfo nid naddr def, mip) | ||
326 | 355 | ||
327 | -- TODO [robustness] match range of returned node ids with the | 356 | -- TODO [robustness] match range of returned node ids with the |
328 | -- expected range and either filter bad nodes or discard response at | 357 | -- expected range and either filter bad nodes or discard response at |
329 | -- all throwing an exception | 358 | -- all throwing an exception |
330 | -- findNodeQ :: Address ip => TableKey key => key -> IterationI ip NodeInfo | 359 | -- findNodeQ :: Address ip => TableKey key => key -> IterationI ip NodeInfo |
331 | findNodeQ proxy key NodeInfo {..} = do | 360 | findNodeQ proxy key ni = do |
332 | closest <- fmap DHT.foundNodes $ DHT.findNodeMessage proxy key <@> nodeAddr | 361 | closest <- fmap DHT.foundNodes $ DHT.findNodeMessage proxy key <@> ni |
333 | $(logInfoS) "findNodeQ" $ "NodeFound\n" | 362 | $(logInfoS) "findNodeQ" $ "NodeFound\n" |
334 | <> T.pack (L.unlines $ L.map ((' ' :) . show . pPrint) closest) | 363 | <> T.pack (L.unlines $ L.map ((' ' :) . show . pPrint) closest) |
335 | return $ Right closest | 364 | return $ Right closest |
336 | 365 | ||
337 | #ifdef VERSION_bencoding | 366 | #ifdef VERSION_bencoding |
338 | getPeersQ :: Address ip => InfoHash -> Iteration BValue KMessageOf () ip PeerAddr | 367 | getPeersQ :: Address ip => InfoHash -> Iteration BValue KMessageOf () ip PeerAddr |
339 | getPeersQ topic NodeInfo {..} = do | 368 | getPeersQ topic ni = do |
340 | GotPeers {..} <- GetPeers topic <@> nodeAddr | 369 | GotPeers {..} <- GetPeers topic <@> ni |
341 | let dist = distance (toNodeId topic) nodeId | 370 | let dist = distance (toNodeId topic) (nodeId ni) |
342 | $(logInfoS) "getPeersQ" $ T.pack | 371 | $(logInfoS) "getPeersQ" $ T.pack |
343 | $ "distance: " <> render (pPrint dist) <> " , result: " | 372 | $ "distance: " <> render (pPrint dist) <> " , result: " |
344 | <> case peers of { Left _ -> "NODES"; Right _ -> "PEERS" } | 373 | <> case peers of { Left _ -> "NODES"; Right _ -> "PEERS" } |
345 | return peers | 374 | return peers |
346 | 375 | ||
347 | announceQ :: Address ip => InfoHash -> PortNumber -> Iteration BValue KMessageOf () ip NodeAddr | 376 | announceQ :: Address ip => InfoHash -> PortNumber -> Iteration BValue KMessageOf () ip NodeAddr |
348 | announceQ ih p NodeInfo {..} = do | 377 | announceQ ih p ni = do |
349 | GotPeers {..} <- GetPeers ih <@> nodeAddr | 378 | GotPeers {..} <- GetPeers ih <@> ni |
350 | case peers of | 379 | case peers of |
351 | Left ns | 380 | Left ns |
352 | | False -> undefined -- TODO check if we can announce | 381 | | False -> undefined -- TODO check if we can announce |
353 | | otherwise -> return (Left ns) | 382 | | otherwise -> return (Left ns) |
354 | Right _ -> do -- TODO *probably* add to peer cache | 383 | Right _ -> do -- TODO *probably* add to peer cache |
355 | Announced <- Announce False ih Nothing p grantedToken <@> nodeAddr | 384 | Announced <- Announce False ih Nothing p grantedToken <@> ni |
356 | return (Right [nodeAddr]) | 385 | return (Right [nodeAddr ni]) |
357 | #endif | 386 | #endif |
358 | 387 | ||
359 | {----------------------------------------------------------------------- | 388 | {----------------------------------------------------------------------- |
@@ -393,7 +422,7 @@ ioFindNode :: ( DHT.Kademlia dht | |||
393 | ioFindNode ih = do | 422 | ioFindNode ih = do |
394 | session <- ask | 423 | session <- ask |
395 | return $ \ni -> runDHT session $ do | 424 | return $ \ni -> runDHT session $ do |
396 | ns <- fmap DHT.foundNodes $ DHT.findNodeMessage Proxy ih <@> nodeAddr ni | 425 | ns <- fmap DHT.foundNodes $ DHT.findNodeMessage Proxy ih <@> ni |
397 | let ns' = L.map (fmap (const def)) ns | 426 | let ns' = L.map (fmap (const def)) ns |
398 | return $ L.partition (\n -> nodeId n /= toNodeId ih) ns' | 427 | return $ L.partition (\n -> nodeId n /= toNodeId ih) ns' |
399 | 428 | ||
@@ -422,7 +451,7 @@ ioFindNodes :: ( DHT.Kademlia dht | |||
422 | ioFindNodes ih = do | 451 | ioFindNodes ih = do |
423 | session <- ask | 452 | session <- ask |
424 | return $ \ni -> runDHT session $ do | 453 | return $ \ni -> runDHT session $ do |
425 | ns <- fmap DHT.foundNodes $ DHT.findNodeMessage Proxy ih <@> nodeAddr ni | 454 | ns <- fmap DHT.foundNodes $ DHT.findNodeMessage Proxy ih <@> ni |
426 | let ns' = L.map (fmap (const def)) ns | 455 | let ns' = L.map (fmap (const def)) ns |
427 | return ([], ns') | 456 | return ([], ns') |
428 | 457 | ||
@@ -504,9 +533,9 @@ probeNode :: ( Default u | |||
504 | , FiniteBits (NodeId dht) | 533 | , FiniteBits (NodeId dht) |
505 | , Show (NodeId dht) | 534 | , Show (NodeId dht) |
506 | , Show (QueryMethod dht) | 535 | , Show (QueryMethod dht) |
507 | ) => NodeAddr ip -> DHT raw dht u ip (Bool , Maybe ReflectedIP) | 536 | ) => NodeInfo dht ip u -> DHT raw dht u ip (Bool , Maybe ReflectedIP) |
508 | probeNode addr = do | 537 | probeNode addr = do |
509 | $(logDebugS) "routing.questionable_node" (T.pack (render (pPrint addr))) | 538 | $(logDebugS) "routing.questionable_node" (T.pack (render (pPrint $ nodeAddr addr))) |
510 | result <- try $ pingQ addr | 539 | result <- try $ pingQ addr |
511 | let _ = fmap (const ()) result :: Either QueryFailure () | 540 | let _ = fmap (const ()) result :: Either QueryFailure () |
512 | return $ either (const (False,Nothing)) (\(_,mip)->(True,mip)) result | 541 | return $ either (const (False,Nothing)) (\(_,mip)->(True,mip)) result |
@@ -549,7 +578,7 @@ refreshNodes nid = do | |||
549 | $(logWarnS) "refreshNodes" $ "received " <> T.pack (show (L.length ns)) <> " nodes." | 578 | $(logWarnS) "refreshNodes" $ "received " <> T.pack (show (L.length ns)) <> " nodes." |
550 | _ <- queryParallel $ flip L.map ns $ \n -> do | 579 | _ <- queryParallel $ flip L.map ns $ \n -> do |
551 | $(logWarnS) "refreshNodes" $ "received node: " <> T.pack (show (pPrint n)) | 580 | $(logWarnS) "refreshNodes" $ "received node: " <> T.pack (show (pPrint n)) |
552 | pingQ (nodeAddr n) | 581 | pingQ n |
553 | -- pingQ takes care of inserting the node. | 582 | -- pingQ takes care of inserting the node. |
554 | return () | 583 | return () |
555 | return () -- \$ L.concat nss | 584 | return () -- \$ L.concat nss |
@@ -622,7 +651,7 @@ insertNode1 = do | |||
622 | , fallbackID = nid :: NodeId dht | 651 | , fallbackID = nid :: NodeId dht |
623 | , adjustID = dhtAdjustID Proxy (DHT.fallbackID params) :: SockAddr -> Event dht ip u -> NodeId dht | 652 | , adjustID = dhtAdjustID Proxy (DHT.fallbackID params) :: SockAddr -> Event dht ip u -> NodeId dht |
624 | , logMessage = logm :: Char -> String -> IO () | 653 | , logMessage = logm :: Char -> String -> IO () |
625 | , pingProbe = probe :: NodeAddr ip -> IO (Bool, Maybe ReflectedIP) | 654 | , pingProbe = probe :: NodeInfo dht ip u -> IO (Bool, Maybe ReflectedIP) |
626 | } | 655 | } |
627 | tbl <- asks routingInfo | 656 | tbl <- asks routingInfo |
628 | let state = DHT.TableKeeper | 657 | let state = DHT.TableKeeper |
@@ -651,7 +680,7 @@ queryNode :: forall raw dht u a b ip. | |||
651 | , Show (QueryMethod dht) | 680 | , Show (QueryMethod dht) |
652 | , SerializableTo raw (Response dht (Ping dht)) | 681 | , SerializableTo raw (Response dht (Ping dht)) |
653 | , SerializableTo raw (Query dht (Ping dht)) | 682 | , SerializableTo raw (Query dht (Ping dht)) |
654 | ) => NodeAddr ip -> a -> DHT raw dht u ip (NodeId dht, b) | 683 | ) => NodeInfo dht ip u -> a -> DHT raw dht u ip (NodeId dht, b) |
655 | queryNode addr q = fmap (\(n,b,_) -> (n,b)) $ queryNode' addr q | 684 | queryNode addr q = fmap (\(n,b,_) -> (n,b)) $ queryNode' addr q |
656 | 685 | ||
657 | queryNode' :: forall raw dht u a b ip. | 686 | queryNode' :: forall raw dht u a b ip. |
@@ -672,15 +701,39 @@ queryNode' :: forall raw dht u a b ip. | |||
672 | , Show (QueryMethod dht) | 701 | , Show (QueryMethod dht) |
673 | , SerializableTo raw (Response dht (Ping dht)) | 702 | , SerializableTo raw (Response dht (Ping dht)) |
674 | , SerializableTo raw (Query dht (Ping dht)) | 703 | , SerializableTo raw (Query dht (Ping dht)) |
675 | ) => NodeAddr ip -> a -> DHT raw dht u ip (NodeId dht, b, Maybe ReflectedIP) | 704 | ) => NodeInfo dht ip u -> a -> DHT raw dht u ip (NodeId dht, b, Maybe ReflectedIP) |
676 | queryNode' addr q = do | 705 | queryNode' ni q = do |
677 | nid <- myNodeIdAccordingTo addr | 706 | let addr = nodeAddr ni |
707 | dest = makeAddress (Left $ nodeId ni) (toSockAddr addr) | ||
708 | coldQueryNode' addr dest q | ||
709 | |||
710 | coldQueryNode' :: forall raw dht u a b ip. | ||
711 | ( Address ip | ||
712 | , Default u | ||
713 | , Show u | ||
714 | , DHT.Kademlia dht | ||
715 | , KRPC dht (Query dht a) (Response dht b) | ||
716 | , KRPC dht (Query dht (Ping dht)) (Response dht (Ping dht)) | ||
717 | , Ord (TransactionID dht) | ||
718 | , Serialize (TransactionID dht) | ||
719 | , WireFormat raw dht | ||
720 | , SerializableTo raw (Response dht b) | ||
721 | , SerializableTo raw (Query dht a) | ||
722 | , Ord (NodeId dht) | ||
723 | , FiniteBits (NodeId dht) | ||
724 | , Show (NodeId dht) | ||
725 | , Show (QueryMethod dht) | ||
726 | , SerializableTo raw (Response dht (Ping dht)) | ||
727 | , SerializableTo raw (Query dht (Ping dht)) | ||
728 | ) => NodeAddr ip -> PacketDestination dht -> a -> DHT raw dht u ip (NodeId dht, b, Maybe ReflectedIP) | ||
729 | coldQueryNode' addr dest q = do | ||
730 | nid <- myNodeIdAccordingTo $ fromMaybe (error "TODO: coldQueryNode' myNodeIdAccordingTo") $ fromAddr dest | ||
678 | dta <- asks dhtData | 731 | dta <- asks dhtData |
679 | qextra <- liftIO $ makeQueryExtra dta nid (Proxy :: Proxy (Query dht q)) (Proxy :: Proxy (Response dht b)) | 732 | qextra <- liftIO $ makeQueryExtra dta nid (Proxy :: Proxy (Query dht q)) (Proxy :: Proxy (Response dht b)) |
680 | let read_only = False -- TODO: check for NAT issues. (BEP 43) | 733 | let read_only = False -- TODO: check for NAT issues. (BEP 43) |
681 | -- let KRPC.Method name = KRPC.method :: KRPC.Method dht (Query dht a) (Response dht b) | 734 | -- let KRPC.Method name = KRPC.method :: KRPC.Method dht (Query dht a) (Response dht b) |
682 | mgr <- asks manager | 735 | mgr <- asks manager |
683 | (Response rextra r, remoteId, witnessed_ip) <- liftIO $ query' mgr (toSockAddr addr) (Query qextra q) | 736 | (Response rextra r, remoteId, witnessed_ip) <- liftIO $ query' mgr dest (Query qextra q) |
684 | -- \$(logDebugS) "queryNode" $ "Witnessed address: " <> T.pack (show witnessed_ip) | 737 | -- \$(logDebugS) "queryNode" $ "Witnessed address: " <> T.pack (show witnessed_ip) |
685 | -- <> " by " <> T.pack (show (toSockAddr addr)) | 738 | -- <> " by " <> T.pack (show (toSockAddr addr)) |
686 | _ <- insertNode (NodeInfo remoteId addr def) witnessed_ip | 739 | _ <- insertNode (NodeInfo remoteId addr def) witnessed_ip |
@@ -704,6 +757,6 @@ queryNode' addr q = do | |||
704 | , SerializableTo raw (Query dht (Ping dht)) | 757 | , SerializableTo raw (Query dht (Ping dht)) |
705 | , WireFormat raw dht | 758 | , WireFormat raw dht |
706 | , Kademlia dht | 759 | , Kademlia dht |
707 | ) => a -> NodeAddr ip -> DHT raw dht u ip b | 760 | ) => a -> NodeInfo dht ip u -> DHT raw dht u ip b |
708 | q <@> addr = snd <$> queryNode addr q | 761 | q <@> addr = snd <$> queryNode addr q |
709 | {-# INLINE (<@>) #-} | 762 | {-# INLINE (<@>) #-} |