summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-04-04 21:44:18 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-04-04 21:44:18 +0400
commit052bed30a3d83aa8fb7b8b42509ad96f573439af (patch)
tree106b44c06226595870c3bf54f890824eec2b7f0e
parent88ef120511caae5ed74a48a87617b43aec4b7f76 (diff)
Move HashList to Torrent module
-rw-r--r--bittorrent.cabal1
-rw-r--r--src/Data/Torrent.hs199
-rw-r--r--src/Data/Torrent/Bitfield.hs2
-rw-r--r--src/Data/Torrent/Piece.hs232
-rw-r--r--src/Network/BitTorrent/DHT/Session.hs2
-rw-r--r--src/Network/BitTorrent/Exchange/Assembler.hs2
-rw-r--r--src/Network/BitTorrent/Exchange/Block.hs2
-rw-r--r--src/Network/BitTorrent/Exchange/Message.hs10
-rw-r--r--src/Network/BitTorrent/Exchange/Session.hs3
-rw-r--r--src/Network/BitTorrent/Exchange/Session/Metadata.hs1
-rw-r--r--src/Network/BitTorrent/Exchange/Session/Status.hs2
-rw-r--r--src/System/Torrent/Storage.hs2
-rw-r--r--tests/Data/Torrent/MetainfoSpec.hs1
-rw-r--r--tests/Data/Torrent/PieceSpec.hs2
-rw-r--r--tests/Network/BitTorrent/Exchange/Session/MetadataSpec.hs5
-rw-r--r--tests/System/Torrent/StorageSpec.hs3
16 files changed, 213 insertions, 256 deletions
diff --git a/bittorrent.cabal b/bittorrent.cabal
index 9d687d7d..9a86702d 100644
--- a/bittorrent.cabal
+++ b/bittorrent.cabal
@@ -46,7 +46,6 @@ library
46 hs-source-dirs: src 46 hs-source-dirs: src
47 exposed-modules: Data.Torrent 47 exposed-modules: Data.Torrent
48 Data.Torrent.Bitfield 48 Data.Torrent.Bitfield
49 Data.Torrent.Piece
50 Data.Torrent.Progress 49 Data.Torrent.Progress
51 Data.Torrent.Tree 50 Data.Torrent.Tree
52 Network.BitTorrent 51 Network.BitTorrent
diff --git a/src/Data/Torrent.hs b/src/Data/Torrent.hs
index 701da9dd..98d6f94e 100644
--- a/src/Data/Torrent.hs
+++ b/src/Data/Torrent.hs
@@ -86,6 +86,34 @@ module Data.Torrent
86 -- ** Internal 86 -- ** Internal
87 , sizeInBase 87 , sizeInBase
88 88
89 -- * Pieces
90 -- ** Attributes
91 , PieceIx
92 , PieceCount
93 , PieceSize
94 , minPieceSize
95 , maxPieceSize
96 , defaultPieceSize
97 , PieceHash
98
99 -- ** Piece data
100 , Piece (..)
101 , pieceSize
102 , hashPiece
103
104 -- ** Piece control
105 , HashList (..)
106 , PieceInfo (..)
107 , pieceCount
108
109 -- ** Lens
110 , pieceLength
111 , pieceHashes
112
113 -- ** Validation
114 , pieceHash
115 , checkPieceLazy
116
89 -- * Info dictionary 117 -- * Info dictionary
90 , InfoDict (..) 118 , InfoDict (..)
91 , infoDictionary 119 , infoDictionary
@@ -133,8 +161,11 @@ import Control.Exception
133import Control.Lens hiding (unsnoc) 161import Control.Lens hiding (unsnoc)
134import Control.Monad 162import Control.Monad
135import qualified Crypto.Hash.SHA1 as C 163import qualified Crypto.Hash.SHA1 as C
164import qualified Crypto.Hash.SHA1 as SHA1
136import Data.BEncode as BE 165import Data.BEncode as BE
137import Data.BEncode.Types as BE 166import Data.BEncode.Types as BE
167import Data.Bits
168import Data.Bits.Extras
138import Data.ByteString as BS 169import Data.ByteString as BS
139import Data.ByteString.Base16 as Base16 170import Data.ByteString.Base16 as Base16
140import Data.ByteString.Base32 as Base32 171import Data.ByteString.Base32 as Base32
@@ -146,6 +177,7 @@ import Data.Convertible
146import Data.Default 177import Data.Default
147import Data.Foldable as F 178import Data.Foldable as F
148import Data.Hashable as Hashable 179import Data.Hashable as Hashable
180import Data.Int
149import qualified Data.List as L 181import qualified Data.List as L
150import Data.Map as M 182import Data.Map as M
151import Data.Maybe 183import Data.Maybe
@@ -166,7 +198,6 @@ import Text.PrettyPrint.Class
166import System.FilePath 198import System.FilePath
167import System.Posix.Types 199import System.Posix.Types
168 200
169import Data.Torrent.Piece
170import Network.BitTorrent.Core.NodeInfo 201import Network.BitTorrent.Core.NodeInfo
171 202
172 203
@@ -527,6 +558,171 @@ sizeInBase n b = fromIntegral (n `div` fromIntegral b) + align
527{-# SPECIALIZE sizeInBase :: Integer -> Int -> Int #-} 558{-# SPECIALIZE sizeInBase :: Integer -> Int -> Int #-}
528 559
529{----------------------------------------------------------------------- 560{-----------------------------------------------------------------------
561-- Piece attributes
562-----------------------------------------------------------------------}
563
564-- | Zero-based index of piece in torrent content.
565type PieceIx = Int
566
567-- | Size of piece in bytes. Should be a power of 2.
568--
569-- NOTE: Have max and min size constrained to wide used
570-- semi-standard values. This bounds should be used to make decision
571-- about piece size for new torrents.
572--
573type PieceSize = Int
574
575-- | Number of pieces in torrent or a part of torrent.
576type PieceCount = Int
577
578defaultBlockSize :: Int
579defaultBlockSize = 16 * 1024
580
581-- | Optimal number of pieces in torrent.
582optimalPieceCount :: PieceCount
583optimalPieceCount = 1000
584{-# INLINE optimalPieceCount #-}
585
586-- | Piece size should not be less than this value.
587minPieceSize :: Int
588minPieceSize = defaultBlockSize * 4
589{-# INLINE minPieceSize #-}
590
591-- | To prevent transfer degradation piece size should not exceed this
592-- value.
593maxPieceSize :: Int
594maxPieceSize = 4 * 1024 * 1024
595{-# INLINE maxPieceSize #-}
596
597toPow2 :: Int -> Int
598toPow2 x = bit $ fromIntegral (leadingZeros (0 :: Int) - leadingZeros x)
599
600-- | Find the optimal piece size for a given torrent size.
601defaultPieceSize :: Int64 -> Int
602defaultPieceSize x = max minPieceSize $ min maxPieceSize $ toPow2 pc
603 where
604 pc = fromIntegral (x `div` fromIntegral optimalPieceCount)
605
606{-----------------------------------------------------------------------
607-- Piece data
608-----------------------------------------------------------------------}
609
610type PieceHash = ByteString
611
612hashsize :: Int
613hashsize = 20
614{-# INLINE hashsize #-}
615
616-- TODO check if pieceLength is power of 2
617-- | Piece payload should be strict or lazy bytestring.
618data Piece a = Piece
619 { -- | Zero-based piece index in torrent.
620 pieceIndex :: {-# UNPACK #-} !PieceIx
621
622 -- | Payload.
623 , pieceData :: !a
624 } deriving (Show, Read, Eq, Functor, Typeable)
625
626instance NFData (Piece a)
627
628-- | Payload bytes are omitted.
629instance Pretty (Piece a) where
630 pretty Piece {..} = "Piece" <+> braces ("index" <+> "=" <+> int pieceIndex)
631
632-- | Get size of piece in bytes.
633pieceSize :: Piece BL.ByteString -> PieceSize
634pieceSize Piece {..} = fromIntegral (BL.length pieceData)
635
636-- | Get piece hash.
637hashPiece :: Piece BL.ByteString -> PieceHash
638hashPiece Piece {..} = SHA1.hashlazy pieceData
639
640{-----------------------------------------------------------------------
641-- Piece control
642-----------------------------------------------------------------------}
643
644-- | A flat array of SHA1 hash for each piece.
645newtype HashList = HashList { unHashList :: ByteString }
646 deriving (Show, Read, Eq, BEncode, Typeable)
647
648-- | Empty hash list.
649instance Default HashList where
650 def = HashList ""
651
652-- | Part of torrent file used for torrent content validation.
653data PieceInfo = PieceInfo
654 { piPieceLength :: {-# UNPACK #-} !PieceSize
655 -- ^ Number of bytes in each piece.
656
657 , piPieceHashes :: !HashList
658 -- ^ Concatenation of all 20-byte SHA1 hash values.
659 } deriving (Show, Read, Eq, Typeable)
660
661-- | Number of bytes in each piece.
662makeLensesFor [("piPieceLength", "pieceLength")] ''PieceInfo
663
664-- | Concatenation of all 20-byte SHA1 hash values.
665makeLensesFor [("piPieceHashes", "pieceHashes")] ''PieceInfo
666
667instance NFData PieceInfo
668
669instance Default PieceInfo where
670 def = PieceInfo 1 def
671
672class Lint a where
673 lint :: a -> Either String a
674
675instance Lint PieceInfo where
676 lint pinfo @ PieceInfo {..}
677 | BS.length (unHashList piPieceHashes) `rem` hashsize == 0
678 , piPieceLength >= 0 = return pinfo
679 | otherwise = Left undefined
680
681
682putPieceInfo :: Data.Torrent.Put PieceInfo
683putPieceInfo PieceInfo {..} cont =
684 "piece length" .=! piPieceLength
685 .: "pieces" .=! piPieceHashes
686 .: cont
687
688getPieceInfo :: BE.Get PieceInfo
689getPieceInfo = do
690 PieceInfo <$>! "piece length"
691 <*>! "pieces"
692
693instance BEncode PieceInfo where
694 toBEncode = toDict . (`putPieceInfo` endDict)
695 fromBEncode = fromDict getPieceInfo
696
697-- | Hashes are omitted.
698instance Pretty PieceInfo where
699 pretty PieceInfo {..} = "Piece size: " <> int piPieceLength
700
701slice :: Int -> Int -> ByteString -> ByteString
702slice start len = BS.take len . BS.drop start
703{-# INLINE slice #-}
704
705-- | Extract validation hash by specified piece index.
706pieceHash :: PieceInfo -> PieceIx -> PieceHash
707pieceHash PieceInfo {..} i = slice (hashsize * i) hashsize (unHashList piPieceHashes)
708
709-- | Find count of pieces in the torrent. If torrent size is not a
710-- multiple of piece size then the count is rounded up.
711pieceCount :: PieceInfo -> PieceCount
712pieceCount PieceInfo {..} = BS.length (unHashList piPieceHashes) `quot` hashsize
713
714-- | Test if this is last piece in torrent content.
715isLastPiece :: PieceInfo -> PieceIx -> Bool
716isLastPiece ci i = pieceCount ci == succ i
717
718-- | Validate piece with metainfo hash.
719checkPieceLazy :: PieceInfo -> Piece BL.ByteString -> Bool
720checkPieceLazy pinfo @ PieceInfo {..} Piece {..}
721 = (fromIntegral (BL.length pieceData) == piPieceLength
722 || isLastPiece pinfo pieceIndex)
723 && SHA1.hashlazy pieceData == pieceHash pinfo pieceIndex
724
725{-----------------------------------------------------------------------
530-- Info dictionary 726-- Info dictionary
531-----------------------------------------------------------------------} 727-----------------------------------------------------------------------}
532 728
@@ -620,6 +816,7 @@ instance Pretty InfoDict where
620{----------------------------------------------------------------------- 816{-----------------------------------------------------------------------
621-- Torrent info 817-- Torrent info
622-----------------------------------------------------------------------} 818-----------------------------------------------------------------------}
819-- TODO add torrent file validation
623 820
624-- | Metainfo about particular torrent. 821-- | Metainfo about particular torrent.
625data Torrent = Torrent 822data Torrent = Torrent
diff --git a/src/Data/Torrent/Bitfield.hs b/src/Data/Torrent/Bitfield.hs
index b65f058b..ff701d75 100644
--- a/src/Data/Torrent/Bitfield.hs
+++ b/src/Data/Torrent/Bitfield.hs
@@ -92,7 +92,7 @@ import Data.List (foldl')
92import Data.Monoid 92import Data.Monoid
93import Data.Ratio 93import Data.Ratio
94 94
95import Data.Torrent.Piece 95import Data.Torrent
96 96
97-- TODO cache some operations 97-- TODO cache some operations
98 98
diff --git a/src/Data/Torrent/Piece.hs b/src/Data/Torrent/Piece.hs
deleted file mode 100644
index d4b2c399..00000000
--- a/src/Data/Torrent/Piece.hs
+++ /dev/null
@@ -1,232 +0,0 @@
1-- |
2-- Copyright : (c) Sam Truzjan 2013
3-- License : BSD3
4-- Maintainer : pxqr.sta@gmail.com
5-- Stability : experimental
6-- Portability : portable
7--
8-- Pieces are used to validate torrent content.
9--
10{-# LANGUAGE TemplateHaskell #-}
11{-# LANGUAGE DeriveDataTypeable #-}
12{-# LANGUAGE DeriveFunctor #-}
13{-# LANGUAGE GeneralizedNewtypeDeriving #-}
14module Data.Torrent.Piece
15 ( -- * Piece attributes
16 PieceIx
17 , PieceCount
18 , PieceSize
19 , minPieceSize
20 , maxPieceSize
21 , defaultPieceSize
22 , PieceHash
23
24 -- * Piece data
25 , Piece (..)
26 , pieceSize
27 , hashPiece
28
29 -- * Piece control
30 , HashList (..)
31 , PieceInfo (..)
32 , pieceCount
33
34 -- * Lens
35 , pieceLength
36 , pieceHashes
37
38 -- * Validation
39 , pieceHash
40 , checkPieceLazy
41
42 -- * Internal
43 , getPieceInfo
44 , putPieceInfo
45 ) where
46
47import Control.DeepSeq
48import Control.Lens
49import qualified Crypto.Hash.SHA1 as SHA1
50import Data.BEncode
51import Data.BEncode.Types
52import Data.Bits
53import Data.Bits.Extras
54import Data.ByteString as BS
55import qualified Data.ByteString.Lazy as BL
56import qualified Data.ByteString.Base64 as Base64
57import Data.Default
58import Data.Int
59import Data.Text.Encoding as T
60import Data.Typeable
61import Text.PrettyPrint
62import Text.PrettyPrint.Class
63
64
65-- TODO add torrent file validation
66class Lint a where
67 lint :: a -> Either String a
68
69--class Validation a where
70-- validate :: PieceInfo -> Piece a -> Bool
71
72{-----------------------------------------------------------------------
73-- Piece attributes
74-----------------------------------------------------------------------}
75
76-- | Zero-based index of piece in torrent content.
77type PieceIx = Int
78
79-- | Size of piece in bytes. Should be a power of 2.
80--
81-- NOTE: Have max and min size constrained to wide used
82-- semi-standard values. This bounds should be used to make decision
83-- about piece size for new torrents.
84--
85type PieceSize = Int
86
87-- | Number of pieces in torrent or a part of torrent.
88type PieceCount = Int
89
90defaultBlockSize :: Int
91defaultBlockSize = 16 * 1024
92
93-- | Optimal number of pieces in torrent.
94optimalPieceCount :: PieceCount
95optimalPieceCount = 1000
96{-# INLINE optimalPieceCount #-}
97
98-- | Piece size should not be less than this value.
99minPieceSize :: Int
100minPieceSize = defaultBlockSize * 4
101{-# INLINE minPieceSize #-}
102
103-- | To prevent transfer degradation piece size should not exceed this
104-- value.
105maxPieceSize :: Int
106maxPieceSize = 4 * 1024 * 1024
107{-# INLINE maxPieceSize #-}
108
109toPow2 :: Int -> Int
110toPow2 x = bit $ fromIntegral (leadingZeros (0 :: Int) - leadingZeros x)
111
112-- | Find the optimal piece size for a given torrent size.
113defaultPieceSize :: Int64 -> Int
114defaultPieceSize x = max minPieceSize $ min maxPieceSize $ toPow2 pc
115 where
116 pc = fromIntegral (x `div` fromIntegral optimalPieceCount)
117
118{-----------------------------------------------------------------------
119-- Piece data
120-----------------------------------------------------------------------}
121
122type PieceHash = ByteString
123
124hashsize :: Int
125hashsize = 20
126{-# INLINE hashsize #-}
127
128-- TODO check if pieceLength is power of 2
129-- | Piece payload should be strict or lazy bytestring.
130data Piece a = Piece
131 { -- | Zero-based piece index in torrent.
132 pieceIndex :: {-# UNPACK #-} !PieceIx
133
134 -- | Payload.
135 , pieceData :: !a
136 } deriving (Show, Read, Eq, Functor, Typeable)
137
138instance NFData (Piece a)
139
140-- | Payload bytes are omitted.
141instance Pretty (Piece a) where
142 pretty Piece {..} = "Piece" <+> braces ("index" <+> "=" <+> int pieceIndex)
143
144-- | Get size of piece in bytes.
145pieceSize :: Piece BL.ByteString -> PieceSize
146pieceSize Piece {..} = fromIntegral (BL.length pieceData)
147
148-- | Get piece hash.
149hashPiece :: Piece BL.ByteString -> PieceHash
150hashPiece Piece {..} = SHA1.hashlazy pieceData
151
152{-----------------------------------------------------------------------
153-- Piece control
154-----------------------------------------------------------------------}
155
156-- | A flat array of SHA1 hash for each piece.
157newtype HashList = HashList { unHashList :: ByteString }
158 deriving (Show, Read, Eq, BEncode, Typeable)
159
160-- | Empty hash list.
161instance Default HashList where
162 def = HashList ""
163
164-- | Part of torrent file used for torrent content validation.
165data PieceInfo = PieceInfo
166 { piPieceLength :: {-# UNPACK #-} !PieceSize
167 -- ^ Number of bytes in each piece.
168
169 , piPieceHashes :: !HashList
170 -- ^ Concatenation of all 20-byte SHA1 hash values.
171 } deriving (Show, Read, Eq, Typeable)
172
173-- | Number of bytes in each piece.
174makeLensesFor [("piPieceLength", "pieceLength")] ''PieceInfo
175
176-- | Concatenation of all 20-byte SHA1 hash values.
177makeLensesFor [("piPieceHashes", "pieceHashes")] ''PieceInfo
178
179instance NFData PieceInfo
180
181instance Default PieceInfo where
182 def = PieceInfo 1 def
183
184instance Lint PieceInfo where
185 lint pinfo @ PieceInfo {..}
186 | BS.length (unHashList piPieceHashes) `rem` hashsize == 0
187 , piPieceLength >= 0 = return pinfo
188 | otherwise = Left undefined
189
190
191putPieceInfo :: PieceInfo -> BDict -> BDict
192putPieceInfo PieceInfo {..} cont =
193 "piece length" .=! piPieceLength
194 .: "pieces" .=! piPieceHashes
195 .: cont
196
197getPieceInfo :: Get PieceInfo
198getPieceInfo = do
199 PieceInfo <$>! "piece length"
200 <*>! "pieces"
201
202instance BEncode PieceInfo where
203 toBEncode = toDict . (`putPieceInfo` endDict)
204 fromBEncode = fromDict getPieceInfo
205
206-- | Hashes are omitted.
207instance Pretty PieceInfo where
208 pretty PieceInfo {..} = "Piece size: " <> int piPieceLength
209
210slice :: Int -> Int -> ByteString -> ByteString
211slice start len = BS.take len . BS.drop start
212{-# INLINE slice #-}
213
214-- | Extract validation hash by specified piece index.
215pieceHash :: PieceInfo -> PieceIx -> PieceHash
216pieceHash PieceInfo {..} i = slice (hashsize * i) hashsize (unHashList piPieceHashes)
217
218-- | Find count of pieces in the torrent. If torrent size is not a
219-- multiple of piece size then the count is rounded up.
220pieceCount :: PieceInfo -> PieceCount
221pieceCount PieceInfo {..} = BS.length (unHashList piPieceHashes) `quot` hashsize
222
223-- | Test if this is last piece in torrent content.
224isLastPiece :: PieceInfo -> PieceIx -> Bool
225isLastPiece ci i = pieceCount ci == succ i
226
227-- | Validate piece with metainfo hash.
228checkPieceLazy :: PieceInfo -> Piece BL.ByteString -> Bool
229checkPieceLazy pinfo @ PieceInfo {..} Piece {..}
230 = (fromIntegral (BL.length pieceData) == piPieceLength
231 || isLastPiece pinfo pieceIndex)
232 && SHA1.hashlazy pieceData == pieceHash pinfo pieceIndex
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs
index 87a6d4ea..8fe81abd 100644
--- a/src/Network/BitTorrent/DHT/Session.hs
+++ b/src/Network/BitTorrent/DHT/Session.hs
@@ -91,7 +91,7 @@ import System.Random (randomIO)
91import Text.PrettyPrint as PP hiding ((<>), ($$)) 91import Text.PrettyPrint as PP hiding ((<>), ($$))
92import Text.PrettyPrint.Class 92import Text.PrettyPrint.Class
93 93
94import Data.Torrent 94import Data.Torrent as Torrent
95import Network.KRPC hiding (Options, def) 95import Network.KRPC hiding (Options, def)
96import qualified Network.KRPC as KRPC (def) 96import qualified Network.KRPC as KRPC (def)
97import Network.BitTorrent.Core 97import Network.BitTorrent.Core
diff --git a/src/Network/BitTorrent/Exchange/Assembler.hs b/src/Network/BitTorrent/Exchange/Assembler.hs
index e5834948..e17dfbe2 100644
--- a/src/Network/BitTorrent/Exchange/Assembler.hs
+++ b/src/Network/BitTorrent/Exchange/Assembler.hs
@@ -67,7 +67,7 @@ import Data.Map as M
67import Data.Maybe 67import Data.Maybe
68import Data.IP 68import Data.IP
69 69
70import Data.Torrent.Piece 70import Data.Torrent
71import Network.BitTorrent.Core 71import Network.BitTorrent.Core
72import Network.BitTorrent.Exchange.Block as B 72import Network.BitTorrent.Exchange.Block as B
73 73
diff --git a/src/Network/BitTorrent/Exchange/Block.hs b/src/Network/BitTorrent/Exchange/Block.hs
index 16c124e9..ccc7a0a9 100644
--- a/src/Network/BitTorrent/Exchange/Block.hs
+++ b/src/Network/BitTorrent/Exchange/Block.hs
@@ -69,7 +69,7 @@ import Numeric
69import Text.PrettyPrint as PP hiding ((<>)) 69import Text.PrettyPrint as PP hiding ((<>))
70import Text.PrettyPrint.Class 70import Text.PrettyPrint.Class
71 71
72import Data.Torrent.Piece 72import Data.Torrent
73 73
74{----------------------------------------------------------------------- 74{-----------------------------------------------------------------------
75-- Block attributes 75-- Block attributes
diff --git a/src/Network/BitTorrent/Exchange/Message.hs b/src/Network/BitTorrent/Exchange/Message.hs
index bd5c6526..5ca7c97e 100644
--- a/src/Network/BitTorrent/Exchange/Message.hs
+++ b/src/Network/BitTorrent/Exchange/Message.hs
@@ -118,8 +118,8 @@ import Text.PrettyPrint as PP hiding ((<>))
118import Text.PrettyPrint.Class 118import Text.PrettyPrint.Class
119 119
120import Data.Torrent.Bitfield 120import Data.Torrent.Bitfield
121import Data.Torrent 121import Data.Torrent hiding (Piece (..))
122import qualified Data.Torrent.Piece as P 122import qualified Data.Torrent as P (Piece (..))
123import Network.BitTorrent.Core 123import Network.BitTorrent.Core
124import Network.BitTorrent.Exchange.Block 124import Network.BitTorrent.Exchange.Block
125 125
@@ -864,7 +864,7 @@ instance PeerMessage ExtendedMetadata where
864 864
865-- | All 'Piece's in 'MetadataData' messages MUST have size equal to 865-- | All 'Piece's in 'MetadataData' messages MUST have size equal to
866-- this value. The last trailing piece can be shorter. 866-- this value. The last trailing piece can be shorter.
867metadataPieceSize :: P.PieceSize 867metadataPieceSize :: PieceSize
868metadataPieceSize = 16 * 1024 868metadataPieceSize = 16 * 1024
869 869
870isLastPiece :: P.Piece a -> Int -> Bool 870isLastPiece :: P.Piece a -> Int -> Bool
@@ -877,8 +877,8 @@ isLastPiece P.Piece {..} total = succ pieceIndex == pcnt
877-- length; otherwise serialization MUST fail. 877-- length; otherwise serialization MUST fail.
878isValidPiece :: P.Piece BL.ByteString -> Int -> Bool 878isValidPiece :: P.Piece BL.ByteString -> Int -> Bool
879isValidPiece p @ P.Piece {..} total 879isValidPiece p @ P.Piece {..} total
880 | isLastPiece p total = P.pieceSize p <= metadataPieceSize 880 | isLastPiece p total = pieceSize p <= metadataPieceSize
881 | otherwise = P.pieceSize p == metadataPieceSize 881 | otherwise = pieceSize p == metadataPieceSize
882 882
883setMetadataPayload :: BS.ByteString -> ExtendedMetadata -> ExtendedMetadata 883setMetadataPayload :: BS.ByteString -> ExtendedMetadata -> ExtendedMetadata
884setMetadataPayload bs (MetadataData (P.Piece pix _) t) = 884setMetadataPayload bs (MetadataData (P.Piece pix _) t) =
diff --git a/src/Network/BitTorrent/Exchange/Session.hs b/src/Network/BitTorrent/Exchange/Session.hs
index 0adb08c8..cae3a2d5 100644
--- a/src/Network/BitTorrent/Exchange/Session.hs
+++ b/src/Network/BitTorrent/Exchange/Session.hs
@@ -45,8 +45,7 @@ import Text.PrettyPrint.Class
45import System.Log.FastLogger (LogStr, ToLogStr (..)) 45import System.Log.FastLogger (LogStr, ToLogStr (..))
46 46
47import Data.BEncode as BE 47import Data.BEncode as BE
48import Data.Torrent as T 48import Data.Torrent as Torrent
49import Data.Torrent.Piece as Torrent
50import Data.Torrent.Bitfield as BF 49import Data.Torrent.Bitfield as BF
51import Network.BitTorrent.Internal.Types 50import Network.BitTorrent.Internal.Types
52import Network.BitTorrent.Core 51import Network.BitTorrent.Core
diff --git a/src/Network/BitTorrent/Exchange/Session/Metadata.hs b/src/Network/BitTorrent/Exchange/Session/Metadata.hs
index bdd5b322..a4e54659 100644
--- a/src/Network/BitTorrent/Exchange/Session/Metadata.hs
+++ b/src/Network/BitTorrent/Exchange/Session/Metadata.hs
@@ -27,7 +27,6 @@ import Data.Tuple
27 27
28import Data.BEncode as BE 28import Data.BEncode as BE
29import Data.Torrent as Torrent 29import Data.Torrent as Torrent
30import Data.Torrent.Piece as Torrent
31import Network.BitTorrent.Core 30import Network.BitTorrent.Core
32import Network.BitTorrent.Exchange.Block as Block 31import Network.BitTorrent.Exchange.Block as Block
33import Network.BitTorrent.Exchange.Message as Message hiding (Status) 32import Network.BitTorrent.Exchange.Message as Message hiding (Status)
diff --git a/src/Network/BitTorrent/Exchange/Session/Status.hs b/src/Network/BitTorrent/Exchange/Session/Status.hs
index 565c3bf3..4feff8d6 100644
--- a/src/Network/BitTorrent/Exchange/Session/Status.hs
+++ b/src/Network/BitTorrent/Exchange/Session/Status.hs
@@ -28,7 +28,7 @@ import Data.Map as M
28import Data.Set as S 28import Data.Set as S
29import Data.Tuple 29import Data.Tuple
30 30
31import Data.Torrent.Piece 31import Data.Torrent
32import Data.Torrent.Bitfield as BF 32import Data.Torrent.Bitfield as BF
33import Network.BitTorrent.Core 33import Network.BitTorrent.Core
34import Network.BitTorrent.Exchange.Block as Block 34import Network.BitTorrent.Exchange.Block as Block
diff --git a/src/System/Torrent/Storage.hs b/src/System/Torrent/Storage.hs
index 697e3def..1123cea9 100644
--- a/src/System/Torrent/Storage.hs
+++ b/src/System/Torrent/Storage.hs
@@ -57,8 +57,6 @@ import Data.Typeable
57 57
58import Data.Torrent 58import Data.Torrent
59import Data.Torrent.Bitfield as BF 59import Data.Torrent.Bitfield as BF
60import Data.Torrent
61import Data.Torrent.Piece
62import System.Torrent.FileMap as FM 60import System.Torrent.FileMap as FM
63 61
64 62
diff --git a/tests/Data/Torrent/MetainfoSpec.hs b/tests/Data/Torrent/MetainfoSpec.hs
index 537b3f99..1a8f97c7 100644
--- a/tests/Data/Torrent/MetainfoSpec.hs
+++ b/tests/Data/Torrent/MetainfoSpec.hs
@@ -14,7 +14,6 @@ import Test.QuickCheck
14import Test.QuickCheck.Instances () 14import Test.QuickCheck.Instances ()
15 15
16import Data.Torrent 16import Data.Torrent
17import Data.Torrent.Piece
18import Data.Torrent.LayoutSpec () 17import Data.Torrent.LayoutSpec ()
19import Network.BitTorrent.Core.NodeInfoSpec () 18import Network.BitTorrent.Core.NodeInfoSpec ()
20 19
diff --git a/tests/Data/Torrent/PieceSpec.hs b/tests/Data/Torrent/PieceSpec.hs
index ef1f2938..d3933396 100644
--- a/tests/Data/Torrent/PieceSpec.hs
+++ b/tests/Data/Torrent/PieceSpec.hs
@@ -3,7 +3,7 @@ module Data.Torrent.PieceSpec (spec) where
3import Control.Applicative 3import Control.Applicative
4import Test.Hspec 4import Test.Hspec
5import Test.QuickCheck 5import Test.QuickCheck
6import Data.Torrent.Piece 6import Data.Torrent
7 7
8 8
9instance Arbitrary a => Arbitrary (Piece a) where 9instance Arbitrary a => Arbitrary (Piece a) where
diff --git a/tests/Network/BitTorrent/Exchange/Session/MetadataSpec.hs b/tests/Network/BitTorrent/Exchange/Session/MetadataSpec.hs
index 975ceb5b..5392d74b 100644
--- a/tests/Network/BitTorrent/Exchange/Session/MetadataSpec.hs
+++ b/tests/Network/BitTorrent/Exchange/Session/MetadataSpec.hs
@@ -7,8 +7,7 @@ import Test.Hspec
7import Test.QuickCheck 7import Test.QuickCheck
8 8
9import Data.BEncode as BE 9import Data.BEncode as BE
10import Data.Torrent 10import Data.Torrent as Torrent
11import Data.Torrent.Piece as P
12import Network.BitTorrent.Core 11import Network.BitTorrent.Core
13import Network.BitTorrent.Exchange.Message 12import Network.BitTorrent.Exchange.Message
14import Network.BitTorrent.Exchange.Session.Metadata 13import Network.BitTorrent.Exchange.Session.Metadata
@@ -36,7 +35,7 @@ simulateFetch :: InfoDict -> Updates (Maybe InfoDict)
36simulateFetch dict = go 35simulateFetch dict = go
37 where 36 where
38 blocks = chunkBy metadataPieceSize (BL.toStrict (BE.encode dict)) 37 blocks = chunkBy metadataPieceSize (BL.toStrict (BE.encode dict))
39 packPiece ix = P.Piece ix (blocks !! ix) 38 packPiece ix = Torrent.Piece ix (blocks !! ix)
40 ih = idInfoHash dict 39 ih = idInfoHash dict
41 40
42 go = do 41 go = do
diff --git a/tests/System/Torrent/StorageSpec.hs b/tests/System/Torrent/StorageSpec.hs
index ebf4fe3e..96f1b036 100644
--- a/tests/System/Torrent/StorageSpec.hs
+++ b/tests/System/Torrent/StorageSpec.hs
@@ -7,9 +7,8 @@ import System.Directory
7import System.IO.Unsafe 7import System.IO.Unsafe
8import Test.Hspec 8import Test.Hspec
9 9
10import Data.Torrent.Bitfield as BF
11import Data.Torrent 10import Data.Torrent
12import Data.Torrent.Piece 11import Data.Torrent.Bitfield as BF
13import System.Torrent.Storage 12import System.Torrent.Storage
14 13
15 14