summaryrefslogtreecommitdiff
path: root/src/Network
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-02-12 19:00:33 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-02-12 19:00:33 +0400
commit920dd0a8eb40ec65f794fd6480835a14066d8a99 (patch)
tree810e824d3ecd65bbc745cd94386bd9ce08a5e2b7 /src/Network
parent59b812124590dc4d4d11b51dff4073b495231363 (diff)
Initialize exchange session fields
Diffstat (limited to 'src/Network')
-rw-r--r--src/Network/BitTorrent/Client/Handle.hs8
-rw-r--r--src/Network/BitTorrent/Exchange/Session.hs92
2 files changed, 77 insertions, 23 deletions
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.
74openTorrent :: Torrent -> BitTorrent Handle 74openTorrent :: FilePath -> Torrent -> BitTorrent Handle
75openTorrent t @ Torrent {..} = do 75openTorrent 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 ()
91closeHandle h @ Handle {..} = do 92closeHandle 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
11import Control.Applicative
11import Control.Concurrent 12import Control.Concurrent
12import Control.Exception 13import Control.Exception
13import Control.Lens 14import Control.Lens
@@ -15,12 +16,14 @@ import Control.Monad.Reader
15import Control.Monad.State 16import Control.Monad.State
16import Data.Function 17import Data.Function
17import Data.IORef 18import Data.IORef
18import Data.Map 19import Data.Maybe
20import Data.Map as M
19import Data.Ord 21import Data.Ord
20import Data.Typeable 22import Data.Typeable
21import Text.PrettyPrint 23import Text.PrettyPrint
22 24
23import Data.Torrent.Bitfield 25import Data.Torrent (InfoDict (..))
26import Data.Torrent.Bitfield as BF
24import Data.Torrent.InfoHash 27import Data.Torrent.InfoHash
25import Network.BitTorrent.Core 28import Network.BitTorrent.Core
26import Network.BitTorrent.Exchange.Assembler 29import Network.BitTorrent.Exchange.Assembler
@@ -31,13 +34,9 @@ import Network.BitTorrent.Exchange.Wire
31import System.Torrent.Storage 34import System.Torrent.Storage
32 35
33 36
34data ExchangeError
35 = InvalidPieceIx PieceIx
36 | InvalidBlock BlockIx
37 | CorruptedPiece PieceIx
38
39data Session = Session 37data 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 47newSession :: PeerAddr (Maybe IP) -- ^ /external/ address of this peer;
49newSession :: PeerAddr IP -> Storage -> Bitfield -> IO Session 48 -> FilePath -- ^ root directory for content files;
50newSession addr st bf = do 49 -> InfoDict -- ^ torrent info dictionary;
50 -> IO Session -- ^
51newSession 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
60closeSession :: Session -> IO () 64closeSession :: Session -> IO ()
61closeSession = undefined 65closeSession = undefined
62 66
63insert :: PeerAddr IP -> {- Maybe Socket -> -} Session -> IO () 67insert :: PeerAddr IP
68 -> {- Maybe Socket
69 -> -} Session -> IO ()
64insert addr ses @ Session {..} = do 70insert 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
68delete :: PeerAddr IP -> Session -> IO () 82delete :: PeerAddr IP -> Session -> IO ()
69delete = undefined 83delete = undefined
@@ -74,6 +88,44 @@ deleteAll = undefined
74{----------------------------------------------------------------------- 88{-----------------------------------------------------------------------
75-- Event loop 89-- Event loop
76-----------------------------------------------------------------------} 90-----------------------------------------------------------------------}
91{-
92data ExchangeError
93 = InvalidRequest BlockIx StorageFailure
94 | CorruptedPiece PieceIx
95
96packException :: Exception e => (e -> ExchangeError) -> IO a -> IO a
97packException f m = try >>= either (throwIO . f) m
98
99readBlock :: BlockIx -> Storage -> IO (Block ByteString)
100readBlock 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-}
107handleMessage :: Message -> Wire Session ()
108handleMessage KeepAlive = return ()
109handleMessage (Status s) = undefined
110handleMessage (Available a) = undefined
111handleMessage (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 ()
121handleMessage (Port n) = undefined
122handleMessage (Fast _) = return ()
123handleMessage (Extended _) = return ()
124
125exchange :: Wire Session ()
126exchange = do
127 e <- recvMessage
128 liftIO $ print e
77 129
78type Exchange = StateT Session (ReaderT (Connection Session) IO) 130type Exchange = StateT Session (ReaderT (Connection Session) IO)
79 131