diff options
Diffstat (limited to 'src/Network/BitTorrent/DHT/Session.hs')
-rw-r--r-- | src/Network/BitTorrent/DHT/Session.hs | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs index 71400609..9243ef49 100644 --- a/src/Network/BitTorrent/DHT/Session.hs +++ b/src/Network/BitTorrent/DHT/Session.hs | |||
@@ -5,8 +5,7 @@ | |||
5 | {-# LANGUAGE MultiParamTypeClasses #-} | 5 | {-# LANGUAGE MultiParamTypeClasses #-} |
6 | {-# LANGUAGE ScopedTypeVariables #-} | 6 | {-# LANGUAGE ScopedTypeVariables #-} |
7 | {-# LANGUAGE TypeFamilies #-} | 7 | {-# LANGUAGE TypeFamilies #-} |
8 | 8 | {-# LANGUAGE TemplateHaskell #-} | |
9 | {-# LANGUAGE RankNTypes #-} -- TODO remove | ||
10 | module Network.BitTorrent.DHT.Session | 9 | module Network.BitTorrent.DHT.Session |
11 | ( -- * Session | 10 | ( -- * Session |
12 | DHT | 11 | DHT |
@@ -35,19 +34,27 @@ module Network.BitTorrent.DHT.Session | |||
35 | import Control.Applicative | 34 | import Control.Applicative |
36 | import Control.Concurrent.STM | 35 | import Control.Concurrent.STM |
37 | import Control.Exception hiding (Handler) | 36 | import Control.Exception hiding (Handler) |
38 | import Control.Monad.Reader | ||
39 | import Control.Monad.Base | 37 | import Control.Monad.Base |
38 | import Control.Monad.Logger | ||
39 | import Control.Monad.Reader | ||
40 | import Control.Monad.Trans.Control | 40 | import Control.Monad.Trans.Control |
41 | import Control.Monad.Trans.Resource | 41 | import Control.Monad.Trans.Resource |
42 | import Data.Default | 42 | import Data.Default |
43 | import Data.Hashable | 43 | import Data.Hashable |
44 | import Data.List as L | 44 | import Data.List as L |
45 | import Data.Monoid | ||
46 | import Data.Text as T | ||
47 | import Data.Text.Encoding as T | ||
45 | import Data.Time | 48 | import Data.Time |
46 | import Data.Time.Clock.POSIX | 49 | import Data.Time.Clock.POSIX |
50 | import System.Log.FastLogger | ||
47 | import System.Random (randomIO) | 51 | import System.Random (randomIO) |
52 | import Text.PrettyPrint as PP hiding ((<>)) | ||
53 | import Text.PrettyPrint.Class | ||
48 | 54 | ||
49 | import Data.Torrent.InfoHash | 55 | import Data.Torrent.InfoHash |
50 | import Network.KRPC | 56 | import Network.KRPC |
57 | import Network.KRPC.Method | ||
51 | import Network.BitTorrent.Core | 58 | import Network.BitTorrent.Core |
52 | import Network.BitTorrent.Core.PeerAddr as P | 59 | import Network.BitTorrent.Core.PeerAddr as P |
53 | import Network.BitTorrent.DHT.Message | 60 | import Network.BitTorrent.DHT.Message |
@@ -89,6 +96,7 @@ data Node ip = Node | |||
89 | , routingTable :: !(TVar (Table ip)) | 96 | , routingTable :: !(TVar (Table ip)) |
90 | , contactInfo :: !(TVar (PeerStore ip)) | 97 | , contactInfo :: !(TVar (PeerStore ip)) |
91 | , sessionTokens :: !(TVar SessionTokens) | 98 | , sessionTokens :: !(TVar SessionTokens) |
99 | , loggerFun :: !(Loc -> LogSource -> LogLevel -> LogStr -> IO ()) | ||
92 | } | 100 | } |
93 | 101 | ||
94 | newtype DHT ip a = DHT { unDHT :: ReaderT (Node ip) (ResourceT IO) a } | 102 | newtype DHT ip a = DHT { unDHT :: ReaderT (Node ip) (ResourceT IO) a } |
@@ -96,6 +104,7 @@ newtype DHT ip a = DHT { unDHT :: ReaderT (Node ip) (ResourceT IO) a } | |||
96 | , MonadIO, MonadBase IO | 104 | , MonadIO, MonadBase IO |
97 | , MonadReader (Node ip) | 105 | , MonadReader (Node ip) |
98 | ) | 106 | ) |
107 | |||
99 | instance MonadBaseControl IO (DHT ip) where | 108 | instance MonadBaseControl IO (DHT ip) where |
100 | newtype StM (DHT ip) a = StM { | 109 | newtype StM (DHT ip) a = StM { |
101 | unSt :: StM (ReaderT (Node ip) (ResourceT IO)) a | 110 | unSt :: StM (ReaderT (Node ip) (ResourceT IO)) a |
@@ -110,19 +119,26 @@ instance MonadBaseControl IO (DHT ip) where | |||
110 | instance MonadKRPC (DHT ip) (DHT ip) where | 119 | instance MonadKRPC (DHT ip) (DHT ip) where |
111 | getManager = asks manager | 120 | getManager = asks manager |
112 | 121 | ||
122 | instance MonadLogger (DHT ip) where | ||
123 | monadLoggerLog loc src lvl msg = do | ||
124 | logger <- asks loggerFun | ||
125 | liftIO $ logger loc src lvl (toLogStr msg) | ||
126 | |||
113 | runDHT :: forall ip a. Address ip | 127 | runDHT :: forall ip a. Address ip |
114 | => NodeAddr ip -- ^ node address to bind; | 128 | => NodeAddr ip -- ^ node address to bind; |
115 | -> [Handler (DHT ip)] -- ^ handlers to run on accepted queries; | 129 | -> [Handler (DHT ip)] -- ^ handlers to run on accepted queries; |
116 | -> DHT ip a -- ^ DHT action to run; | 130 | -> DHT ip a -- ^ DHT action to run; |
117 | -> IO a -- ^ result. | 131 | -> IO a -- ^ result. |
118 | runDHT naddr handlers action = runResourceT $ do | 132 | runDHT naddr handlers action = runResourceT $ do |
119 | (_, m) <- allocate (newManager (toSockAddr naddr) handlers) closeManager | 133 | runStderrLoggingT $ LoggingT $ \ logger -> do |
120 | myId <- liftIO genNodeId | 134 | (_, m) <- allocate (newManager (toSockAddr naddr) handlers) closeManager |
121 | node <- liftIO $ Node m | 135 | myId <- liftIO genNodeId |
136 | node <- liftIO $ Node m | ||
122 | <$> newTVarIO (nullTable myId) | 137 | <$> newTVarIO (nullTable myId) |
123 | <*> newTVarIO def | 138 | <*> newTVarIO def |
124 | <*> (newTVarIO =<< nullSessionTokens) | 139 | <*> (newTVarIO =<< nullSessionTokens) |
125 | runReaderT (unDHT (listen >> action)) node | 140 | <*> pure logger |
141 | runReaderT (unDHT (listen >> action)) node | ||
126 | 142 | ||
127 | {----------------------------------------------------------------------- | 143 | {----------------------------------------------------------------------- |
128 | -- Routing | 144 | -- Routing |
@@ -135,12 +151,14 @@ routing = runRouting ping refreshNodes getTimestamp | |||
135 | -- TODO add timeout | 151 | -- TODO add timeout |
136 | ping :: Address ip => NodeAddr ip -> DHT ip Bool | 152 | ping :: Address ip => NodeAddr ip -> DHT ip Bool |
137 | ping addr = do | 153 | ping addr = do |
154 | $(logDebugS) "routing.questionable_node" (T.pack (render (pretty addr))) | ||
138 | Ping <- Ping <@> addr | 155 | Ping <- Ping <@> addr |
139 | return True | 156 | return True |
140 | 157 | ||
141 | -- FIXME do not use getClosest sinse we should /refresh/ them | 158 | -- FIXME do not use getClosest sinse we should /refresh/ them |
142 | refreshNodes :: Address ip => NodeId -> DHT ip [NodeInfo ip] | 159 | refreshNodes :: Address ip => NodeId -> DHT ip [NodeInfo ip] |
143 | refreshNodes nid = do | 160 | refreshNodes nid = do |
161 | $(logDebugS) "routing.refresh_bucket" (T.pack (render (pretty nid))) | ||
144 | nodes <- getClosest nid | 162 | nodes <- getClosest nid |
145 | nss <- forM (nodeAddr <$> nodes) $ \ addr -> do | 163 | nss <- forM (nodeAddr <$> nodes) $ \ addr -> do |
146 | NodeFound ns <- FindNode nid <@> addr | 164 | NodeFound ns <- FindNode nid <@> addr |
@@ -148,7 +166,10 @@ refreshNodes nid = do | |||
148 | return $ L.concat nss | 166 | return $ L.concat nss |
149 | 167 | ||
150 | getTimestamp :: DHT ip Timestamp | 168 | getTimestamp :: DHT ip Timestamp |
151 | getTimestamp = liftIO $ utcTimeToPOSIXSeconds <$> getCurrentTime | 169 | getTimestamp = do |
170 | timestamp <- liftIO $ getCurrentTime | ||
171 | $(logDebugS) "routing.make_timestamp" (T.pack (render (pretty timestamp))) | ||
172 | return $ utcTimeToPOSIXSeconds timestamp | ||
152 | 173 | ||
153 | {----------------------------------------------------------------------- | 174 | {----------------------------------------------------------------------- |
154 | -- Tokens | 175 | -- Tokens |
@@ -204,6 +225,9 @@ insertNode info = do | |||
204 | t' <- routing (R.insert info t) | 225 | t' <- routing (R.insert info t) |
205 | putTable t' | 226 | putTable t' |
206 | 227 | ||
228 | let logMsg = "Routing table updated: " <> pretty t <> " -> " <> pretty t' | ||
229 | $(logDebugS) "insertNode" (T.pack (render logMsg)) | ||
230 | |||
207 | {----------------------------------------------------------------------- | 231 | {----------------------------------------------------------------------- |
208 | -- Peer storage | 232 | -- Peer storage |
209 | -----------------------------------------------------------------------} | 233 | -----------------------------------------------------------------------} |
@@ -231,11 +255,17 @@ getPeerList ih = do | |||
231 | -- Messaging | 255 | -- Messaging |
232 | -----------------------------------------------------------------------} | 256 | -----------------------------------------------------------------------} |
233 | 257 | ||
234 | (<@>) :: Address ip => KRPC (Query a) (Response b) | 258 | (<@>) :: forall a b ip. Address ip => KRPC (Query a) (Response b) |
235 | => a -> NodeAddr ip -> DHT ip b | 259 | => a -> NodeAddr ip -> DHT ip b |
236 | q <@> addr = do | 260 | q <@> addr = do |
237 | nid <- getNodeId | 261 | nid <- getNodeId |
262 | |||
263 | let Method name = method :: Method (Query a) (Response b) | ||
264 | let signature = T.decodeUtf8 name <> " @ " <> T.pack (render (pretty addr)) | ||
265 | $(logDebugS) "queryNode" $ "Query sent | " <> signature | ||
238 | Response remoteId r <- query (toSockAddr addr) (Query nid q) | 266 | Response remoteId r <- query (toSockAddr addr) (Query nid q) |
267 | $(logDebugS) "queryNode" $ "Query recv | " <> signature | ||
268 | |||
239 | insertNode (NodeInfo remoteId addr) | 269 | insertNode (NodeInfo remoteId addr) |
240 | return r | 270 | return r |
241 | 271 | ||