summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Exchange/Assembler.hs
blob: a490d2dc7645e5a917d9bb56979340f3787de632 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
module Network.BitTorrent.Exchange.Assembler
       ( Assembler
       , insert

         -- * Query
       , pendingPieces
       , completeBlocks
       , incompleteBlocks
       ) where

import Data.IntMap.Strict as IM
import Data.Maybe
import Data.Torrent.Piece
import Data.Torrent.Block

type PieceMap = IntMap

-- TODO move to Data.Torrent.Piece ?
-- assembler is also a block selector?
data Assembler a = Assembler
  { piecePending :: PieceMap [Block a]
  , pieceInfo    :: PieceInfo
  }


data Result a
  = Assembled (Piece a)
  | Failed     PieceIx

-- | You should check if a returned by peer block is actually have
-- been requested and in-flight. This is needed to avoid "I send
-- random corrupted block" attacks.
insert :: Block a -> Assembler a -> (Assembler a, Maybe (Result a))
insert Block {..} Assembler {..} = undefined
--  updateWithKey bixPiece

pendingPieces :: Assembler a -> [PieceIx]
pendingPieces Assembler {..} = keys piecePending

completeBlocks :: Assembler a -> PieceIx -> [Block a]
completeBlocks Assembler {..} pix = fromMaybe [] $ IM.lookup pix piecePending

incompleteBlocks :: Assembler a -> PieceIx -> [BlockIx]
incompleteBlocks = undefined

-- TODO merge BlockSelector with Assembler?
data BlockSelector a = BlockSelector
  { assembler   :: Assembler a -- we do not select already transfered blocks
  , inflightSet :: Set BlockIx -- we do not select blocks in flight
  }

insert :: BlockSelector -> (BlockSelector a, Maybe (Result a))
insert = undefined


data StorageAdapter = StorageAdapter
  { bitfield :: Bitfield
  , requestQ :: Queue PieceIx
  }
-- we do select 'incompleteBlocks' that is not in flight

--assembler :: Assembler -> Conduit (Block a) (Result a)
--assembler = undefined

-- by priority
--   foreign request queue (max queue size)
--   assembler block information (max queue size)
--   selection strategies (bitfields)

-- when in flight queue is full we do not use selector
--   in flight queue information (max queue size)

-- piece select is used when
data PieceSelector = Selector
  { forceQueue        :: TVar (Queue PieceIx)
  , forcePendingQueue :: TVar (Queue PieceIx)
  , assembler :: TVar Assembler
  , strategy  :: Bool
  }

select :: Selector -> (Selector, PieceIx)
select = undefined