diff options
author | Sam T <pxqr.sta@gmail.com> | 2013-06-10 05:42:15 +0400 |
---|---|---|
committer | Sam T <pxqr.sta@gmail.com> | 2013-06-10 05:42:15 +0400 |
commit | 7313c139eb5a75edf4fca36e5d0f401584ab7502 (patch) | |
tree | a89ada3cb1b4fe19f76ed8d80e04115b78ada406 /src/Network | |
parent | f2ebdc9e4b0ad69a5a878c8e14b4e1a6bd34a831 (diff) |
~ Sketch of high level API.
Diffstat (limited to 'src/Network')
-rw-r--r-- | src/Network/BitTorrent.hs | 14 | ||||
-rw-r--r-- | src/Network/BitTorrent/Exchange.hs | 137 | ||||
-rw-r--r-- | src/Network/BitTorrent/Extension.hs | 4 |
3 files changed, 128 insertions, 27 deletions
diff --git a/src/Network/BitTorrent.hs b/src/Network/BitTorrent.hs index ac9ed50a..5d6034f6 100644 --- a/src/Network/BitTorrent.hs +++ b/src/Network/BitTorrent.hs | |||
@@ -6,12 +6,22 @@ | |||
6 | -- Portability : portable | 6 | -- Portability : portable |
7 | -- | 7 | -- |
8 | module Network.BitTorrent | 8 | module Network.BitTorrent |
9 | (module BT | 9 | ( module BT |
10 | 10 | ||
11 | -- , ClientSession, newClient | 11 | -- * Tracker |
12 | |||
13 | -- * P2P | ||
14 | , ClientSession, newClient | ||
15 | , SwarmSession, newLeacher, newSeeder | ||
16 | , PeerSession | ||
12 | ) where | 17 | ) where |
13 | 18 | ||
19 | import Network.BitTorrent.Internal | ||
20 | |||
14 | import Network.BitTorrent.Extension as BT | 21 | import Network.BitTorrent.Extension as BT |
15 | import Network.BitTorrent.Peer as BT | 22 | import Network.BitTorrent.Peer as BT |
16 | import Network.BitTorrent.Exchange as BT | 23 | import Network.BitTorrent.Exchange as BT |
17 | import Network.BitTorrent.Tracker as BT | 24 | import Network.BitTorrent.Tracker as BT |
25 | |||
26 | --discover :: SwarmSession -> (Chan PeerAddr -> IO a) -> IO a | ||
27 | --discover = undefined | ||
diff --git a/src/Network/BitTorrent/Exchange.hs b/src/Network/BitTorrent/Exchange.hs index 425ed2a3..4fe90cda 100644 --- a/src/Network/BitTorrent/Exchange.hs +++ b/src/Network/BitTorrent/Exchange.hs | |||
@@ -6,27 +6,34 @@ | |||
6 | -- Portability : portable | 6 | -- Portability : portable |
7 | -- | 7 | -- |
8 | {-# LANGUAGE DoAndIfThenElse #-} | 8 | {-# LANGUAGE DoAndIfThenElse #-} |
9 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
10 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
11 | {-# LANGUAGE RecordWildCards #-} | ||
9 | module Network.BitTorrent.Exchange | 12 | module Network.BitTorrent.Exchange |
10 | ( | 13 | ( P2P, withPeer |
11 | -- * Session | ||
12 | PeerSession, newLeacher, newSeeder | ||
13 | ) where | 14 | ) where |
14 | 15 | ||
15 | import Control.Applicative | 16 | import Control.Applicative |
16 | import Control.Concurrent | 17 | import Control.Concurrent |
17 | import Control.Concurrent.STM | 18 | import Control.Concurrent.STM |
19 | import Control.Exception | ||
20 | import Control.Monad.Reader | ||
21 | import Control.Monad.State | ||
22 | |||
18 | import Data.IORef | 23 | import Data.IORef |
19 | import Data.Function | 24 | import Data.Function |
20 | import Data.Ord | 25 | import Data.Ord |
21 | import Data.Set as S | 26 | import Data.Set as S |
22 | 27 | ||
23 | import Data.Conduit | 28 | import Data.Conduit as C |
24 | import Data.Conduit.Cereal | 29 | import Data.Conduit.Cereal |
25 | import Data.Conduit.Network | 30 | import Data.Conduit.Network |
26 | import Data.Serialize | 31 | import Data.Serialize as S |
32 | |||
33 | import Network | ||
27 | 34 | ||
28 | import Network.BitTorrent.Exchange.Selection as PW | 35 | import Network.BitTorrent.Exchange.Selection |
29 | import Network.BitTorrent.Exchange.Protocol as PW | 36 | import Network.BitTorrent.Exchange.Protocol |
30 | 37 | ||
31 | import Network.BitTorrent.Internal | 38 | import Network.BitTorrent.Internal |
32 | import Network.BitTorrent.Extension | 39 | import Network.BitTorrent.Extension |
@@ -38,29 +45,113 @@ import Data.Torrent | |||
38 | P2P monad | 45 | P2P monad |
39 | -----------------------------------------------------------------------} | 46 | -----------------------------------------------------------------------} |
40 | 47 | ||
41 | {- | 48 | type PeerWire = ConduitM Message Message IO |
42 | type P2P = Reader PeerSession (ConduitM Message Message IO) | 49 | |
50 | waitMessage :: PeerWire Message | ||
51 | waitMessage = await >>= maybe waitMessage return | ||
52 | |||
53 | signalMessage :: Message -> PeerWire () | ||
54 | signalMessage = C.yield | ||
43 | 55 | ||
44 | conduit :: Socket -> P2P a -> IO a | 56 | newtype P2P a = P2P { |
45 | conduit sock p2p = | 57 | runP2P :: ReaderT PeerSession PeerWire a |
58 | } deriving (Monad, MonadReader PeerSession, MonadIO) | ||
59 | |||
60 | instance MonadState Bitfield P2P where | ||
61 | |||
62 | runConduit :: Socket -> Conduit Message IO Message -> IO () | ||
63 | runConduit sock p2p = | ||
46 | sourceSocket sock $= | 64 | sourceSocket sock $= |
47 | conduitGet get $= | 65 | conduitGet S.get $= |
48 | messageLoop p2p $= | 66 | forever p2p $= |
49 | conduitPut put $$ | 67 | conduitPut S.put $$ |
50 | sinkSocket sock | 68 | sinkSocket sock |
51 | 69 | ||
52 | messageLoop :: P2P () -> P2P () | 70 | withPeer :: SwarmSession -> PeerAddr -> P2P () -> IO () |
53 | messageLoop = undefined | 71 | withPeer se addr p2p = |
54 | 72 | withPeerSession se addr $ \(sock, pses) -> do | |
55 | runP2P :: SSession -> PeerAddr -> P2P a -> IO a | 73 | runConduit sock (runReaderT (runP2P p2p) pses) |
56 | runP2P se addr p2p = withPeer se addr $ conduit messageLoop | ||
57 | 74 | ||
58 | data Event = Available | 75 | data Event = Available Bitfield |
59 | | Want | 76 | | Want |
60 | | Block | 77 | | Block |
61 | 78 | ||
62 | {- | 79 | |
80 | |||
63 | waitForEvent :: P2P Event | 81 | waitForEvent :: P2P Event |
82 | waitForEvent = P2P (ReaderT nextEvent) | ||
83 | where | ||
84 | nextEvent se @ PeerSession {..} = waitMessage >>= diff | ||
85 | where | ||
86 | -- diff finds difference between | ||
87 | diff KeepAlive = do | ||
88 | signalMessage KeepAlive | ||
89 | nextEvent se | ||
90 | |||
91 | handleMessage Choke = do | ||
92 | SessionStatus {..} <- liftIO $ readIORef peerSessionStatus | ||
93 | if psChoking sePeerStatus | ||
94 | then nextEvent se | ||
95 | else undefined | ||
96 | |||
97 | handleMessage Unchoke = return $ Available BF.difference | ||
98 | |||
99 | handleMessage Interested = return undefined | ||
100 | handleMessage NotInterested = return undefined | ||
101 | |||
102 | handleMessage (Have ix) = do | ||
103 | pc <- liftIO $ getPieceCount se | ||
104 | haveMessage $ have ix (haveNone pc) -- TODO singleton | ||
105 | |||
106 | handleMessage (Bitfield bf) = undefined | ||
107 | handleMessage (Request bix) = do | ||
108 | undefined | ||
109 | |||
110 | handleMessage (Piece blk) = undefined | ||
111 | handleMessage (Port _) | ||
112 | = checkExtension msg ExtDHT $ do | ||
113 | undefined | ||
114 | |||
115 | handleMessage msg @ HaveAll | ||
116 | = checkExtension msg ExtFast $ do | ||
117 | pc <- liftIO $ getPieceCount se | ||
118 | haveMessage (haveAll pc) | ||
119 | |||
120 | handleMessage msg @ HaveNone | ||
121 | = checkExtension msg ExtFast $ do | ||
122 | pc <- liftIO $ getPieceCount se | ||
123 | haveMessage (haveNone pc) | ||
124 | |||
125 | handleMessage msg @ (SuggestPiece ix) | ||
126 | = checkExtension msg ExtFast $ do | ||
127 | undefined | ||
128 | |||
129 | handleMessage msg @ (RejectRequest ix) | ||
130 | = checkExtension msg ExtFast $ do | ||
131 | undefined | ||
132 | |||
133 | handleMessage msg @ (AllowedFast pix) | ||
134 | = checkExtension msg ExtFast $ do | ||
135 | undefined | ||
136 | |||
137 | haveMessage bf = do | ||
138 | cbf <- liftIO $ readIORef $ clientBitfield swarmSession | ||
139 | if undefined -- ix `member` bf | ||
140 | then nextEvent se | ||
141 | else return $ Available diff | ||
142 | |||
143 | checkExtension msg requredExtension action | ||
144 | | requredExtension `elem` enabledExtensions = action | ||
145 | | otherwise = liftIO $ throwIO $ userError errorMsg | ||
146 | where | ||
147 | errorMsg = show (ppExtension requredExtension) | ||
148 | ++ "not enabled, but peer sent" | ||
149 | ++ show (ppMessage msg) | ||
150 | |||
151 | |||
152 | |||
153 | getPieceCount :: PeerSession -> IO PieceCount | ||
154 | getPieceCount = undefined | ||
155 | |||
64 | signalEvent :: Event -> P2P () | 156 | signalEvent :: Event -> P2P () |
65 | -} | 157 | signalEvent = undefined |
66 | -} \ No newline at end of file | ||
diff --git a/src/Network/BitTorrent/Extension.hs b/src/Network/BitTorrent/Extension.hs index 0526ace7..13a30581 100644 --- a/src/Network/BitTorrent/Extension.hs +++ b/src/Network/BitTorrent/Extension.hs | |||
@@ -12,8 +12,8 @@ | |||
12 | -- | 12 | -- |
13 | {-# LANGUAGE OverloadedStrings #-} | 13 | {-# LANGUAGE OverloadedStrings #-} |
14 | module Network.BitTorrent.Extension | 14 | module Network.BitTorrent.Extension |
15 | ( Capabilities, ppCaps, defaultCaps, enabledCaps | 15 | ( Capabilities, ppCaps, defaultCaps, enabledCaps |
16 | , Extension, ppExtension, encodeExts, decodeExts | 16 | , Extension(..), ppExtension, encodeExts, decodeExts |
17 | ) where | 17 | ) where |
18 | 18 | ||
19 | import Data.Bits | 19 | import Data.Bits |