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")]