diff options
author | Sam Truzjan <pxqr.sta@gmail.com> | 2014-01-02 16:36:43 +0400 |
---|---|---|
committer | Sam Truzjan <pxqr.sta@gmail.com> | 2014-01-02 16:36:43 +0400 |
commit | 5d576086294166fd97b24585c54c2b3820bab6aa (patch) | |
tree | 773add2e6cb3592718316742034d575af843013f /src | |
parent | 2b1ce778669dc58e8b2bf60a942722ede2c0515b (diff) |
Add documentation to the root DHT module
Diffstat (limited to 'src')
-rw-r--r-- | src/Network/BitTorrent/DHT.hs | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/src/Network/BitTorrent/DHT.hs b/src/Network/BitTorrent/DHT.hs index 155a50ca..7eef0c67 100644 --- a/src/Network/BitTorrent/DHT.hs +++ b/src/Network/BitTorrent/DHT.hs | |||
@@ -1,11 +1,29 @@ | |||
1 | -- | | ||
2 | -- Copyright : (c) Sam Truzjan 2013 | ||
3 | -- License : BSD3 | ||
4 | -- Maintainer : pxqr.sta@gmail.com | ||
5 | -- Stability : experimental | ||
6 | -- Portability : portable | ||
7 | -- | ||
8 | -- BitTorrent uses a \"distributed sloppy hash table\" (DHT) for | ||
9 | -- storing peer contact information for \"trackerless\" torrents. In | ||
10 | -- effect, each peer becomes a tracker. | ||
11 | -- | ||
12 | -- Normally you don't need to import other DHT modules. | ||
13 | -- | ||
14 | -- For more info see: | ||
15 | -- <http://www.bittorrent.org/beps/bep_0005.html> | ||
16 | -- | ||
1 | {-# LANGUAGE FlexibleInstances #-} | 17 | {-# LANGUAGE FlexibleInstances #-} |
2 | {-# LANGUAGE TemplateHaskell #-} | 18 | {-# LANGUAGE TemplateHaskell #-} |
3 | module Network.BitTorrent.DHT | 19 | module Network.BitTorrent.DHT |
4 | ( dht | 20 | ( -- * Distributed Hash Table |
5 | , ping | 21 | DHT |
22 | , dht | ||
6 | , Network.BitTorrent.DHT.bootstrap | 23 | , Network.BitTorrent.DHT.bootstrap |
7 | , Network.BitTorrent.DHT.lookup | 24 | , Network.BitTorrent.DHT.lookup |
8 | , Network.BitTorrent.DHT.insert | 25 | , Network.BitTorrent.DHT.insert |
26 | , Network.BitTorrent.DHT.delete | ||
9 | ) where | 27 | ) where |
10 | 28 | ||
11 | import Control.Applicative | 29 | import Control.Applicative |
@@ -67,13 +85,11 @@ handlers = [pingH, findNodeH, getPeersH, announceH] | |||
67 | dht :: Address ip => NodeAddr ip -> DHT ip a -> IO a | 85 | dht :: Address ip => NodeAddr ip -> DHT ip a -> IO a |
68 | dht addr = runDHT addr handlers | 86 | dht addr = runDHT addr handlers |
69 | 87 | ||
70 | ping :: Address ip => NodeAddr ip -> DHT ip () | 88 | -- | One good node may be sufficient. The list of bootstrapping nodes |
71 | ping addr = do | 89 | -- usually obtained from 'Data.Torrent.tNodes' field. |
72 | Ping <- Ping <@> addr | 90 | -- |
73 | return () | 91 | -- (TODO) This operation is asynchronous and do not block. |
74 | 92 | -- | |
75 | -- TODO fork? | ||
76 | -- | One good node may be sufficient. <note about 'Data.Torrent.tNodes'> | ||
77 | bootstrap :: Address ip => [NodeAddr ip] -> DHT ip () | 93 | bootstrap :: Address ip => [NodeAddr ip] -> DHT ip () |
78 | bootstrap startNodes = do | 94 | bootstrap startNodes = do |
79 | $(logInfoS) "bootstrap" "Start node bootstrapping" | 95 | $(logInfoS) "bootstrap" "Start node bootstrapping" |
@@ -95,22 +111,29 @@ bootstrap startNodes = do | |||
95 | $(logDebug) ("Get a list of closest nodes: " <> | 111 | $(logDebug) ("Get a list of closest nodes: " <> |
96 | T.pack (PP.render (pretty closest))) | 112 | T.pack (PP.render (pretty closest))) |
97 | forM_ (L.take 2 closest) $ \ info @ NodeInfo {..} -> do | 113 | forM_ (L.take 2 closest) $ \ info @ NodeInfo {..} -> do |
98 | insertNode info | 114 | _ <- insertNode info |
99 | let prettyAddr = T.pack (show (pretty nodeAddr)) | 115 | let prettyAddr = T.pack (show (pretty nodeAddr)) |
100 | $(logInfoS) "bootstrap" $ "table detalization" <> prettyAddr | 116 | $(logInfoS) "bootstrap" $ "table detalization" <> prettyAddr |
101 | fork $ insertClosest nodeAddr | 117 | fork $ insertClosest nodeAddr |
102 | 118 | ||
103 | -- | Get list of peers which downloading | 119 | -- | Get list of peers which downloading this torrent. |
120 | -- | ||
121 | -- (TODO) This operation is synchronous and do block. | ||
122 | -- | ||
104 | lookup :: Address ip => InfoHash -> DHT ip [PeerAddr ip] | 123 | lookup :: Address ip => InfoHash -> DHT ip [PeerAddr ip] |
105 | lookup ih = getClosestHash ih >>= collect | 124 | lookup topic = getClosestHash topic >>= collect |
125 | -- TODO retry getClosestHash if bucket is empty | ||
106 | where | 126 | where |
107 | collect nodes = L.concat <$> forM (nodeAddr <$> nodes) retrieve | 127 | collect nodes = L.concat <$> forM (nodeAddr <$> nodes) retrieve |
108 | retrieve addr = do | 128 | retrieve addr = do |
109 | GotPeers {..} <- GetPeers ih <@> addr | 129 | GotPeers {..} <- GetPeers topic <@> addr |
110 | either collect pure peers | 130 | either collect pure peers |
111 | 131 | ||
112 | -- | Announce that /this/ peer may have some pieces of the specified | 132 | -- | Announce that /this/ peer may have some pieces of the specified |
113 | -- torrent. | 133 | -- torrent. |
134 | -- | ||
135 | -- (TODO) This operation is asynchronous and do not block. | ||
136 | -- | ||
114 | insert :: Address ip => InfoHash -> PortNumber -> DHT ip () | 137 | insert :: Address ip => InfoHash -> PortNumber -> DHT ip () |
115 | insert ih port = do | 138 | insert ih port = do |
116 | nodes <- getClosestHash ih | 139 | nodes <- getClosestHash ih |
@@ -118,3 +141,10 @@ insert ih port = do | |||
118 | -- GotPeers {..} <- GetPeers ih <@> addr | 141 | -- GotPeers {..} <- GetPeers ih <@> addr |
119 | -- Announced <- Announce False ih undefined grantedToken <@> addr | 142 | -- Announced <- Announce False ih undefined grantedToken <@> addr |
120 | return () | 143 | return () |
144 | |||
145 | -- | Stop announcing /this/ peer for the specified torrent. | ||
146 | -- | ||
147 | -- This operation is atomic and do not block. | ||
148 | -- | ||
149 | delete :: Address ip => InfoHash -> DHT ip () | ||
150 | delete = error "DHT.delete: not implemented" \ No newline at end of file | ||