]> git.rkrishnan.org Git - functorrent.git/commitdiff
refactor the piecemap initialization
authorRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Thu, 17 Sep 2015 22:04:12 +0000 (03:34 +0530)
committerRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Thu, 17 Sep 2015 22:04:12 +0000 (03:34 +0530)
Move parts of the download resume code into Main, since it avoids
duplication of some code and makes the flow, a lot more easy to
understand.

src/FuncTorrent/Peer.hs
src/FuncTorrent/Server.hs
src/FuncTorrent/Utils.hs
src/main/Main.hs

index 13c07e3a8e2ab8824670a6af416c824321924e05..157dab0c021e7d5155169fdc638f200c29b48a3d 100644 (file)
@@ -1,14 +1,16 @@
 {-# LANGUAGE OverloadedStrings #-}
 module FuncTorrent.Peer
     (Peer(..),
 {-# LANGUAGE OverloadedStrings #-}
 module FuncTorrent.Peer
     (Peer(..),
+     PieceMap,
      handlePeerMsgs,
      handlePeerMsgs,
-     bytesDownloaded
+     bytesDownloaded,
+     initPieceMap,
+     pieceMapFromFile
     ) where
 
 import Prelude hiding (lookup, concat, replicate, splitAt, take, filter)
 
 import System.IO (Handle, BufferMode(..), hSetBuffering)
     ) where
 
 import Prelude hiding (lookup, concat, replicate, splitAt, take, filter)
 
 import System.IO (Handle, BufferMode(..), hSetBuffering)
-import System.Directory (doesFileExist)
 import Data.ByteString (ByteString, unpack, concat, hGet, hPut, take, empty)
 import qualified Data.ByteString.Char8 as BC (length)
 import Network (connectTo, PortID(..))
 import Data.ByteString (ByteString, unpack, concat, hGet, hPut, take, empty)
 import qualified Data.ByteString.Char8 as BC (length)
 import Network (connectTo, PortID(..))
@@ -20,7 +22,7 @@ import qualified Crypto.Hash.SHA1 as SHA1 (hash)
 import Safe (headMay)
 
 import FuncTorrent.Metainfo (Info(..), Metainfo(..))
 import Safe (headMay)
 
 import FuncTorrent.Metainfo (Info(..), Metainfo(..))
-import FuncTorrent.Utils (splitN, splitNum, createDummyFile, writeFileAtOffset, readFileAtOffset)
+import FuncTorrent.Utils (splitN, splitNum, writeFileAtOffset, readFileAtOffset)
 import FuncTorrent.PeerMsgs (Peer(..), PeerMsg(..), sendMsg, getMsg, genHandshakeMsg)
 
 data PState = PState { handle :: Handle
 import FuncTorrent.PeerMsgs (Peer(..), PeerMsg(..), sendMsg, getMsg, genHandshakeMsg)
 
 data PState = PState { handle :: Handle
@@ -61,14 +63,6 @@ initPieceMap pieceHash fileLen pieceLen = fromList kvs
     hashes = splitN 20 pieceHash
     pLengths = (splitNum fileLen pieceLen)
 
     hashes = splitN 20 pieceHash
     pLengths = (splitNum fileLen pieceLen)
 
-updatePieceMap :: FilePath -> PieceMap -> IO PieceMap
-updatePieceMap filePath pieceMap = do
-  dfe <- doesFileExist filePath
-  -- TODO: this is not enough, file should have the same size as well
-  if dfe
-    then pieceMapFromFile filePath pieceMap
-    else return pieceMap
-
 pieceMapFromFile :: FilePath -> PieceMap -> IO PieceMap
 pieceMapFromFile filePath pieceMap = do
   traverseWithKey f pieceMap
 pieceMapFromFile :: FilePath -> PieceMap -> IO PieceMap
 pieceMapFromFile filePath pieceMap = do
   traverseWithKey f pieceMap
@@ -139,19 +133,13 @@ updatePieceAvailability pieceStatus p pieceList =
                        then (pd { peers = p : peers pd })
                        else pd) pieceStatus
 
                        then (pd { peers = p : peers pd })
                        else pd) pieceStatus
 
-handlePeerMsgs :: Peer -> String -> Metainfo -> IO ()
-handlePeerMsgs p peerId m = do
+handlePeerMsgs :: Peer -> String -> Metainfo -> PieceMap -> IO ()
+handlePeerMsgs p peerId m pieceMap = do
   h <- connectToPeer p
   doHandshake h p (infoHash m) peerId
   let pstate = toPeerState h p False False True True
   h <- connectToPeer p
   doHandshake h p (infoHash m) peerId
   let pstate = toPeerState h p False False True True
-      pieceHash = pieces (info m)
-      pLen = pieceLength (info m)
-      fileLen = lengthInBytes (info m)
-      fileName = name (info m)
-      pieceStatus = initPieceMap pieceHash fileLen pLen
-  pieceStatus' <- updatePieceMap fileName pieceStatus
-  createDummyFile fileName (fromIntegral fileLen)
-  _ <- runStateT (msgLoop pieceStatus' fileName) pstate
+      filePath = name (info m)
+  _ <- runStateT (msgLoop pieceMap filePath) pstate
   return ()
 
 msgLoop :: PieceMap -> FilePath -> StateT PState IO ()
   return ()
 
 msgLoop :: PieceMap -> FilePath -> StateT PState IO ()
index e675c6c1c4ee44ff9f460fb9b9bb48803814e4df..b78be297b935628a90bf10101f8dd836d0578042 100644 (file)
@@ -7,7 +7,7 @@ import Network (withSocketsDo, listenOn, accept, Socket, PortID ( PortNumber ))
 import System.IO (hSetBuffering, BufferMode ( NoBuffering ))
 
 import FuncTorrent.Metainfo (Metainfo)
 import System.IO (hSetBuffering, BufferMode ( NoBuffering ))
 
 import FuncTorrent.Metainfo (Metainfo)
-import FuncTorrent.Peer (handlePeerMsgs, Peer(..))
+import FuncTorrent.Peer (handlePeerMsgs, Peer(..), PieceMap)
 
 -- server is listening on any port from 6881 - 6889
 -- return the port number used
 
 -- server is listening on any port from 6881 - 6889
 -- return the port number used
@@ -17,9 +17,9 @@ start = withSocketsDo $ do
   sock <- listenOn $ PortNumber $ fromIntegral (head portnums)
   return (sock, PortNumber $ head portnums)
 
   sock <- listenOn $ PortNumber $ fromIntegral (head portnums)
   return (sock, PortNumber $ head portnums)
 
-run :: Socket -> String -> Metainfo -> IO ()
-run listenSock peerid m = forever $ do
+run :: Socket -> String -> Metainfo -> PieceMap -> IO ()
+run listenSock peerid m pieceMap = forever $ do
   (handle, ip, port) <- accept listenSock
   let peer = Peer "" ip (fromIntegral port)
   hSetBuffering handle NoBuffering
   (handle, ip, port) <- accept listenSock
   let peer = Peer "" ip (fromIntegral port)
   hSetBuffering handle NoBuffering
-  forkIO $ handlePeerMsgs peer peerid m
+  forkIO $ handlePeerMsgs peer peerid m pieceMap
index de2a4561c36f070c76841f944f0d134616943d19..ac08927dc348b905d326e58af99fe147b95930aa 100644 (file)
@@ -13,7 +13,6 @@ import System.IO (withFile, hSeek, IOMode(..), SeekMode(..))
 import System.Directory (doesFileExist)
 import Data.ByteString (ByteString, writeFile, hPut, hGet)
 import qualified Data.ByteString.Char8 as BC
 import System.Directory (doesFileExist)
 import Data.ByteString (ByteString, writeFile, hPut, hGet)
 import qualified Data.ByteString.Char8 as BC
-import qualified Data.ByteString.Char8 as BC (replicate)
 
 splitN :: Int -> BC.ByteString -> [BC.ByteString]
 splitN n bs | BC.null bs = []
 
 splitN :: Int -> BC.ByteString -> [BC.ByteString]
 splitN n bs | BC.null bs = []
index ae3c0354e76a7b714db629388211551bd091600f..79cd9bf7f06fc7497d8ba81f02aa644f49c7e644 100644 (file)
@@ -1,10 +1,10 @@
 {-# LANGUAGE OverloadedStrings #-}
 module Main where
 
 {-# LANGUAGE OverloadedStrings #-}
 module Main where
 
-import Prelude hiding (log, length, readFile, getContents)
+import Prelude hiding (log, length, readFile, getContents, replicate, writeFile)
 
 import Control.Concurrent (forkIO)
 
 import Control.Concurrent (forkIO)
-import Data.ByteString.Char8 (ByteString, getContents, readFile, unpack)
+import Data.ByteString.Char8 (ByteString, getContents, readFile, writeFile, unpack, replicate)
 import Network (PortID (PortNumber))
 import System.Environment (getArgs)
 import System.Exit (exitSuccess)
 import Network (PortID (PortNumber))
 import System.Environment (getArgs)
 import System.Exit (exitSuccess)
@@ -13,7 +13,7 @@ import System.Random (getStdGen, randomRs)
 
 import FuncTorrent.Logger (initLogger, logMessage, logStop)
 import FuncTorrent.Metainfo (Info(..), Metainfo(..), torrentToMetainfo)
 
 import FuncTorrent.Logger (initLogger, logMessage, logStop)
 import FuncTorrent.Metainfo (Info(..), Metainfo(..), torrentToMetainfo)
-import FuncTorrent.Peer (handlePeerMsgs)
+import FuncTorrent.Peer (initPieceMap, handlePeerMsgs, pieceMapFromFile)
 import qualified FuncTorrent.Server as Server
 import FuncTorrent.Tracker (peers, getTrackerResponse)
 
 import qualified FuncTorrent.Server as Server
 import FuncTorrent.Tracker (peers, getTrackerResponse)
 
@@ -57,18 +57,30 @@ main = do
     case torrentToMetainfo torrentStr of
      Left e -> logError e log
      Right m -> do
     case torrentToMetainfo torrentStr of
      Left e -> logError e log
      Right m -> do
-       let p = name (info m)
-       log $ "Downloading file : " ++ p
        -- if we had downloaded the file before (partly or completely)
        -- then we should check the current directory for the existence
        -- of the file and then update the map of each piece' availability.
        -- This can be donw by reading each piece and verifying the checksum.
        -- If the checksum does not match, we don't have that piece.
        -- if we had downloaded the file before (partly or completely)
        -- then we should check the current directory for the existence
        -- of the file and then update the map of each piece' availability.
        -- This can be donw by reading each piece and verifying the checksum.
        -- If the checksum does not match, we don't have that piece.
+       let filePath = name (info m) -- really this is just the file name, not file path
+           fileLen = lengthInBytes (info m)
+           pieceHash = pieces (info m)
+           pLen = pieceLength (info m)
+           defaultPieceMap = initPieceMap pieceHash fileLen pLen
+       log $ "Downloading file : " ++ filePath
+       dfe <- doesFileExist filePath
+       pieceMap <- if dfe
+                   then
+                     pieceMapFromFile filePath defaultPieceMap
+                   else do
+                     -- create a dummy file
+                     _ <- writeFile filePath (replicate (fromIntegral fileLen) '\0')
+                     return defaultPieceMap
        log $ "starting server"
        (serverSock, (PortNumber portnum)) <- Server.start
        log $ "server started on " ++ show portnum
        log "Trying to fetch peers"
        log $ "starting server"
        (serverSock, (PortNumber portnum)) <- Server.start
        log $ "server started on " ++ show portnum
        log "Trying to fetch peers"
-       forkIO $ Server.run serverSock peerId m
+       forkIO $ Server.run serverSock peerId m pieceMap
        log $ "Trackers: " ++ head (announceList m)
        trackerResp <- getTrackerResponse portnum peerId m
        case  trackerResp of
        log $ "Trackers: " ++ head (announceList m)
        trackerResp <- getTrackerResponse portnum peerId m
        case  trackerResp of
@@ -76,5 +88,5 @@ main = do
         Right peerList -> do
           log $ "Peers List : " ++ (show . peers $ peerList)
           let p1 = head (peers peerList)
         Right peerList -> do
           log $ "Peers List : " ++ (show . peers $ peerList)
           let p1 = head (peers peerList)
-          handlePeerMsgs p1 peerId m
+          handlePeerMsgs p1 peerId m pieceMap
     logStop logR
     logStop logR