diff options
author | Sam Truzjan <pxqr.sta@gmail.com> | 2014-01-02 23:28:05 +0400 |
---|---|---|
committer | Sam Truzjan <pxqr.sta@gmail.com> | 2014-01-02 23:28:05 +0400 |
commit | 51e1c37e415e502902d58f8552ac09e379c12504 (patch) | |
tree | 694ba9f84b7e244184c0794490ab0688590933fc /src/Network/BitTorrent | |
parent | 61619558b26b96048ffd18a7bf4cbe41d5fffa2f (diff) |
Implement DHT lookup operation
Diffstat (limited to 'src/Network/BitTorrent')
-rw-r--r-- | src/Network/BitTorrent/DHT.hs | 36 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Session.hs | 6 |
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 #-} | ||
19 | module Network.BitTorrent.DHT | 20 | module Network.BitTorrent.DHT |
20 | ( -- * Distributed Hash Table | 21 | ( -- * Distributed Hash Table |
21 | DHT | 22 | DHT |
@@ -29,13 +30,16 @@ module Network.BitTorrent.DHT | |||
29 | import Control.Applicative | 30 | import Control.Applicative |
30 | import Control.Concurrent.Lifted hiding (yield) | 31 | import Control.Concurrent.Lifted hiding (yield) |
31 | import Control.Exception.Lifted | 32 | import Control.Exception.Lifted |
32 | import Control.Monad | 33 | import Control.Monad as M |
33 | import Control.Monad.Logger | 34 | import Control.Monad.Logger |
35 | import Control.Monad.Trans | ||
36 | import Data.Conduit as C | ||
37 | import Data.Conduit.List as C | ||
34 | import Data.List as L | 38 | import Data.List as L |
35 | import Data.Monoid | 39 | import Data.Monoid |
36 | import Data.Text as T | 40 | import Data.Text as T |
37 | import Network.Socket (PortNumber) | 41 | import Network.Socket (PortNumber) |
38 | import Text.PrettyPrint as PP hiding ((<>)) | 42 | import Text.PrettyPrint as PP hiding ((<>), ($$)) |
39 | import Text.PrettyPrint.Class | 43 | import Text.PrettyPrint.Class |
40 | 44 | ||
41 | import Data.Torrent.InfoHash | 45 | import Data.Torrent.InfoHash |
@@ -82,6 +86,20 @@ handlers = [pingH, findNodeH, getPeersH, announceH] | |||
82 | -- Query | 86 | -- Query |
83 | -----------------------------------------------------------------------} | 87 | -----------------------------------------------------------------------} |
84 | 88 | ||
89 | findNodeQ :: Address ip => NodeId -> Iteration ip NodeAddr NodeInfo | ||
90 | findNodeQ nid addr = do | ||
91 | NodeFound closest <- FindNode nid <@> addr | ||
92 | return $ Right closest | ||
93 | |||
94 | getPeersQ :: Address ip => InfoHash -> Iteration ip NodeInfo PeerAddr | ||
95 | getPeersQ 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> |
86 | dht :: Address ip | 104 | dht :: 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 | |||
100 | bootstrap :: Address ip => [NodeAddr ip] -> DHT ip () | 118 | bootstrap :: Address ip => [NodeAddr ip] -> DHT ip () |
101 | bootstrap startNodes = do | 119 | bootstrap 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 | -- |
127 | lookup :: Address ip => InfoHash -> DHT ip [PeerAddr ip] | 145 | lookup :: Address ip => InfoHash -> DHT ip `Source` [PeerAddr ip] |
128 | lookup topic = getClosestHash topic >>= collect | 146 | lookup 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 | ||