summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/DHT/Query.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/DHT/Query.hs')
-rw-r--r--src/Network/BitTorrent/DHT/Query.hs73
1 files changed, 39 insertions, 34 deletions
diff --git a/src/Network/BitTorrent/DHT/Query.hs b/src/Network/BitTorrent/DHT/Query.hs
index 68c67900..254b347c 100644
--- a/src/Network/BitTorrent/DHT/Query.hs
+++ b/src/Network/BitTorrent/DHT/Query.hs
@@ -80,6 +80,7 @@ import Text.PrettyPrint as PP hiding ((<>), ($$))
80import Text.PrettyPrint.HughesPJClass hiding ((<>),($$)) 80import Text.PrettyPrint.HughesPJClass hiding ((<>),($$))
81import Data.Time 81import Data.Time
82import Data.Time.Clock.POSIX 82import Data.Time.Clock.POSIX
83import Data.Hashable (Hashable)
83 84
84import Network.DatagramServer as KRPC hiding (Options, def) 85import Network.DatagramServer as KRPC hiding (Options, def)
85import Network.KRPC.Method as KRPC 86import Network.KRPC.Method as KRPC
@@ -109,13 +110,9 @@ import Control.Monad.Trans.Control
109 110
110nodeHandler :: ( Address ip 111nodeHandler :: ( Address ip
111 , KRPC (Query a) (Response b) 112 , KRPC (Query a) (Response b)
112#ifdef VERSION_bencoding 113 )
113 , KRPC.Envelope (Query a) (Response b) ~ BValue ) 114 => (NodeInfo KMessageOf ip () -> Maybe ReflectedIP -> IO ()) -> (NodeAddr ip -> IO (NodeId KMessageOf)) -> (Char -> String -> Text -> IO ()) -> QueryMethod KMessageOf -> (NodeAddr ip -> a -> IO b) -> NodeHandler
114#else 115nodeHandler insertNode myNodeIdAccordingTo logm method action = handler method $ \ sockAddr qry -> do
115 , KPRC.Envelope (Query a) (Response b) ~ ByteString )
116#endif
117 => QueryMethod KMessageOf -> (NodeAddr ip -> a -> DHT ip b) -> NodeHandler ip
118nodeHandler method action = handler method $ \ sockAddr qry -> do
119#ifdef VERSION_bencoding 116#ifdef VERSION_bencoding
120 let remoteId = queringNodeId qry 117 let remoteId = queringNodeId qry
121 read_only = queryIsReadOnly qry 118 read_only = queryIsReadOnly qry
@@ -131,53 +128,55 @@ nodeHandler method action = handler method $ \ sockAddr qry -> do
131 let ni = NodeInfo remoteId naddr () 128 let ni = NodeInfo remoteId naddr ()
132 -- Do not route read-only nodes. (bep 43) 129 -- Do not route read-only nodes. (bep 43)
133 if read_only 130 if read_only
134 then $(logWarnS) "nodeHandler" $ "READ-ONLY " <> T.pack (show $ pPrint ni) 131 then logm 'W' "nodeHandler" $ "READ-ONLY " <> T.pack (show $ pPrint ni)
135 else insertNode ni Nothing >> return () -- TODO need to block. why? 132 else insertNode ni Nothing >> return () -- TODO need to block. why?
136 Response 133 Response
137 <$> myNodeIdAccordingTo naddr 134 <$> myNodeIdAccordingTo naddr
138 <*> action naddr q 135 <*> action naddr q
139 136
140-- | Default 'Ping' handler. 137-- | Default 'Ping' handler.
141pingH :: Address ip => NodeHandler ip 138pingH :: NodeAddr ip -> Ping -> IO Ping
142#ifdef VERSION_bencoding 139pingH _ Ping = return Ping
143pingH = nodeHandler "ping" $ \ _ Ping -> return Ping 140-- pingH = nodeHandler $ \ _ p@PingPayload{} -> return p { isPong = True }
144#else
145pingH = nodeHandler $ \ _ p@PingPayload{} -> return p { isPong = True }
146#endif
147 141
148-- | Default 'FindNode' handler. 142-- | Default 'FindNode' handler.
149findNodeH :: Address ip => NodeHandler ip 143findNodeH :: (NodeId KMessageOf -> IO [NodeInfo KMessageOf ip ()]) -> NodeAddr ip -> FindNode ip -> IO (NodeFound ip)
150findNodeH = nodeHandler "find-nodes" $ \ _ (FindNode nid) -> do 144findNodeH getclosest _ (FindNode nid) = NodeFound <$> getclosest nid
151 NodeFound <$> getClosest nid
152 145
153#ifdef VERSION_bencoding
154-- | Default 'GetPeers' handler. 146-- | Default 'GetPeers' handler.
155getPeersH :: Ord ip => Address ip => NodeHandler ip 147getPeersH :: Hashable ip => (InfoHash -> IO (PeerList ip)) -> TVar SessionTokens -> NodeAddr ip -> GetPeers ip -> IO (GotPeers ip)
156getPeersH = nodeHandler "get_peers" $ \ naddr (GetPeers ih) -> do 148getPeersH getPeerList toks naddr (GetPeers ih) = do
157 ps <- getPeerList ih 149 ps <- getPeerList ih
158 tok <- grantToken naddr 150 tok <- grantToken toks naddr
159 return $ GotPeers ps tok 151 return $ GotPeers ps tok
160 152
161-- | Default 'Announce' handler. 153-- | Default 'Announce' handler.
162announceH :: Ord ip => Address ip => NodeHandler ip 154announceH :: ( Ord ip, Hashable ip ) => TVar (PeerStore ip) -> TVar SessionTokens -> NodeAddr ip -> Announce -> IO Announced
163announceH = nodeHandler "announce_peer" $ \ naddr @ NodeAddr {..} (Announce {..}) -> do 155announceH peers toks naddr @ NodeAddr {..} (Announce {..}) = do
164 valid <- checkToken naddr sessionToken 156 valid <- checkToken toks naddr sessionToken
165 unless valid $ do 157 unless valid $ do
166 throwIO $ InvalidParameter "token" 158 throwIO $ InvalidParameter "token"
167 159
168 let annPort = if impliedPort then nodePort else port 160 let annPort = if impliedPort then nodePort else port
169 peerAddr = PeerAddr Nothing nodeHost annPort 161 peerAddr = PeerAddr Nothing nodeHost annPort
170 insertPeer topic announcedName peerAddr 162 insertPeer peers topic announcedName peerAddr
171 return Announced 163 return Announced
172 164
173-- | Includes all default query handlers. 165-- | Includes all default query handlers.
174defaultHandlers :: Ord ip => Address ip => [NodeHandler ip] 166defaultHandlers :: forall ip. (Eq ip, Ord ip, Address ip) => LogFun -> DHT ip [NodeHandler]
175defaultHandlers = [pingH, findNodeH, getPeersH, announceH] 167defaultHandlers logger = do
176#else 168 groknode <- insertNode1
177-- | Includes all default query handlers. 169 toks <- asks sessionTokens
178defaultHandlers :: Ord ip => Address ip => [NodeHandler ip] 170 getclosest <- getClosest1
179defaultHandlers = [pingH, findNodeH] 171 mynid <- myNodeIdAccordingTo1
180#endif 172 peers <- asks contactInfo
173 getpeers <- getPeerList1
174 let handler :: KRPC (Query a) (Response b) => QueryMethod KMessageOf -> (NodeAddr ip -> a -> IO b) -> NodeHandler
175 handler = nodeHandler groknode mynid (logt logger)
176 return [ handler "ping" $ pingH
177 , handler "find-nodes" $ findNodeH getclosest
178 , handler "get_peers" $ getPeersH getpeers toks
179 , handler "announce_peer" $ announceH peers toks ]
181 180
182{----------------------------------------------------------------------- 181{-----------------------------------------------------------------------
183-- Basic queries 182-- Basic queries
@@ -324,6 +323,11 @@ logc c = $(logInfoS) "insertNode" . T.pack . (c :) . (':' :)
324-- routing table. 323-- routing table.
325insertNode :: forall ip. Address ip => NodeInfo KMessageOf ip () -> Maybe ReflectedIP -> DHT ip () 324insertNode :: forall ip. Address ip => NodeInfo KMessageOf ip () -> Maybe ReflectedIP -> DHT ip ()
326insertNode info witnessed_ip0 = do 325insertNode info witnessed_ip0 = do
326 f <- insertNode1
327 liftIO $ f info witnessed_ip0
328
329insertNode1 :: forall ip. Address ip => DHT ip (NodeInfo KMessageOf ip () -> Maybe ReflectedIP -> IO ())
330insertNode1 = do
327 bc <- optBucketCount <$> asks options 331 bc <- optBucketCount <$> asks options
328 nid <- asks tentativeNodeId 332 nid <- asks tentativeNodeId
329 logm0 <- embed_ (uncurry logc) 333 logm0 <- embed_ (uncurry logc)
@@ -349,7 +353,7 @@ insertNode info witnessed_ip0 = do
349 , grokNode = DHT.insertNode params state 353 , grokNode = DHT.insertNode params state
350 , grokAddress = \_ _ -> return () -- :: Maybe SockAddr -> ReflectedIP -> IO () 354 , grokAddress = \_ _ -> return () -- :: Maybe SockAddr -> ReflectedIP -> IO ()
351 } 355 }
352 liftIO $ DHT.insertNode params state info witnessed_ip0 356 return $ \info witnessed_ip0 -> DHT.insertNode params state info witnessed_ip0
353 357
354-- | Throws exception if node is not responding. 358-- | Throws exception if node is not responding.
355queryNode :: forall a b ip. Address ip => KRPC (Query a) (Response b) 359queryNode :: forall a b ip. Address ip => KRPC (Query a) (Response b)
@@ -362,7 +366,8 @@ queryNode' addr q = do
362 nid <- myNodeIdAccordingTo addr 366 nid <- myNodeIdAccordingTo addr
363 let read_only = False -- TODO: check for NAT issues. (BEP 43) 367 let read_only = False -- TODO: check for NAT issues. (BEP 43)
364 let KRPC.Method name = KRPC.method :: KRPC.Method (Query a) (Response b) 368 let KRPC.Method name = KRPC.method :: KRPC.Method (Query a) (Response b)
365 (Response remoteId r, witnessed_ip) <- query' name (toSockAddr addr) (Query nid read_only q) 369 mgr <- asks manager
370 (Response remoteId r, witnessed_ip) <- liftIO $ query' mgr name (toSockAddr addr) (Query nid read_only q)
366 -- \$(logDebugS) "queryNode" $ "Witnessed address: " <> T.pack (show witnessed_ip) 371 -- \$(logDebugS) "queryNode" $ "Witnessed address: " <> T.pack (show witnessed_ip)
367 -- <> " by " <> T.pack (show (toSockAddr addr)) 372 -- <> " by " <> T.pack (show (toSockAddr addr))
368 _ <- insertNode (NodeInfo remoteId addr ()) witnessed_ip 373 _ <- insertNode (NodeInfo remoteId addr ()) witnessed_ip