summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Exchange.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/Exchange.hs')
-rw-r--r--src/Network/BitTorrent/Exchange.hs37
1 files changed, 26 insertions, 11 deletions
diff --git a/src/Network/BitTorrent/Exchange.hs b/src/Network/BitTorrent/Exchange.hs
index 3235a626..978e86db 100644
--- a/src/Network/BitTorrent/Exchange.hs
+++ b/src/Network/BitTorrent/Exchange.hs
@@ -17,12 +17,14 @@ module Network.BitTorrent.Exchange
17 -- * Event 17 -- * Event
18 , Event(..) 18 , Event(..)
19 19
20 , P2P, withPeer 20 , P2P
21 , runP2P, spawnP2P
21 , awaitEvent, yieldEvent 22 , awaitEvent, yieldEvent
22 ) where 23 ) where
23 24
24import Control.Applicative 25import Control.Applicative
25import Control.Exception 26import Control.Exception
27import Control.Concurrent
26import Control.Lens 28import Control.Lens
27import Control.Monad.Reader 29import Control.Monad.Reader
28import Control.Monad.Trans.Resource 30import Control.Monad.Trans.Resource
@@ -54,8 +56,8 @@ data Event = Available Bitfield
54 56
55type PeerWire = ConduitM Message Message IO 57type PeerWire = ConduitM Message Message IO
56 58
57runConduit :: Socket -> PeerWire () -> IO () 59runPeerWire :: Socket -> PeerWire () -> IO ()
58runConduit sock p2p = 60runPeerWire sock p2p =
59 sourceSocket sock $= 61 sourceSocket sock $=
60 conduitGet S.get $= 62 conduitGet S.get $=
61 forever p2p $= 63 forever p2p $=
@@ -81,7 +83,6 @@ yieldMessage msg = P2P $ ReaderT $ \se -> do
81 liftIO $ print $ "sent:" <+> ppMessage msg 83 liftIO $ print $ "sent:" <+> ppMessage msg
82 liftIO $ updateOutcoming se 84 liftIO $ updateOutcoming se
83 85
84
85peerWant :: P2P Bitfield 86peerWant :: P2P Bitfield
86peerWant = BF.difference <$> getClientBF <*> use bitfield 87peerWant = BF.difference <$> getClientBF <*> use bitfield
87 88
@@ -272,18 +273,32 @@ checkPiece = undefined
272-- | 273-- |
273-- Exceptions: 274-- Exceptions:
274-- 275--
275-- * SessionException: is visible with one peer session. Use this 276-- * SessionException: is visible only within one peer
276-- exception to terminate P2P session, but not the swarm session. 277-- session. Use this exception to terminate P2P session, but not
278-- the swarm session.
277-- 279--
278newtype P2P a = P2P { 280newtype P2P a = P2P {
279 runP2P :: ReaderT PeerSession PeerWire a 281 unP2P :: ReaderT PeerSession PeerWire a
280 } deriving ( Functor, Applicative, Monad 282 } deriving ( Functor, Applicative, Monad
281 , MonadIO, MonadThrow, MonadActive 283 , MonadIO, MonadThrow, MonadActive
282 , MonadReader PeerSession 284 , MonadReader PeerSession
283 ) 285 )
284 286
285withPeer :: SwarmSession -> PeerAddr -> P2P () -> IO () 287runSession :: SwarmSession -> PeerAddr -> P2P () -> IO ()
286withPeer se addr p2p = 288runSession se addr p2p =
287 withPeerSession se addr $ \(sock, pses) -> do 289 withPeerSession se addr $ \(sock, pses) -> do
288 handle putSessionException $ 290 runPeerWire sock (runReaderT (unP2P p2p) pses)
289 runConduit sock (runReaderT (runP2P p2p) pses) 291
292-- | Run P2P session in the current thread. Normally you don't need this
293-- function in client application.
294runP2P :: SwarmSession -> PeerAddr -> P2P () -> IO ()
295runP2P se addr p2p = waitVacancy se $ runSession se addr p2p
296
297-- | Run P2P session in forked thread. Might be used in listener or
298-- some other loop. Note that this function may block while waiting
299-- for a vacant place: use forkIO and runP2P instead.
300spawnP2P :: SwarmSession -> PeerAddr -> P2P () -> IO ThreadId
301spawnP2P se addr p2p = do
302 enterSwarm se
303 forkIO $ do
304 runSession se addr p2p `finally` leaveSwarm se