summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Exchange/Wire.hs
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-01-03 21:29:44 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-01-03 21:29:44 +0400
commit7571c99b816087bd1422c2c3a948e53662ddba3b (patch)
treea934836fb0e3a465373b778d79c304a7843ee809 /src/Network/BitTorrent/Exchange/Wire.hs
parent65107192f9c5f8ff134362a7b9d37cb3f73dad7e (diff)
Add getMetadata function
Diffstat (limited to 'src/Network/BitTorrent/Exchange/Wire.hs')
-rw-r--r--src/Network/BitTorrent/Exchange/Wire.hs41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/Network/BitTorrent/Exchange/Wire.hs b/src/Network/BitTorrent/Exchange/Wire.hs
index 369f0746..427d7676 100644
--- a/src/Network/BitTorrent/Exchange/Wire.hs
+++ b/src/Network/BitTorrent/Exchange/Wire.hs
@@ -55,6 +55,7 @@ module Network.BitTorrent.Exchange.Wire
55 , getConnection 55 , getConnection
56 , getExtCaps 56 , getExtCaps
57 , getStats 57 , getStats
58 , getMetadata
58 ) where 59 ) where
59 60
60import Control.Applicative 61import Control.Applicative
@@ -689,3 +690,43 @@ acceptWire :: Socket -> PeerAddr IP -> Wire () -> IO ()
689acceptWire sock peerAddr wire = do 690acceptWire sock peerAddr wire = do
690 bracket (return sock) close $ \ _ -> do 691 bracket (return sock) close $ \ _ -> do
691 error "acceptWire: not implemented" 692 error "acceptWire: not implemented"
693
694{-----------------------------------------------------------------------
695-- Metadata exchange
696-----------------------------------------------------------------------}
697-- TODO introduce new metadata exchange specific exceptions
698
699fetchMetadata :: Wire [BS.ByteString]
700fetchMetadata = loop 0
701 where
702 recvData = recvMessage >>= inspect
703 where
704 inspect (Extended (EMetadata _ meta)) =
705 case meta of
706 MetadataRequest pix -> do
707 sendMessage (MetadataReject pix)
708 recvData
709 MetadataData {..} -> return (piece, totalSize)
710 MetadataReject _ -> disconnectPeer
711 MetadataUnknown _ -> recvData
712 inspect _ = recvData
713
714 loop i = do
715 sendMessage (MetadataRequest i)
716 (piece, totalSize) <- recvData
717 unless (pieceIndex piece == i) $ do
718 disconnectPeer
719
720 if piece `isLastPiece` totalSize
721 then pure [pieceData piece]
722 else (pieceData piece :) <$> loop (succ i)
723
724getMetadata :: Wire InfoDict
725getMetadata = do
726 chunks <- fetchMetadata
727 Connection {..} <- getConnection
728 case BE.decode (BS.concat chunks) of
729 Right (infodict @ InfoDict {..})
730 | connTopic == idInfoHash -> return infodict
731 | otherwise -> error "broken infodict"
732 Left err -> error $ "unable to parse infodict" ++ err