summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2013-12-02 00:17:05 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2013-12-02 00:17:05 +0400
commit10fcabb96e9f5b2d25cdfae22973cbcb99282139 (patch)
tree94ceeddd0c4f6998317f921feccddc1d7498ed7e /src
parent2abd00f548b7b9565b2a6bc1bed793d2a6f8c9cd (diff)
Add http tracker server-side skeleton
Diffstat (limited to 'src')
-rw-r--r--src/Network/BitTorrent/Tracker/RPC/Message.hs49
-rw-r--r--src/Network/BitTorrent/Tracker/Wai.hs102
2 files changed, 145 insertions, 6 deletions
diff --git a/src/Network/BitTorrent/Tracker/RPC/Message.hs b/src/Network/BitTorrent/Tracker/RPC/Message.hs
index cec68169..cefe96d5 100644
--- a/src/Network/BitTorrent/Tracker/RPC/Message.hs
+++ b/src/Network/BitTorrent/Tracker/RPC/Message.hs
@@ -32,10 +32,18 @@ module Network.BitTorrent.Tracker.RPC.Message
32 , ParamParseFailure 32 , ParamParseFailure
33 , parseAnnounceQuery 33 , parseAnnounceQuery
34 34
35 -- ** Request
36 , AnnounceQueryExt (..)
37 , AnnounceRequest (..)
38 , parseAnnounceRequest
39 , renderAnnounceRequest
40
35 -- ** Info 41 -- ** Info
36 , PeerList (..) 42 , PeerList (..)
37 , AnnounceInfo(..) 43 , AnnounceInfo(..)
38 , defaultNumWant 44 , defaultNumWant
45 , defaultMaxNumWant
46 , defaultReannounceInterval
39 , parseFailureStatus 47 , parseFailureStatus
40 48
41 -- * Scrape 49 -- * Scrape
@@ -47,6 +55,9 @@ module Network.BitTorrent.Tracker.RPC.Message
47 -- ** Info 55 -- ** Info
48 , ScrapeEntry (..) 56 , ScrapeEntry (..)
49 , ScrapeInfo 57 , ScrapeInfo
58
59 -- ** Extra
60 , queryToSimpleQuery
50 ) 61 )
51 where 62 where
52 63
@@ -223,15 +234,15 @@ instance QueryLike AnnounceQuery where
223 , ("event" , toQueryValue reqEvent) 234 , ("event" , toQueryValue reqEvent)
224 ] 235 ]
225 236
226filterMaybes :: [(a, Maybe b)] -> [(a, b)] 237queryToSimpleQuery :: Query -> SimpleQuery
227filterMaybes = catMaybes . L.map f 238queryToSimpleQuery = catMaybes . L.map f
228 where 239 where
229 f (_, Nothing) = Nothing 240 f (_, Nothing) = Nothing
230 f (a, Just b ) = Just (a, b) 241 f (a, Just b ) = Just (a, b)
231 242
232-- | Encode announce query and add it to the base tracker URL. 243-- | Encode announce query and add it to the base tracker URL.
233renderAnnounceQuery :: AnnounceQuery -> SimpleQuery 244renderAnnounceQuery :: AnnounceQuery -> SimpleQuery
234renderAnnounceQuery = filterMaybes . toQuery 245renderAnnounceQuery = queryToSimpleQuery . toQuery
235 246
236data QueryParam 247data QueryParam
237 = ParamInfoHash 248 = ParamInfoHash
@@ -320,8 +331,27 @@ parseAnnounceQuery params = AnnounceQuery
320 <*> optParam ParamNumWant params 331 <*> optParam ParamNumWant params
321 <*> optParam ParamEvent params 332 <*> optParam ParamEvent params
322 333
323-- TODO add extension datatype 334data AnnounceQueryExt = AnnounceQueryExt
324--type AnnounceRequest = () 335 { extCompact :: Maybe Bool -- | "compact" param
336 , extNoPeerId :: Maybe Bool -- | "no_peer_id" param
337 } deriving (Show, Eq, Typeable)
338
339parseAnnounceQueryExt :: SimpleQuery -> AnnounceQueryExt
340parseAnnounceQueryExt = undefined
341
342renderAnnounceQueryExt :: AnnounceQueryExt -> SimpleQuery
343renderAnnounceQueryExt = undefined
344
345data AnnounceRequest = AnnounceRequest
346 { announceQuery :: AnnounceQuery
347 , announceAdvises :: AnnounceQueryExt
348 } deriving (Show, Eq, Typeable)
349
350parseAnnounceRequest :: SimpleQuery -> Either ParamParseFailure AnnounceRequest
351parseAnnounceRequest = undefined
352
353renderAnnounceRequest :: AnnounceRequest -> SimpleQuery
354renderAnnounceRequest = undefined
325 355
326{----------------------------------------------------------------------- 356{-----------------------------------------------------------------------
327-- Announce response 357-- Announce response
@@ -449,6 +479,13 @@ instance Serialize AnnounceInfo where
449defaultNumWant :: Int 479defaultNumWant :: Int
450defaultNumWant = 50 480defaultNumWant = 50
451 481
482defaultMaxNumWant :: Int
483defaultMaxNumWant = 200
484
485defaultReannounceInterval :: Int
486defaultReannounceInterval = 30 * 60
487
488
452missingOffset :: Int 489missingOffset :: Int
453missingOffset = 101 490missingOffset = 101
454 491
@@ -500,7 +537,7 @@ isScrapeParam :: BS.ByteString -> Bool
500isScrapeParam = (==) scrapeParam 537isScrapeParam = (==) scrapeParam
501 538
502renderScrapeQuery :: ScrapeQuery -> SimpleQuery 539renderScrapeQuery :: ScrapeQuery -> SimpleQuery
503renderScrapeQuery = filterMaybes . L.map mkPair 540renderScrapeQuery = queryToSimpleQuery . L.map mkPair
504 where 541 where
505 mkPair ih = (scrapeParam, toQueryValue ih) 542 mkPair ih = (scrapeParam, toQueryValue ih)
506 543
diff --git a/src/Network/BitTorrent/Tracker/Wai.hs b/src/Network/BitTorrent/Tracker/Wai.hs
new file mode 100644
index 00000000..f290c380
--- /dev/null
+++ b/src/Network/BitTorrent/Tracker/Wai.hs
@@ -0,0 +1,102 @@
1-- supported extensions:
2--
3-- no_peer_id - do not send peer id if no_peer_id=1 specified
4-- http://www.bittorrent.org/beps/bep_0023.html
5--
6-- compact - compact=1 or compact=0
7-- http://permalink.gmane.org/gmane.network.bit-torrent.general/4030
8--
9--
10{-# LANGUAGE RecordWildCards #-}
11module Network.BitTorrent.Tracker.Wai
12 ( tracker
13 ) where
14
15import Control.Monad.Trans.Resource
16import Data.BEncode as BE
17import Data.ByteString
18import Data.Default
19import Data.List as L
20import Network.HTTP.Types
21import Network.Wai
22
23import Data.Torrent.Progress
24import Network.BitTorrent.Core.PeerId
25import Network.BitTorrent.Core.PeerAddr
26import Network.BitTorrent.Tracker.RPC.Message
27
28
29data TrackerSettings = TrackerSettings
30 { -- | If peer did not specified the "numwant" then this value is
31 -- used.
32 defNumWant :: {-# UNPACK #-} !Int
33
34 -- | If peer specified to big numwant value.
35 , maxNumWant :: {-# UNPACK #-} !Int
36
37 -- | Recommended time interval to wait between regular announce
38 -- requests.
39 , reannounceInterval :: {-# UNPACK #-} !Int
40
41 -- | Minimum time interval to wait between regular announce
42 -- requests.
43 , reannounceMinInterval :: !(Maybe Int)
44
45 -- | Whether to send count of seeders.
46 , completePeers :: !Bool
47
48 -- | Whether to send count of leechers.
49 , incompletePeers :: !Bool
50
51 -- | Do not send peer id in response. Peer can override this value
52 -- by setting "no_peer_id" to 0 or 1.
53 , noPeerId :: !Bool
54
55 -- | Whether to send compact peer list. Peer can override this
56 -- value by setting "compact" to 0 or 1.
57 , compactPeerList :: !Bool
58 }
59
60instance Default TrackerSettings where
61 def = TrackerSettings
62 { defNumWant = defaultNumWant
63 , maxNumWant = defaultMaxNumWant
64 , reannounceInterval = defaultReannounceInterval
65 , reannounceMinInterval = Nothing
66 , compactPeerList = False
67 , completePeers = False
68 , incompletePeers = False
69 , noPeerId = False
70 }
71
72getAnnounceR :: AnnounceRequest -> ResourceT IO AnnounceInfo
73getAnnounceR = undefined
74
75getScrapeR :: ScrapeQuery -> ResourceT IO ScrapeInfo
76getScrapeR = undefined
77
78-- content-type: "text/plain" ?
79tracker :: Application
80tracker Request {..}
81 | requestMethod /= methodGet
82 = return $ responseLBS methodNotAllowed405 [] ""
83
84 | otherwise = do
85 case pathInfo of
86 ["announce"] ->
87 case parseAnnounceRequest $ queryToSimpleQuery queryString of
88 Right query -> do
89 info <- getAnnounceR query
90 return $ responseLBS ok200 [] $ BE.encode info
91 Left msg ->
92 return $ responseLBS (parseFailureStatus msg) [] ""
93
94 ["scrape"] ->
95 case Right $ parseScrapeQuery $ queryToSimpleQuery queryString of -- TODO
96 Right query -> do
97 info <- getScrapeR query
98 return $ responseLBS ok200 [] $ BE.encode info
99 Left _ ->
100 return $ responseLBS badRequest400 [] ""
101
102 _ -> undefined --badPath