summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bittorrent.cabal1
-rw-r--r--examples/Main.hs3
-rw-r--r--src/Data/Torrent.hs8
-rw-r--r--src/Network/BitTorrent.hs3
-rw-r--r--src/Network/BitTorrent/Sessions.hs43
-rw-r--r--src/Network/BitTorrent/Sessions/Types.lhs8
-rw-r--r--tests/Main.hs2
7 files changed, 42 insertions, 26 deletions
diff --git a/bittorrent.cabal b/bittorrent.cabal
index c5b04e42..e5fbc058 100644
--- a/bittorrent.cabal
+++ b/bittorrent.cabal
@@ -52,6 +52,7 @@ library
52 if flag(testing) 52 if flag(testing)
53 exposed-modules: Network.BitTorrent.Exchange.Protocol 53 exposed-modules: Network.BitTorrent.Exchange.Protocol
54 , Network.BitTorrent.Tracker.Protocol 54 , Network.BitTorrent.Tracker.Protocol
55 , Network.BitTorrent.DHT.Protocol
55 , System.IO.MMap.Fixed 56 , System.IO.MMap.Fixed
56 if !flag(testing) 57 if !flag(testing)
57 other-modules: Network.BitTorrent.Exchange.Protocol 58 other-modules: Network.BitTorrent.Exchange.Protocol
diff --git a/examples/Main.hs b/examples/Main.hs
index 1d3b711b..b8e3c11f 100644
--- a/examples/Main.hs
+++ b/examples/Main.hs
@@ -8,3 +8,6 @@ main = do
8 [path] <- getArgs 8 [path] <- getArgs
9 torrent <- fromFile path 9 torrent <- fromFile path
10 print (contentLayout "./" (tInfo torrent)) 10 print (contentLayout "./" (tInfo torrent))
11
12 withDefaultClient 3000 3001 $ \ client ->
13 addTorrent client $ TorrentLoc path "/tmp"
diff --git a/src/Data/Torrent.hs b/src/Data/Torrent.hs
index ae40bef4..3f555a5b 100644
--- a/src/Data/Torrent.hs
+++ b/src/Data/Torrent.hs
@@ -27,7 +27,7 @@
27module Data.Torrent 27module Data.Torrent
28 ( -- * Torrent 28 ( -- * Torrent
29 Torrent(..), ContentInfo(..), FileInfo(..) 29 Torrent(..), ContentInfo(..), FileInfo(..)
30 , torrent, simpleTorrent 30 , mktorrent, simpleTorrent
31 , torrentExt, isTorrentPath 31 , torrentExt, isTorrentPath
32 , fromFile 32 , fromFile
33 33
@@ -279,16 +279,16 @@ instance Hashable Torrent where
279-} 279-}
280 280
281-- | Smart constructor for 'Torrent' which compute info hash. 281-- | Smart constructor for 'Torrent' which compute info hash.
282torrent :: URI -> ContentInfo 282mktorrent :: URI -> ContentInfo
283 -> Maybe [[URI]] -> Maybe Text -> Maybe ByteString 283 -> Maybe [[URI]] -> Maybe Text -> Maybe ByteString
284 -> Maybe Time -> Maybe ByteString -> Maybe URI 284 -> Maybe Time -> Maybe ByteString -> Maybe URI
285 -> Maybe URI -> Maybe ByteString 285 -> Maybe URI -> Maybe ByteString
286 -> Torrent 286 -> Torrent
287torrent announce info = Torrent (hashlazy (BE.encoded info)) announce info 287mktorrent announce info = Torrent (hashlazy (BE.encoded info)) announce info
288 288
289-- | A simple torrent contains only required fields. 289-- | A simple torrent contains only required fields.
290simpleTorrent :: URI -> ContentInfo -> Torrent 290simpleTorrent :: URI -> ContentInfo -> Torrent
291simpleTorrent announce info = torrent announce info 291simpleTorrent announce info = mktorrent announce info
292 Nothing Nothing Nothing 292 Nothing Nothing Nothing
293 Nothing Nothing Nothing 293 Nothing Nothing Nothing
294 Nothing Nothing 294 Nothing Nothing
diff --git a/src/Network/BitTorrent.hs b/src/Network/BitTorrent.hs
index 8c3189d3..c166b1b1 100644
--- a/src/Network/BitTorrent.hs
+++ b/src/Network/BitTorrent.hs
@@ -46,8 +46,7 @@ import System.Torrent.Storage
46-- | Client session with default parameters. Use it for testing only. 46-- | Client session with default parameters. Use it for testing only.
47withDefaultClient :: PortNumber -> PortNumber -> (ClientSession -> IO ()) -> IO () 47withDefaultClient :: PortNumber -> PortNumber -> (ClientSession -> IO ()) -> IO ()
48withDefaultClient dhtPort listPort action = do 48withDefaultClient dhtPort listPort action = do
49 withClientSession defaultThreadCount defaultExtensions $ \client -> do 49 withClientSession defaultThreadCount defaultExtensions listPort dhtPort action
50 action client
51 50
52{----------------------------------------------------------------------- 51{-----------------------------------------------------------------------
53 Torrent management 52 Torrent management
diff --git a/src/Network/BitTorrent/Sessions.hs b/src/Network/BitTorrent/Sessions.hs
index 2e51fde6..9a1d0c6a 100644
--- a/src/Network/BitTorrent/Sessions.hs
+++ b/src/Network/BitTorrent/Sessions.hs
@@ -48,7 +48,7 @@ module Network.BitTorrent.Sessions
48 , discover 48 , discover
49 ) where 49 ) where
50 50
51import Prelude hiding (mapM_) 51import Prelude hiding (mapM_, elem)
52 52
53import Control.Applicative 53import Control.Applicative
54import Control.Concurrent 54import Control.Concurrent
@@ -61,6 +61,7 @@ import Control.Monad.Trans
61import Data.IORef 61import Data.IORef
62import Data.Map as M 62import Data.Map as M
63import Data.HashMap.Strict as HM 63import Data.HashMap.Strict as HM
64import Data.Foldable as F
64import Data.Set as S 65import Data.Set as S
65 66
66import Data.Serialize hiding (get) 67import Data.Serialize hiding (get)
@@ -141,14 +142,13 @@ startDHT ClientSession {..} nodePort = withRunning peerListener failure start
141 142
142-- | Create a new client session. The data passed to this function are 143-- | Create a new client session. The data passed to this function are
143-- usually loaded from configuration file. 144-- usually loaded from configuration file.
144openClientSession :: SessionCount -- ^ Maximum count of active P2P Sessions. 145openClientSession :: SessionCount -> [Extension] -> PortNumber -> PortNumber -> IO ClientSession
145 -> [Extension] -- ^ Extensions allowed to use. 146openClientSession n exts listenerPort _ = do
146 -> IO ClientSession -- ^ Client with unique peer ID.
147openClientSession n exts = do
148 mgr <- Ev.new 147 mgr <- Ev.new
149 -- TODO kill this thread when leave client 148 -- TODO kill this thread when leave client
150 _ <- forkIO $ loop mgr 149 _ <- forkIO $ loop mgr
151 ClientSession 150
151 cs <- ClientSession
152 <$> genPeerId 152 <$> genPeerId
153 <*> pure exts 153 <*> pure exts
154 <*> newEmptyMVar 154 <*> newEmptyMVar
@@ -160,13 +160,21 @@ openClientSession n exts = do
160 <*> newTVarIO (startProgress 0) 160 <*> newTVarIO (startProgress 0)
161 <*> newTVarIO HM.empty 161 <*> newTVarIO HM.empty
162 162
163 startListener cs listenerPort
164 return cs
165
163closeClientSession :: ClientSession -> IO () 166closeClientSession :: ClientSession -> IO ()
164closeClientSession ClientSession {..} = 167closeClientSession ClientSession {..} = do
165 stopService nodeListener `finally` stopService peerListener 168 stopService nodeListener
166-- TODO stop all swarm sessions 169 stopService peerListener
170
171 sws <- readTVarIO swarmSessions
172 forM_ sws closeSwarmSession
167 173
168withClientSession :: SessionCount -> [Extension] -> (ClientSession -> IO ()) -> IO () 174withClientSession :: SessionCount -> [Extension]
169withClientSession c es = bracket (openClientSession c es) closeClientSession 175 -> PortNumber -> PortNumber
176 -> (ClientSession -> IO ()) -> IO ()
177withClientSession c es l d = bracket (openClientSession c es l d) closeClientSession
170 178
171-- | Get current global progress of the client. This value is usually 179-- | Get current global progress of the client. This value is usually
172-- shown to a user. 180-- shown to a user.
@@ -222,6 +230,14 @@ discover swarm @ SwarmSession {..} action = {-# SCC discover #-} do
222 initiatePeerSession swarm addr $ \conn -> 230 initiatePeerSession swarm addr $ \conn ->
223 runP2P conn action 231 runP2P conn action
224 232
233registerSwarmSession :: SwarmSession -> IO ()
234registerSwarmSession = undefined
235
236unregisterSwarmSession :: SwarmSession -> IO ()
237unregisterSwarmSession SwarmSession {..} =
238 atomically $ modifyTVar (swarmSessions clientSession) $
239 M.delete $ tInfoHash torrentMeta
240
225newSwarmSession :: Int -> Bitfield -> ClientSession -> Torrent 241newSwarmSession :: Int -> Bitfield -> ClientSession -> Torrent
226 -> IO SwarmSession 242 -> IO SwarmSession
227newSwarmSession n bf cs @ ClientSession {..} t @ Torrent {..} 243newSwarmSession n bf cs @ ClientSession {..} t @ Torrent {..}
@@ -246,11 +262,6 @@ closeSwarmSession se @ SwarmSession {..} = do
246 -- TODO the order is important! 262 -- TODO the order is important!
247 closeStorage storage 263 closeStorage storage
248 264
249unregisterSwarmSession :: SwarmSession -> IO ()
250unregisterSwarmSession SwarmSession {..} =
251 atomically $ modifyTVar (swarmSessions clientSession) $
252 M.delete $ tInfoHash torrentMeta
253
254getSwarm :: ClientSession -> InfoHash -> IO SwarmSession 265getSwarm :: ClientSession -> InfoHash -> IO SwarmSession
255getSwarm cs @ ClientSession {..} ih = do 266getSwarm cs @ ClientSession {..} ih = do
256 ss <- readTVarIO swarmSessions 267 ss <- readTVarIO swarmSessions
diff --git a/src/Network/BitTorrent/Sessions/Types.lhs b/src/Network/BitTorrent/Sessions/Types.lhs
index f94dbfa6..3f9c6db1 100644
--- a/src/Network/BitTorrent/Sessions/Types.lhs
+++ b/src/Network/BitTorrent/Sessions/Types.lhs
@@ -73,10 +73,12 @@ Thread layout
73 73
74When client session created 2 new threads appear: 74When client session created 2 new threads appear:
75 75
76 * DHT listener - replies to DHT requests;
77
78 * Peer listener - accept new P2P connection initiated by other 76 * Peer listener - accept new P2P connection initiated by other
79peers. 77peers;
78
79 * Tracker announcer - announce that the peer have this torrent.
80
81 * OPTIONAL: DHT listener - replies to DHT requests;
80 82
81When swarn session created 3 new threads appear: 83When swarn session created 3 new threads appear:
82 84
diff --git a/tests/Main.hs b/tests/Main.hs
index adb50380..c0ef52db 100644
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -118,7 +118,7 @@ instance Arbitrary ContentInfo where
118 ] 118 ]
119 119
120instance Arbitrary Torrent where 120instance Arbitrary Torrent where
121 arbitrary = torrent <$> arbitrary 121 arbitrary = mktorrent <$> arbitrary
122 <*> arbitrary <*> arbitrary <*> arbitrary 122 <*> arbitrary <*> arbitrary <*> arbitrary
123 <*> arbitrary <*> arbitrary <*> arbitrary 123 <*> arbitrary <*> arbitrary <*> arbitrary
124 <*> arbitrary <*> pure Nothing <*> arbitrary 124 <*> arbitrary <*> pure Nothing <*> arbitrary