summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-01-09 05:28:09 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-01-09 05:28:09 +0400
commit735cddf5d2be9f5423d8e5dba18902d8276896aa (patch)
tree7e8e3cccb34cef337ba14edbfd62e6c6b8347113
parent299a299412b0c3c15966996f3466db3960e324e7 (diff)
Merge gettorrent to mktorrent
-rw-r--r--bittorrent.cabal22
-rw-r--r--examples/GetTorrent.hs75
-rw-r--r--examples/MkTorrent.hs78
3 files changed, 79 insertions, 96 deletions
diff --git a/bittorrent.cabal b/bittorrent.cabal
index 28c26baf..9e63c227 100644
--- a/bittorrent.cabal
+++ b/bittorrent.cabal
@@ -104,7 +104,7 @@ library
104 , transformers-base 104 , transformers-base
105 105
106 -- Concurrency 106 -- Concurrency
107-- , SafeSemaphore 107 , SafeSemaphore
108-- , BoundedChan >= 1.0.1.0 108-- , BoundedChan >= 1.0.1.0
109 , stm >= 2.4 109 , stm >= 2.4
110 110
@@ -256,31 +256,19 @@ executable mktorrent
256 , text 256 , text
257 , pretty-class 257 , pretty-class
258 258
259 , mtl
260 , conduit
259 , lens 261 , lens
260 , parallel-io 262 , parallel-io
263
261 , network 264 , network
262 , bittorrent 265 , bittorrent
263 266
267 , filepath
264 , optparse-applicative 268 , optparse-applicative
265 , hslogger 269 , hslogger
266 ghc-options: -Wall -O2 -threaded 270 ghc-options: -Wall -O2 -threaded
267 271
268-- Utility to fetch
269executable gettorrent
270 if !flag(examples)
271 buildable: False
272 default-language: Haskell2010
273 hs-source-dirs: examples
274 main-is: GetTorrent.hs
275 build-depends: base == 4.*
276 , optparse-applicative
277 , data-default
278 , conduit
279 , mtl
280 , network
281 , filepath
282 , bittorrent
283
284-- nonfunctioning example of very basic bittorrent client 272-- nonfunctioning example of very basic bittorrent client
285executable client 273executable client
286 if !flag(examples) 274 if !flag(examples)
diff --git a/examples/GetTorrent.hs b/examples/GetTorrent.hs
deleted file mode 100644
index 9a203bf0..00000000
--- a/examples/GetTorrent.hs
+++ /dev/null
@@ -1,75 +0,0 @@
1{-# LANGUAGE RecordWildCards #-}
2module Main (main) where
3import Control.Applicative
4import Control.Concurrent
5import Control.Monad
6import Control.Monad.Trans
7import Data.Conduit as C
8import Data.Conduit.List as C
9import Data.Default
10import Options.Applicative
11import System.Exit
12import System.FilePath
13
14import Data.Torrent
15import Data.Torrent.InfoHash
16import Network.BitTorrent.Core
17import Network.BitTorrent.DHT.Session
18import Network.BitTorrent.DHT as DHT
19import Network.BitTorrent.Exchange.Message
20import Network.BitTorrent.Exchange.Wire
21
22
23data Params = Params
24 { topic :: InfoHash
25 , thisNode :: NodeAddr IPv4
26 , bootNode :: NodeAddr IPv4
27 , buckets :: Int
28 } deriving Show
29
30paramsParser :: Parser Params
31paramsParser = Params
32 <$> option (long "infohash" <> short 'i'
33 <> metavar "SHA1" <> help "infohash of torrent file")
34 <*> option (long "port" <> short 'p'
35 <> value def <> showDefault
36 <> metavar "NUM" <> help "port number to bind"
37 )
38 <*> option (long "boot" <> short 'b'
39 <> metavar "NODE" <> help "bootstrap node address"
40 )
41 <*> option (long "bucket" <> short 'n'
42 <> value 2 <> showDefault
43 <> metavar "NUM" <> help "number of buckets to maintain"
44 )
45
46programInfo :: ParserInfo Params
47programInfo = info (helper <*> paramsParser)
48 ( fullDesc
49 <> progDesc ""
50 <> header "gettorrent - get torrent file by infohash"
51 )
52
53exchangeTorrent :: PeerAddr IP -> InfoHash -> IO InfoDict
54exchangeTorrent addr ih = do
55 pid <- genPeerId
56 var <- newEmptyMVar
57 let hs = Handshake def (toCaps [ExtExtended]) ih pid
58 connectWire hs addr (toCaps [ExtMetadata]) $ do
59 infodict <- getMetadata
60 liftIO $ putMVar var infodict
61 takeMVar var
62
63getTorrent :: Params -> IO ()
64getTorrent Params {..} = do
65 dht (def { optBucketCount = buckets }) thisNode $ do
66 bootstrap [bootNode]
67 DHT.lookup topic $$ C.mapM_ $ \ peers -> do
68 liftIO $ forM_ peers $ \ peer -> do
69 infodict <- exchangeTorrent (IPv4 <$> peer) topic
70 let torrent = nullTorrent infodict -- TODO add tNodes, tCreated, etc?
71 toFile (show topic <.> torrentExt) torrent
72 exitSuccess
73
74main :: IO ()
75main = execParser programInfo >>= getTorrent
diff --git a/examples/MkTorrent.hs b/examples/MkTorrent.hs
index 16e1e245..ab3144b4 100644
--- a/examples/MkTorrent.hs
+++ b/examples/MkTorrent.hs
@@ -5,12 +5,16 @@
5module Main (main) where 5module Main (main) where
6 6
7import Prelude as P 7import Prelude as P
8import Control.Concurrent
8import Control.Concurrent.ParallelIO 9import Control.Concurrent.ParallelIO
9import Control.Exception 10import Control.Exception
10import Control.Lens hiding (argument) 11import Control.Lens hiding (argument, (<.>))
11import Control.Monad 12import Control.Monad
13import Control.Monad.Trans
14import Data.Conduit as C
15import Data.Conduit.List as C
12import Data.List as L 16import Data.List as L
13import Data.Maybe 17import Data.Maybe as L
14import Data.Monoid 18import Data.Monoid
15import Data.Text as T 19import Data.Text as T
16import qualified Data.Text.IO as T 20import qualified Data.Text.IO as T
@@ -18,18 +22,25 @@ import Data.Text.Read as T
18import Data.Version 22import Data.Version
19import Network.URI 23import Network.URI
20import Options.Applicative 24import Options.Applicative
25import System.Exit
26import System.FilePath
21import System.Log 27import System.Log
22import System.Log.Logger 28import System.Log.Logger
23import System.Exit
24import Text.Read 29import Text.Read
25import Text.PrettyPrint.Class 30import Text.PrettyPrint.Class
26 31
27import Paths_bittorrent (version) 32import Paths_bittorrent (version)
28import Data.Torrent 33import Data.Torrent
29import Data.Torrent.Bitfield as BF 34import Data.Torrent.Bitfield as BF
35import Data.Torrent.InfoHash
30import Data.Torrent.Piece 36import Data.Torrent.Piece
31import Data.Torrent.Layout 37import Data.Torrent.Layout
32import Data.Torrent.Magnet hiding (Magnet) 38import Data.Torrent.Magnet hiding (Magnet)
39import Network.BitTorrent.Core
40import Network.BitTorrent.DHT.Session hiding (Options)
41import Network.BitTorrent.DHT as DHT
42import Network.BitTorrent.Exchange.Message
43import Network.BitTorrent.Exchange.Wire hiding (Options)
33import System.Torrent.Storage 44import System.Torrent.Storage
34 45
35 46
@@ -179,7 +190,7 @@ validateStorage s pinfo = do
179 let total = totalPieces s 190 let total = totalPieces s
180 pixs <- parallel $ L.map (validatePiece s pinfo) [0 .. total - 1] 191 pixs <- parallel $ L.map (validatePiece s pinfo) [0 .. total - 1]
181 infoM "check" "storage validation finished" 192 infoM "check" "storage validation finished"
182 return $ fromList total $ catMaybes pixs 193 return $ fromList total $ L.catMaybes pixs
183 194
184-- TODO use local thread pool 195-- TODO use local thread pool
185checkContent :: Storage -> PieceInfo -> IO () 196checkContent :: Storage -> PieceInfo -> IO ()
@@ -297,6 +308,62 @@ putTorrent opts @ ShowOpts {..} = do
297 msg = "Torrent file is either invalid or do not exist" 308 msg = "Torrent file is either invalid or do not exist"
298 309
299{----------------------------------------------------------------------- 310{-----------------------------------------------------------------------
311-- Get command - fetch torrent by infohash
312-----------------------------------------------------------------------}
313
314data GetOpts = GetOpts
315 { topic :: InfoHash
316 , thisNode :: NodeAddr IPv4
317 , bootNode :: NodeAddr IPv4
318 , buckets :: Int
319 } deriving Show
320
321paramsParser :: Parser GetOpts
322paramsParser = GetOpts
323 <$> option (long "infohash" <> short 'i'
324 <> metavar "SHA1" <> help "infohash of torrent file")
325 <*> option (long "port" <> short 'p'
326 <> value def <> showDefault
327 <> metavar "NUM" <> help "port number to bind"
328 )
329 <*> option (long "boot" <> short 'b'
330 <> metavar "NODE" <> help "bootstrap node address"
331 )
332 <*> option (long "bucket" <> short 'n'
333 <> value 2 <> showDefault
334 <> metavar "NUM" <> help "number of buckets to maintain"
335 )
336
337getInfo :: ParserInfo GetOpts
338getInfo = info (helper <*> paramsParser)
339 ( fullDesc
340 <> progDesc "Get torrent file by infohash"
341 <> header "get torrent file by infohash"
342 )
343
344exchangeTorrent :: PeerAddr IP -> InfoHash -> IO InfoDict
345exchangeTorrent addr ih = do
346 pid <- genPeerId
347 var <- newEmptyMVar
348 let hs = Handshake def (toCaps [ExtExtended]) ih pid
349 connectWire hs addr (toCaps [ExtMetadata]) $ do
350 infodict <- getMetadata
351 liftIO $ putMVar var infodict
352 takeMVar var
353
354getTorrent :: GetOpts -> IO ()
355getTorrent GetOpts {..} = do
356 dht (def { optBucketCount = buckets }) thisNode $ do
357 bootstrap [bootNode]
358 DHT.lookup topic $$ C.mapM_ $ \ peers -> do
359 liftIO $ forM_ peers $ \ peer -> do
360 infodict <- exchangeTorrent (IPv4 <$> peer) topic
361 -- TODO add tNodes, tCreated, etc?
362 let torrent = nullTorrent infodict
363 toFile (show topic <.> torrentExt) torrent
364 exitSuccess
365
366{-----------------------------------------------------------------------
300-- Command 367-- Command
301-----------------------------------------------------------------------} 368-----------------------------------------------------------------------}
302 369
@@ -304,6 +371,7 @@ data Command
304 = Amend AmendOpts 371 = Amend AmendOpts
305 | Check CheckOpts 372 | Check CheckOpts
306-- | Create CreateOpts 373-- | Create CreateOpts
374 | Get GetOpts
307 | Magnet MagnetOpts 375 | Magnet MagnetOpts
308 | Show ShowOpts 376 | Show ShowOpts
309 deriving Show 377 deriving Show
@@ -313,6 +381,7 @@ commandOpts = subparser $ mconcat
313 [ command "amend" (Amend <$> amendInfo) 381 [ command "amend" (Amend <$> amendInfo)
314 , command "check" (Check <$> checkInfo) 382 , command "check" (Check <$> checkInfo)
315-- , command "create" (Create <$> createInfo) 383-- , command "create" (Create <$> createInfo)
384 , command "get" (Get <$> getInfo)
316 , command "magnet" (Magnet <$> magnetInfo) 385 , command "magnet" (Magnet <$> magnetInfo)
317 , command "show" (Show <$> showInfo) 386 , command "show" (Show <$> showInfo)
318 ] 387 ]
@@ -396,6 +465,7 @@ run :: Command -> IO ()
396run (Amend opts) = amend opts 465run (Amend opts) = amend opts
397run (Check opts) = checkTorrent opts 466run (Check opts) = checkTorrent opts
398--run (Create opts) = createTorrent opts 467--run (Create opts) = createTorrent opts
468run (Get opts) = getTorrent opts
399run (Magnet opts) = magnet opts 469run (Magnet opts) = magnet opts
400run (Show opts) = putTorrent opts 470run (Show opts) = putTorrent opts
401 471