summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2013-12-28 12:19:59 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2013-12-28 12:19:59 +0400
commit75880c7cdd6ec3eac89a04f5c473dfd4efbff012 (patch)
treeef583c032316c67036c551e2d167daf49da164e6
parent143f73d83852aa1c676b9bc09d1b624e526ba294 (diff)
Add logging to DHT
-rw-r--r--bittorrent.cabal4
-rw-r--r--src/Network/BitTorrent/DHT.hs15
-rw-r--r--src/Network/BitTorrent/DHT/Session.hs48
3 files changed, 56 insertions, 11 deletions
diff --git a/bittorrent.cabal b/bittorrent.cabal
index 9bc91647..5b06f0a7 100644
--- a/bittorrent.cabal
+++ b/bittorrent.cabal
@@ -108,6 +108,10 @@ library
108 , network-conduit >= 1.0 108 , network-conduit >= 1.0
109 , cereal-conduit >= 0.5 109 , cereal-conduit >= 0.5
110 110
111 -- * Logging
112 , fast-logger >= 2.0
113 , monad-logger >= 0.3.4
114
111 -- Data & Data structures 115 -- Data & Data structures
112 , bytestring >= 0.10 116 , bytestring >= 0.10
113 , containers >= 0.5 117 , containers >= 0.5
diff --git a/src/Network/BitTorrent/DHT.hs b/src/Network/BitTorrent/DHT.hs
index bdb76c76..7cc7e803 100644
--- a/src/Network/BitTorrent/DHT.hs
+++ b/src/Network/BitTorrent/DHT.hs
@@ -1,3 +1,5 @@
1{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE TemplateHaskell #-}
1module Network.BitTorrent.DHT 3module Network.BitTorrent.DHT
2 ( dht 4 ( dht
3 , ping 5 , ping
@@ -8,9 +10,13 @@ module Network.BitTorrent.DHT
8 10
9import Control.Applicative 11import Control.Applicative
10import Control.Monad 12import Control.Monad
11import Control.Monad.Reader 13import Control.Monad.Logger
12import Data.List as L 14import Data.List as L
15import Data.Monoid
16import Data.Text as T
13import Network.Socket (PortNumber) 17import Network.Socket (PortNumber)
18import Text.PrettyPrint as PP hiding ((<>))
19import Text.PrettyPrint.Class
14 20
15import Data.Torrent.InfoHash 21import Data.Torrent.InfoHash
16import Network.BitTorrent.Core 22import Network.BitTorrent.Core
@@ -59,11 +65,16 @@ ping addr = do
59 65
60-- | One good node may be sufficient. <note about 'Data.Torrent.tNodes'> 66-- | One good node may be sufficient. <note about 'Data.Torrent.tNodes'>
61bootstrap :: Address ip => [NodeAddr ip] -> DHT ip () 67bootstrap :: Address ip => [NodeAddr ip] -> DHT ip ()
62bootstrap = mapM_ insertClosest 68bootstrap startNodes = do
69 $(logInfoS) "bootstrap" "Start node bootstrapping"
70 mapM_ insertClosest startNodes
71 $(logInfoS) "bootstrap" "Node bootstrapping finished"
63 where 72 where
64 insertClosest addr = do 73 insertClosest addr = do
65 nid <- getNodeId 74 nid <- getNodeId
66 NodeFound closest <- FindNode nid <@> addr 75 NodeFound closest <- FindNode nid <@> addr
76 $(logDebug) ("Get a list of closest nodes: " <>
77 T.pack (PP.render (pretty closest)))
67 forM_ closest insertNode 78 forM_ closest insertNode
68 79
69-- | Get list of peers which downloading 80-- | Get list of peers which downloading
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
10module Network.BitTorrent.DHT.Session 9module Network.BitTorrent.DHT.Session
11 ( -- * Session 10 ( -- * Session
12 DHT 11 DHT
@@ -35,19 +34,27 @@ module Network.BitTorrent.DHT.Session
35import Control.Applicative 34import Control.Applicative
36import Control.Concurrent.STM 35import Control.Concurrent.STM
37import Control.Exception hiding (Handler) 36import Control.Exception hiding (Handler)
38import Control.Monad.Reader
39import Control.Monad.Base 37import Control.Monad.Base
38import Control.Monad.Logger
39import Control.Monad.Reader
40import Control.Monad.Trans.Control 40import Control.Monad.Trans.Control
41import Control.Monad.Trans.Resource 41import Control.Monad.Trans.Resource
42import Data.Default 42import Data.Default
43import Data.Hashable 43import Data.Hashable
44import Data.List as L 44import Data.List as L
45import Data.Monoid
46import Data.Text as T
47import Data.Text.Encoding as T
45import Data.Time 48import Data.Time
46import Data.Time.Clock.POSIX 49import Data.Time.Clock.POSIX
50import System.Log.FastLogger
47import System.Random (randomIO) 51import System.Random (randomIO)
52import Text.PrettyPrint as PP hiding ((<>))
53import Text.PrettyPrint.Class
48 54
49import Data.Torrent.InfoHash 55import Data.Torrent.InfoHash
50import Network.KRPC 56import Network.KRPC
57import Network.KRPC.Method
51import Network.BitTorrent.Core 58import Network.BitTorrent.Core
52import Network.BitTorrent.Core.PeerAddr as P 59import Network.BitTorrent.Core.PeerAddr as P
53import Network.BitTorrent.DHT.Message 60import 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
94newtype DHT ip a = DHT { unDHT :: ReaderT (Node ip) (ResourceT IO) a } 102newtype 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
99instance MonadBaseControl IO (DHT ip) where 108instance 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
110instance MonadKRPC (DHT ip) (DHT ip) where 119instance MonadKRPC (DHT ip) (DHT ip) where
111 getManager = asks manager 120 getManager = asks manager
112 121
122instance MonadLogger (DHT ip) where
123 monadLoggerLog loc src lvl msg = do
124 logger <- asks loggerFun
125 liftIO $ logger loc src lvl (toLogStr msg)
126
113runDHT :: forall ip a. Address ip 127runDHT :: 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.
118runDHT naddr handlers action = runResourceT $ do 132runDHT 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
136ping :: Address ip => NodeAddr ip -> DHT ip Bool 152ping :: Address ip => NodeAddr ip -> DHT ip Bool
137ping addr = do 153ping 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
142refreshNodes :: Address ip => NodeId -> DHT ip [NodeInfo ip] 159refreshNodes :: Address ip => NodeId -> DHT ip [NodeInfo ip]
143refreshNodes nid = do 160refreshNodes 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
150getTimestamp :: DHT ip Timestamp 168getTimestamp :: DHT ip Timestamp
151getTimestamp = liftIO $ utcTimeToPOSIXSeconds <$> getCurrentTime 169getTimestamp = 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
236q <@> addr = do 260q <@> 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