diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Network/BitTorrent/Tracker/RPC.hs | 18 | ||||
-rw-r--r-- | src/Network/BitTorrent/Tracker/RPC/HTTP.hs | 8 | ||||
-rw-r--r-- | src/Network/BitTorrent/Tracker/RPC/UDP.hs | 9 |
3 files changed, 26 insertions, 9 deletions
diff --git a/src/Network/BitTorrent/Tracker/RPC.hs b/src/Network/BitTorrent/Tracker/RPC.hs index 3acffce9..b3e962fa 100644 --- a/src/Network/BitTorrent/Tracker/RPC.hs +++ b/src/Network/BitTorrent/Tracker/RPC.hs | |||
@@ -5,7 +5,11 @@ | |||
5 | -- Stability : experimental | 5 | -- Stability : experimental |
6 | -- Portability : portable | 6 | -- Portability : portable |
7 | -- | 7 | -- |
8 | -- Protocol independent bittorrent tracker API. | 8 | -- This module provides unified RPC interface to BitTorrent |
9 | -- trackers. The tracker is an UDP/HTTP/HTTPS service used to discovery | ||
10 | -- peers for a particular existing torrent and keep statistics about | ||
11 | -- the swarm. This module also provides a way to easily request | ||
12 | -- scrape info for a particular torrent list. | ||
9 | -- | 13 | -- |
10 | {-# LANGUAGE DeriveDataTypeable #-} | 14 | {-# LANGUAGE DeriveDataTypeable #-} |
11 | module Network.BitTorrent.Tracker.RPC | 15 | module Network.BitTorrent.Tracker.RPC |
@@ -104,18 +108,26 @@ data Manager = Manager | |||
104 | , udpMgr :: !UDP.Manager | 108 | , udpMgr :: !UDP.Manager |
105 | } | 109 | } |
106 | 110 | ||
107 | -- | Normally a bittorrent client session need a single RPC manager | 111 | -- | Create a new 'Manager'. You /must/ manually 'closeManager' |
108 | -- only. | 112 | -- otherwise resource leakage is possible. Normally, a bittorrent |
113 | -- client need a single RPC manager only. | ||
114 | -- | ||
115 | -- This function can throw 'IOException' on invalid 'Options'. | ||
116 | -- | ||
109 | newManager :: Options -> PeerInfo -> IO Manager | 117 | newManager :: Options -> PeerInfo -> IO Manager |
110 | newManager opts info = do | 118 | newManager opts info = do |
111 | h <- HTTP.newManager (optHttpRPC opts) | 119 | h <- HTTP.newManager (optHttpRPC opts) |
112 | u <- UDP.newManager (optUdpRPC opts) `onException` HTTP.closeManager h | 120 | u <- UDP.newManager (optUdpRPC opts) `onException` HTTP.closeManager h |
113 | return $ Manager opts info h u | 121 | return $ Manager opts info h u |
114 | 122 | ||
123 | -- | Close all pending RPCs. Behaviour of currently in-flight RPCs can | ||
124 | -- differ depending on underlying protocol used. No rpc calls should | ||
125 | -- be performed after manager becomes closed. | ||
115 | closeManager :: Manager -> IO () | 126 | closeManager :: Manager -> IO () |
116 | closeManager Manager {..} = do | 127 | closeManager Manager {..} = do |
117 | UDP.closeManager udpMgr `finally` HTTP.closeManager httpMgr | 128 | UDP.closeManager udpMgr `finally` HTTP.closeManager httpMgr |
118 | 129 | ||
130 | -- | Normally you need to use 'Control.Monad.Trans.Resource.allocate'. | ||
119 | withManager :: Options -> PeerInfo -> (Manager -> IO a) -> IO a | 131 | withManager :: Options -> PeerInfo -> (Manager -> IO a) -> IO a |
120 | withManager opts info = bracket (newManager opts info) closeManager | 132 | withManager opts info = bracket (newManager opts info) closeManager |
121 | 133 | ||
diff --git a/src/Network/BitTorrent/Tracker/RPC/HTTP.hs b/src/Network/BitTorrent/Tracker/RPC/HTTP.hs index 00fc9331..37ddb5ad 100644 --- a/src/Network/BitTorrent/Tracker/RPC/HTTP.hs +++ b/src/Network/BitTorrent/Tracker/RPC/HTTP.hs | |||
@@ -5,10 +5,7 @@ | |||
5 | -- Stability : provisional | 5 | -- Stability : provisional |
6 | -- Portability : portable | 6 | -- Portability : portable |
7 | -- | 7 | -- |
8 | -- The tracker is an HTTP/HTTPS service used to discovery peers for | 8 | -- This module implement HTTP tracker protocol. |
9 | -- a particular existing torrent and keep statistics about the | ||
10 | -- swarm. This module also provides a way to easily request scrape | ||
11 | -- info for a particular torrent list. | ||
12 | -- | 9 | -- |
13 | -- For more information see: | 10 | -- For more information see: |
14 | -- <https://wiki.theory.org/BitTorrentSpecification#Tracker_HTTP.2FHTTPS_Protocol> | 11 | -- <https://wiki.theory.org/BitTorrentSpecification#Tracker_HTTP.2FHTTPS_Protocol> |
@@ -102,12 +99,15 @@ data Manager = Manager | |||
102 | , httpMgr :: !HTTP.Manager | 99 | , httpMgr :: !HTTP.Manager |
103 | } | 100 | } |
104 | 101 | ||
102 | -- | | ||
105 | newManager :: Options -> IO Manager | 103 | newManager :: Options -> IO Manager |
106 | newManager opts = Manager opts <$> HTTP.newManager (optHttpOptions opts) | 104 | newManager opts = Manager opts <$> HTTP.newManager (optHttpOptions opts) |
107 | 105 | ||
106 | -- | | ||
108 | closeManager :: Manager -> IO () | 107 | closeManager :: Manager -> IO () |
109 | closeManager Manager {..} = HTTP.closeManager httpMgr | 108 | closeManager Manager {..} = HTTP.closeManager httpMgr |
110 | 109 | ||
110 | -- | Normally you need to use 'Control.Monad.Trans.Resource.allocate'. | ||
111 | withManager :: Options -> (Manager -> IO a) -> IO a | 111 | withManager :: Options -> (Manager -> IO a) -> IO a |
112 | withManager opts = bracket (newManager opts) closeManager | 112 | withManager opts = bracket (newManager opts) closeManager |
113 | 113 | ||
diff --git a/src/Network/BitTorrent/Tracker/RPC/UDP.hs b/src/Network/BitTorrent/Tracker/RPC/UDP.hs index 632e3d86..160397dd 100644 --- a/src/Network/BitTorrent/Tracker/RPC/UDP.hs +++ b/src/Network/BitTorrent/Tracker/RPC/UDP.hs | |||
@@ -5,7 +5,8 @@ | |||
5 | -- Stability : provisional | 5 | -- Stability : provisional |
6 | -- Portability : portable | 6 | -- Portability : portable |
7 | -- | 7 | -- |
8 | -- This module implement low-level UDP tracker protocol. | 8 | -- This module implement UDP tracker protocol. |
9 | -- | ||
9 | -- For more info see: | 10 | -- For more info see: |
10 | -- <http://www.bittorrent.org/beps/bep_0015.html> | 11 | -- <http://www.bittorrent.org/beps/bep_0015.html> |
11 | -- | 12 | -- |
@@ -142,6 +143,7 @@ type PendingResponse = MVar (Either RpcException Response) | |||
142 | type PendingTransactions = Map TransactionId PendingResponse | 143 | type PendingTransactions = Map TransactionId PendingResponse |
143 | type PendingQueries = Map SockAddr PendingTransactions | 144 | type PendingQueries = Map SockAddr PendingTransactions |
144 | 145 | ||
146 | -- | UDP tracker manager. | ||
145 | data Manager = Manager | 147 | data Manager = Manager |
146 | { options :: !Options | 148 | { options :: !Options |
147 | , sock :: !Socket | 149 | , sock :: !Socket |
@@ -176,7 +178,7 @@ resetState Manager {..} = do | |||
176 | where | 178 | where |
177 | err = error "UDP tracker manager closed" | 179 | err = error "UDP tracker manager closed" |
178 | 180 | ||
179 | -- | This function will throw 'IOException' if or | 181 | -- | This function will throw 'IOException' on invalid 'Options'. |
180 | newManager :: Options -> IO Manager | 182 | newManager :: Options -> IO Manager |
181 | newManager opts = do | 183 | newManager opts = do |
182 | checkOptions opts | 184 | checkOptions opts |
@@ -185,6 +187,8 @@ newManager opts = do | |||
185 | putMVar (listenerThread mgr) tid | 187 | putMVar (listenerThread mgr) tid |
186 | return mgr | 188 | return mgr |
187 | 189 | ||
190 | -- | Unblock all RPCs by throwing 'ManagerClosed' exception. No rpc | ||
191 | -- calls should be performed after manager becomes closed. | ||
188 | closeManager :: Manager -> IO () | 192 | closeManager :: Manager -> IO () |
189 | closeManager Manager {..} = do | 193 | closeManager Manager {..} = do |
190 | close sock | 194 | close sock |
@@ -193,6 +197,7 @@ closeManager Manager {..} = do | |||
193 | Nothing -> return () | 197 | Nothing -> return () |
194 | Just tid -> killThread tid | 198 | Just tid -> killThread tid |
195 | 199 | ||
200 | -- | Normally you need to use 'Control.Monad.Trans.Resource.allocate'. | ||
196 | withManager :: Options -> (Manager -> IO a) -> IO a | 201 | withManager :: Options -> (Manager -> IO a) -> IO a |
197 | withManager opts = bracket (newManager opts) closeManager | 202 | withManager opts = bracket (newManager opts) closeManager |
198 | 203 | ||