import Data.Char (chr)
import Data.List (intercalate)
import Data.Map as M (lookup)
+import Network (PortNumber)
import Network.HTTP.Base (urlEncode)
import qualified Data.ByteString.Base16 as B16 (encode)
where (ip', port') = splitAt 4 peer
-- | Connect to a tracker and get peer info
-tracker :: String -> Metainfo -> IO ByteString
-tracker peer_id m = do
- get (head . announceList $ m) $ mkArgs peer_id m
+tracker :: PortNumber -> String -> Metainfo -> IO ByteString
+tracker port peer_id m = do
+ get (head . announceList $ m) $ mkArgs port peer_id m
-getTrackerResponse :: String -> Metainfo -> IO (Either ByteString TrackerResponse)
-getTrackerResponse peerId m = do
- resp <- tracker peerId m
+getTrackerResponse :: PortNumber -> String -> Metainfo -> IO (Either ByteString TrackerResponse)
+getTrackerResponse port peerId m = do
+ resp <- tracker port peerId m
case decode resp of
Right trackerInfo -> return $ mkTrackerResponse trackerInfo
Left e -> return $ Left (pack (show e))
-- | Make arguments that should be posted to tracker.
-- This is a separate pure function for testability.
-mkArgs :: String -> Metainfo -> [(String, ByteString)]
-mkArgs peer_id m = [("info_hash", pack . urlEncodeHash . B16.encode . infoHash $ m),
- ("peer_id", pack . urlEncode $ peer_id),
- ("port", "6881"),
- ("uploaded", "0"),
- ("downloaded", "0"),
- ("left", pack . show . lengthInBytes $ info m),
- ("compact", "1"),
- ("event", "started")]
+mkArgs :: PortNumber -> String -> Metainfo -> [(String, ByteString)]
+mkArgs port peer_id m = [("info_hash", pack . urlEncodeHash . B16.encode . infoHash $ m),
+ ("peer_id", pack . urlEncode $ peer_id),
+ ("port", pack $ show port),
+ ("uploaded", "0"),
+ ("downloaded", "0"),
+ ("left", pack . show . lengthInBytes $ info m),
+ ("compact", "1"),
+ ("event", "started")]
import Control.Concurrent (forkIO)
import Data.ByteString.Char8 (ByteString, getContents, readFile, unpack)
+import Network (PortID (PortNumber))
import System.Environment (getArgs)
import System.Exit (exitSuccess)
import System.Directory (doesFileExist)
log $ "Downloading file : " ++ name (info m)
log $ "starting server"
- (serverSock, portnum) <- Server.start
+ (serverSock, (PortNumber portnum)) <- Server.start
+ log $ "server started on " ++ show portnum
log "Trying to fetch peers"
forkIO $ Server.run serverSock peerId m
log $ "Trackers: " ++ head (announceList m)
- trackerResp <- getTrackerResponse peerId m
+ trackerResp <- getTrackerResponse portnum peerId m
case trackerResp of
Left e -> log $ "Error" ++ unpack e
Right peerList -> do