summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Data/Torrent.hs9
-rw-r--r--src/Data/Torrent/Block.hs7
-rw-r--r--src/Data/Torrent/Piece.hs48
3 files changed, 46 insertions, 18 deletions
diff --git a/src/Data/Torrent.hs b/src/Data/Torrent.hs
index 36b9de50..8d62b068 100644
--- a/src/Data/Torrent.hs
+++ b/src/Data/Torrent.hs
@@ -26,6 +26,8 @@
26module Data.Torrent 26module Data.Torrent
27 ( -- * Info dictionary 27 ( -- * Info dictionary
28 InfoDict (..) 28 InfoDict (..)
29
30 -- ** Lenses
29 , infohash 31 , infohash
30 , layoutInfo 32 , layoutInfo
31 , pieceInfo 33 , pieceInfo
@@ -33,6 +35,8 @@ module Data.Torrent
33 35
34 -- * Torrent file 36 -- * Torrent file
35 , Torrent(..) 37 , Torrent(..)
38
39 -- ** Lenses
36 , announce 40 , announce
37 , announceList 41 , announceList
38 , comment 42 , comment
@@ -44,11 +48,14 @@ module Data.Torrent
44 , publisherURL 48 , publisherURL
45 , signature 49 , signature
46 50
51 -- * Construction
47 , nullTorrent 52 , nullTorrent
48 53
49 -- * IO 54 -- * File paths
50 , torrentExt 55 , torrentExt
51 , isTorrentPath 56 , isTorrentPath
57
58 -- * IO
52 , fromFile 59 , fromFile
53 , toFile 60 , toFile
54 ) where 61 ) where
diff --git a/src/Data/Torrent/Block.hs b/src/Data/Torrent/Block.hs
index affbfa78..cb50302c 100644
--- a/src/Data/Torrent/Block.hs
+++ b/src/Data/Torrent/Block.hs
@@ -53,9 +53,14 @@ import Text.PrettyPrint
53-----------------------------------------------------------------------} 53-----------------------------------------------------------------------}
54 54
55-- | Zero-based index of piece in torrent content. 55-- | Zero-based index of piece in torrent content.
56type PieceIx = Int 56type PieceIx = Int
57 57
58-- | Size of piece in bytes. Should be a power of 2. 58-- | Size of piece in bytes. Should be a power of 2.
59--
60-- NOTE: Have max and min size constrained to wide used
61-- semi-standard values. This bounds should be used to make decision
62-- about piece size for new torrents.
63--
59type PieceSize = Int 64type PieceSize = Int
60 65
61{----------------------------------------------------------------------- 66{-----------------------------------------------------------------------
diff --git a/src/Data/Torrent/Piece.hs b/src/Data/Torrent/Piece.hs
index 572b136f..9e7280b0 100644
--- a/src/Data/Torrent/Piece.hs
+++ b/src/Data/Torrent/Piece.hs
@@ -15,9 +15,9 @@ module Data.Torrent.Piece
15 PieceIx 15 PieceIx
16 , PieceCount 16 , PieceCount
17 , PieceSize 17 , PieceSize
18 , defaultPieceSize
19 , maxPieceSize
20 , minPieceSize 18 , minPieceSize
19 , maxPieceSize
20 , defaultPieceSize
21 21
22 -- * Piece data 22 -- * Piece data
23 , Piece (..) 23 , Piece (..)
@@ -28,10 +28,14 @@ module Data.Torrent.Piece
28 -- * Piece control 28 -- * Piece control
29 , PieceInfo (..) 29 , PieceInfo (..)
30 , ppPieceInfo 30 , ppPieceInfo
31 , pieceCount
32
33 -- * Lens
31 , pieceLength 34 , pieceLength
32 , pieceHashes 35 , pieceHashes
36
37 -- * Validation
33 , pieceHash 38 , pieceHash
34 , pieceCount
35 , checkPieceLazy 39 , checkPieceLazy
36 40
37 -- * Internal 41 -- * Internal
@@ -64,6 +68,13 @@ import Data.Torrent.Block
64class Lint a where 68class Lint a where
65 lint :: a -> Either String a 69 lint :: a -> Either String a
66 70
71--class Validation a where
72-- validate :: PieceInfo -> Piece a -> Bool
73
74{-----------------------------------------------------------------------
75-- Piece attributes
76-----------------------------------------------------------------------}
77
67-- | Number of pieces in torrent or a part of torrent. 78-- | Number of pieces in torrent or a part of torrent.
68type PieceCount = Int 79type PieceCount = Int
69 80
@@ -72,18 +83,17 @@ optimalPieceCount :: PieceCount
72optimalPieceCount = 1000 83optimalPieceCount = 1000
73{-# INLINE optimalPieceCount #-} 84{-# INLINE optimalPieceCount #-}
74 85
75-- | NOTE: Have max and min size constrained to wide used 86-- | Piece size should not be less than this value.
76-- semi-standard values. This bounds should be used to make decision
77-- about piece size for new torrents.
78--
79maxPieceSize :: Int
80maxPieceSize = 4 * 1024 * 1024
81{-# INLINE maxPieceSize #-}
82
83minPieceSize :: Int 87minPieceSize :: Int
84minPieceSize = defaultTransferSize * 4 88minPieceSize = defaultTransferSize * 4
85{-# INLINE minPieceSize #-} 89{-# INLINE minPieceSize #-}
86 90
91-- | To prevent transfer degradation piece size should not exceed this
92-- value.
93maxPieceSize :: Int
94maxPieceSize = 4 * 1024 * 1024
95{-# INLINE maxPieceSize #-}
96
87toPow2 :: Int -> Int 97toPow2 :: Int -> Int
88toPow2 x = bit $ fromIntegral (leadingZeros (0 :: Int) - leadingZeros x) 98toPow2 x = bit $ fromIntegral (leadingZeros (0 :: Int) - leadingZeros x)
89 99
@@ -93,6 +103,10 @@ defaultPieceSize x = max minPieceSize $ min maxPieceSize $ toPow2 pc
93 where 103 where
94 pc = fromIntegral (x `div` fromIntegral optimalPieceCount) 104 pc = fromIntegral (x `div` fromIntegral optimalPieceCount)
95 105
106{-----------------------------------------------------------------------
107-- Piece data
108-----------------------------------------------------------------------}
109
96-- TODO check if pieceLength is power of 2 110-- TODO check if pieceLength is power of 2
97-- | Piece payload should be strict or lazy bytestring. 111-- | Piece payload should be strict or lazy bytestring.
98data Piece a = Piece 112data Piece a = Piece
@@ -118,10 +132,14 @@ pieceSize Piece {..} = fromIntegral (BL.length pieceData)
118 132
119-- | Test if a block can be safely turned into a piece. 133-- | Test if a block can be safely turned into a piece.
120isPiece :: PieceSize -> Block BL.ByteString -> Bool 134isPiece :: PieceSize -> Block BL.ByteString -> Bool
121isPiece pieceSize blk @ (Block i offset _) = 135isPiece pieceLen blk @ (Block i offset _) =
122 offset == 0 && blockSize blk == pieceSize && i >= 0 136 offset == 0 && blockSize blk == pieceLen && i >= 0
123{-# INLINE isPiece #-} 137{-# INLINE isPiece #-}
124 138
139{-----------------------------------------------------------------------
140-- Piece control
141-----------------------------------------------------------------------}
142
125newtype HashArray = HashArray { unHashArray :: ByteString } 143newtype HashArray = HashArray { unHashArray :: ByteString }
126 deriving (Show, Read, Eq, BEncode) 144 deriving (Show, Read, Eq, BEncode)
127 145
@@ -196,12 +214,10 @@ pieceHash PieceInfo {..} i = slice (hashsize * i) hashsize (unHashArray piPieceH
196pieceCount :: PieceInfo -> PieceCount 214pieceCount :: PieceInfo -> PieceCount
197pieceCount PieceInfo {..} = BS.length (unHashArray piPieceHashes) `quot` hashsize 215pieceCount PieceInfo {..} = BS.length (unHashArray piPieceHashes) `quot` hashsize
198 216
217-- | Test if this is last piece in torrent content.
199isLastPiece :: PieceInfo -> PieceIx -> Bool 218isLastPiece :: PieceInfo -> PieceIx -> Bool
200isLastPiece ci i = pieceCount ci == succ i 219isLastPiece ci i = pieceCount ci == succ i
201 220
202class Validation a where
203 validate :: PieceInfo -> Piece a -> Bool
204
205-- | Validate piece with metainfo hash. 221-- | Validate piece with metainfo hash.
206checkPieceLazy :: PieceInfo -> Piece BL.ByteString -> Bool 222checkPieceLazy :: PieceInfo -> Piece BL.ByteString -> Bool
207checkPieceLazy pinfo @ PieceInfo {..} Piece {..} 223checkPieceLazy pinfo @ PieceInfo {..} Piece {..}