summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Client
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/Client')
-rw-r--r--src/Network/BitTorrent/Client/Handle.hs58
-rw-r--r--src/Network/BitTorrent/Client/Types.hs10
2 files changed, 45 insertions, 23 deletions
diff --git a/src/Network/BitTorrent/Client/Handle.hs b/src/Network/BitTorrent/Client/Handle.hs
index 19ad1675..fcc0adad 100644
--- a/src/Network/BitTorrent/Client/Handle.hs
+++ b/src/Network/BitTorrent/Client/Handle.hs
@@ -29,7 +29,7 @@ import Data.HashMap.Strict as HM
29import Data.Torrent 29import Data.Torrent
30import Data.Torrent.InfoHash 30import Data.Torrent.InfoHash
31import Data.Torrent.Magnet 31import Data.Torrent.Magnet
32import Network.BitTorrent.Client.Types 32import Network.BitTorrent.Client.Types as Types
33import Network.BitTorrent.DHT as DHT 33import Network.BitTorrent.DHT as DHT
34import Network.BitTorrent.Exchange as Exchange 34import Network.BitTorrent.Exchange as Exchange
35import Network.BitTorrent.Tracker as Tracker 35import Network.BitTorrent.Tracker as Tracker
@@ -86,11 +86,13 @@ openTorrent :: FilePath -> Torrent -> BitTorrent Handle
86openTorrent rootPath t @ Torrent {..} = do 86openTorrent rootPath t @ Torrent {..} = do
87 let ih = idInfoHash tInfoDict 87 let ih = idInfoHash tInfoDict
88 allocHandle ih $ do 88 allocHandle ih $ do
89 statusVar <- newMVar Types.Stopped
89 tses <- liftIO $ Tracker.newSession ih (trackerList t) 90 tses <- liftIO $ Tracker.newSession ih (trackerList t)
90 eses <- newExchangeSession rootPath (Right tInfoDict) 91 eses <- newExchangeSession rootPath (Right tInfoDict)
91 return $ Handle 92 return $ Handle
92 { handleTopic = ih 93 { handleTopic = ih
93 , handlePrivate = idPrivate tInfoDict 94 , handlePrivate = idPrivate tInfoDict
95 , handleStatus = statusVar
94 , handleTrackers = tses 96 , handleTrackers = tses
95 , handleExchange = eses 97 , handleExchange = eses
96 } 98 }
@@ -99,11 +101,13 @@ openTorrent rootPath t @ Torrent {..} = do
99openMagnet :: FilePath -> Magnet -> BitTorrent Handle 101openMagnet :: FilePath -> Magnet -> BitTorrent Handle
100openMagnet rootPath Magnet {..} = do 102openMagnet rootPath Magnet {..} = do
101 allocHandle exactTopic $ do 103 allocHandle exactTopic $ do
104 statusVar <- newMVar Types.Stopped
102 tses <- liftIO $ Tracker.newSession exactTopic def 105 tses <- liftIO $ Tracker.newSession exactTopic def
103 eses <- newExchangeSession rootPath (Left exactTopic) 106 eses <- newExchangeSession rootPath (Left exactTopic)
104 return $ Handle 107 return $ Handle
105 { handleTopic = exactTopic 108 { handleTopic = exactTopic
106 , handlePrivate = False 109 , handlePrivate = False
110 , handleStatus = statusVar
107 , handleTrackers = tses 111 , handleTrackers = tses
108 , handleExchange = eses 112 , handleExchange = eses
109 } 113 }
@@ -124,21 +128,32 @@ closeHandle h @ Handle {..} = do
124-- Control 128-- Control
125-----------------------------------------------------------------------} 129-----------------------------------------------------------------------}
126 130
131modifyStatus :: HandleStatus -> Handle -> (HandleStatus -> BitTorrent ()) -> BitTorrent ()
132modifyStatus targetStatus Handle {..} targetAction = do
133 modifyMVar_ handleStatus $ \ actualStatus -> do
134 unless (actualStatus == targetStatus) $ do
135 targetAction actualStatus
136 return targetStatus
137
127-- | Start downloading, uploading and announcing this torrent. 138-- | Start downloading, uploading and announcing this torrent.
128-- 139--
129-- This operation is blocking, use 140-- This operation is blocking, use
130-- 'Control.Concurrent.Async.Lifted.async' if needed. 141-- 'Control.Concurrent.Async.Lifted.async' if needed.
131start :: Handle -> BitTorrent () 142start :: Handle -> BitTorrent ()
132start Handle {..} = do 143start h @ Handle {..} = do
133 Client {..} <- getClient 144 modifyStatus Types.Running h $ \ status -> do
134 liftIO $ Tracker.notify trackerManager handleTrackers Tracker.Started 145 case status of
135 unless handlePrivate $ do 146 Types.Running -> return ()
136 liftDHT $ DHT.insert handleTopic (error "start") 147 Types.Stopped -> do
137 liftIO $ do 148 Client {..} <- getClient
138 peers <- askPeers trackerManager handleTrackers 149 liftIO $ Tracker.notify trackerManager handleTrackers Tracker.Started
139 print $ "got: " ++ show (L.length peers) ++ " peers" 150 unless handlePrivate $ do
140 forM_ peers $ \ peer -> do 151 liftDHT $ DHT.insert handleTopic (error "start")
141 Exchange.connect peer handleExchange 152 liftIO $ do
153 peers <- askPeers trackerManager handleTrackers
154 print $ "got: " ++ show (L.length peers) ++ " peers"
155 forM_ peers $ \ peer -> do
156 Exchange.connect peer handleExchange
142 157
143-- | Stop downloading this torrent. 158-- | Stop downloading this torrent.
144pause :: Handle -> BitTorrent () 159pause :: Handle -> BitTorrent ()
@@ -146,21 +161,20 @@ pause _ = return ()
146 161
147-- | Stop downloading, uploading and announcing this torrent. 162-- | Stop downloading, uploading and announcing this torrent.
148stop :: Handle -> BitTorrent () 163stop :: Handle -> BitTorrent ()
149stop Handle {..} = do 164stop h @ Handle {..} = do
150 Client {..} <- getClient 165 modifyStatus Types.Stopped h $ \ status -> do
151 unless handlePrivate $ do 166 case status of
152 liftDHT $ DHT.delete handleTopic (error "stop") 167 Types.Stopped -> return ()
153 liftIO $ Tracker.notify trackerManager handleTrackers Tracker.Stopped 168 Types.Running -> do
169 Client {..} <- getClient
170 unless handlePrivate $ do
171 liftDHT $ DHT.delete handleTopic (error "stop")
172 liftIO $ Tracker.notify trackerManager handleTrackers Tracker.Stopped
154 173
155{----------------------------------------------------------------------- 174{-----------------------------------------------------------------------
156-- Query 175-- Query
157-----------------------------------------------------------------------} 176-----------------------------------------------------------------------}
158 177
159data HandleStatus
160 = Running
161 | Paused
162 | Stopped
163
164getHandle :: InfoHash -> BitTorrent Handle 178getHandle :: InfoHash -> BitTorrent Handle
165getHandle ih = do 179getHandle ih = do
166 mhandle <- lookupHandle ih 180 mhandle <- lookupHandle ih
@@ -169,4 +183,4 @@ getHandle ih = do
169 Just h -> return h 183 Just h -> return h
170 184
171getStatus :: Handle -> IO HandleStatus 185getStatus :: Handle -> IO HandleStatus
172getStatus = undefined 186getStatus Handle {..} = readMVar handleStatus
diff --git a/src/Network/BitTorrent/Client/Types.hs b/src/Network/BitTorrent/Client/Types.hs
index c0d50175..5ceb4119 100644
--- a/src/Network/BitTorrent/Client/Types.hs
+++ b/src/Network/BitTorrent/Client/Types.hs
@@ -4,7 +4,8 @@
4{-# LANGUAGE GeneralizedNewtypeDeriving #-} 4{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5module Network.BitTorrent.Client.Types 5module Network.BitTorrent.Client.Types
6 ( -- * Core types 6 ( -- * Core types
7 Handle (..) 7 HandleStatus (..)
8 , Handle (..)
8 , Client (..) 9 , Client (..)
9 , externalAddr 10 , externalAddr
10 11
@@ -39,9 +40,16 @@ import Network.BitTorrent.DHT as DHT
39import Network.BitTorrent.Exchange as Exchange 40import Network.BitTorrent.Exchange as Exchange
40import Network.BitTorrent.Tracker as Tracker 41import Network.BitTorrent.Tracker as Tracker
41 42
43data HandleStatus
44 = Running
45 | Stopped
46 deriving (Show, Eq)
47
42data Handle = Handle 48data Handle = Handle
43 { handleTopic :: !InfoHash 49 { handleTopic :: !InfoHash
44 , handlePrivate :: !Bool 50 , handlePrivate :: !Bool
51
52 , handleStatus :: !(MVar HandleStatus)
45 , handleTrackers :: !Tracker.Session 53 , handleTrackers :: !Tracker.Session
46 , handleExchange :: !Exchange.Session 54 , handleExchange :: !Exchange.Session
47 } 55 }