diff options
-rw-r--r-- | src/Network/BitTorrent/Client.hs | 50 | ||||
-rw-r--r-- | src/Network/BitTorrent/Client/Types.hs | 16 |
2 files changed, 44 insertions, 22 deletions
diff --git a/src/Network/BitTorrent/Client.hs b/src/Network/BitTorrent/Client.hs index 349283c3..905d3384 100644 --- a/src/Network/BitTorrent/Client.hs +++ b/src/Network/BitTorrent/Client.hs | |||
@@ -39,10 +39,10 @@ import Control.Exception | |||
39 | import Control.Concurrent | 39 | import Control.Concurrent |
40 | import Control.Monad.Logger | 40 | import Control.Monad.Logger |
41 | import Control.Monad.Trans | 41 | import Control.Monad.Trans |
42 | import Control.Monad.Trans.Resource | ||
42 | 43 | ||
43 | import Data.Default | 44 | import Data.Default |
44 | import Data.HashMap.Strict as HM | 45 | import Data.HashMap.Strict as HM |
45 | import Data.Maybe | ||
46 | import Data.Text | 46 | import Data.Text |
47 | import Network | 47 | import Network |
48 | 48 | ||
@@ -86,38 +86,52 @@ exchangeOptions pid Options {..} = Exchange.Options | |||
86 | connHandler :: MVar (HashMap InfoHash Handle) -> Exchange.Handler | 86 | connHandler :: MVar (HashMap InfoHash Handle) -> Exchange.Handler |
87 | connHandler _tmap = undefined | 87 | connHandler _tmap = undefined |
88 | 88 | ||
89 | newClient :: Options -> LogFun -> IO Client | 89 | initClient :: Options -> LogFun -> ResIO Client |
90 | newClient opts @ Options {..} logger = do | 90 | initClient opts @ Options {..} logFun = do |
91 | pid <- genPeerId | 91 | pid <- liftIO genPeerId |
92 | tmap <- newMVar HM.empty | 92 | tmap <- liftIO $ newMVar HM.empty |
93 | tmgr <- Tracker.newManager def (PeerInfo pid Nothing optPort) | 93 | |
94 | emgr <- Exchange.newManager (exchangeOptions pid opts) (connHandler tmap) | 94 | let peerInfo = PeerInfo pid Nothing optPort |
95 | node <- do | 95 | let mkTracker = Tracker.newManager def peerInfo |
96 | node <- startNode defaultHandlers def optNodeAddr logger | 96 | (_, tmgr) <- allocate mkTracker Tracker.closeManager |
97 | runDHT node $ bootstrap (maybeToList optBootNode) | 97 | |
98 | return node | 98 | let mkEx = Exchange.newManager (exchangeOptions pid opts) (connHandler tmap) |
99 | (_, emgr) <- allocate mkEx Exchange.closeManager | ||
100 | |||
101 | let mkNode = startNode defaultHandlers def optNodeAddr logFun | ||
102 | (_, node) <- allocate mkNode stopNode | ||
103 | |||
104 | resourceMap <- getInternalState | ||
99 | return Client | 105 | return Client |
100 | { clientPeerId = pid | 106 | { clientPeerId = pid |
101 | , clientListenerPort = optPort | 107 | , clientListenerPort = optPort |
102 | , allowedExtensions = toCaps optExtensions | 108 | , allowedExtensions = toCaps optExtensions |
109 | , clientResources = resourceMap | ||
103 | , trackerManager = tmgr | 110 | , trackerManager = tmgr |
104 | , exchangeManager = emgr | 111 | , exchangeManager = emgr |
105 | , clientNode = node | 112 | , clientNode = node |
106 | , clientTorrents = tmap | 113 | , clientTorrents = tmap |
107 | , clientLogger = logger | 114 | , clientLogger = logFun |
108 | } | 115 | } |
109 | 116 | ||
117 | newClient :: Options -> LogFun -> IO Client | ||
118 | newClient opts logFun = do | ||
119 | s <- createInternalState | ||
120 | runInternalState (initClient opts logFun) s | ||
121 | `onException` closeInternalState s | ||
122 | |||
110 | closeClient :: Client -> IO () | 123 | closeClient :: Client -> IO () |
111 | closeClient Client {..} = do | 124 | closeClient Client {..} = closeInternalState clientResources |
112 | Exchange.closeManager exchangeManager | ||
113 | Tracker.closeManager trackerManager | ||
114 | DHT.stopNode clientNode | ||
115 | return () | ||
116 | -- closeNode clientNode | ||
117 | 125 | ||
118 | withClient :: Options -> LogFun -> (Client -> IO a) -> IO a | 126 | withClient :: Options -> LogFun -> (Client -> IO a) -> IO a |
119 | withClient opts lf action = bracket (newClient opts lf) closeClient action | 127 | withClient opts lf action = bracket (newClient opts lf) closeClient action |
120 | 128 | ||
129 | -- do not perform IO in 'initClient', do it in the 'boot' | ||
130 | --boot :: BitTorrent () | ||
131 | --boot = do | ||
132 | -- Options {..} <- asks options | ||
133 | -- liftDHT $ bootstrap (maybeToList optBootNode) | ||
134 | |||
121 | -- | Run bittorrent client with default options and log to @stderr@. | 135 | -- | Run bittorrent client with default options and log to @stderr@. |
122 | -- | 136 | -- |
123 | -- For testing purposes only. | 137 | -- For testing purposes only. |
diff --git a/src/Network/BitTorrent/Client/Types.hs b/src/Network/BitTorrent/Client/Types.hs index 63971518..c2f79460 100644 --- a/src/Network/BitTorrent/Client/Types.hs +++ b/src/Network/BitTorrent/Client/Types.hs | |||
@@ -13,6 +13,7 @@ module Network.BitTorrent.Client.Types | |||
13 | , MonadBitTorrent (..) | 13 | , MonadBitTorrent (..) |
14 | ) where | 14 | ) where |
15 | 15 | ||
16 | import Control.Applicative | ||
16 | import Control.Concurrent | 17 | import Control.Concurrent |
17 | import Control.Monad.Logger | 18 | import Control.Monad.Logger |
18 | import Control.Monad.Reader | 19 | import Control.Monad.Reader |
@@ -40,6 +41,7 @@ data Client = Client | |||
40 | { clientPeerId :: !PeerId | 41 | { clientPeerId :: !PeerId |
41 | , clientListenerPort :: !PortNumber | 42 | , clientListenerPort :: !PortNumber |
42 | , allowedExtensions :: !Caps | 43 | , allowedExtensions :: !Caps |
44 | , clientResources :: !InternalState | ||
43 | , trackerManager :: !Tracker.Manager | 45 | , trackerManager :: !Tracker.Manager |
44 | , exchangeManager :: !Exchange.Manager | 46 | , exchangeManager :: !Exchange.Manager |
45 | , clientNode :: !(Node IPv4) | 47 | , clientNode :: !(Node IPv4) |
@@ -68,8 +70,10 @@ externalAddr Client {..} = PeerAddr | |||
68 | -----------------------------------------------------------------------} | 70 | -----------------------------------------------------------------------} |
69 | 71 | ||
70 | newtype BitTorrent a = BitTorrent | 72 | newtype BitTorrent a = BitTorrent |
71 | { unBitTorrent :: ReaderT Client (ResourceT IO) a | 73 | { unBitTorrent :: ReaderT Client IO a |
72 | } deriving (Functor, Monad, MonadIO) | 74 | } deriving ( Functor, Applicative, Monad |
75 | , MonadIO, MonadThrow, MonadUnsafeIO | ||
76 | ) | ||
73 | 77 | ||
74 | class MonadBitTorrent m where | 78 | class MonadBitTorrent m where |
75 | liftBT :: BitTorrent a -> m a | 79 | liftBT :: BitTorrent a -> m a |
@@ -77,6 +81,11 @@ class MonadBitTorrent m where | |||
77 | instance MonadBitTorrent BitTorrent where | 81 | instance MonadBitTorrent BitTorrent where |
78 | liftBT = id | 82 | liftBT = id |
79 | 83 | ||
84 | instance MonadResource BitTorrent where | ||
85 | liftResourceT m = BitTorrent $ do | ||
86 | s <- asks clientResources | ||
87 | liftIO $ runInternalState m s | ||
88 | |||
80 | instance MonadDHT BitTorrent where | 89 | instance MonadDHT BitTorrent where |
81 | liftDHT action = BitTorrent $ do | 90 | liftDHT action = BitTorrent $ do |
82 | node <- asks clientNode | 91 | node <- asks clientNode |
@@ -88,8 +97,7 @@ instance MonadLogger BitTorrent where | |||
88 | liftIO $ logger loc src lvl (toLogStr msg) | 97 | liftIO $ logger loc src lvl (toLogStr msg) |
89 | 98 | ||
90 | runBitTorrent :: Client -> BitTorrent a -> IO a | 99 | runBitTorrent :: Client -> BitTorrent a -> IO a |
91 | runBitTorrent client action = runResourceT $ | 100 | runBitTorrent client action = runReaderT (unBitTorrent action) client |
92 | runReaderT (unBitTorrent action) client | ||
93 | {-# INLINE runBitTorrent #-} | 101 | {-# INLINE runBitTorrent #-} |
94 | 102 | ||
95 | getClient :: BitTorrent Client | 103 | getClient :: BitTorrent Client |