1 module FuncTorrent.FileSystem
11 import Control.Concurrent (ThreadId, forkIO)
12 import Control.Concurrent.Chan (Chan, newChan, readChan)
13 import Control.Concurrent.MVar (MVar, putMVar)
14 import Control.Monad (forever)
15 import Data.Map (traverseWithKey)
17 import qualified Data.ByteString as BS
19 import System.IO (Handle, openFile, IOMode (ReadWriteMode))
21 import FuncTorrent.PieceManager (PieceDlState(..), PieceData(..), PieceMap, pieceNumToOffset)
22 import FuncTorrent.Utils (readFileAtOffset, writeFileAtOffset, verifyHash)
24 type PieceNum = Integer
25 data Piece = Piece PieceNum BS.ByteString
27 data Msg = ReadPiece PieceNum Integer (MVar Piece)
29 | VerifyPiece PieceNum (MVar Bool)
31 type MsgChannel = Chan Msg
33 -- init :: FileName -> IO (Handle, MsgChannel)
34 initFS :: FilePath -> IO (Handle, MsgChannel)
37 h <- openFile filepath ReadWriteMode
40 startThread :: Handle -> MsgChannel -> PieceMap -> IO ThreadId
41 startThread handle c pieceMap = do
42 forkIO $ forever $ recvMsg >>= sendResponse
47 ReadPiece n len' var -> do
48 bs <- readPiece n len'
49 putMVar var (Piece n bs)
50 WritePiece (Piece n bs) -> do
52 VerifyPiece n var -> do
53 isHashValid <- verifyPiece n
54 putMVar var isHashValid
56 let offset = pieceNumToOffset pieceMap n
57 readFileAtOffset handle offset len'
58 writePiece n piece = do
59 let offset = pieceNumToOffset pieceMap n
60 writeFileAtOffset handle offset piece
62 let offset = pieceNumToOffset pieceMap n
63 hash' = hash (pieceMap ! n)
64 len' = len (pieceMap ! n)
65 bs' <- readFileAtOffset handle offset len'
66 return $ verifyHash bs' hash'
68 pieceMapFromFile :: Handle -> PieceMap -> IO PieceMap
69 pieceMapFromFile handle pieceMap = do
70 traverseWithKey f pieceMap
73 let offset = pieceNumToOffset pieceMap k
74 isHashValid <- flip verifyHash (hash v) <$> readFileAtOffset handle offset (len v)
76 then return $ v { dlstate = Have }