1 {-# LANGUAGE OverloadedStrings #-}
4 import Prelude hiding (log, length, readFile, writeFile)
5 import Data.ByteString.Char8 (ByteString, readFile, writeFile, unpack)
6 import System.Environment (getArgs)
7 import System.Exit (exitSuccess)
8 import System.Directory (doesFileExist)
9 import Text.ParserCombinators.Parsec (ParseError)
11 import FuncTorrent.Bencode (decode)
12 import FuncTorrent.Logger (initLogger, logMessage, logStop)
13 import FuncTorrent.Metainfo (Info(..), Metainfo(..), mkMetaInfo)
14 import FuncTorrent.Peer (handShake, msgLoop)
15 import FuncTorrent.Tracker (tracker, peers, mkTrackerResponse)
17 logError :: ParseError -> (String -> IO ()) -> IO ()
18 logError e logMsg = logMsg $ "parse error: \n" ++ show e
21 peerId = "-HS0001-*-*-20150215"
27 usage = putStrLn "usage: functorrent torrent-file"
29 parse :: [String] -> IO ByteString
30 parse [] = usage >> exit
32 fileExist <- doesFileExist a
35 else error "file does not exist"
42 let log = logMessage logR
43 log "Starting up functorrent"
44 log $ "Parsing input file " ++ concat args
45 torrentStr <- parse args
46 case decode torrentStr of
49 Nothing -> log "Unable to make meta info file"
52 log $ "Downloading file : " ++ name (info m)
53 log "Trying to fetch peers"
55 log $ "Trackers: " ++ head (announceList m)
56 response <- tracker m peerId
58 -- TODO: Write to ~/.functorrent/caches
59 writeFile (name (info m) ++ ".cache") response
61 case decode response of
63 case mkTrackerResponse trackerInfo of
65 log $ "Peers List : " ++ (show . peers $ peerResp)
66 let p1 = head (peers peerResp)
67 h <- handShake p1 (infoHash m) peerId
69 msgLoop h (pieces (info m))
70 Left e -> log $ "Error" ++ unpack e
71 Left e -> logError e log
73 Left e -> logError e log