diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Data/Bitfield.hs | 12 | ||||
-rw-r--r-- | src/Network/BitTorrent.hs | 4 | ||||
-rw-r--r-- | src/Network/BitTorrent/Exchange.hs | 39 | ||||
-rw-r--r-- | src/Network/BitTorrent/Internal.hs | 5 | ||||
-rw-r--r-- | src/System/Torrent/Storage.hs | 18 |
5 files changed, 43 insertions, 35 deletions
diff --git a/src/Data/Bitfield.hs b/src/Data/Bitfield.hs index 89461fd2..acfca0d0 100644 --- a/src/Data/Bitfield.hs +++ b/src/Data/Bitfield.hs | |||
@@ -236,28 +236,28 @@ rarest xs | |||
236 | 236 | ||
237 | -- | Find indices at least one peer have. | 237 | -- | Find indices at least one peer have. |
238 | union :: Bitfield -> Bitfield -> Bitfield | 238 | union :: Bitfield -> Bitfield -> Bitfield |
239 | union a b = Bitfield { | 239 | union a b = {-# SCC union #-} Bitfield { |
240 | bfSize = bfSize a `max` bfSize b | 240 | bfSize = bfSize a `max` bfSize b |
241 | , bfSet = bfSet a `S.union` bfSet b | 241 | , bfSet = bfSet a `S.union` bfSet b |
242 | } | 242 | } |
243 | 243 | ||
244 | -- | Find indices both peers have. | 244 | -- | Find indices both peers have. |
245 | intersection :: Bitfield -> Bitfield -> Bitfield | 245 | intersection :: Bitfield -> Bitfield -> Bitfield |
246 | intersection a b = Bitfield { | 246 | intersection a b = {-# SCC intersection #-} Bitfield { |
247 | bfSize = bfSize a `min` bfSize b | 247 | bfSize = bfSize a `min` bfSize b |
248 | , bfSet = bfSet a `S.intersection` bfSet b | 248 | , bfSet = bfSet a `S.intersection` bfSet b |
249 | } | 249 | } |
250 | 250 | ||
251 | -- | Find indices which have first peer but do not have the second peer. | 251 | -- | Find indices which have first peer but do not have the second peer. |
252 | difference :: Bitfield -> Bitfield -> Bitfield | 252 | difference :: Bitfield -> Bitfield -> Bitfield |
253 | difference a b = Bitfield { | 253 | difference a b = {-# SCC difference #-} Bitfield { |
254 | bfSize = bfSize a -- FIXME is it reasonable? | 254 | bfSize = bfSize a -- FIXME is it reasonable? |
255 | , bfSet = bfSet a `S.difference` bfSet b | 255 | , bfSet = bfSet a `S.difference` bfSet b |
256 | } | 256 | } |
257 | 257 | ||
258 | -- | Find indices the any of the peers have. | 258 | -- | Find indices the any of the peers have. |
259 | unions :: [Bitfield] -> Bitfield | 259 | unions :: [Bitfield] -> Bitfield |
260 | unions = foldl' union (haveNone 0) | 260 | unions = {-# SCC unions #-} foldl' union (haveNone 0) |
261 | 261 | ||
262 | {----------------------------------------------------------------------- | 262 | {----------------------------------------------------------------------- |
263 | Serialization | 263 | Serialization |
@@ -270,7 +270,7 @@ toList Bitfield {..} = S.toList bfSet | |||
270 | -- | Unpack 'Bitfield' from tightly packed bit array. Note resulting | 270 | -- | Unpack 'Bitfield' from tightly packed bit array. Note resulting |
271 | -- size might be more than real bitfield size, use 'adjustSize'. | 271 | -- size might be more than real bitfield size, use 'adjustSize'. |
272 | fromBitmap :: ByteString -> Bitfield | 272 | fromBitmap :: ByteString -> Bitfield |
273 | fromBitmap bs = Bitfield { | 273 | fromBitmap bs = {-# SCC fromBitmap #-} Bitfield { |
274 | bfSize = B.length bs * 8 | 274 | bfSize = B.length bs * 8 |
275 | , bfSet = S.fromByteString bs | 275 | , bfSet = S.fromByteString bs |
276 | } | 276 | } |
@@ -278,7 +278,7 @@ fromBitmap bs = Bitfield { | |||
278 | 278 | ||
279 | -- | Pack a 'Bitfield' to tightly packed bit array. | 279 | -- | Pack a 'Bitfield' to tightly packed bit array. |
280 | toBitmap :: Bitfield -> Lazy.ByteString | 280 | toBitmap :: Bitfield -> Lazy.ByteString |
281 | toBitmap Bitfield {..} = Lazy.fromChunks [intsetBM, alignment] | 281 | toBitmap Bitfield {..} = {-# SCC toBitmap #-} Lazy.fromChunks [intsetBM, alignment] |
282 | where | 282 | where |
283 | byteSize = bfSize `div` 8 + if bfSize `mod` 8 == 0 then 0 else 1 | 283 | byteSize = bfSize `div` 8 + if bfSize `mod` 8 == 0 then 0 else 1 |
284 | alignment = B.replicate (byteSize - B.length intsetBM) 0 | 284 | alignment = B.replicate (byteSize - B.length intsetBM) 0 |
diff --git a/src/Network/BitTorrent.hs b/src/Network/BitTorrent.hs index b6e2eadf..95a4c4e3 100644 --- a/src/Network/BitTorrent.hs +++ b/src/Network/BitTorrent.hs | |||
@@ -102,7 +102,7 @@ defaultClient = newClient defaultThreadCount defaultExtensions | |||
102 | -- thus we can obtain an unified interface | 102 | -- thus we can obtain an unified interface |
103 | 103 | ||
104 | discover :: SwarmSession -> P2P () -> IO () | 104 | discover :: SwarmSession -> P2P () -> IO () |
105 | discover swarm action = do | 105 | discover swarm action = {-# SCC discover #-} do |
106 | port <- forkListener (error "discover") | 106 | port <- forkListener (error "discover") |
107 | 107 | ||
108 | let conn = TConnection (tAnnounce (torrentMeta swarm)) | 108 | let conn = TConnection (tAnnounce (torrentMeta swarm)) |
@@ -134,7 +134,7 @@ discover swarm action = do | |||
134 | 134 | ||
135 | -- | Default P2P action. | 135 | -- | Default P2P action. |
136 | exchange :: Storage -> P2P () | 136 | exchange :: Storage -> P2P () |
137 | exchange storage = awaitEvent >>= handler | 137 | exchange storage = {-# SCC exchange #-} (awaitEvent >>= handler) |
138 | where | 138 | where |
139 | handler (Available bf) = do | 139 | handler (Available bf) = do |
140 | liftIO (print (completeness bf)) | 140 | liftIO (print (completeness bf)) |
diff --git a/src/Network/BitTorrent/Exchange.hs b/src/Network/BitTorrent/Exchange.hs index 66112f14..9f119d13 100644 --- a/src/Network/BitTorrent/Exchange.hs +++ b/src/Network/BitTorrent/Exchange.hs | |||
@@ -110,17 +110,21 @@ runPeerWire sock p2p = | |||
110 | sinkSocket sock | 110 | sinkSocket sock |
111 | 111 | ||
112 | awaitMessage :: P2P Message | 112 | awaitMessage :: P2P Message |
113 | awaitMessage = P2P $ ReaderT $ const go | 113 | awaitMessage = P2P $ ReaderT $ const $ {-# SCC awaitMessage #-} go |
114 | where | 114 | where |
115 | go = await >>= maybe (monadThrow PeerDisconnected) return | 115 | go = await >>= maybe (monadThrow PeerDisconnected) return |
116 | {-# INLINE awaitMessage #-} | 116 | {-# INLINE awaitMessage #-} |
117 | 117 | ||
118 | yieldMessage :: Message -> P2P () | 118 | yieldMessage :: Message -> P2P () |
119 | yieldMessage msg = P2P $ ReaderT $ const (C.yield msg) | 119 | yieldMessage msg = P2P $ ReaderT $ const $ {-# SCC yieldMessage #-} C.yield msg |
120 | {-# INLINE yieldMessage #-} | 120 | {-# INLINE yieldMessage #-} |
121 | 121 | ||
122 | flushPending :: P2P () | 122 | flushPending :: P2P () |
123 | flushPending = ask >>= liftIO . getPending >>= mapM_ yieldMessage | 123 | flushPending = {-# SCC flushPending #-} do |
124 | se <- ask | ||
125 | q <- liftIO (getPending se) | ||
126 | -- TODO send vectored | ||
127 | mapM_ yieldMessage q | ||
124 | 128 | ||
125 | {----------------------------------------------------------------------- | 129 | {----------------------------------------------------------------------- |
126 | P2P monad | 130 | P2P monad |
@@ -321,7 +325,7 @@ data Event | |||
321 | -- forall (Fragment block). isPiece block == True | 325 | -- forall (Fragment block). isPiece block == True |
322 | -- | 326 | -- |
323 | awaitEvent :: P2P Event | 327 | awaitEvent :: P2P Event |
324 | awaitEvent = awaitMessage >>= go | 328 | awaitEvent = {-# SCC awaitEvent #-} awaitMessage >>= go |
325 | where | 329 | where |
326 | go KeepAlive = awaitEvent | 330 | go KeepAlive = awaitEvent |
327 | go Choke = do | 331 | go Choke = do |
@@ -439,22 +443,21 @@ awaitEvent = awaitMessage >>= go | |||
439 | -- most likely will be ignored without any network IO. | 443 | -- most likely will be ignored without any network IO. |
440 | -- | 444 | -- |
441 | yieldEvent :: Event -> P2P () | 445 | yieldEvent :: Event -> P2P () |
442 | yieldEvent (Available ixs) = asks swarmSession >>= liftIO . available ixs | 446 | yieldEvent e = {-# SCC yieldEvent #-} go e |
443 | yieldEvent (Want bix) = do | 447 | where |
444 | offer <- peerOffer | 448 | go (Available ixs) = asks swarmSession >>= liftIO . available ixs |
445 | if ixPiece bix `BF.member` offer | 449 | go (Want bix) = do |
446 | then yieldMessage (Request bix) | 450 | offer <- peerOffer |
447 | else return () | 451 | if ixPiece bix `BF.member` offer |
452 | then yieldMessage (Request bix) | ||
453 | else return () | ||
448 | 454 | ||
449 | yieldEvent (Fragment blk) = do | 455 | go (Fragment blk) = do |
450 | offer <- clientOffer | 456 | offer <- clientOffer |
451 | if blkPiece blk `BF.member` offer | 457 | if blkPiece blk `BF.member` offer |
452 | then yieldMessage (Piece blk) | 458 | then yieldMessage (Piece blk) |
453 | else return () | 459 | else return () |
454 | 460 | ||
455 | 461 | ||
456 | handleEvent :: (Event -> P2P Event) -> P2P () | 462 | handleEvent :: (Event -> P2P Event) -> P2P () |
457 | handleEvent action = awaitEvent >>= action >>= yieldEvent | 463 | handleEvent action = awaitEvent >>= action >>= yieldEvent |
458 | |||
459 | checkPiece :: PieceLIx -> {-ByteString -> -} P2P Bool | ||
460 | checkPiece = undefined | ||
diff --git a/src/Network/BitTorrent/Internal.hs b/src/Network/BitTorrent/Internal.hs index eaeb04e8..5a7e493f 100644 --- a/src/Network/BitTorrent/Internal.hs +++ b/src/Network/BitTorrent/Internal.hs | |||
@@ -538,7 +538,7 @@ findPieceCount = pieceCount . tInfo . torrentMeta . swarmSession | |||
538 | -- 3. Signal to the all other peer about this. | 538 | -- 3. Signal to the all other peer about this. |
539 | 539 | ||
540 | available :: Bitfield -> SwarmSession -> IO () | 540 | available :: Bitfield -> SwarmSession -> IO () |
541 | available bf se @ SwarmSession {..} = do | 541 | available bf se @ SwarmSession {..} = {-# SCC available #-} do |
542 | mark >> atomically broadcast | 542 | mark >> atomically broadcast |
543 | where | 543 | where |
544 | mark = do | 544 | mark = do |
@@ -561,7 +561,8 @@ available bf se @ SwarmSession {..} = do | |||
561 | -- changed client state. Resulting queue should be sent to a peer | 561 | -- changed client state. Resulting queue should be sent to a peer |
562 | -- immediately. | 562 | -- immediately. |
563 | getPending :: PeerSession -> IO [Message] | 563 | getPending :: PeerSession -> IO [Message] |
564 | getPending PeerSession {..} = atomically (readAvail pendingMessages) | 564 | getPending PeerSession {..} = {-# SCC getPending #-} do |
565 | atomically (readAvail pendingMessages) | ||
565 | 566 | ||
566 | readAvail :: TChan a -> STM [a] | 567 | readAvail :: TChan a -> STM [a] |
567 | readAvail chan = do | 568 | readAvail chan = do |
diff --git a/src/System/Torrent/Storage.hs b/src/System/Torrent/Storage.hs index cb0494e8..8a884196 100644 --- a/src/System/Torrent/Storage.hs +++ b/src/System/Torrent/Storage.hs | |||
@@ -110,7 +110,8 @@ withStorage se path = bracket (se `bindTo` path) unbind | |||
110 | -- TODO make block_payload :: Lazy.ByteString | 110 | -- TODO make block_payload :: Lazy.ByteString |
111 | 111 | ||
112 | selBlk :: MonadIO m => PieceIx -> Storage -> m [BlockIx] | 112 | selBlk :: MonadIO m => PieceIx -> Storage -> m [BlockIx] |
113 | selBlk pix st @ Storage {..} = liftIO $ atomically $ do | 113 | selBlk pix st @ Storage {..} |
114 | = liftIO $ {-# SCC selBlk #-} atomically $ do | ||
114 | mask <- pieceMask pix st | 115 | mask <- pieceMask pix st |
115 | select mask <$> readTVar blocks | 116 | select mask <$> readTVar blocks |
116 | where | 117 | where |
@@ -137,7 +138,8 @@ selBlk pix st @ Storage {..} = liftIO $ atomically $ do | |||
137 | -- | 138 | -- |
138 | -- | 139 | -- |
139 | putBlk :: MonadIO m => Block -> Storage -> m Bool | 140 | putBlk :: MonadIO m => Block -> Storage -> m Bool |
140 | putBlk blk @ Block {..} st @ Storage {..} = liftIO $ do | 141 | putBlk blk @ Block {..} st @ Storage {..} |
142 | = liftIO $ {-# SCC putBlk #-} do | ||
141 | -- let blkIx = undefined | 143 | -- let blkIx = undefined |
142 | -- bm <- readTVarIO blocks | 144 | -- bm <- readTVarIO blocks |
143 | -- unless (member blkIx bm) $ do | 145 | -- unless (member blkIx bm) $ do |
@@ -149,7 +151,7 @@ putBlk blk @ Block {..} st @ Storage {..} = liftIO $ do | |||
149 | validatePiece blkPiece st | 151 | validatePiece blkPiece st |
150 | 152 | ||
151 | markBlock :: Block -> Storage -> IO () | 153 | markBlock :: Block -> Storage -> IO () |
152 | markBlock Block {..} Storage {..} = do | 154 | markBlock Block {..} Storage {..} = {-# SCC markBlock #-} do |
153 | let piLen = pieceLength session | 155 | let piLen = pieceLength session |
154 | let glIx = (piLen `div` blockSize) * blkPiece + (blkOffset `div` blockSize) | 156 | let glIx = (piLen `div` blockSize) * blkPiece + (blkOffset `div` blockSize) |
155 | atomically $ modifyTVar' blocks (have glIx) | 157 | atomically $ modifyTVar' blocks (have glIx) |
@@ -160,25 +162,27 @@ markBlock Block {..} Storage {..} = do | |||
160 | -- Do not block. | 162 | -- Do not block. |
161 | -- | 163 | -- |
162 | getBlk :: MonadIO m => BlockIx -> Storage -> m Block | 164 | getBlk :: MonadIO m => BlockIx -> Storage -> m Block |
163 | getBlk ix @ BlockIx {..} st @ Storage {..} = liftIO $ do | 165 | getBlk ix @ BlockIx {..} st @ Storage {..} |
166 | = liftIO $ {-# SCC getBlk #-} do | ||
164 | -- TODO check if __piece__ is available | 167 | -- TODO check if __piece__ is available |
165 | bs <- readBytes (ixInterval (pieceLength session) ix) payload | 168 | bs <- readBytes (ixInterval (pieceLength session) ix) payload |
166 | return $ Block ixPiece ixOffset (Lazy.toStrict bs) | 169 | return $ Block ixPiece ixOffset (Lazy.toStrict bs) |
167 | 170 | ||
168 | getPiece :: PieceIx -> Storage -> IO ByteString | 171 | getPiece :: PieceIx -> Storage -> IO ByteString |
169 | getPiece pix st @ Storage {..} = do | 172 | getPiece pix st @ Storage {..} = {-# SCC getPiece #-} do |
170 | let pieceLen = pieceLength session | 173 | let pieceLen = pieceLength session |
171 | let bix = BlockIx pix 0 (pieceLength session) | 174 | let bix = BlockIx pix 0 (pieceLength session) |
172 | bs <- readBytes (ixInterval pieceLen bix) payload | 175 | bs <- readBytes (ixInterval pieceLen bix) payload |
173 | return (Lazy.toStrict bs) | 176 | return (Lazy.toStrict bs) |
174 | 177 | ||
175 | resetPiece :: PieceIx -> Storage -> IO () | 178 | resetPiece :: PieceIx -> Storage -> IO () |
176 | resetPiece pix st @ Storage {..} = atomically $ do | 179 | resetPiece pix st @ Storage {..} |
180 | = {-# SCC resetPiece #-} atomically $ do | ||
177 | mask <- pieceMask pix st | 181 | mask <- pieceMask pix st |
178 | modifyTVar' blocks (`difference` mask) | 182 | modifyTVar' blocks (`difference` mask) |
179 | 183 | ||
180 | validatePiece :: PieceIx -> Storage -> IO Bool | 184 | validatePiece :: PieceIx -> Storage -> IO Bool |
181 | validatePiece pix st @ Storage {..} = do | 185 | validatePiece pix st @ Storage {..} = {-# SCC validatePiece #-} do |
182 | downloaded <- atomically $ isDownloaded pix st | 186 | downloaded <- atomically $ isDownloaded pix st |
183 | if not downloaded then return False | 187 | if not downloaded then return False |
184 | else do | 188 | else do |