diff options
Diffstat (limited to 'src/Network/BitTorrent/Exchange.hs')
-rw-r--r-- | src/Network/BitTorrent/Exchange.hs | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/src/Network/BitTorrent/Exchange.hs b/src/Network/BitTorrent/Exchange.hs index b0a94853..3f3346d2 100644 --- a/src/Network/BitTorrent/Exchange.hs +++ b/src/Network/BitTorrent/Exchange.hs | |||
@@ -60,6 +60,7 @@ module Network.BitTorrent.Exchange | |||
60 | , awaitEvent | 60 | , awaitEvent |
61 | , yieldEvent | 61 | , yieldEvent |
62 | , handleEvent | 62 | , handleEvent |
63 | , exchange | ||
63 | 64 | ||
64 | -- * Exceptions | 65 | -- * Exceptions |
65 | , disconnect | 66 | , disconnect |
@@ -85,16 +86,14 @@ import Data.Conduit.Network | |||
85 | import Data.Serialize as S | 86 | import Data.Serialize as S |
86 | import Text.PrettyPrint as PP hiding (($$)) | 87 | import Text.PrettyPrint as PP hiding (($$)) |
87 | 88 | ||
88 | |||
89 | import Network | 89 | import Network |
90 | 90 | ||
91 | 91 | import Data.Bitfield as BF | |
92 | import Network.BitTorrent.Internal | 92 | import Network.BitTorrent.Internal |
93 | import Network.BitTorrent.Extension | 93 | import Network.BitTorrent.Extension |
94 | import Network.BitTorrent.Peer | 94 | import Network.BitTorrent.Peer |
95 | import Network.BitTorrent.Exchange.Protocol | 95 | import Network.BitTorrent.Exchange.Protocol |
96 | import Data.Bitfield as BF | 96 | import System.Torrent.Storage |
97 | |||
98 | 97 | ||
99 | {----------------------------------------------------------------------- | 98 | {----------------------------------------------------------------------- |
100 | Peer wire | 99 | Peer wire |
@@ -464,3 +463,43 @@ yieldEvent e = {-# SCC yieldEvent #-} go e | |||
464 | 463 | ||
465 | handleEvent :: (Event -> P2P Event) -> P2P () | 464 | handleEvent :: (Event -> P2P Event) -> P2P () |
466 | handleEvent action = awaitEvent >>= action >>= yieldEvent | 465 | handleEvent action = awaitEvent >>= action >>= yieldEvent |
466 | |||
467 | -- Event translation table looks like: | ||
468 | -- | ||
469 | -- Available -> Want | ||
470 | -- Want -> Fragment | ||
471 | -- Fragment -> Available | ||
472 | -- | ||
473 | -- If we join the chain we get the event loop: | ||
474 | -- | ||
475 | -- Available -> Want -> Fragment --\ | ||
476 | -- /|\ | | ||
477 | -- \---------------------------/ | ||
478 | -- | ||
479 | |||
480 | |||
481 | -- | Default P2P action. | ||
482 | exchange :: Storage -> P2P () | ||
483 | exchange storage = {-# SCC exchange #-} (awaitEvent >>= handler) | ||
484 | where | ||
485 | handler (Available bf) = do | ||
486 | liftIO (print (completeness bf)) | ||
487 | ixs <- selBlk (findMin bf) storage | ||
488 | mapM_ (yieldEvent . Want) ixs -- TODO yield vectored | ||
489 | |||
490 | handler (Want bix) = do | ||
491 | blk <- liftIO $ getBlk bix storage | ||
492 | yieldEvent (Fragment blk) | ||
493 | |||
494 | handler (Fragment blk @ Block {..}) = do | ||
495 | liftIO $ print (ppBlock blk) | ||
496 | done <- liftIO $ putBlk blk storage | ||
497 | when done $ do | ||
498 | yieldEvent $ Available $ singleton blkPiece (succ blkPiece) | ||
499 | |||
500 | -- WARN this is not reliable: if peer do not return all piece | ||
501 | -- block we could slow don't until some other event occured | ||
502 | offer <- peerOffer | ||
503 | if BF.null offer | ||
504 | then return () | ||
505 | else handler (Available offer) | ||