diff options
Diffstat (limited to 'src/Network/BitTorrent/Exchange/Session.hs')
-rw-r--r-- | src/Network/BitTorrent/Exchange/Session.hs | 92 |
1 files changed, 72 insertions, 20 deletions
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 | ||