diff options
author | Sam Truzjan <pxqr.sta@gmail.com> | 2014-04-04 04:51:36 +0400 |
---|---|---|
committer | Sam Truzjan <pxqr.sta@gmail.com> | 2014-04-04 04:51:36 +0400 |
commit | 1beb66f98504a39c8a6c976f243a1f69ffb48d8d (patch) | |
tree | e26f7eff93b2ef100a768e01b0fbeb239c09dd8a /src/Network/BitTorrent/Tracker/Session.hs | |
parent | 13793b8d4cf7c5b4a914d778e3523e950aa2493a (diff) |
[Internal] Add EventSource class
Diffstat (limited to 'src/Network/BitTorrent/Tracker/Session.hs')
-rw-r--r-- | src/Network/BitTorrent/Tracker/Session.hs | 49 |
1 files changed, 22 insertions, 27 deletions
diff --git a/src/Network/BitTorrent/Tracker/Session.hs b/src/Network/BitTorrent/Tracker/Session.hs index e82501dd..5aa9c0eb 100644 --- a/src/Network/BitTorrent/Tracker/Session.hs +++ b/src/Network/BitTorrent/Tracker/Session.hs | |||
@@ -8,17 +8,18 @@ | |||
8 | -- Multitracker sessions. | 8 | -- Multitracker sessions. |
9 | -- | 9 | -- |
10 | {-# LANGUAGE FlexibleInstances #-} | 10 | {-# LANGUAGE FlexibleInstances #-} |
11 | {-# LANGUAGE TypeFamilies #-} | ||
11 | {-# LANGUAGE TypeSynonymInstances #-} | 12 | {-# LANGUAGE TypeSynonymInstances #-} |
12 | {-# LANGUAGE TemplateHaskell #-} | 13 | {-# LANGUAGE TemplateHaskell #-} |
13 | module Network.BitTorrent.Tracker.Session | 14 | module Network.BitTorrent.Tracker.Session |
14 | ( -- * Session | 15 | ( -- * Session |
15 | Session | 16 | Session |
17 | , Event (..) | ||
16 | , newSession | 18 | , newSession |
17 | , closeSession | 19 | , closeSession |
18 | , withSession | 20 | , withSession |
19 | 21 | ||
20 | -- * Client send notifications | 22 | -- * Client send notifications |
21 | , Event (..) | ||
22 | , notify | 23 | , notify |
23 | , askPeers | 24 | , askPeers |
24 | 25 | ||
@@ -39,16 +40,12 @@ module Network.BitTorrent.Tracker.Session | |||
39 | , addTracker | 40 | , addTracker |
40 | , removeTracker | 41 | , removeTracker |
41 | , getTrustedTrackers | 42 | , getTrustedTrackers |
42 | |||
43 | -- * Events | ||
44 | , SessionEvent (..) | ||
45 | , subscribe | ||
46 | ) where | 43 | ) where |
47 | 44 | ||
48 | import Control.Applicative | 45 | import Control.Applicative |
49 | import Control.Exception | 46 | import Control.Exception |
50 | import Control.Concurrent | 47 | import Control.Concurrent |
51 | import Control.Concurrent.Chan.Split | 48 | import Control.Concurrent.Chan.Split as CS |
52 | import Control.Monad | 49 | import Control.Monad |
53 | import Data.Aeson | 50 | import Data.Aeson |
54 | import Data.Aeson.TH | 51 | import Data.Aeson.TH |
@@ -66,6 +63,7 @@ import Data.Torrent.InfoHash | |||
66 | import Data.Torrent.JSON | 63 | import Data.Torrent.JSON |
67 | import Network.BitTorrent.Core | 64 | import Network.BitTorrent.Core |
68 | import Network.BitTorrent.Internal.Cache | 65 | import Network.BitTorrent.Internal.Cache |
66 | import Network.BitTorrent.Internal.Types | ||
69 | import Network.BitTorrent.Tracker.List as TL | 67 | import Network.BitTorrent.Tracker.List as TL |
70 | import Network.BitTorrent.Tracker.Message | 68 | import Network.BitTorrent.Tracker.Message |
71 | import Network.BitTorrent.Tracker.RPC as RPC | 69 | import Network.BitTorrent.Tracker.RPC as RPC |
@@ -123,7 +121,7 @@ instance Default TrackerSession where | |||
123 | def = TrackerSession Nothing def def | 121 | def = TrackerSession Nothing def def |
124 | 122 | ||
125 | -- | Do we need to notify this /specific/ tracker? | 123 | -- | Do we need to notify this /specific/ tracker? |
126 | needNotify :: Event -> Maybe Status -> Maybe Bool | 124 | needNotify :: AnnounceEvent -> Maybe Status -> Maybe Bool |
127 | needNotify Started Nothing = Just True | 125 | needNotify Started Nothing = Just True |
128 | needNotify Stopped Nothing = Just False | 126 | needNotify Stopped Nothing = Just False |
129 | needNotify Completed Nothing = Just False | 127 | needNotify Completed Nothing = Just False |
@@ -135,7 +133,7 @@ needNotify Stopped (Just Paused ) = Just False | |||
135 | needNotify Completed (Just Paused ) = Just True | 133 | needNotify Completed (Just Paused ) = Just True |
136 | 134 | ||
137 | -- | Client status after event announce succeed. | 135 | -- | Client status after event announce succeed. |
138 | nextStatus :: Event -> Maybe Status | 136 | nextStatus :: AnnounceEvent -> Maybe Status |
139 | nextStatus Started = Just Running | 137 | nextStatus Started = Just Running |
140 | nextStatus Stopped = Just Paused | 138 | nextStatus Stopped = Just Paused |
141 | nextStatus Completed = Nothing -- must keep previous status | 139 | nextStatus Completed = Nothing -- must keep previous status |
@@ -159,7 +157,7 @@ cacheScrape AnnounceInfo {..} = | |||
159 | } | 157 | } |
160 | 158 | ||
161 | -- | Make announce request to specific tracker returning new state. | 159 | -- | Make announce request to specific tracker returning new state. |
162 | notifyTo :: Manager -> Session -> Event | 160 | notifyTo :: Manager -> Session -> AnnounceEvent |
163 | -> TierEntry TrackerSession -> IO TrackerSession | 161 | -> TierEntry TrackerSession -> IO TrackerSession |
164 | notifyTo mgr s @ Session {..} event (uri, entry @ TrackerSession {..}) = do | 162 | notifyTo mgr s @ Session {..} event (uri, entry @ TrackerSession {..}) = do |
165 | let shouldNotify = needNotify event statusSent | 163 | let shouldNotify = needNotify event statusSent |
@@ -193,9 +191,20 @@ data Session = Session | |||
193 | -- must take a lock. | 191 | -- must take a lock. |
194 | , sessionTrackers :: !(MVar (TrackerList TrackerSession)) | 192 | , sessionTrackers :: !(MVar (TrackerList TrackerSession)) |
195 | 193 | ||
196 | , sessionEvents :: !(SendPort SessionEvent) | 194 | , sessionEvents :: !(SendPort (Event Session)) |
197 | } | 195 | } |
198 | 196 | ||
197 | instance EventSource Session where | ||
198 | data Event Session | ||
199 | = TrackerAdded URI | ||
200 | | TrackerConfirmed URI | ||
201 | | TrackerRemoved URI | ||
202 | | AnnouncedTo URI | ||
203 | | SessionClosed | ||
204 | |||
205 | listen Session {..} = CS.listen sessionEvents | ||
206 | |||
207 | |||
199 | -- | Create a new multitracker session in paused state. Tracker list | 208 | -- | Create a new multitracker session in paused state. Tracker list |
200 | -- must contant only /trusted/ tracker uris. To start announcing | 209 | -- must contant only /trusted/ tracker uris. To start announcing |
201 | -- client presence use 'notify'. | 210 | -- client presence use 'notify'. |
@@ -221,20 +230,6 @@ closeSession m s @ Session {..} = do | |||
221 | send sessionEvents SessionClosed | 230 | send sessionEvents SessionClosed |
222 | 231 | ||
223 | {----------------------------------------------------------------------- | 232 | {----------------------------------------------------------------------- |
224 | -- Events | ||
225 | -----------------------------------------------------------------------} | ||
226 | |||
227 | data SessionEvent | ||
228 | = TrackerAdded URI | ||
229 | | TrackerConfirmed URI | ||
230 | | TrackerRemoved URI | ||
231 | | AnnouncedTo URI | ||
232 | | SessionClosed | ||
233 | |||
234 | subscribe :: Session -> IO (ReceivePort SessionEvent) | ||
235 | subscribe Session {..} = listen sessionEvents | ||
236 | |||
237 | {----------------------------------------------------------------------- | ||
238 | -- Operations | 233 | -- Operations |
239 | -----------------------------------------------------------------------} | 234 | -----------------------------------------------------------------------} |
240 | 235 | ||
@@ -253,12 +248,12 @@ getSessionState Session {..} = TL.toList <$> readMVar sessionTrackers | |||
253 | 248 | ||
254 | -- | Do we need to sent this event to a first working tracker or to | 249 | -- | Do we need to sent this event to a first working tracker or to |
255 | -- the all known good trackers? | 250 | -- the all known good trackers? |
256 | allNotify :: Event -> Bool | 251 | allNotify :: AnnounceEvent -> Bool |
257 | allNotify Started = False | 252 | allNotify Started = False |
258 | allNotify Stopped = True | 253 | allNotify Stopped = True |
259 | allNotify Completed = True | 254 | allNotify Completed = True |
260 | 255 | ||
261 | notifyAll :: Manager -> Session -> Event -> IO () | 256 | notifyAll :: Manager -> Session -> AnnounceEvent -> IO () |
262 | notifyAll mgr s @ Session {..} event = do | 257 | notifyAll mgr s @ Session {..} event = do |
263 | modifyMVar_ sessionTrackers $ | 258 | modifyMVar_ sessionTrackers $ |
264 | (traversal (notifyTo mgr s event)) | 259 | (traversal (notifyTo mgr s event)) |
@@ -271,7 +266,7 @@ notifyAll mgr s @ Session {..} event = do | |||
271 | -- | | 266 | -- | |
272 | -- | 267 | -- |
273 | -- This function /may/ block until tracker query proceed. | 268 | -- This function /may/ block until tracker query proceed. |
274 | notify :: Manager -> Session -> Event -> IO () | 269 | notify :: Manager -> Session -> AnnounceEvent -> IO () |
275 | notify mgr ses event = do | 270 | notify mgr ses event = do |
276 | prevStatus <- atomicModifyIORef (sessionStatus ses) $ \ s -> | 271 | prevStatus <- atomicModifyIORef (sessionStatus ses) $ \ s -> |
277 | (fromMaybe s (nextStatus event), s) | 272 | (fromMaybe s (nextStatus event), s) |