summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-01-02 23:28:05 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-01-02 23:28:05 +0400
commit51e1c37e415e502902d58f8552ac09e379c12504 (patch)
tree694ba9f84b7e244184c0794490ab0688590933fc /src
parent61619558b26b96048ffd18a7bf4cbe41d5fffa2f (diff)
Implement DHT lookup operation
Diffstat (limited to 'src')
-rw-r--r--src/Network/BitTorrent/DHT.hs36
-rw-r--r--src/Network/BitTorrent/DHT/Session.hs6
2 files changed, 29 insertions, 13 deletions
diff --git a/src/Network/BitTorrent/DHT.hs b/src/Network/BitTorrent/DHT.hs
index 38de1f91..c35b5bd6 100644
--- a/src/Network/BitTorrent/DHT.hs
+++ b/src/Network/BitTorrent/DHT.hs
@@ -16,6 +16,7 @@
16-- 16--
17{-# LANGUAGE FlexibleInstances #-} 17{-# LANGUAGE FlexibleInstances #-}
18{-# LANGUAGE TemplateHaskell #-} 18{-# LANGUAGE TemplateHaskell #-}
19{-# LANGUAGE TypeOperators #-}
19module Network.BitTorrent.DHT 20module Network.BitTorrent.DHT
20 ( -- * Distributed Hash Table 21 ( -- * Distributed Hash Table
21 DHT 22 DHT
@@ -29,13 +30,16 @@ module Network.BitTorrent.DHT
29import Control.Applicative 30import Control.Applicative
30import Control.Concurrent.Lifted hiding (yield) 31import Control.Concurrent.Lifted hiding (yield)
31import Control.Exception.Lifted 32import Control.Exception.Lifted
32import Control.Monad 33import Control.Monad as M
33import Control.Monad.Logger 34import Control.Monad.Logger
35import Control.Monad.Trans
36import Data.Conduit as C
37import Data.Conduit.List as C
34import Data.List as L 38import Data.List as L
35import Data.Monoid 39import Data.Monoid
36import Data.Text as T 40import Data.Text as T
37import Network.Socket (PortNumber) 41import Network.Socket (PortNumber)
38import Text.PrettyPrint as PP hiding ((<>)) 42import Text.PrettyPrint as PP hiding ((<>), ($$))
39import Text.PrettyPrint.Class 43import Text.PrettyPrint.Class
40 44
41import Data.Torrent.InfoHash 45import Data.Torrent.InfoHash
@@ -82,6 +86,20 @@ handlers = [pingH, findNodeH, getPeersH, announceH]
82-- Query 86-- Query
83-----------------------------------------------------------------------} 87-----------------------------------------------------------------------}
84 88
89findNodeQ :: Address ip => NodeId -> Iteration ip NodeAddr NodeInfo
90findNodeQ nid addr = do
91 NodeFound closest <- FindNode nid <@> addr
92 return $ Right closest
93
94getPeersQ :: Address ip => InfoHash -> Iteration ip NodeInfo PeerAddr
95getPeersQ topic NodeInfo {..} = do
96 GotPeers {..} <- GetPeers topic <@> nodeAddr
97 return peers
98
99{-----------------------------------------------------------------------
100-- DHT operations
101-----------------------------------------------------------------------}
102
85-- | Run DHT on specified port. <add note about resources> 103-- | Run DHT on specified port. <add note about resources>
86dht :: Address ip 104dht :: Address ip
87 => Options -- ^ normally you need to use 'Data.Default.def'; 105 => Options -- ^ normally you need to use 'Data.Default.def';
@@ -100,7 +118,7 @@ dht = runDHT handlers
100bootstrap :: Address ip => [NodeAddr ip] -> DHT ip () 118bootstrap :: Address ip => [NodeAddr ip] -> DHT ip ()
101bootstrap startNodes = do 119bootstrap startNodes = do
102 $(logInfoS) "bootstrap" "Start node bootstrapping" 120 $(logInfoS) "bootstrap" "Start node bootstrapping"
103 mapM_ insertClosest startNodes 121 M.mapM_ insertClosest startNodes
104 $(logInfoS) "bootstrap" "Node bootstrapping finished" 122 $(logInfoS) "bootstrap" "Node bootstrapping finished"
105 where 123 where
106 insertClosest addr = do 124 insertClosest addr = do
@@ -124,14 +142,10 @@ bootstrap startNodes = do
124-- 142--
125-- (TODO) This operation is synchronous and do block. 143-- (TODO) This operation is synchronous and do block.
126-- 144--
127lookup :: Address ip => InfoHash -> DHT ip [PeerAddr ip] 145lookup :: Address ip => InfoHash -> DHT ip `Source` [PeerAddr ip]
128lookup topic = getClosestHash topic >>= collect 146lookup topic = do -- TODO retry getClosestHash if bucket is empty
129 -- TODO retry getClosestHash if bucket is empty 147 closest <- lift $ getClosestHash topic
130 where 148 sourceList [closest] $= search (getPeersQ topic)
131 collect nodes = L.concat <$> forM (nodeAddr <$> nodes) retrieve
132 retrieve addr = do
133 GotPeers {..} <- GetPeers topic <@> addr
134 either collect pure peers
135 149
136-- | Announce that /this/ peer may have some pieces of the specified 150-- | Announce that /this/ peer may have some pieces of the specified
137-- torrent. 151-- torrent.
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs
index d3315a42..6c43c732 100644
--- a/src/Network/BitTorrent/DHT/Session.hs
+++ b/src/Network/BitTorrent/DHT/Session.hs
@@ -383,5 +383,7 @@ search action = do
383 alpha <- lift $ asks (optAlpha . options) 383 alpha <- lift $ asks (optAlpha . options)
384 awaitForever $ \ inputs -> do 384 awaitForever $ \ inputs -> do
385 forM_ (L.take alpha inputs) $ \ input -> do 385 forM_ (L.take alpha inputs) $ \ input -> do
386 result <- lift $ action input 386 result <- lift $ try $ action input
387 either leftover yield result 387 case result of
388 Left e -> let _ = e :: IOError in return ()
389 Right r -> either leftover yield r