summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Tracker
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2013-12-16 20:19:07 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2013-12-16 20:19:07 +0400
commit0cf1c142d0e18eef05e1190d0fdaa94d2fa4df59 (patch)
treeb7103d0a55c665bd738eb23ccc3784f3e8d13c18 /src/Network/BitTorrent/Tracker
parentf393a2ec1611d2e5587f6fc97317294377c72d5d (diff)
Add spec for AnnounceInfo encoding
Diffstat (limited to 'src/Network/BitTorrent/Tracker')
-rw-r--r--src/Network/BitTorrent/Tracker/Message.hs67
1 files changed, 59 insertions, 8 deletions
diff --git a/src/Network/BitTorrent/Tracker/Message.hs b/src/Network/BitTorrent/Tracker/Message.hs
index d0be1c36..da46628b 100644
--- a/src/Network/BitTorrent/Tracker/Message.hs
+++ b/src/Network/BitTorrent/Tracker/Message.hs
@@ -70,7 +70,6 @@ module Network.BitTorrent.Tracker.Message
70 70
71import Control.Applicative 71import Control.Applicative
72import Control.Monad 72import Control.Monad
73import Data.Aeson (ToJSON(..), FromJSON(..))
74import Data.Aeson.TH 73import Data.Aeson.TH
75import Data.BEncode as BE hiding (Result) 74import Data.BEncode as BE hiding (Result)
76import Data.BEncode.BDict as BE 75import Data.BEncode.BDict as BE
@@ -79,8 +78,10 @@ import Data.ByteString.Char8 as BC
79import Data.Char as Char 78import Data.Char as Char
80import Data.Convertible 79import Data.Convertible
81import Data.Default 80import Data.Default
81import Data.Either
82import Data.List as L 82import Data.List as L
83import Data.Maybe 83import Data.Maybe
84import Data.Monoid
84import Data.Serialize as S hiding (Result) 85import Data.Serialize as S hiding (Result)
85import Data.String 86import Data.String
86import Data.Text (Text) 87import Data.Text (Text)
@@ -193,9 +194,9 @@ instance Serialize AnnounceQuery where
193 put reqPeerId 194 put reqPeerId
194 put reqProgress 195 put reqProgress
195 putEvent reqEvent 196 putEvent reqEvent
196 putWord32be $ fromMaybe 0 reqIP 197 putWord32host $ fromMaybe 0 reqIP
197 putWord32be $ 0 -- TODO what the fuck is "key"? 198 putWord32be $ 0 -- TODO what the fuck is "key"?
198 putWord32be $ fromIntegral $ fromMaybe (-1) reqNumWant 199 putWord32be $ fromIntegral $ fromMaybe (-1) reqNumWant
199 200
200 put reqPort 201 put reqPort
201 202
@@ -415,7 +416,9 @@ data AnnounceRequest = AnnounceRequest
415 } deriving (Show, Eq, Typeable) 416 } deriving (Show, Eq, Typeable)
416 417
417instance QueryLike AnnounceRequest where 418instance QueryLike AnnounceRequest where
418 toQuery AnnounceRequest{..} = toQuery announceAdvises ++ toQuery announceQuery 419 toQuery AnnounceRequest{..} =
420 toQuery announceAdvises <>
421 toQuery announceQuery
419 422
420-- | Parse announce request from query string. 423-- | Parse announce request from query string.
421parseAnnounceRequest :: SimpleQuery -> ParseResult AnnounceRequest 424parseAnnounceRequest :: SimpleQuery -> ParseResult AnnounceRequest
@@ -441,6 +444,11 @@ data PeerList ip
441 | CompactPeerList [PeerAddr ip] 444 | CompactPeerList [PeerAddr ip]
442 deriving (Show, Eq, Typeable, Functor) 445 deriving (Show, Eq, Typeable, Functor)
443 446
447-- | The empty non-compact peer list.
448instance Default (PeerList IP) where
449 def = PeerList []
450 {-# INLINE def #-}
451
444getPeerList :: PeerList IP -> [PeerAddr IP] 452getPeerList :: PeerList IP -> [PeerAddr IP]
445getPeerList (PeerList xs) = xs 453getPeerList (PeerList xs) = xs
446getPeerList (CompactPeerList xs) = xs 454getPeerList (CompactPeerList xs) = xs
@@ -482,6 +490,17 @@ data AnnounceInfo =
482 , respWarning :: !(Maybe Text) 490 , respWarning :: !(Maybe Text)
483 } deriving (Show, Eq, Typeable) 491 } deriving (Show, Eq, Typeable)
484 492
493-- | Empty peer list with default reannounce interval.
494instance Default AnnounceInfo where
495 def = AnnounceInfo
496 { respComplete = Nothing
497 , respIncomplete = Nothing
498 , respInterval = defaultReannounceInterval
499 , respMinInterval = Nothing
500 , respPeers = def
501 , respWarning = Nothing
502 }
503
485-- | HTTP tracker protocol compatible encoding. 504-- | HTTP tracker protocol compatible encoding.
486instance BEncode AnnounceInfo where 505instance BEncode AnnounceInfo where
487 toBEncode (Failure t) = toDict $ 506 toBEncode (Failure t) = toDict $
@@ -494,10 +513,24 @@ instance BEncode AnnounceInfo where
494 .: "interval" .=! respInterval 513 .: "interval" .=! respInterval
495 .: "min interval" .=? respMinInterval 514 .: "min interval" .=? respMinInterval
496 .: "peers" .=! peers 515 .: "peers" .=! peers
497 .: "peers6" .=! peers6 516 .: "peers6" .=? peers6
498 .: "warning message" .=? respWarning 517 .: "warning message" .=? respWarning
499 .: endDict 518 .: endDict
500 where (peers,peers6) = splitIPList $ getPeerList respPeers 519 where
520 (peers, peers6) = prttn respPeers
521
522 prttn :: PeerList IP -> (PeerList IPv4, Maybe (PeerList IPv6))
523 prttn (PeerList xs) = (PeerList xs, Nothing)
524 prttn (CompactPeerList xs) = mk $ partitionEithers $ toEither <$> xs
525 where
526 mk (v4s, v6s)
527 | L.null v6s = (CompactPeerList v4s, Nothing)
528 | otherwise = (CompactPeerList v4s, Just (CompactPeerList v6s))
529
530 toEither :: PeerAddr IP -> Either (PeerAddr IPv4) (PeerAddr IPv6)
531 toEither PeerAddr {..} = case peerHost of
532 IPv4 ipv4 -> Left $ PeerAddr peerId ipv4 peerPort
533 IPv6 ipv6 -> Right $ PeerAddr peerId ipv6 peerPort
501 534
502 fromBEncode (BDict d) 535 fromBEncode (BDict d)
503 | Just t <- BE.lookup "failure reason" d = Failure <$> fromBEncode t 536 | Just t <- BE.lookup "failure reason" d = Failure <$> fromBEncode t
@@ -507,8 +540,26 @@ instance BEncode AnnounceInfo where
507 <*>? "incomplete" 540 <*>? "incomplete"
508 <*>! "interval" 541 <*>! "interval"
509 <*>? "min interval" 542 <*>? "min interval"
510 <*> (PeerList <$> (mergeIPLists <$>! "peers" <*>? "peers6")) 543 <*> (uncurry merge =<< (,) <$>! "peers" <*>? "peers6")
511 <*>? "warning message" 544 <*>? "warning message"
545 where
546 merge :: PeerList IPv4 -> Maybe (PeerList IPv6) -> BE.Get (PeerList IP)
547 merge (PeerList ips) Nothing = pure (PeerList ips)
548 merge (PeerList _ ) (Just _)
549 = fail "PeerList: non-compact peer list provided, \
550 \but the `peers6' field present"
551
552 merge (CompactPeerList ipv4s) Nothing
553 = pure $ CompactPeerList (fmap IPv4 <$> ipv4s)
554
555 merge (CompactPeerList _ ) (Just (PeerList _))
556 = fail "PeerList: the `peers6' field value \
557 \should contain *compact* peer list"
558
559 merge (CompactPeerList ipv4s) (Just (CompactPeerList ipv6s))
560 = pure $ CompactPeerList $
561 (fmap IPv4 <$> ipv4s) <> (fmap IPv6 <$> ipv6s)
562
512 fromBEncode _ = decodingError "Announce info" 563 fromBEncode _ = decodingError "Announce info"
513 564
514-- | UDP tracker protocol compatible encoding. 565-- | UDP tracker protocol compatible encoding.