diff options
author | Sam T <pxqr.sta@gmail.com> | 2013-06-14 15:50:23 +0400 |
---|---|---|
committer | Sam T <pxqr.sta@gmail.com> | 2013-06-14 15:50:23 +0400 |
commit | 9ee6f55b2aa3df52f8bdb9a53759644e4fd14694 (patch) | |
tree | 0004d2e492c029fbbd04fa24ddcde4aedaf18fdb /src/Network/BitTorrent | |
parent | 07ac8270807140fac201b7c973e12f924ca4b36b (diff) |
+ Add docs to progress and client session.
Diffstat (limited to 'src/Network/BitTorrent')
-rw-r--r-- | src/Network/BitTorrent/Exchange.hs | 16 | ||||
-rw-r--r-- | src/Network/BitTorrent/Internal.hs | 113 |
2 files changed, 97 insertions, 32 deletions
diff --git a/src/Network/BitTorrent/Exchange.hs b/src/Network/BitTorrent/Exchange.hs index 862611f9..98b19357 100644 --- a/src/Network/BitTorrent/Exchange.hs +++ b/src/Network/BitTorrent/Exchange.hs | |||
@@ -20,6 +20,8 @@ module Network.BitTorrent.Exchange | |||
20 | , P2P | 20 | , P2P |
21 | , runP2P, spawnP2P | 21 | , runP2P, spawnP2P |
22 | , awaitEvent, yieldEvent | 22 | , awaitEvent, yieldEvent |
23 | |||
24 | , disconnect, protocolError | ||
23 | ) where | 25 | ) where |
24 | 26 | ||
25 | import Control.Applicative | 27 | import Control.Applicative |
@@ -181,13 +183,13 @@ requireExtension required = do | |||
181 | -----------------------------------------------------------------------} | 183 | -----------------------------------------------------------------------} |
182 | 184 | ||
183 | -- | | 185 | -- | |
184 | -- +----------+---------+ | 186 | -- > +----------+---------+ |
185 | -- | Leacher | Seeder | | 187 | -- > | Leacher | Seeder | |
186 | -- |----------+---------+ | 188 | -- > |----------+---------+ |
187 | -- | Available| | | 189 | -- > | Available| | |
188 | -- | Want | Want | | 190 | -- > | Want | Want | |
189 | -- | Fragment | | | 191 | -- > | Fragment | | |
190 | -- +----------+---------+ | 192 | -- > +----------+---------+ |
191 | -- | 193 | -- |
192 | -- | 194 | -- |
193 | -- properties: | 195 | -- properties: |
diff --git a/src/Network/BitTorrent/Internal.hs b/src/Network/BitTorrent/Internal.hs index db84e879..e07698dd 100644 --- a/src/Network/BitTorrent/Internal.hs +++ b/src/Network/BitTorrent/Internal.hs | |||
@@ -27,9 +27,16 @@ module Network.BitTorrent.Internal | |||
27 | 27 | ||
28 | -- * Client | 28 | -- * Client |
29 | , ClientSession (clientPeerID, allowedExtensions) | 29 | , ClientSession (clientPeerID, allowedExtensions) |
30 | , newClient, getCurrentProgress | ||
31 | 30 | ||
32 | , ThreadCount, defaultThreadCount | 31 | , ThreadCount |
32 | , defaultThreadCount | ||
33 | |||
34 | , newClient | ||
35 | |||
36 | , getCurrentProgress | ||
37 | , getSwarmCount | ||
38 | , getPeerCount | ||
39 | |||
33 | 40 | ||
34 | -- * Swarm | 41 | -- * Swarm |
35 | , SwarmSession(SwarmSession, torrentMeta, clientSession) | 42 | , SwarmSession(SwarmSession, torrentMeta, clientSession) |
@@ -95,52 +102,93 @@ import Network.BitTorrent.Tracker.Protocol as BT | |||
95 | -----------------------------------------------------------------------} | 102 | -----------------------------------------------------------------------} |
96 | 103 | ||
97 | -- | 'Progress' contains upload/download/left stats about | 104 | -- | 'Progress' contains upload/download/left stats about |
98 | -- current client state. | 105 | -- current client state and used to notify the tracker |
99 | -- | 106 | -- |
100 | -- This data is considered as dynamic within one session. | 107 | -- This data is considered as dynamic within one client |
108 | -- session. This data also should be shared across client | ||
109 | -- application sessions (e.g. files), otherwise use 'startProgress' | ||
110 | -- to get initial 'Progress'. | ||
101 | -- | 111 | -- |
102 | data Progress = Progress { | 112 | data Progress = Progress { |
103 | prUploaded :: Integer -- ^ Total amount of bytes uploaded. | 113 | prUploaded :: !Integer -- ^ Total amount of bytes uploaded. |
104 | , prDownloaded :: Integer -- ^ Total amount of bytes downloaded. | 114 | , prDownloaded :: !Integer -- ^ Total amount of bytes downloaded. |
105 | , prLeft :: Integer -- ^ Total amount of bytes left. | 115 | , prLeft :: !Integer -- ^ Total amount of bytes left. |
106 | } deriving Show | 116 | } deriving (Show, Read, Eq) |
107 | 117 | ||
118 | -- TODO make lenses | ||
119 | |||
120 | -- | Initial progress is used when there are no session before. | ||
121 | -- | ||
122 | -- Please note that tracker might penalize client some way if the do | ||
123 | -- not accumulate progress. If possible and save 'Progress' between | ||
124 | -- client sessions to avoid that. | ||
125 | -- | ||
108 | startProgress :: Integer -> Progress | 126 | startProgress :: Integer -> Progress |
109 | startProgress = Progress 0 0 | 127 | startProgress = Progress 0 0 |
110 | 128 | ||
111 | |||
112 | {----------------------------------------------------------------------- | 129 | {----------------------------------------------------------------------- |
113 | Client session | 130 | Client session |
114 | -----------------------------------------------------------------------} | 131 | -----------------------------------------------------------------------} |
115 | 132 | ||
116 | -- TODO comment thread count bounding | 133 | {- NOTE: If we will not restrict number of threads we could end up |
134 | with thousands of connected swarm and make no particular progress. | ||
135 | |||
136 | Note also we do not bound number of swarms! This is not optimal | ||
137 | strategy because each swarm might have say 1 thread and we could end | ||
138 | up bounded by the meaningless limit. Bounding global number of p2p | ||
139 | sessions should work better, and simpler.-} | ||
140 | |||
141 | -- | Each client might have a limited number of threads. | ||
117 | type ThreadCount = Int | 142 | type ThreadCount = Int |
118 | 143 | ||
144 | -- | The number of threads suitable for a typical BT client. | ||
119 | defaultThreadCount :: ThreadCount | 145 | defaultThreadCount :: ThreadCount |
120 | defaultThreadCount = 1000 | 146 | defaultThreadCount = 1000 |
121 | 147 | ||
122 | -- | In one application we could have many clients with difference | 148 | {- NOTE: basically, client session should contain options which user |
123 | -- ID's and different enabled extensions. | 149 | app store in configuration files. (related to the protocol) Moreover |
150 | it should contain the all client identification info. (e.g. DHT) -} | ||
151 | |||
152 | -- | Client session is the basic unit of bittorrent network, it has: | ||
153 | -- | ||
154 | -- * The /peer ID/ used as unique identifier of the client in | ||
155 | -- network. Obviously, this value is not changed during client | ||
156 | -- session. | ||
157 | -- | ||
158 | -- * The number of /protocol extensions/ it might use. This value | ||
159 | -- is static as well, but if you want to dynamically reconfigure | ||
160 | -- the client you might kill the end the current session and | ||
161 | -- create a new with the fresh required extensions. | ||
162 | -- | ||
163 | -- * The number of /swarms/ to join, each swarm described by the | ||
164 | -- 'SwarmSession'. | ||
165 | -- | ||
166 | -- Normally, you would have one client session, however, if we need, | ||
167 | -- in one application we could have many clients with different peer | ||
168 | -- ID's and different enabled extensions at the same time. | ||
169 | -- | ||
124 | data ClientSession = ClientSession { | 170 | data ClientSession = ClientSession { |
125 | -- | Our peer ID used in handshaked and discovery mechanism. The | 171 | -- | Used in handshakes and discovery mechanism. |
126 | -- clientPeerID is unique 'ClientSession' identifier. | ||
127 | clientPeerID :: !PeerID | 172 | clientPeerID :: !PeerID |
128 | 173 | ||
129 | -- | Extensions we should try to use. Hovewer some particular peer | 174 | -- | Extensions we should try to use. Hovewer some particular peer |
130 | -- might not support some extension, so we keep enableExtension in | 175 | -- might not support some extension, so we keep enabledExtension in |
131 | -- 'PeerSession'. | 176 | -- 'PeerSession'. |
132 | , allowedExtensions :: [Extension] | 177 | , allowedExtensions :: [Extension] |
133 | 178 | ||
134 | -- | Semaphor used to bound number of active P2P sessions. | 179 | -- | Semaphor used to bound number of active P2P sessions. |
135 | , activeThreads :: MSem ThreadCount | 180 | , activeThreads :: !(MSem ThreadCount) |
136 | 181 | ||
137 | -- | Max number of active connections. | 182 | -- | Max number of active connections. |
138 | , maxActive :: ThreadCount | 183 | , maxActive :: !ThreadCount |
139 | 184 | ||
140 | , swarmSessions :: TVar (Set SwarmSession) | 185 | -- | Used to traverse the swarm session. |
186 | , swarmSessions :: !(TVar (Set SwarmSession)) | ||
141 | 187 | ||
142 | , eventManager :: EventManager | 188 | , eventManager :: !EventManager |
143 | , currentProgress :: TVar Progress | 189 | |
190 | -- | Used to keep track global client progress. | ||
191 | , currentProgress :: !(TVar Progress) | ||
144 | } | 192 | } |
145 | 193 | ||
146 | instance Eq ClientSession where | 194 | instance Eq ClientSession where |
@@ -149,12 +197,27 @@ instance Eq ClientSession where | |||
149 | instance Ord ClientSession where | 197 | instance Ord ClientSession where |
150 | compare = comparing clientPeerID | 198 | compare = comparing clientPeerID |
151 | 199 | ||
200 | -- | Get current global progress of the client. This value is usually | ||
201 | -- shown to a user. | ||
152 | getCurrentProgress :: MonadIO m => ClientSession -> m Progress | 202 | getCurrentProgress :: MonadIO m => ClientSession -> m Progress |
153 | getCurrentProgress = liftIO . readTVarIO . currentProgress | 203 | getCurrentProgress = liftIO . readTVarIO . currentProgress |
154 | 204 | ||
155 | newClient :: ThreadCount -- ^ Maximum count of active P2P Sessions. | 205 | -- | Get number of swarms client aware of. |
206 | getSwarmCount :: MonadIO m => ClientSession -> m SessionCount | ||
207 | getSwarmCount ClientSession {..} = liftIO $ | ||
208 | S.size <$> readTVarIO swarmSessions | ||
209 | |||
210 | -- | Get number of peers the client currently connected to. | ||
211 | getPeerCount :: MonadIO m => ClientSession -> m ThreadCount | ||
212 | getPeerCount ClientSession {..} = liftIO $ do | ||
213 | unused <- peekAvail activeThreads | ||
214 | return (maxActive - unused) | ||
215 | |||
216 | -- | Create a new client session. The data passed to this function are | ||
217 | -- usually loaded from configuration file. | ||
218 | newClient :: SessionCount -- ^ Maximum count of active P2P Sessions. | ||
156 | -> [Extension] -- ^ Extensions allowed to use. | 219 | -> [Extension] -- ^ Extensions allowed to use. |
157 | -> IO ClientSession | 220 | -> IO ClientSession -- ^ Client with unique peer ID. |
158 | 221 | ||
159 | newClient n exts = do | 222 | newClient n exts = do |
160 | mgr <- Ev.new | 223 | mgr <- Ev.new |
@@ -183,11 +246,11 @@ defSeederConns = defaultUnchokeSlots | |||
183 | defLeacherConns :: SessionCount | 246 | defLeacherConns :: SessionCount |
184 | defLeacherConns = defaultNumWant | 247 | defLeacherConns = defaultNumWant |
185 | 248 | ||
186 | 249 | -- | Swarm session is | |
187 | -- | Extensions are set globally by | ||
188 | -- Swarm session are un | ||
189 | data SwarmSession = SwarmSession { | 250 | data SwarmSession = SwarmSession { |
190 | torrentMeta :: !Torrent | 251 | torrentMeta :: !Torrent |
252 | |||
253 | -- | | ||
191 | , clientSession :: !ClientSession | 254 | , clientSession :: !ClientSession |
192 | 255 | ||
193 | -- | Represent count of peers we _currently_ can connect to in the | 256 | -- | Represent count of peers we _currently_ can connect to in the |