summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Network/BitTorrent/Core/Fingerprint.hs7
-rw-r--r--src/Network/BitTorrent/Tracker/RPC.hs1
-rw-r--r--src/Network/BitTorrent/Tracker/RPC/HTTP.hs34
3 files changed, 31 insertions, 11 deletions
diff --git a/src/Network/BitTorrent/Core/Fingerprint.hs b/src/Network/BitTorrent/Core/Fingerprint.hs
index a81edd8b..d743acd0 100644
--- a/src/Network/BitTorrent/Core/Fingerprint.hs
+++ b/src/Network/BitTorrent/Core/Fingerprint.hs
@@ -25,11 +25,13 @@ module Network.BitTorrent.Core.Fingerprint
25 ( ClientImpl (..) 25 ( ClientImpl (..)
26 , Fingerprint (..) 26 , Fingerprint (..)
27 , libFingerprint 27 , libFingerprint
28 , libUserAgent
28 ) where 29 ) where
29 30
30import Data.Default 31import Data.Default
31import Data.List as L 32import Data.List as L
32import Data.List.Split as L 33import Data.List.Split as L
34import Data.Monoid
33import Data.String 35import Data.String
34import Data.Version 36import Data.Version
35import Text.PrettyPrint hiding ((<>)) 37import Text.PrettyPrint hiding ((<>))
@@ -190,6 +192,11 @@ instance Pretty Fingerprint where
190libFingerprint :: Fingerprint 192libFingerprint :: Fingerprint
191libFingerprint = Fingerprint IlibHSbittorrent version 193libFingerprint = Fingerprint IlibHSbittorrent version
192 194
195-- | HTTP user agent of this (the bittorrent library) package. Can be
196-- used in HTTP tracker requests.
197libUserAgent :: String
198libUserAgent = render (pretty IlibHSbittorrent <> "/" <> pretty version)
199
193{----------------------------------------------------------------------- 200{-----------------------------------------------------------------------
194-- For torrent file 201-- For torrent file
195-----------------------------------------------------------------------} 202-----------------------------------------------------------------------}
diff --git a/src/Network/BitTorrent/Tracker/RPC.hs b/src/Network/BitTorrent/Tracker/RPC.hs
index 3fe5157c..45bd62d8 100644
--- a/src/Network/BitTorrent/Tracker/RPC.hs
+++ b/src/Network/BitTorrent/Tracker/RPC.hs
@@ -18,6 +18,7 @@ module Network.BitTorrent.Tracker.RPC
18 , withManager 18 , withManager
19 19
20 -- * RPC 20 -- * RPC
21 , SAnnounceQuery (..)
21 , announce 22 , announce
22 , scrape 23 , scrape
23 ) where 24 ) where
diff --git a/src/Network/BitTorrent/Tracker/RPC/HTTP.hs b/src/Network/BitTorrent/Tracker/RPC/HTTP.hs
index d30c0e9d..7d69df1a 100644
--- a/src/Network/BitTorrent/Tracker/RPC/HTTP.hs
+++ b/src/Network/BitTorrent/Tracker/RPC/HTTP.hs
@@ -31,7 +31,7 @@ import Control.Applicative
31import Control.Exception 31import Control.Exception
32import Control.Monad.Trans.Resource 32import Control.Monad.Trans.Resource
33import Data.BEncode as BE 33import Data.BEncode as BE
34import Data.ByteString as B 34import Data.ByteString as BS
35import Data.ByteString.Char8 as BC 35import Data.ByteString.Char8 as BC
36import Data.ByteString.Lazy as BL 36import Data.ByteString.Lazy as BL
37import Data.Default 37import Data.Default
@@ -42,9 +42,11 @@ import Network.HTTP.Conduit hiding
42 (Manager, newManager, closeManager, withManager) 42 (Manager, newManager, closeManager, withManager)
43import qualified Network.HTTP.Conduit as HTTP 43import qualified Network.HTTP.Conduit as HTTP
44import Network.HTTP.Conduit.Internal (setUri) 44import Network.HTTP.Conduit.Internal (setUri)
45import Network.HTTP.Types.URI 45import Network.HTTP.Types.Header (hUserAgent)
46import Network.HTTP.Types.URI (SimpleQuery, renderSimpleQuery)
46 47
47import Data.Torrent.InfoHash 48import Data.Torrent.InfoHash (InfoHash)
49import Network.BitTorrent.Core.Fingerprint (libUserAgent)
48import Network.BitTorrent.Tracker.Message 50import Network.BitTorrent.Tracker.Message
49 51
50{----------------------------------------------------------------------- 52{-----------------------------------------------------------------------
@@ -59,6 +61,9 @@ data Options = Options
59 -- | Whether to use HTTP proxy for HTTP tracker requests. 61 -- | Whether to use HTTP proxy for HTTP tracker requests.
60 , optHttpProxy :: !(Maybe Proxy) 62 , optHttpProxy :: !(Maybe Proxy)
61 63
64 -- | Value to put in HTTP user agent header.
65 , optUserAgent :: !BS.ByteString
66
62 -- | HTTP manager options. 67 -- | HTTP manager options.
63 , optHttpOptions :: !ManagerSettings 68 , optHttpOptions :: !ManagerSettings
64 } 69 }
@@ -67,6 +72,7 @@ instance Default Options where
67 def = Options 72 def = Options
68 { optAnnounceExt = def 73 { optAnnounceExt = def
69 , optHttpProxy = Nothing 74 , optHttpProxy = Nothing
75 , optUserAgent = BC.pack libUserAgent
70 , optHttpOptions = def 76 , optHttpOptions = def
71 } 77 }
72 78
@@ -89,15 +95,21 @@ withManager opts = bracket (newManager opts) closeManager
89-- Queries 95-- Queries
90-----------------------------------------------------------------------} 96-----------------------------------------------------------------------}
91 97
92setSimpleQuery :: SimpleQuery -> Request m -> Request m 98fillRequest :: Options -> SimpleQuery -> Request m -> Request m
93setSimpleQuery q r = r 99fillRequest Options {..} q r = r
94 { queryString = renderSimpleQuery False q 100 { queryString = joinQuery (queryString r) (renderSimpleQuery False q)
101 , requestHeaders = (hUserAgent, optUserAgent) : requestHeaders r
102 , proxy = optHttpProxy
95 } 103 }
104 where
105 joinQuery a b
106 | BS.null a = b
107 | otherwise = a <> "&" <> b
96 108
97httpTracker :: BEncode a => Manager -> URI -> SimpleQuery -> ResourceT IO a 109httpTracker :: BEncode a => Manager -> URI -> SimpleQuery -> ResourceT IO a
98httpTracker Manager {..} uri q = do 110httpTracker Manager {..} uri q = do
99 request <- setSimpleQuery q <$> setUri def uri 111 request <- fillRequest options q <$> setUri def uri
100 response <- httpLbs request { proxy = optHttpProxy options } httpMgr 112 response <- httpLbs request httpMgr
101 case BE.decode $ BL.toStrict $ responseBody response of 113 case BE.decode $ BL.toStrict $ responseBody response of
102 Left msg -> error $ "httpTracker: " ++ msg 114 Left msg -> error $ "httpTracker: " ++ msg
103 Right info -> return info 115 Right info -> return info
@@ -127,9 +139,9 @@ scrapeURL uri = do
127 where 139 where
128 replace p 140 replace p
129 | ps <- BC.splitWith (== '/') p 141 | ps <- BC.splitWith (== '/') p
130 , "announce" `B.isPrefixOf` L.last ps 142 , "announce" `BS.isPrefixOf` L.last ps
131 = let newSuff = "scrape" <> B.drop (B.length "announce") (L.last ps) 143 = let newSuff = "scrape" <> BS.drop (BS.length "announce") (L.last ps)
132 in Just (B.intercalate "/" (L.init ps ++ [newSuff])) 144 in Just (BS.intercalate "/" (L.init ps ++ [newSuff]))
133 | otherwise = Nothing 145 | otherwise = Nothing
134 146
135-- | For each 'InfoHash' of torrents request scrape info from the tracker. 147-- | For each 'InfoHash' of torrents request scrape info from the tracker.