diff options
author | Sam Truzjan <pxqr.sta@gmail.com> | 2014-02-12 19:00:33 +0400 |
---|---|---|
committer | Sam Truzjan <pxqr.sta@gmail.com> | 2014-02-12 19:00:33 +0400 |
commit | 920dd0a8eb40ec65f794fd6480835a14066d8a99 (patch) | |
tree | 810e824d3ecd65bbc745cd94386bd9ce08a5e2b7 | |
parent | 59b812124590dc4d4d11b51dff4073b495231363 (diff) |
Initialize exchange session fields
-rw-r--r-- | examples/Client.hs | 2 | ||||
-rw-r--r-- | src/Network/BitTorrent/Client/Handle.hs | 8 | ||||
-rw-r--r-- | src/Network/BitTorrent/Exchange/Session.hs | 92 |
3 files changed, 78 insertions, 24 deletions
diff --git a/examples/Client.hs b/examples/Client.hs index 0ed4bb6f..320b4269 100644 --- a/examples/Client.hs +++ b/examples/Client.hs | |||
@@ -21,6 +21,6 @@ main = do | |||
21 | path <- parseArgs | 21 | path <- parseArgs |
22 | torrent <- fromFile path | 22 | torrent <- fromFile path |
23 | simpleClient $ do | 23 | simpleClient $ do |
24 | h <- openTorrent torrent | 24 | h <- openTorrent "data" torrent |
25 | start h | 25 | start h |
26 | liftIO $ threadDelay 10000000000 | 26 | liftIO $ threadDelay 10000000000 |
diff --git a/src/Network/BitTorrent/Client/Handle.hs b/src/Network/BitTorrent/Client/Handle.hs index 39d8393a..7aaaf5aa 100644 --- a/src/Network/BitTorrent/Client/Handle.hs +++ b/src/Network/BitTorrent/Client/Handle.hs | |||
@@ -71,12 +71,13 @@ lookupHandle ih = do | |||
71 | 71 | ||
72 | -- | Open a torrent in 'stop'ed state. Use 'nullTorrent' to open | 72 | -- | Open a torrent in 'stop'ed state. Use 'nullTorrent' to open |
73 | -- handle from 'InfoDict'. This operation do not block. | 73 | -- handle from 'InfoDict'. This operation do not block. |
74 | openTorrent :: Torrent -> BitTorrent Handle | 74 | openTorrent :: FilePath -> Torrent -> BitTorrent Handle |
75 | openTorrent t @ Torrent {..} = do | 75 | openTorrent rootPath t @ Torrent {..} = do |
76 | let ih = idInfoHash tInfoDict | 76 | let ih = idInfoHash tInfoDict |
77 | allocHandle ih $ do | 77 | allocHandle ih $ do |
78 | c @ Client {..} <- getClient | ||
78 | tses <- liftIO $ Tracker.newSession ih (trackerList t) | 79 | tses <- liftIO $ Tracker.newSession ih (trackerList t) |
79 | eses <- liftIO $ Exchange.newSession undefined undefined undefined | 80 | eses <- liftIO $ Exchange.newSession (externalAddr c) rootPath tInfoDict |
80 | return $ Handle ih (idPrivate tInfoDict) tses eses | 81 | return $ Handle ih (idPrivate tInfoDict) tses eses |
81 | 82 | ||
82 | -- | Use 'nullMagnet' to open handle from 'InfoHash'. | 83 | -- | Use 'nullMagnet' to open handle from 'InfoHash'. |
@@ -91,6 +92,7 @@ closeHandle :: Handle -> BitTorrent () | |||
91 | closeHandle h @ Handle {..} = do | 92 | closeHandle h @ Handle {..} = do |
92 | freeHandle topic $ do | 93 | freeHandle topic $ do |
93 | stop h | 94 | stop h |
95 | liftIO $ Exchange.closeSession exchange | ||
94 | liftIO $ Tracker.closeSession trackers | 96 | liftIO $ Tracker.closeSession trackers |
95 | 97 | ||
96 | {----------------------------------------------------------------------- | 98 | {----------------------------------------------------------------------- |
diff --git a/src/Network/BitTorrent/Exchange/Session.hs b/src/Network/BitTorrent/Exchange/Session.hs index 885dcb13..d798a8c6 100644 --- a/src/Network/BitTorrent/Exchange/Session.hs +++ b/src/Network/BitTorrent/Exchange/Session.hs | |||
@@ -8,6 +8,7 @@ module Network.BitTorrent.Exchange.Session | |||
8 | , Network.BitTorrent.Exchange.Session.insert | 8 | , Network.BitTorrent.Exchange.Session.insert |
9 | ) where | 9 | ) where |
10 | 10 | ||
11 | import Control.Applicative | ||
11 | import Control.Concurrent | 12 | import Control.Concurrent |
12 | import Control.Exception | 13 | import Control.Exception |
13 | import Control.Lens | 14 | import Control.Lens |
@@ -15,12 +16,14 @@ import Control.Monad.Reader | |||
15 | import Control.Monad.State | 16 | import Control.Monad.State |
16 | import Data.Function | 17 | import Data.Function |
17 | import Data.IORef | 18 | import Data.IORef |
18 | import Data.Map | 19 | import Data.Maybe |
20 | import Data.Map as M | ||
19 | import Data.Ord | 21 | import Data.Ord |
20 | import Data.Typeable | 22 | import Data.Typeable |
21 | import Text.PrettyPrint | 23 | import Text.PrettyPrint |
22 | 24 | ||
23 | import Data.Torrent.Bitfield | 25 | import Data.Torrent (InfoDict (..)) |
26 | import Data.Torrent.Bitfield as BF | ||
24 | import Data.Torrent.InfoHash | 27 | import Data.Torrent.InfoHash |
25 | import Network.BitTorrent.Core | 28 | import Network.BitTorrent.Core |
26 | import Network.BitTorrent.Exchange.Assembler | 29 | import Network.BitTorrent.Exchange.Assembler |
@@ -31,13 +34,9 @@ import Network.BitTorrent.Exchange.Wire | |||
31 | import System.Torrent.Storage | 34 | import System.Torrent.Storage |
32 | 35 | ||
33 | 36 | ||
34 | data ExchangeError | ||
35 | = InvalidPieceIx PieceIx | ||
36 | | InvalidBlock BlockIx | ||
37 | | CorruptedPiece PieceIx | ||
38 | |||
39 | data Session = Session | 37 | data Session = Session |
40 | { tpeerId :: PeerId | 38 | { tpeerId :: PeerId |
39 | , infohash :: InfoHash | ||
41 | , bitfield :: Bitfield | 40 | , bitfield :: Bitfield |
42 | , assembler :: Assembler | 41 | , assembler :: Assembler |
43 | , storage :: Storage | 42 | , storage :: Storage |
@@ -45,25 +44,40 @@ data Session = Session | |||
45 | , connections :: MVar (Map (PeerAddr IP) (Connection Session)) | 44 | , connections :: MVar (Map (PeerAddr IP) (Connection Session)) |
46 | } | 45 | } |
47 | 46 | ||
48 | 47 | newSession :: PeerAddr (Maybe IP) -- ^ /external/ address of this peer; | |
49 | newSession :: PeerAddr IP -> Storage -> Bitfield -> IO Session | 48 | -> FilePath -- ^ root directory for content files; |
50 | newSession addr st bf = do | 49 | -> InfoDict -- ^ torrent info dictionary; |
50 | -> IO Session -- ^ | ||
51 | newSession addr rootPath dict = do | ||
52 | connVar <- newMVar M.empty | ||
53 | store <- openInfoDict ReadWriteEx rootPath dict | ||
51 | return Session | 54 | return Session |
52 | { tpeerId = undefined | 55 | { tpeerId = fromMaybe (error "newSession: impossible") (peerId addr) |
53 | , bitfield = undefined | 56 | , infohash = idInfoHash dict |
54 | , assembler = undefined | 57 | , bitfield = BF.haveNone (totalPieces store) |
55 | , storage = undefined | 58 | , assembler = error "newSession" |
56 | , unchoked = undefined | 59 | , storage = store |
57 | , connections = undefined | 60 | , unchoked = [] |
61 | , connections = connVar | ||
58 | } | 62 | } |
59 | 63 | ||
60 | closeSession :: Session -> IO () | 64 | closeSession :: Session -> IO () |
61 | closeSession = undefined | 65 | closeSession = undefined |
62 | 66 | ||
63 | insert :: PeerAddr IP -> {- Maybe Socket -> -} Session -> IO () | 67 | insert :: PeerAddr IP |
68 | -> {- Maybe Socket | ||
69 | -> -} Session -> IO () | ||
64 | insert addr ses @ Session {..} = do | 70 | insert addr ses @ Session {..} = do |
65 | undefined | 71 | forkIO $ do |
66 | -- forkIO $ connectWire hs addr caps (runStateT ses handler) | 72 | let caps = def |
73 | let ecaps = def | ||
74 | let hs = Handshake def caps infohash tpeerId | ||
75 | connectWire ses hs addr ecaps $ do | ||
76 | conn <- getConnection | ||
77 | -- liftIO $ modifyMVar_ connections $ pure . M.insert addr conn | ||
78 | exchange | ||
79 | -- liftIO $ modifyMVar_ connections $ pure . M.delete addr | ||
80 | return () | ||
67 | 81 | ||
68 | delete :: PeerAddr IP -> Session -> IO () | 82 | delete :: PeerAddr IP -> Session -> IO () |
69 | delete = undefined | 83 | delete = undefined |
@@ -74,6 +88,44 @@ deleteAll = undefined | |||
74 | {----------------------------------------------------------------------- | 88 | {----------------------------------------------------------------------- |
75 | -- Event loop | 89 | -- Event loop |
76 | -----------------------------------------------------------------------} | 90 | -----------------------------------------------------------------------} |
91 | {- | ||
92 | data ExchangeError | ||
93 | = InvalidRequest BlockIx StorageFailure | ||
94 | | CorruptedPiece PieceIx | ||
95 | |||
96 | packException :: Exception e => (e -> ExchangeError) -> IO a -> IO a | ||
97 | packException f m = try >>= either (throwIO . f) m | ||
98 | |||
99 | readBlock :: BlockIx -> Storage -> IO (Block ByteString) | ||
100 | readBlock bix @ BlockIx {..} s = do | ||
101 | p <- packException (InvalidRequest bix) $ do readPiece ixPiece storage | ||
102 | let chunk = BS.take ixLength $ BS.drop ixOffset p | ||
103 | if BS.length chunk == ixLength | ||
104 | then return chunk | ||
105 | else throwIO $ InvalidRequest bix (InvalidSize ixLength) | ||
106 | -} | ||
107 | handleMessage :: Message -> Wire Session () | ||
108 | handleMessage KeepAlive = return () | ||
109 | handleMessage (Status s) = undefined | ||
110 | handleMessage (Available a) = undefined | ||
111 | handleMessage (Transfer msg) = case msg of | ||
112 | Request bix -> do | ||
113 | -- Session {..} <- getSession | ||
114 | -- addr <- getRemoteAddr | ||
115 | -- when (addr `elem` unchoked && ixPiece bix `BF.member` bitfield) $ do | ||
116 | -- blk <- liftIO $ readBlock bix storage | ||
117 | -- sendMsg (Piece blk) | ||
118 | return () | ||
119 | Piece blk -> return () | ||
120 | Cancel bix -> return () | ||
121 | handleMessage (Port n) = undefined | ||
122 | handleMessage (Fast _) = return () | ||
123 | handleMessage (Extended _) = return () | ||
124 | |||
125 | exchange :: Wire Session () | ||
126 | exchange = do | ||
127 | e <- recvMessage | ||
128 | liftIO $ print e | ||
77 | 129 | ||
78 | type Exchange = StateT Session (ReaderT (Connection Session) IO) | 130 | type Exchange = StateT Session (ReaderT (Connection Session) IO) |
79 | 131 | ||