diff options
Diffstat (limited to 'src/Network/BitTorrent/Exchange.hs')
-rw-r--r-- | src/Network/BitTorrent/Exchange.hs | 37 |
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 | ||
24 | import Control.Applicative | 25 | import Control.Applicative |
25 | import Control.Exception | 26 | import Control.Exception |
27 | import Control.Concurrent | ||
26 | import Control.Lens | 28 | import Control.Lens |
27 | import Control.Monad.Reader | 29 | import Control.Monad.Reader |
28 | import Control.Monad.Trans.Resource | 30 | import Control.Monad.Trans.Resource |
@@ -54,8 +56,8 @@ data Event = Available Bitfield | |||
54 | 56 | ||
55 | type PeerWire = ConduitM Message Message IO | 57 | type PeerWire = ConduitM Message Message IO |
56 | 58 | ||
57 | runConduit :: Socket -> PeerWire () -> IO () | 59 | runPeerWire :: Socket -> PeerWire () -> IO () |
58 | runConduit sock p2p = | 60 | runPeerWire 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 | |||
85 | peerWant :: P2P Bitfield | 86 | peerWant :: P2P Bitfield |
86 | peerWant = BF.difference <$> getClientBF <*> use bitfield | 87 | peerWant = 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 | -- |
278 | newtype P2P a = P2P { | 280 | newtype 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 | ||
285 | withPeer :: SwarmSession -> PeerAddr -> P2P () -> IO () | 287 | runSession :: SwarmSession -> PeerAddr -> P2P () -> IO () |
286 | withPeer se addr p2p = | 288 | runSession 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. | ||
294 | runP2P :: SwarmSession -> PeerAddr -> P2P () -> IO () | ||
295 | runP2P 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. | ||
300 | spawnP2P :: SwarmSession -> PeerAddr -> P2P () -> IO ThreadId | ||
301 | spawnP2P se addr p2p = do | ||
302 | enterSwarm se | ||
303 | forkIO $ do | ||
304 | runSession se addr p2p `finally` leaveSwarm se | ||