import Control.Applicative ((<$>), liftA3)
import Data.Bits
import Data.Word (Word8)
-import Data.Map (Map(..))
+import Data.Map (Map(..), fromList)
import FuncTorrent.Metainfo (Info(..), Metainfo(..))
+import FuncTorrent.Utils (splitN)
+
type ID = String
type IP = String
type Port = Integer
-- should probably be a TVar.
type Pieces = [PieceData]
-data PieceState = Pending
- | InProgress
- | Have
- deriving (Show)
+data PieceDlState = Pending
+ | InProgress
+ | Have
+ deriving (Show)
-- todo - map with index to a new data structure (peers who have that piece amd state)
data PieceData = PieceData { peers :: [Peer] -- ^ list of peers who have this piece
- , state :: PieceState } -- ^ state of the piece from download perspective.
+ , state :: PieceDlState -- ^ state of the piece from download perspective.
+ , hash :: ByteString } -- ^ piece hash
-- which piece is with which peers
type PieceMap = Map Integer PieceData
| PortMsg Port
deriving (Show)
+-- Make the initial Piece map, with the assumption that no peer has the
+-- piece and that every piece is pending download.
+mkPieceMap :: Integer -> ByteString -> Map Integer PieceData
+mkPieceMap numPieces pieceHash = fromList kvs
+ where kvs = [(i, PieceData { peers = []
+ , state = Pending
+ , hash = h }) | (i, h) <- zip [0..numPieces] hashes]
+ hashes = splitN (fromIntegral numPieces) pieceHash
+
genHandShakeMsg :: ByteString -> String -> ByteString
genHandShakeMsg infoHash peer_id = concat [pstrlen, pstr, reserved, infoHash, peerID]
where pstrlen = singleton 19
msgLoop :: Handle -> ByteString -> IO ()
msgLoop h pieceHash =
let numPieces = (toInteger . (`quot` 20) . BC.length) pieceHash
+ pieceStatus = mkPieceMap numPieces pieceHash
in
forever $ do
msg <- getMsg h