summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Network/BitTorrent/DHT/Query.hs43
-rw-r--r--src/Network/DHT/Mainline.hs8
-rw-r--r--src/Network/DHT/Types.hs11
-rw-r--r--src/Network/DatagramServer.hs18
-rw-r--r--src/Network/DatagramServer/Mainline.hs11
-rw-r--r--src/Network/DatagramServer/Types.hs5
-rw-r--r--src/Network/KRPC/Method.hs3
7 files changed, 64 insertions, 35 deletions
diff --git a/src/Network/BitTorrent/DHT/Query.hs b/src/Network/BitTorrent/DHT/Query.hs
index 4c980e22..87081d38 100644
--- a/src/Network/BitTorrent/DHT/Query.hs
+++ b/src/Network/BitTorrent/DHT/Query.hs
@@ -127,32 +127,37 @@ nodeHandler :: ( Address ip
127 ) 127 )
128 => (NodeInfo KMessageOf ip () -> Maybe ReflectedIP -> IO ()) -> (NodeAddr ip -> IO (NodeId KMessageOf)) -> (Char -> String -> Text -> IO ()) -> QueryMethod KMessageOf -> (NodeAddr ip -> a -> IO b) -> NodeHandler 128 => (NodeInfo KMessageOf ip () -> Maybe ReflectedIP -> IO ()) -> (NodeAddr ip -> IO (NodeId KMessageOf)) -> (Char -> String -> Text -> IO ()) -> QueryMethod KMessageOf -> (NodeAddr ip -> a -> IO b) -> NodeHandler
129-} 129-}
130nodeHandler :: 130nodeHandler :: forall raw dht addr u t q r.
131 (Address addr, WireFormat raw msg, Pretty (NodeInfo dht addr u), 131 (Address addr, WireFormat raw dht, Pretty (NodeInfo dht addr u),
132 Default u, 132 Default u,
133 IsString t, Functor msg, 133 IsString t, Functor dht,
134 KRPC dht (Query dht q) (Response dht r),
134 SerializableTo raw (Response dht r), 135 SerializableTo raw (Response dht r),
135 SerializableTo raw (Query dht q)) => 136 SerializableTo raw (Query dht q)) =>
136 (NodeInfo dht addr u -> Maybe ReflectedIP -> IO ()) 137 (NodeInfo dht addr u -> Maybe ReflectedIP -> IO ())
137 -> (NodeAddr addr -> IO (NodeId dht)) 138 -> (NodeAddr addr -> IO (NodeId dht))
138 -> (Char -> t -> Text -> IO ()) 139 -> (Char -> t -> Text -> IO ())
139 -> QueryMethod msg 140 -> DHTData dht addr
141 -> QueryMethod dht
140 -> (NodeAddr addr -> q -> IO r) 142 -> (NodeAddr addr -> q -> IO r)
141 -> Handler IO msg raw 143 -> Handler IO dht raw
142nodeHandler insertNode myNodeIdAccordingTo logm method action = handler method $ \ sockAddr qry -> do 144nodeHandler insertNode myNodeIdAccordingTo logm dta method action = handler method $ \ sockAddr qry -> do
143 let remoteId = queringNodeId qry 145 let remoteId = queringNodeId qry
144 read_only = queryIsReadOnly qry 146 qextra = queryExtra qry
145 q = queryParams qry 147 resptype = Proxy :: Proxy (Response dht r)
148 q = queryParams qry
146 case fromSockAddr sockAddr of 149 case fromSockAddr sockAddr of
147 Nothing -> throwIO BadAddress 150 Nothing -> throwIO BadAddress
148 Just naddr -> do 151 Just naddr -> do
152 rextra <- liftIO $ makeResponseExtra dta qry resptype
149 let ni = NodeInfo remoteId naddr def 153 let ni = NodeInfo remoteId naddr def
150 -- Do not route read-only nodes. (bep 43) 154 -- Do not route read-only nodes. (bep 43)
151 if read_only 155 if fromRoutableNode qextra
152 then logm 'W' "nodeHandler" $ "READ-ONLY " <> T.pack (show $ pPrint ni) 156 then insertNode ni Nothing >> return () -- TODO need to block. why?
153 else insertNode ni Nothing >> return () -- TODO need to block. why? 157 else logm 'W' "nodeHandler" $ "READ-ONLY " <> T.pack (show $ pPrint ni)
154 Response 158 Response
155 <$> myNodeIdAccordingTo naddr 159 <$> myNodeIdAccordingTo naddr
160 <*> pure rextra
156 <*> action naddr q 161 <*> action naddr q
157 162
158-- | Default 'Ping' handler. 163-- | Default 'Ping' handler.
@@ -208,11 +213,12 @@ kademliaHandlers :: forall raw dht u ip. (Eq ip, Ord ip, Address ip
208kademliaHandlers logger = do 213kademliaHandlers logger = do
209 groknode <- insertNode1 214 groknode <- insertNode1
210 mynid <- myNodeIdAccordingTo1 215 mynid <- myNodeIdAccordingTo1
216 dta <- asks dhtData
211 let handler :: ( KRPC dht (Query dht a) (Response dht b) 217 let handler :: ( KRPC dht (Query dht a) (Response dht b)
212 , SerializableTo raw (Response dht b) 218 , SerializableTo raw (Response dht b)
213 , SerializableTo raw (Query dht a) 219 , SerializableTo raw (Query dht a)
214 ) => QueryMethod dht -> (NodeAddr ip -> a -> IO b) -> Handler IO dht raw 220 ) => QueryMethod dht -> (NodeAddr ip -> a -> IO b) -> Handler IO dht raw
215 handler = nodeHandler groknode mynid (logt logger) 221 handler = nodeHandler groknode mynid (logt logger) dta
216 dht = Proxy :: Proxy dht 222 dht = Proxy :: Proxy dht
217 getclosest <- getClosest1 223 getclosest <- getClosest1
218 return [ handler (namePing dht) $ pingH dht 224 return [ handler (namePing dht) $ pingH dht
@@ -248,6 +254,7 @@ bthandlers getclosest dta =
248data MethodHandler raw dht ip = 254data MethodHandler raw dht ip =
249 forall a b. ( SerializableTo raw (Response dht b) 255 forall a b. ( SerializableTo raw (Response dht b)
250 , SerializableTo raw (Query dht a) 256 , SerializableTo raw (Query dht a)
257 , KRPC dht (Query dht a) (Response dht b)
251 ) => MethodHandler (QueryMethod dht) (NodeAddr ip -> a -> IO b) 258 ) => MethodHandler (QueryMethod dht) (NodeAddr ip -> a -> IO b)
252 259
253-- | Includes all default query handlers. 260-- | Includes all default query handlers.
@@ -275,9 +282,9 @@ defaultHandlers :: forall raw dht u ip.
275defaultHandlers logger = do 282defaultHandlers logger = do
276 groknode <- insertNode1 283 groknode <- insertNode1
277 mynid <- myNodeIdAccordingTo1 284 mynid <- myNodeIdAccordingTo1
278 let handler :: MethodHandler raw dht ip -> Handler IO dht raw
279 handler (MethodHandler name action) = nodeHandler groknode mynid (logt logger) name action
280 dta <- asks dhtData 285 dta <- asks dhtData
286 let handler :: MethodHandler raw dht ip -> Handler IO dht raw
287 handler (MethodHandler name action) = nodeHandler groknode mynid (logt logger) dta name action
281 getclosest <- getClosest1 288 getclosest <- getClosest1
282 hs <- kademliaHandlers logger 289 hs <- kademliaHandlers logger
283 return $ hs ++ L.map handler (dataHandlers (fmap (fmap (fmap (const ()))) . getclosest) dta) 290 return $ hs ++ L.map handler (dataHandlers (fmap (fmap (fmap (const ()))) . getclosest) dta)
@@ -664,10 +671,12 @@ queryNode' :: forall raw dht u a b ip.
664 ) => NodeAddr ip -> a -> DHT raw dht u ip (NodeId dht, b, Maybe ReflectedIP) 671 ) => NodeAddr ip -> a -> DHT raw dht u ip (NodeId dht, b, Maybe ReflectedIP)
665queryNode' addr q = do 672queryNode' addr q = do
666 nid <- myNodeIdAccordingTo addr 673 nid <- myNodeIdAccordingTo addr
674 dta <- asks dhtData
675 qextra <- liftIO $ makeQueryExtra dta (Proxy :: Proxy (Query dht q)) (Proxy :: Proxy (Response dht b))
667 let read_only = False -- TODO: check for NAT issues. (BEP 43) 676 let read_only = False -- TODO: check for NAT issues. (BEP 43)
668 let KRPC.Method name = KRPC.method :: KRPC.Method dht (Query dht a) (Response dht b) 677 -- let KRPC.Method name = KRPC.method :: KRPC.Method dht (Query dht a) (Response dht b)
669 mgr <- asks manager 678 mgr <- asks manager
670 (Response remoteId r, witnessed_ip) <- liftIO $ query' mgr name (toSockAddr addr) (Query nid read_only q) 679 (Response remoteId rextra r , witnessed_ip) <- liftIO $ query' mgr (toSockAddr addr) (Query nid qextra q)
671 -- \$(logDebugS) "queryNode" $ "Witnessed address: " <> T.pack (show witnessed_ip) 680 -- \$(logDebugS) "queryNode" $ "Witnessed address: " <> T.pack (show witnessed_ip)
672 -- <> " by " <> T.pack (show (toSockAddr addr)) 681 -- <> " by " <> T.pack (show (toSockAddr addr))
673 _ <- insertNode (NodeInfo remoteId addr def) witnessed_ip 682 _ <- insertNode (NodeInfo remoteId addr def) witnessed_ip
diff --git a/src/Network/DHT/Mainline.hs b/src/Network/DHT/Mainline.hs
index 6ef6d450..e5517a3a 100644
--- a/src/Network/DHT/Mainline.hs
+++ b/src/Network/DHT/Mainline.hs
@@ -155,7 +155,7 @@ read_only_key = "ro"
155instance BEncode a => BEncode (Query KMessageOf a) where 155instance BEncode a => BEncode (Query KMessageOf a) where
156 toBEncode Query {..} = toDict $ 156 toBEncode Query {..} = toDict $
157 BDict.union ( node_id_key .=! queringNodeId 157 BDict.union ( node_id_key .=! queringNodeId
158 .: read_only_key .=? bool Nothing (Just (1 :: Integer)) queryIsReadOnly 158 .: read_only_key .=? bool Nothing (Just (1 :: Integer)) (queryIsReadOnly queryExtra)
159 .: endDict) 159 .: endDict)
160 (dict (toBEncode queryParams)) 160 (dict (toBEncode queryParams))
161 where 161 where
@@ -164,7 +164,7 @@ instance BEncode a => BEncode (Query KMessageOf a) where
164 164
165 fromBEncode v = do 165 fromBEncode v = do
166 Query <$> fromDict (field (req node_id_key)) v 166 Query <$> fromDict (field (req node_id_key)) v
167 <*> fromDict (fromMaybe False <$>? read_only_key) v 167 <*> fromDict (IsReadOnlyQuery . fromMaybe False <$>? read_only_key) v
168 <*> fromBEncode v 168 <*> fromBEncode v
169#else 169#else
170data Query a = Query a 170data Query a = Query a
@@ -174,11 +174,11 @@ data Query a = Query a
174instance BEncode a => BEncode (Response KMessageOf a) where 174instance BEncode a => BEncode (Response KMessageOf a) where
175 toBEncode = toBEncode . toQuery 175 toBEncode = toBEncode . toQuery
176 where 176 where
177 toQuery (Response nid a) = Query nid False a 177 toQuery (Response nid MainlineResponseData a) = Query nid (IsReadOnlyQuery False) a
178 178
179 fromBEncode b = fromQuery <$> fromBEncode b 179 fromBEncode b = fromQuery <$> fromBEncode b
180 where 180 where
181 fromQuery (Query nid _ a) = Response nid a 181 fromQuery (Query nid _ a) = Response nid MainlineResponseData a
182#else 182#else
183data Response KMessageOf a = Response KMessageOf a 183data Response KMessageOf a = Response KMessageOf a
184#endif 184#endif
diff --git a/src/Network/DHT/Types.hs b/src/Network/DHT/Types.hs
index 73a7be65..bd2825fb 100644
--- a/src/Network/DHT/Types.hs
+++ b/src/Network/DHT/Types.hs
@@ -27,22 +27,23 @@ data TableParameters msg ip u = TableParameters
27-- of the querying node. 27-- of the querying node.
28data Query dht a = Query 28data Query dht a = Query
29 { queringNodeId :: NodeId dht -- ^ node id of /quering/ node; 29 { queringNodeId :: NodeId dht -- ^ node id of /quering/ node;
30 , queryIsReadOnly :: Bool -- ^ node is read-only as per BEP 43 30 , queryExtra :: QueryExtra dht -- , queryIsReadOnly :: Bool -- node is read-only as per BEP 43
31 , queryParams :: a -- ^ query parameters. 31 , queryParams :: a -- ^ query parameters.
32 } deriving (Typeable,Generic) 32 } deriving (Typeable,Generic)
33 33
34deriving instance (Eq (NodeId dht), Eq a ) => Eq (Query dht a) 34deriving instance (Eq (NodeId dht), Eq (QueryExtra dht), Eq a ) => Eq (Query dht a)
35deriving instance (Show (NodeId dht), Show a ) => Show (Query dht a) 35deriving instance (Show (NodeId dht), Show (QueryExtra dht), Show a ) => Show (Query dht a)
36 36
37-- | All responses have an \"id\" key and value containing the node ID 37-- | All responses have an \"id\" key and value containing the node ID
38-- of the responding node. 38-- of the responding node.
39data Response dht a = Response 39data Response dht a = Response
40 { queredNodeId :: NodeId dht -- ^ node id of /quered/ node; 40 { queredNodeId :: NodeId dht -- ^ node id of /quered/ node;
41 , responseExtra :: ResponseExtra dht
41 , responseVals :: a -- ^ query result. 42 , responseVals :: a -- ^ query result.
42 } deriving (Typeable,Generic) 43 } deriving (Typeable,Generic)
43 44
44deriving instance (Eq (NodeId dht), Eq a ) => Eq (Response dht a) 45deriving instance (Eq (NodeId dht), Eq (ResponseExtra dht), Eq a ) => Eq (Response dht a)
45deriving instance (Show (NodeId dht), Show a ) => Show (Response dht a) 46deriving instance (Show (NodeId dht), Show (ResponseExtra dht), Show a ) => Show (Response dht a)
46 47
47-- | The most basic query is a ping. Ping query is used to check if a 48-- | The most basic query is a ping. Ping query is used to check if a
48-- quered node is still alive. 49-- quered node is still alive.
diff --git a/src/Network/DatagramServer.hs b/src/Network/DatagramServer.hs
index e004eef3..0e0297a0 100644
--- a/src/Network/DatagramServer.hs
+++ b/src/Network/DatagramServer.hs
@@ -329,8 +329,8 @@ query :: forall h a b raw msg.
329 , SerializableTo raw a 329 , SerializableTo raw a
330 , WireFormat raw msg 330 , WireFormat raw msg
331 , KRPC msg a b 331 , KRPC msg a b
332 ) => Manager raw msg -> QueryMethod msg -> SockAddr -> a -> IO b 332 ) => Manager raw msg -> SockAddr -> a -> IO b
333query mgr meth addr params = queryK mgr meth addr params (\_ x _ -> x) 333query mgr addr params = queryK mgr addr params (\_ x _ -> x)
334 334
335-- | Like 'query' but possibly returns your externally routable IP address. 335-- | Like 'query' but possibly returns your externally routable IP address.
336query' :: forall h a b raw msg. 336query' :: forall h a b raw msg.
@@ -340,8 +340,8 @@ query' :: forall h a b raw msg.
340 , Serialize (TransactionID msg) 340 , Serialize (TransactionID msg)
341 , SerializableTo raw a , WireFormat raw msg 341 , SerializableTo raw a , WireFormat raw msg
342 , KRPC msg a b 342 , KRPC msg a b
343 ) => Manager raw msg -> QueryMethod msg -> SockAddr -> a -> IO (b , Maybe ReflectedIP) 343 ) => Manager raw msg -> SockAddr -> a -> IO (b , Maybe ReflectedIP)
344query' mgr meth addr params = queryK mgr meth addr params (const (,)) 344query' mgr addr params = queryK mgr addr params (const (,))
345 345
346-- | Enqueue a query, but give us the complete BEncoded content sent by the 346-- | Enqueue a query, but give us the complete BEncoded content sent by the
347-- remote Node. This is useful for handling extensions that this library does 347-- remote Node. This is useful for handling extensions that this library does
@@ -354,8 +354,8 @@ queryRaw :: forall h a b raw msg.
354 , SerializableTo raw a 354 , SerializableTo raw a
355 , WireFormat raw msg 355 , WireFormat raw msg
356 , KRPC msg a b 356 , KRPC msg a b
357 ) => Manager raw msg -> QueryMethod msg -> SockAddr -> a -> IO (b , raw) 357 ) => Manager raw msg -> SockAddr -> a -> IO (b , raw)
358queryRaw mgr meth addr params = queryK mgr meth addr params (\raw x _ -> (x,raw)) 358queryRaw mgr addr params = queryK mgr addr params (\raw x _ -> (x,raw))
359 359
360queryK :: forall h a b x raw msg. 360queryK :: forall h a b x raw msg.
361 ( SerializableTo raw b 361 ( SerializableTo raw b
@@ -366,10 +366,10 @@ queryK :: forall h a b x raw msg.
366 , Serialize (TransactionID msg) 366 , Serialize (TransactionID msg)
367 , KRPC msg a b 367 , KRPC msg a b
368 ) => 368 ) =>
369 Manager raw msg -> QueryMethod msg -> SockAddr -> a -> (raw -> b -> Maybe ReflectedIP -> x) -> IO x 369 Manager raw msg -> SockAddr -> a -> (raw -> b -> Maybe ReflectedIP -> x) -> IO x
370queryK mgr@Manager{..} meth addr params kont = do 370queryK mgr@Manager{..} addr params kont = do
371 tid <- liftIO $ genTransactionId transactionCounter 371 tid <- liftIO $ genTransactionId transactionCounter
372 -- let queryMethod = method :: Method a b 372 let Method meth = method :: Method msg a b
373 let signature = querySignature meth tid addr 373 let signature = querySignature meth tid addr
374 logMsg 'D' "query.sending" signature 374 logMsg 'D' "query.sending" signature
375 375
diff --git a/src/Network/DatagramServer/Mainline.hs b/src/Network/DatagramServer/Mainline.hs
index 87825ce0..7cf96e44 100644
--- a/src/Network/DatagramServer/Mainline.hs
+++ b/src/Network/DatagramServer/Mainline.hs
@@ -49,6 +49,8 @@ module Network.DatagramServer.Mainline
49 , KMessageOf (..) 49 , KMessageOf (..)
50 , KMessage 50 , KMessage
51 , KQueryArgs 51 , KQueryArgs
52 , QueryExtra(..)
53 , ResponseExtra(..)
52 54
53 , NodeId(..) 55 , NodeId(..)
54 , nodeIdSize 56 , nodeIdSize
@@ -277,6 +279,12 @@ instance Envelope KMessageOf where
277 newtype NodeId KMessageOf = NodeId Word160 279 newtype NodeId KMessageOf = NodeId Word160
278 deriving (Show, Eq, Ord, Typeable, Bits, FiniteBits) 280 deriving (Show, Eq, Ord, Typeable, Bits, FiniteBits)
279 281
282 newtype QueryExtra KMessageOf = IsReadOnlyQuery { queryIsReadOnly :: Bool }
283 deriving (Show, Eq, Ord, Typeable)
284
285 data ResponseExtra KMessageOf = MainlineResponseData
286 deriving (Show, Eq, Ord, Typeable)
287
280 envelopePayload (Q q) = queryArgs q 288 envelopePayload (Q q) = queryArgs q
281 envelopePayload (R r) = respVals r 289 envelopePayload (R r) = respVals r
282 envelopePayload (E _) = error "TODO: messagePayload for KError" 290 envelopePayload (E _) = error "TODO: messagePayload for KError"
@@ -296,6 +304,9 @@ instance Envelope KMessageOf where
296 304
297 uniqueTransactionId cnt = return $ TID $ Char8.pack (show cnt) 305 uniqueTransactionId cnt = return $ TID $ Char8.pack (show cnt)
298 306
307 fromRoutableNode (IsReadOnlyQuery b) = not b
308
309
299instance WireFormat BValue KMessageOf where 310instance WireFormat BValue KMessageOf where
300 type SerializableTo BValue = BEncode 311 type SerializableTo BValue = BEncode
301 type CipherContext BValue KMessageOf = () 312 type CipherContext BValue KMessageOf = ()
diff --git a/src/Network/DatagramServer/Types.hs b/src/Network/DatagramServer/Types.hs
index e2d56dc0..13f79afb 100644
--- a/src/Network/DatagramServer/Types.hs
+++ b/src/Network/DatagramServer/Types.hs
@@ -94,6 +94,8 @@ class Envelope envelope where
94 data TransactionID envelope 94 data TransactionID envelope
95 type QueryMethod envelope 95 type QueryMethod envelope
96 data NodeId envelope 96 data NodeId envelope
97 data QueryExtra envelope
98 data ResponseExtra envelope
97 99
98 envelopePayload :: envelope a -> a 100 envelopePayload :: envelope a -> a
99 envelopeTransaction :: envelope a -> TransactionID envelope 101 envelopeTransaction :: envelope a -> TransactionID envelope
@@ -119,6 +121,9 @@ class Envelope envelope where
119 121
120 uniqueTransactionId :: Int -> IO (TransactionID envelope) 122 uniqueTransactionId :: Int -> IO (TransactionID envelope)
121 123
124 fromRoutableNode :: QueryExtra envelope -> Bool
125 fromRoutableNode _ = True
126
122-- | In Kademlia, the distance metric is XOR and the result is 127-- | In Kademlia, the distance metric is XOR and the result is
123-- interpreted as an unsigned integer. 128-- interpreted as an unsigned integer.
124newtype NodeDistance nodeid = NodeDistance nodeid 129newtype NodeDistance nodeid = NodeDistance nodeid
diff --git a/src/Network/KRPC/Method.hs b/src/Network/KRPC/Method.hs
index 2033f808..a31380cc 100644
--- a/src/Network/KRPC/Method.hs
+++ b/src/Network/KRPC/Method.hs
@@ -35,6 +35,7 @@ import Data.String
35import Data.Typeable 35import Data.Typeable
36import Network.DatagramServer.Mainline 36import Network.DatagramServer.Mainline
37import Network.DatagramServer.Types 37import Network.DatagramServer.Types
38import Network.DHT.Types
38 39
39 40
40-- | Method datatype used to describe method name, parameters and 41-- | Method datatype used to describe method name, parameters and
@@ -105,3 +106,5 @@ class ( Typeable req, Typeable resp)
105 validateExchange :: dht req -> dht resp -> Bool 106 validateExchange :: dht req -> dht resp -> Bool
106 validateExchange _ _ = True 107 validateExchange _ _ = True
107 108
109 makeQueryExtra :: DHTData dht ip -> Proxy req -> Proxy resp -> IO (QueryExtra dht)
110 makeResponseExtra :: DHTData dht ip -> req -> Proxy resp -> IO (ResponseExtra dht)