summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-02-06 03:37:01 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-02-06 03:37:01 +0400
commit24ecfb12c6e2c1d8948f6a250d3332af50eab08e (patch)
treef35e54ee14eebf14f1ec15fca88e640b356888d9 /src/Network/BitTorrent
parent7fefe66f1a3cb2f6f0a80383424592697f79b8b2 (diff)
Add HTTP tracker RpcExceptions
Diffstat (limited to 'src/Network/BitTorrent')
-rw-r--r--src/Network/BitTorrent/Tracker/RPC/HTTP.hs33
1 files changed, 29 insertions, 4 deletions
diff --git a/src/Network/BitTorrent/Tracker/RPC/HTTP.hs b/src/Network/BitTorrent/Tracker/RPC/HTTP.hs
index 0a7e9a08..32a5e79c 100644
--- a/src/Network/BitTorrent/Tracker/RPC/HTTP.hs
+++ b/src/Network/BitTorrent/Tracker/RPC/HTTP.hs
@@ -13,6 +13,7 @@
13-- For more information see: 13-- For more information see:
14-- <https://wiki.theory.org/BitTorrentSpecification#Tracker_HTTP.2FHTTPS_Protocol> 14-- <https://wiki.theory.org/BitTorrentSpecification#Tracker_HTTP.2FHTTPS_Protocol>
15-- 15--
16{-# LANGUAGE DeriveDataTypeable #-}
16module Network.BitTorrent.Tracker.RPC.HTTP 17module Network.BitTorrent.Tracker.RPC.HTTP
17 ( -- * Manager 18 ( -- * Manager
18 Options (..) 19 Options (..)
@@ -22,6 +23,7 @@ module Network.BitTorrent.Tracker.RPC.HTTP
22 , withManager 23 , withManager
23 24
24 -- * RPC 25 -- * RPC
26 , RpcException (..)
25 , announce 27 , announce
26 , scrape 28 , scrape
27 , scrapeOne 29 , scrapeOne
@@ -37,6 +39,7 @@ import Data.ByteString.Lazy as BL
37import Data.Default 39import Data.Default
38import Data.List as L 40import Data.List as L
39import Data.Monoid 41import Data.Monoid
42import Data.Typeable
40import Network.URI 43import Network.URI
41import Network.HTTP.Conduit hiding 44import Network.HTTP.Conduit hiding
42 (Manager, newManager, closeManager, withManager) 45 (Manager, newManager, closeManager, withManager)
@@ -50,6 +53,22 @@ import Network.BitTorrent.Core.Fingerprint (libUserAgent)
50import Network.BitTorrent.Tracker.Message 53import Network.BitTorrent.Tracker.Message
51 54
52{----------------------------------------------------------------------- 55{-----------------------------------------------------------------------
56-- Exceptions
57-----------------------------------------------------------------------}
58
59data RpcException
60 = RequestFailed HttpException -- ^ failed HTTP request.
61 | ParserFailure String -- ^ unable to decode tracker response;
62 | ScrapelessTracker -- ^ tracker do not support scraping;
63 | BadScrape -- ^ unable to find info hash in response dict;
64 deriving (Show, Typeable)
65
66instance Exception RpcException
67
68packHttpException :: IO a -> IO a
69packHttpException m = try m >>= either (throwIO . RequestFailed) return
70
71{-----------------------------------------------------------------------
53-- Manager 72-- Manager
54-----------------------------------------------------------------------} 73-----------------------------------------------------------------------}
55 74
@@ -109,9 +128,9 @@ fillRequest Options {..} q r = r
109httpTracker :: BEncode a => Manager -> URI -> SimpleQuery -> IO a 128httpTracker :: BEncode a => Manager -> URI -> SimpleQuery -> IO a
110httpTracker Manager {..} uri q = do 129httpTracker Manager {..} uri q = do
111 request <- fillRequest options q <$> setUri def uri 130 request <- fillRequest options q <$> setUri def uri
112 response <- runResourceT $ httpLbs request httpMgr 131 response <- packHttpException $ runResourceT $ httpLbs request httpMgr
113 case BE.decode $ BL.toStrict $ responseBody response of 132 case BE.decode $ BL.toStrict $ responseBody response of
114 Left msg -> error $ "httpTracker: " ++ msg 133 Left msg -> throwIO (ParserFailure msg)
115 Right info -> return info 134 Right info -> return info
116 135
117{----------------------------------------------------------------------- 136{-----------------------------------------------------------------------
@@ -121,6 +140,8 @@ httpTracker Manager {..} uri q = do
121-- | Send request and receive response from the tracker specified in 140-- | Send request and receive response from the tracker specified in
122-- announce list. 141-- announce list.
123-- 142--
143-- This function can throw 'RpcException'.
144--
124announce :: Manager -> URI -> AnnounceQuery -> IO AnnounceInfo 145announce :: Manager -> URI -> AnnounceQuery -> IO AnnounceInfo
125announce mgr uri q = httpTracker mgr uri (renderAnnounceRequest uriQ) 146announce mgr uri q = httpTracker mgr uri (renderAnnounceRequest uriQ)
126 where 147 where
@@ -148,17 +169,21 @@ scrapeURL uri = do
148-- However if the info hash list is 'null', the tracker should list 169-- However if the info hash list is 'null', the tracker should list
149-- all available torrents. 170-- all available torrents.
150-- 171--
172-- This function can throw 'RpcException'.
173--
151scrape :: Manager -> URI -> ScrapeQuery -> IO ScrapeInfo 174scrape :: Manager -> URI -> ScrapeQuery -> IO ScrapeInfo
152scrape m u q = do 175scrape m u q = do
153 case scrapeURL u of 176 case scrapeURL u of
154 Nothing -> error "Tracker do not support scraping" 177 Nothing -> throwIO ScrapelessTracker
155 Just uri -> httpTracker m uri (renderScrapeQuery q) 178 Just uri -> httpTracker m uri (renderScrapeQuery q)
156 179
157-- | More particular version of 'scrape', just for one torrent. 180-- | More particular version of 'scrape', just for one torrent.
158-- 181--
182-- This function can throw RpcException.
183--
159scrapeOne :: Manager -> URI -> InfoHash -> IO ScrapeEntry 184scrapeOne :: Manager -> URI -> InfoHash -> IO ScrapeEntry
160scrapeOne m uri ih = do 185scrapeOne m uri ih = do
161 xs <- scrape m uri [ih] 186 xs <- scrape m uri [ih]
162 case L.lookup ih xs of 187 case L.lookup ih xs of
163 Nothing -> error "unable to find info hash in response dict" 188 Nothing -> throwIO BadScrape
164 Just a -> return a 189 Just a -> return a