1 {-# LANGUAGE OverloadedStrings #-}
4 import Prelude hiding (log, length, readFile, getContents)
6 import Control.Concurrent (forkIO)
7 import Data.ByteString.Char8 (ByteString, getContents, readFile, unpack)
8 import System.Environment (getArgs)
9 import System.Exit (exitSuccess)
10 import System.Directory (doesFileExist)
11 import System.Random (getStdGen, randomRs)
13 import FuncTorrent.Logger (initLogger, logMessage, logStop)
14 import FuncTorrent.Metainfo (Info(..), Metainfo(..), torrentToMetainfo)
15 import FuncTorrent.Peer (handlePeerMsgs)
16 import qualified FuncTorrent.Server as Server
17 import FuncTorrent.Tracker (peers, getTrackerResponse)
19 logError :: String -> (String -> IO ()) -> IO ()
20 logError e logMsg = logMsg $ "parse error: \n" ++ e
26 usage = putStrLn "usage: functorrent torrent-file"
28 parse :: [String] -> IO ByteString
29 parse [] = getContents
31 fileExist <- doesFileExist a
34 else error "file does not exist"
37 -- peer id is exactly 20 bytes long.
38 -- peer id starts with '-', followed by 2 char client id'
39 -- followed by 4 ascii digits for version number, followed by
40 -- a '-'. Rest are random digits to fill the 20 bytes.
44 let digits = randomRs (0, 9) stdgen :: [Integer]
45 return $ "-HS9001-" ++ (concatMap show $ take (20 - 8) digits)
52 let log = logMessage logR
53 log "Starting up functorrent"
54 log $ "Parsing arguments " ++ concat args
55 torrentStr <- parse args
56 case torrentToMetainfo torrentStr of
57 Left e -> logError e log
60 log $ "Downloading file : " ++ name (info m)
62 log $ "starting server"
63 (serverSock, portnum) <- Server.start
64 log "Trying to fetch peers"
65 forkIO $ Server.run serverSock peerId m
66 log $ "Trackers: " ++ head (announceList m)
67 trackerResp <- getTrackerResponse peerId m
69 Left e -> log $ "Error" ++ unpack e
71 log $ "Peers List : " ++ (show . peers $ peerList)
72 let p1 = head (peers peerList)
73 handlePeerMsgs p1 peerId m