diff options
author | Sam Truzjan <pxqr.sta@gmail.com> | 2014-02-11 12:30:50 +0400 |
---|---|---|
committer | Sam Truzjan <pxqr.sta@gmail.com> | 2014-02-11 12:30:50 +0400 |
commit | 0ec910a0fb7c1e5d72e06f00806b85111138461a (patch) | |
tree | 396fbcac569a171d9ef0e2ffe59dbd27a7f6978f /src/Network | |
parent | 4fef598f29cbb138e7b93c5011887c2b92a12879 (diff) |
Add exchange manager and session to client session
Diffstat (limited to 'src/Network')
-rw-r--r-- | src/Network/BitTorrent/Client.hs | 43 | ||||
-rw-r--r-- | src/Network/BitTorrent/Client/Handle.hs | 13 | ||||
-rw-r--r-- | src/Network/BitTorrent/Client/Types.hs | 9 | ||||
-rw-r--r-- | src/Network/BitTorrent/Core/PeerAddr.hs | 4 | ||||
-rw-r--r-- | src/Network/BitTorrent/Exchange.hs | 24 | ||||
-rw-r--r-- | src/Network/BitTorrent/Exchange/Manager.hs | 55 | ||||
-rw-r--r-- | src/Network/BitTorrent/Exchange/Session.hs | 57 |
7 files changed, 177 insertions, 28 deletions
diff --git a/src/Network/BitTorrent/Client.hs b/src/Network/BitTorrent/Client.hs index d8c3ee91..255c4dec 100644 --- a/src/Network/BitTorrent/Client.hs +++ b/src/Network/BitTorrent/Client.hs | |||
@@ -28,6 +28,10 @@ module Network.BitTorrent.Client | |||
28 | , openTorrent | 28 | , openTorrent |
29 | , openMagnet | 29 | , openMagnet |
30 | , closeHandle | 30 | , closeHandle |
31 | |||
32 | , start | ||
33 | , pause | ||
34 | , stop | ||
31 | ) where | 35 | ) where |
32 | 36 | ||
33 | import Control.Exception | 37 | import Control.Exception |
@@ -40,12 +44,13 @@ import Data.Maybe | |||
40 | import Data.Text | 44 | import Data.Text |
41 | import Network | 45 | import Network |
42 | 46 | ||
43 | import Network.BitTorrent.Client.Types | 47 | import Network.BitTorrent.Client.Types |
44 | import Network.BitTorrent.Client.Handle | 48 | import Network.BitTorrent.Client.Handle |
45 | import Network.BitTorrent.Core | 49 | import Network.BitTorrent.Core |
46 | import Network.BitTorrent.DHT | 50 | import Network.BitTorrent.DHT |
47 | import Network.BitTorrent.Tracker as Tracker hiding (Options) | 51 | import Network.BitTorrent.Tracker as Tracker hiding (Options) |
48 | import Network.BitTorrent.Exchange.Message | 52 | import Network.BitTorrent.Exchange as Exchange hiding (Options) |
53 | import qualified Network.BitTorrent.Exchange as Exchange (Options(..)) | ||
49 | 54 | ||
50 | 55 | ||
51 | data Options = Options | 56 | data Options = Options |
@@ -67,30 +72,40 @@ instance Default Options where | |||
67 | , optBootNode = Nothing | 72 | , optBootNode = Nothing |
68 | } | 73 | } |
69 | 74 | ||
75 | exchangeOptions :: PeerId -> Options -> Exchange.Options | ||
76 | exchangeOptions pid Options {..} = Exchange.Options | ||
77 | { optPeerAddr = PeerAddr (Just pid) (peerHost def) optPort | ||
78 | , optBacklog = optBacklog def | ||
79 | } | ||
80 | |||
81 | --connHandler :: HashMap InfoHash Handle -> Handler | ||
82 | connHandler tmap = undefined | ||
83 | |||
70 | newClient :: Options -> LogFun -> IO Client | 84 | newClient :: Options -> LogFun -> IO Client |
71 | newClient Options {..} logger = do | 85 | newClient opts @ Options {..} logger = do |
72 | pid <- genPeerId | 86 | pid <- genPeerId |
73 | ts <- newMVar HM.empty | 87 | tmap <- newMVar HM.empty |
74 | let peerInfo = PeerInfo pid Nothing optPort | 88 | tmgr <- Tracker.newManager def (PeerInfo pid Nothing optPort) |
75 | mgr <- Tracker.newManager def peerInfo | 89 | emgr <- Exchange.newManager (exchangeOptions pid opts) connHandler |
76 | node <- runResourceT $ do | 90 | node <- runResourceT $ do |
77 | node <- startNode handlers def optNodeAddr logger | 91 | node <- startNode handlers def optNodeAddr logger |
78 | runDHT node $ bootstrap (maybeToList optBootNode) | 92 | runDHT node $ bootstrap (maybeToList optBootNode) |
79 | return node | 93 | return node |
80 | |||
81 | return Client | 94 | return Client |
82 | { clientPeerId = pid | 95 | { clientPeerId = pid |
83 | , clientListenerPort = optPort | 96 | , clientListenerPort = optPort |
84 | , allowedExtensions = toCaps optExtensions | 97 | , allowedExtensions = toCaps optExtensions |
85 | , trackerManager = mgr | 98 | , trackerManager = tmgr |
99 | , exchangeManager = emgr | ||
86 | , clientNode = node | 100 | , clientNode = node |
87 | , clientTorrents = ts | 101 | , clientTorrents = tmap |
88 | , clientLogger = logger | 102 | , clientLogger = logger |
89 | } | 103 | } |
90 | 104 | ||
91 | closeClient :: Client -> IO () | 105 | closeClient :: Client -> IO () |
92 | closeClient Client {..} = do | 106 | closeClient Client {..} = do |
93 | Tracker.closeManager trackerManager | 107 | Exchange.closeManager exchangeManager |
108 | Tracker.closeManager trackerManager | ||
94 | return () | 109 | return () |
95 | -- closeNode clientNode | 110 | -- closeNode clientNode |
96 | 111 | ||
diff --git a/src/Network/BitTorrent/Client/Handle.hs b/src/Network/BitTorrent/Client/Handle.hs index 467d5745..39d8393a 100644 --- a/src/Network/BitTorrent/Client/Handle.hs +++ b/src/Network/BitTorrent/Client/Handle.hs | |||
@@ -28,8 +28,9 @@ import Data.Torrent | |||
28 | import Data.Torrent.InfoHash | 28 | import Data.Torrent.InfoHash |
29 | import Data.Torrent.Magnet | 29 | import Data.Torrent.Magnet |
30 | import Network.BitTorrent.Client.Types | 30 | import Network.BitTorrent.Client.Types |
31 | import Network.BitTorrent.DHT as DHT | 31 | import Network.BitTorrent.DHT as DHT |
32 | import Network.BitTorrent.Tracker as Tracker | 32 | import Network.BitTorrent.Exchange as Exchange |
33 | import Network.BitTorrent.Tracker as Tracker | ||
33 | 34 | ||
34 | {----------------------------------------------------------------------- | 35 | {----------------------------------------------------------------------- |
35 | -- Safe handle set manupulation | 36 | -- Safe handle set manupulation |
@@ -74,8 +75,9 @@ openTorrent :: Torrent -> BitTorrent Handle | |||
74 | openTorrent t @ Torrent {..} = do | 75 | openTorrent t @ Torrent {..} = do |
75 | let ih = idInfoHash tInfoDict | 76 | let ih = idInfoHash tInfoDict |
76 | allocHandle ih $ do | 77 | allocHandle ih $ do |
77 | ses <- liftIO (Tracker.newSession ih (trackerList t)) | 78 | tses <- liftIO $ Tracker.newSession ih (trackerList t) |
78 | return $ Handle ih (idPrivate tInfoDict) ses | 79 | eses <- liftIO $ Exchange.newSession undefined undefined undefined |
80 | return $ Handle ih (idPrivate tInfoDict) tses eses | ||
79 | 81 | ||
80 | -- | Use 'nullMagnet' to open handle from 'InfoHash'. | 82 | -- | Use 'nullMagnet' to open handle from 'InfoHash'. |
81 | openMagnet :: Magnet -> BitTorrent Handle | 83 | openMagnet :: Magnet -> BitTorrent Handle |
@@ -105,6 +107,9 @@ start Handle {..} = do | |||
105 | liftIO $ Tracker.notify trackerManager trackers Tracker.Started | 107 | liftIO $ Tracker.notify trackerManager trackers Tracker.Started |
106 | unless private $ do | 108 | unless private $ do |
107 | liftDHT $ DHT.insert topic undefined | 109 | liftDHT $ DHT.insert topic undefined |
110 | peers <- liftIO $ askPeers trackerManager trackers | ||
111 | forM_ peers $ \ peer -> do | ||
112 | liftIO $ Exchange.insert peer exchange | ||
108 | 113 | ||
109 | -- | Stop downloading this torrent. | 114 | -- | Stop downloading this torrent. |
110 | pause :: Handle -> BitTorrent () | 115 | pause :: Handle -> BitTorrent () |
diff --git a/src/Network/BitTorrent/Client/Types.hs b/src/Network/BitTorrent/Client/Types.hs index 0da24dc2..603142d5 100644 --- a/src/Network/BitTorrent/Client/Types.hs +++ b/src/Network/BitTorrent/Client/Types.hs | |||
@@ -24,15 +24,15 @@ import System.Log.FastLogger | |||
24 | 24 | ||
25 | import Data.Torrent.InfoHash | 25 | import Data.Torrent.InfoHash |
26 | import Network.BitTorrent.Core | 26 | import Network.BitTorrent.Core |
27 | import Network.BitTorrent.DHT as DHT | 27 | import Network.BitTorrent.DHT as DHT |
28 | import Network.BitTorrent.Tracker as Tracker | 28 | import Network.BitTorrent.Exchange as Exchange |
29 | import Network.BitTorrent.Exchange.Message | 29 | import Network.BitTorrent.Tracker as Tracker |
30 | |||
31 | 30 | ||
32 | data Handle = Handle | 31 | data Handle = Handle |
33 | { topic :: !InfoHash | 32 | { topic :: !InfoHash |
34 | , private :: !Bool | 33 | , private :: !Bool |
35 | , trackers :: !Tracker.Session | 34 | , trackers :: !Tracker.Session |
35 | , exchange :: !Exchange.Session | ||
36 | } | 36 | } |
37 | 37 | ||
38 | data Client = Client | 38 | data Client = Client |
@@ -40,6 +40,7 @@ data Client = Client | |||
40 | , clientListenerPort :: !PortNumber | 40 | , clientListenerPort :: !PortNumber |
41 | , allowedExtensions :: !Caps | 41 | , allowedExtensions :: !Caps |
42 | , trackerManager :: !Tracker.Manager | 42 | , trackerManager :: !Tracker.Manager |
43 | , exchangeManager :: !Exchange.Manager | ||
43 | , clientNode :: !(Node IPv4) | 44 | , clientNode :: !(Node IPv4) |
44 | , clientTorrents :: !(MVar (HashMap InfoHash Handle)) | 45 | , clientTorrents :: !(MVar (HashMap InfoHash Handle)) |
45 | , clientLogger :: !LogFun | 46 | , clientLogger :: !LogFun |
diff --git a/src/Network/BitTorrent/Core/PeerAddr.hs b/src/Network/BitTorrent/Core/PeerAddr.hs index 63885144..b62cb945 100644 --- a/src/Network/BitTorrent/Core/PeerAddr.hs +++ b/src/Network/BitTorrent/Core/PeerAddr.hs | |||
@@ -240,6 +240,10 @@ instance (Serialize a) => Serialize (PeerAddr a) where | |||
240 | instance Default (PeerAddr IPv4) where | 240 | instance Default (PeerAddr IPv4) where |
241 | def = "127.0.0.1:6881" | 241 | def = "127.0.0.1:6881" |
242 | 242 | ||
243 | -- | @127.0.0.1:6881@ | ||
244 | instance Default (PeerAddr IP) where | ||
245 | def = IPv4 <$> def | ||
246 | |||
243 | -- | Example: | 247 | -- | Example: |
244 | -- | 248 | -- |
245 | -- @peerPort \"127.0.0.1:6881\" == 6881@ | 249 | -- @peerPort \"127.0.0.1:6881\" == 6881@ |
diff --git a/src/Network/BitTorrent/Exchange.hs b/src/Network/BitTorrent/Exchange.hs index 934c646d..86e13d58 100644 --- a/src/Network/BitTorrent/Exchange.hs +++ b/src/Network/BitTorrent/Exchange.hs | |||
@@ -6,5 +6,27 @@ | |||
6 | -- Portability : portable | 6 | -- Portability : portable |
7 | -- | 7 | -- |
8 | module Network.BitTorrent.Exchange | 8 | module Network.BitTorrent.Exchange |
9 | ( | 9 | ( -- * Options |
10 | Options (..) | ||
11 | , Caps | ||
12 | , Extension | ||
13 | , toCaps | ||
14 | |||
15 | -- * Manager | ||
16 | , Manager | ||
17 | , Handler | ||
18 | , newManager | ||
19 | , closeManager | ||
20 | |||
21 | -- * Session | ||
22 | , Session | ||
23 | , newSession | ||
24 | , closeSession | ||
25 | |||
26 | -- * Session control | ||
27 | , insert | ||
10 | ) where | 28 | ) where |
29 | |||
30 | import Network.BitTorrent.Exchange.Manager | ||
31 | import Network.BitTorrent.Exchange.Message | ||
32 | import Network.BitTorrent.Exchange.Session \ No newline at end of file | ||
diff --git a/src/Network/BitTorrent/Exchange/Manager.hs b/src/Network/BitTorrent/Exchange/Manager.hs new file mode 100644 index 00000000..1ea9989f --- /dev/null +++ b/src/Network/BitTorrent/Exchange/Manager.hs | |||
@@ -0,0 +1,55 @@ | |||
1 | module Network.BitTorrent.Exchange.Manager | ||
2 | ( Options (..) | ||
3 | , Manager | ||
4 | , Handler | ||
5 | , newManager | ||
6 | , closeManager | ||
7 | ) where | ||
8 | |||
9 | import Control.Concurrent | ||
10 | import Control.Exception hiding (Handler) | ||
11 | import Control.Monad | ||
12 | import Data.Default | ||
13 | import Network.Socket | ||
14 | |||
15 | import Network.BitTorrent.Core | ||
16 | |||
17 | |||
18 | data Options = Options | ||
19 | { optBacklog :: Int | ||
20 | , optPeerAddr :: PeerAddr IP | ||
21 | } deriving (Show, Eq) | ||
22 | |||
23 | instance Default Options where | ||
24 | def = Options | ||
25 | { optBacklog = maxListenQueue | ||
26 | , optPeerAddr = def | ||
27 | } | ||
28 | |||
29 | data Manager = Manager | ||
30 | { listener :: !ThreadId | ||
31 | } | ||
32 | |||
33 | type Handler = Socket -> PeerAddr IP -> IO () | ||
34 | |||
35 | listenIncoming :: Options -> Handler -> IO () | ||
36 | listenIncoming Options {..} handler = do | ||
37 | bracket (socket AF_INET Stream defaultProtocol) close $ \ sock -> do | ||
38 | bind sock (toSockAddr optPeerAddr) | ||
39 | listen sock optBacklog | ||
40 | forever $ do | ||
41 | (conn, addr) <- accept sock | ||
42 | case fromSockAddr addr of | ||
43 | Nothing -> return () | ||
44 | Just paddr -> do | ||
45 | forkIO $ handler conn paddr | ||
46 | return () | ||
47 | |||
48 | newManager :: Options -> Handler -> IO Manager | ||
49 | newManager opts handler = do | ||
50 | tid <- forkIO $ listenIncoming opts handler | ||
51 | return (Manager tid) | ||
52 | |||
53 | closeManager :: Manager -> IO () | ||
54 | closeManager Manager {..} = do | ||
55 | killThread listener \ No newline at end of file | ||
diff --git a/src/Network/BitTorrent/Exchange/Session.hs b/src/Network/BitTorrent/Exchange/Session.hs index d455ec65..5bfc2a71 100644 --- a/src/Network/BitTorrent/Exchange/Session.hs +++ b/src/Network/BitTorrent/Exchange/Session.hs | |||
@@ -1,14 +1,21 @@ | |||
1 | {-# LANGUAGE TemplateHaskell #-} | 1 | {-# LANGUAGE TemplateHaskell #-} |
2 | {-# LANGUAGE DeriveDataTypeable #-} | 2 | {-# LANGUAGE DeriveDataTypeable #-} |
3 | module Network.BitTorrent.Exchange.Session | 3 | module Network.BitTorrent.Exchange.Session |
4 | ( | 4 | ( Session |
5 | , newSession | ||
6 | , closeSession | ||
7 | |||
8 | , Network.BitTorrent.Exchange.Session.insert | ||
5 | ) where | 9 | ) where |
6 | 10 | ||
7 | import Control.Concurrent.STM | 11 | import Control.Concurrent.STM |
8 | import Control.Exception | 12 | import Control.Exception |
9 | import Control.Lens | 13 | import Control.Lens |
14 | import Control.Monad.Reader | ||
15 | import Control.Monad.State | ||
10 | import Data.Function | 16 | import Data.Function |
11 | import Data.IORef | 17 | import Data.IORef |
18 | import Data.Map | ||
12 | import Data.Ord | 19 | import Data.Ord |
13 | import Data.Typeable | 20 | import Data.Typeable |
14 | import Text.PrettyPrint | 21 | import Text.PrettyPrint |
@@ -16,8 +23,12 @@ import Text.PrettyPrint | |||
16 | import Data.Torrent.Bitfield | 23 | import Data.Torrent.Bitfield |
17 | import Data.Torrent.InfoHash | 24 | import Data.Torrent.InfoHash |
18 | import Network.BitTorrent.Core | 25 | import Network.BitTorrent.Core |
26 | import Network.BitTorrent.Exchange.Assembler | ||
27 | import Network.BitTorrent.Exchange.Block | ||
19 | import Network.BitTorrent.Exchange.Message | 28 | import Network.BitTorrent.Exchange.Message |
20 | import Network.BitTorrent.Exchange.Status | 29 | import Network.BitTorrent.Exchange.Status |
30 | import Network.BitTorrent.Exchange.Wire | ||
31 | import System.Torrent.Storage | ||
21 | 32 | ||
22 | 33 | ||
23 | data ExchangeError | 34 | data ExchangeError |
@@ -26,12 +37,45 @@ data ExchangeError | |||
26 | | CorruptedPiece PieceIx | 37 | | CorruptedPiece PieceIx |
27 | 38 | ||
28 | data Session = Session | 39 | data Session = Session |
29 | { storage :: Storage | 40 | { peerId :: PeerId |
30 | , bitfield :: Bitfield | 41 | , bitfield :: Bitfield |
31 | , assembler :: Assembler | 42 | , assembler :: Assembler |
32 | , peerId :: PeerId | 43 | , storage :: Storage |
44 | , unchoked :: [PeerAddr IP] | ||
45 | , handler :: Exchange () | ||
46 | , connections :: Map (PeerAddr IP) Connection | ||
33 | } | 47 | } |
34 | 48 | ||
49 | newSession :: PeerAddr IP -> Storage -> Bitfield -> IO Session | ||
50 | newSession addr st bf = do | ||
51 | return Session | ||
52 | { peerId = undefined | ||
53 | , bitfield = undefined | ||
54 | , assembler = undefined | ||
55 | , storage = undefined | ||
56 | , unchoked = undefined | ||
57 | , handler = undefined | ||
58 | , connections = undefined | ||
59 | } | ||
60 | |||
61 | closeSession :: Session -> IO () | ||
62 | closeSession = undefined | ||
63 | |||
64 | insert :: PeerAddr IP -> {- Maybe Socket -> -} Session -> IO () | ||
65 | insert addr ses @ Session {..} = do | ||
66 | undefined | ||
67 | -- forkIO $ connectWire hs addr caps (runStateT ses handler) | ||
68 | |||
69 | delete :: PeerAddr IP -> Session -> IO () | ||
70 | delete = undefined | ||
71 | |||
72 | deleteAll :: Session -> IO () | ||
73 | deleteAll = undefined | ||
74 | |||
75 | {----------------------------------------------------------------------- | ||
76 | -- Event loop | ||
77 | -----------------------------------------------------------------------} | ||
78 | |||
35 | type Exchange = StateT Session (ReaderT Connection IO) | 79 | type Exchange = StateT Session (ReaderT Connection IO) |
36 | 80 | ||
37 | --runExchange :: Exchange () -> [PeerAddr] -> IO () | 81 | --runExchange :: Exchange () -> [PeerAddr] -> IO () |
@@ -39,6 +83,9 @@ type Exchange = StateT Session (ReaderT Connection IO) | |||
39 | -- forM_ peers $ \ peer -> do | 83 | -- forM_ peers $ \ peer -> do |
40 | -- forkIO $ runReaderT (runStateT exchange session ) | 84 | -- forkIO $ runReaderT (runStateT exchange session ) |
41 | 85 | ||
86 | data Event = NewMessage (PeerAddr IP) Message | ||
87 | | Timeout -- for scheduling | ||
88 | |||
42 | awaitEvent :: Exchange Event | 89 | awaitEvent :: Exchange Event |
43 | awaitEvent = undefined | 90 | awaitEvent = undefined |
44 | 91 | ||