summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Exchange/Session.hs
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2014-02-24 14:21:10 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2014-02-24 14:21:10 +0400
commitbe9c82cd6d3351d02e5f944f041837709d97fa39 (patch)
treea77798caf6bce0e232a2e044050d952469ef46aa /src/Network/BitTorrent/Exchange/Session.hs
parent42eaee8dbcd1cfb922d94e974043d8d564dbd353 (diff)
Implement acceptWire function
Diffstat (limited to 'src/Network/BitTorrent/Exchange/Session.hs')
-rw-r--r--src/Network/BitTorrent/Exchange/Session.hs111
1 files changed, 83 insertions, 28 deletions
diff --git a/src/Network/BitTorrent/Exchange/Session.hs b/src/Network/BitTorrent/Exchange/Session.hs
index 88554807..1537efe1 100644
--- a/src/Network/BitTorrent/Exchange/Session.hs
+++ b/src/Network/BitTorrent/Exchange/Session.hs
@@ -7,11 +7,16 @@ module Network.BitTorrent.Exchange.Session
7 , newSession 7 , newSession
8 , closeSession 8 , closeSession
9 9
10 -- * Connections
10 , Network.BitTorrent.Exchange.Session.insert 11 , Network.BitTorrent.Exchange.Session.insert
12 , Network.BitTorrent.Exchange.Session.attach
13 , Network.BitTorrent.Exchange.Session.delete
14 , Network.BitTorrent.Exchange.Session.deleteAll
11 ) where 15 ) where
12 16
13import Control.Applicative 17import Control.Applicative
14import Control.Concurrent 18import Control.Concurrent
19import Control.Concurrent.STM
15import Control.Exception hiding (Handler) 20import Control.Exception hiding (Handler)
16import Control.Lens 21import Control.Lens
17import Control.Monad.Logger 22import Control.Monad.Logger
@@ -23,6 +28,7 @@ import Data.Conduit.List as CL (iterM)
23import Data.Maybe 28import Data.Maybe
24import Data.Map as M 29import Data.Map as M
25import Data.Monoid 30import Data.Monoid
31import Data.Set as S
26import Data.Text as T 32import Data.Text as T
27import Data.Typeable 33import Data.Typeable
28import Text.PrettyPrint hiding ((<>)) 34import Text.PrettyPrint hiding ((<>))
@@ -70,11 +76,6 @@ data Cached a = Cached
70cache :: BEncode a => a -> Cached a 76cache :: BEncode a => a -> Cached a
71cache s = Cached s (BE.encode s) 77cache s = Cached s (BE.encode s)
72 78
73data ConnectionEntry = ConnectionEntry
74 { initiatedBy :: !ChannelSide
75 , connection :: !(Connection Session)
76 }
77
78data Session = Session 79data Session = Session
79 { tpeerId :: PeerId 80 { tpeerId :: PeerId
80 , infohash :: InfoHash 81 , infohash :: InfoHash
@@ -82,12 +83,15 @@ data Session = Session
82 , storage :: Storage 83 , storage :: Storage
83 , status :: MVar SessionStatus 84 , status :: MVar SessionStatus
84 , unchoked :: [PeerAddr IP] 85 , unchoked :: [PeerAddr IP]
85 , connections :: MVar (Map (PeerAddr IP) ConnectionEntry) 86 , pendingConnections :: TVar (Set (PeerAddr IP))
87 , establishedConnections :: TVar (Map (PeerAddr IP) (Connection Session))
86 , broadcast :: Chan Message 88 , broadcast :: Chan Message
87 , logger :: LogFun 89 , logger :: LogFun
88 , infodict :: MVar (Cached InfoDict) 90 , infodict :: MVar (Cached InfoDict)
89 } 91 }
90 92
93instance Ord IP
94
91-- | Logger function. 95-- | Logger function.
92type LogFun = Loc -> LogSource -> LogLevel -> LogStr -> IO () 96type LogFun = Loc -> LogSource -> LogLevel -> LogStr -> IO ()
93 97
@@ -97,18 +101,21 @@ newSession :: LogFun
97 -> InfoDict -- ^ torrent info dictionary; 101 -> InfoDict -- ^ torrent info dictionary;
98 -> IO Session -- ^ 102 -> IO Session -- ^
99newSession logFun addr rootPath dict = do 103newSession logFun addr rootPath dict = do
100 connVar <- newMVar M.empty 104 pconnVar <- newTVarIO S.empty
105 econnVar <- newTVarIO M.empty
101 store <- openInfoDict ReadWriteEx rootPath dict 106 store <- openInfoDict ReadWriteEx rootPath dict
102 statusVar <- newMVar $ sessionStatus (BF.haveNone (totalPieces store)) 107 statusVar <- newMVar $ sessionStatus (BF.haveNone (totalPieces store))
103 (piPieceLength (idPieceInfo dict)) 108 (piPieceLength (idPieceInfo dict))
104 chan <- newChan 109 chan <- newChan
105 return Session 110 return Session
106 { tpeerId = fromMaybe (error "newSession: impossible") (peerId addr) 111 { tpeerId = fromMaybe (error "newSession: impossible")
107 , infohash = idInfoHash dict 112 (peerId addr)
108 , status = statusVar 113 , infohash = idInfoHash dict
109 , storage = store 114 , status = statusVar
110 , unchoked = [] 115 , storage = store
111 , connections = connVar 116 , unchoked = []
117 , pendingConnections = pconnVar
118 , establishedConnections = econnVar
112 , broadcast = chan 119 , broadcast = chan
113 , logger = logFun 120 , logger = logFun
114 } 121 }
@@ -137,31 +144,79 @@ logEvent :: MonadLogger m => Text -> m ()
137logEvent = logInfoN 144logEvent = logInfoN
138 145
139{----------------------------------------------------------------------- 146{-----------------------------------------------------------------------
147-- Connection slots
148-----------------------------------------------------------------------}
149--- pending -> established -> closed
150--- | /|\
151--- \-------------------------|
152
153pendingConnection :: PeerAddr IP -> Session -> IO Bool
154pendingConnection addr Session {..} = atomically $ do
155 pSet <- readTVar pendingConnections
156 eSet <- readTVar establishedConnections
157 if (addr `S.member` pSet) || (addr `M.member` eSet)
158 then return False
159 else do
160 modifyTVar' pendingConnections (S.insert addr)
161 return True
162
163establishedConnection :: Connected Session ()
164establishedConnection = undefined --atomically $ do
165-- pSet <- readTVar pendingConnections
166-- eSet <- readTVar
167 undefined
168
169finishedConnection :: Connected Session ()
170finishedConnection = return ()
171
172-- | There are no state for this connection, remove it.
173closedConnection :: PeerAddr IP -> Session -> IO ()
174closedConnection addr Session {..} = atomically $ do
175 modifyTVar pendingConnections $ S.delete addr
176 modifyTVar establishedConnections $ M.delete addr
177
178{-----------------------------------------------------------------------
140-- Connections 179-- Connections
141-----------------------------------------------------------------------} 180-----------------------------------------------------------------------}
142-- TODO unmap storage on zero connections 181-- TODO unmap storage on zero connections
143 182
144insert :: PeerAddr IP 183mainWire :: Wire Session ()
145 -> {- Maybe Socket 184mainWire = do
146 -> -} Session -> IO () 185 lift establishedConnection
186 Session {..} <- asks connSession
187 lift $ resizeBitfield (totalPieces storage)
188 logEvent "Connection established"
189 iterM logMessage =$= exchange =$= iterM logMessage
190 lift finishedConnection
191
192getConnectionConfig :: Session -> IO (ConnectionConfig Session)
193getConnectionConfig s @ Session {..} = undefined --ConnectionConfig
194-- let caps = def
195-- let ecaps = def
196-- let hs = Handshake def caps infohash tpeerId
197-- chan <- dupChan broadcast
198
199-- { cfgPrefs = undefined
200-- , cfgSession = ConnectionSession undefined undefined s
201-- , cfgWire = mainWire
202-- }
203
204insert :: PeerAddr IP -> Session -> IO ()
147insert addr ses @ Session {..} = void $ forkIO (action `finally` cleanup) 205insert addr ses @ Session {..} = void $ forkIO (action `finally` cleanup)
148 where 206 where
207 action = do
208 pendingConnection addr ses
209 cfg <- getConnectionConfig ses
210 connectWire addr cfg
211
149 cleanup = do 212 cleanup = do
150 runStatusUpdates status (SS.resetPending addr) 213 runStatusUpdates status (SS.resetPending addr)
151 -- TODO Metata.resetPending addr 214 -- TODO Metata.resetPending addr
215 closedConnection addr ses
152 216
153 action = do 217-- TODO closePending on error
154 let caps = def 218attach :: PendingConnection -> Session -> IO ()
155 let ecaps = def 219attach = undefined
156 let hs = Handshake def caps infohash tpeerId
157 chan <- dupChan broadcast
158 connectWire ses hs addr ecaps chan $ do
159 conn <- ask
160-- liftIO $ modifyMVar_ connections $ pure . M.insert addr conn
161 lift $ resizeBitfield (totalPieces storage)
162 logEvent "Connection established"
163 iterM logMessage =$= exchange =$= iterM logMessage
164-- liftIO $ modifyMVar_ connections $ pure . M.delete addr
165 220
166delete :: PeerAddr IP -> Session -> IO () 221delete :: PeerAddr IP -> Session -> IO ()
167delete = undefined 222delete = undefined