summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2020-01-03 18:22:16 -0500
committerJoe Crayne <joe@jerkface.net>2020-01-07 13:24:59 -0500
commit15ab3290ad04280764968ba4760474a8c0cbfa52 (patch)
tree8df7bdfe38005f5478243427bb2b692d32843283
parentb411ab66ceee7386e4829e2337c735a08fb3d54d (diff)
Modify kademlia search to distinguish a Canceled from timed-out query.
-rw-r--r--dht/TCPProber.hs13
-rw-r--r--dht/examples/dhtd.hs4
-rw-r--r--dht/src/Network/BitTorrent/MainlineDHT.hs26
-rw-r--r--dht/src/Network/Tox.hs2
-rw-r--r--dht/src/Network/Tox/DHT/Handlers.hs12
-rw-r--r--dht/src/Network/Tox/Onion/Handlers.hs19
-rw-r--r--dht/src/Network/Tox/TCP.hs8
-rw-r--r--kad/kad.cabal1
-rw-r--r--kad/src/Network/Kademlia/Search.hs11
9 files changed, 56 insertions, 40 deletions
diff --git a/dht/TCPProber.hs b/dht/TCPProber.hs
index faf8b35c..17b68f64 100644
--- a/dht/TCPProber.hs
+++ b/dht/TCPProber.hs
@@ -26,6 +26,7 @@ import Data.Wrapper.PSQ as PSQ
26import Network.Kademlia.Search 26import Network.Kademlia.Search
27import Network.Tox.NodeId 27import Network.Tox.NodeId
28import qualified Network.Tox.TCP as TCP 28import qualified Network.Tox.TCP as TCP
29import Network.QueryResponse as QR
29 30
30-- Probe TCP ports in a staggered fashion to up the odds of discovering 31-- Probe TCP ports in a staggered fashion to up the odds of discovering
31-- a higher priority port like 443. 32-- a higher priority port like 443.
@@ -156,7 +157,7 @@ runProbeQueue prober client maxjobs = do
156 loop 157 loop
157 158
158 159
159getNodes :: TCPProber -> TCP.TCPClient err Nonce8 -> NodeId -> TCP.NodeInfo -> IO (Maybe ([TCP.NodeInfo],[TCP.NodeInfo],Maybe ())) 160getNodes :: TCPProber -> TCP.TCPClient err Nonce8 -> NodeId -> TCP.NodeInfo -> IO (Result ([TCP.NodeInfo],[TCP.NodeInfo],Maybe ()))
160getNodes prober tcp seeking dst = do 161getNodes prober tcp seeking dst = do
161 r <- TCP.getUDPNodes' tcp seeking (TCP.udpNodeInfo dst) 162 r <- TCP.getUDPNodes' tcp seeking (TCP.udpNodeInfo dst)
162 dput XTCP $ "Got via TCP nodes: " ++ show r 163 dput XTCP $ "Got via TCP nodes: " ++ show r
@@ -164,14 +165,16 @@ getNodes prober tcp seeking dst = do
164 where ns' = do 165 where ns' = do
165 n <- ns 166 n <- ns
166 [ TCP.NodeInfo n 0 ] 167 [ TCP.NodeInfo n 0 ]
167 fmap join $ forM r $ \(ns,gw) -> do 168 case r of
169 Success (ns,gw) -> do
168 let ts = tcps ns 170 let ts = tcps ns
169 if TCP.nodeId gw == TCP.nodeId dst 171 if TCP.nodeId gw == TCP.nodeId dst
170 then return $ Just ts 172 then return $ Success ts
171 else do 173 else do
172 enqueueProbe prober (TCP.udpNodeInfo dst) 174 enqueueProbe prober (TCP.udpNodeInfo dst)
173 return $ Just ts 175 return $ Success ts
174 return $ Just ts 176 return $ Success ts
177 _ -> return $ fmap (const $ error "TCPProber.getNodes: The impossible happened!") r
175 178
176nodeSearch :: TCPProber -> TCP.TCPClient err Nonce8 -> Search NodeId (IP, PortNumber) () TCP.NodeInfo TCP.NodeInfo 179nodeSearch :: TCPProber -> TCP.TCPClient err Nonce8 -> Search NodeId (IP, PortNumber) () TCP.NodeInfo TCP.NodeInfo
177nodeSearch prober tcp = Search 180nodeSearch prober tcp = Search
diff --git a/dht/examples/dhtd.hs b/dht/examples/dhtd.hs
index 26f3f149..6b057af9 100644
--- a/dht/examples/dhtd.hs
+++ b/dht/examples/dhtd.hs
@@ -811,8 +811,8 @@ clientSession s@Session{..} sock cnum h = do
811 where 811 where
812 go | null destination = fmap Right . qhandler self 812 go | null destination = fmap Right . qhandler self
813 | otherwise = case readEither destination of 813 | otherwise = case readEither destination of
814 Right ni -> fmap (maybe (Left "Timeout.") Right) 814 Right ni -> fmap (maybe (Left "Timeout.") Right . resultToMaybe)
815 . flip (searchQuery qsearch) ni 815 . flip (searchQuery qsearch) ni -- TODO report canceled
816 Left e -> const $ return $ Left ("Bad destination: "++e) 816 Left e -> const $ return $ Left ("Bad destination: "++e)
817 maybe (hPutClient h ("Unsupported method: "++method)) 817 maybe (hPutClient h ("Unsupported method: "++method))
818 goQuery 818 goQuery
diff --git a/dht/src/Network/BitTorrent/MainlineDHT.hs b/dht/src/Network/BitTorrent/MainlineDHT.hs
index fc69fedd..8532b492 100644
--- a/dht/src/Network/BitTorrent/MainlineDHT.hs
+++ b/dht/src/Network/BitTorrent/MainlineDHT.hs
@@ -70,7 +70,7 @@ import Network.Kademlia.Search (Search (..))
70import Network.BitTorrent.DHT.Token as Token 70import Network.BitTorrent.DHT.Token as Token
71import qualified Network.Kademlia.Routing as R 71import qualified Network.Kademlia.Routing as R
72 ;import Network.Kademlia.Routing (getTimestamp) 72 ;import Network.Kademlia.Routing (getTimestamp)
73import Network.QueryResponse 73import Network.QueryResponse as QR
74import Network.Socket 74import Network.Socket
75import System.IO.Error 75import System.IO.Error
76import System.IO.Unsafe (unsafeInterleaveIO) 76import System.IO.Unsafe (unsafeInterleaveIO)
@@ -569,7 +569,7 @@ newClient swarms addr = do
569 -- We defer initializing the refreshSearch and refreshPing until we 569 -- We defer initializing the refreshSearch and refreshPing until we
570 -- have a client to send queries with. 570 -- have a client to send queries with.
571 let nullPing = const $ return False 571 let nullPing = const $ return False
572 nullSearch = mainlineSearch $ \_ _ -> return Nothing 572 nullSearch = mainlineSearch $ \_ _ -> return Canceled
573 tbl4 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info R.defaultBucketCount 573 tbl4 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info R.defaultBucketCount
574 refresher4 <- newBucketRefresher tbl4 nullSearch nullPing 574 refresher4 <- newBucketRefresher tbl4 nullSearch nullPing
575 tbl6 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info6 R.defaultBucketCount 575 tbl6 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info6 R.defaultBucketCount
@@ -1045,14 +1045,14 @@ mainlineSend :: ( BEncode xqry
1045 -> MainlineClient 1045 -> MainlineClient
1046 -> qry 1046 -> qry
1047 -> NodeInfo 1047 -> NodeInfo
1048 -> IO (Maybe rsp) 1048 -> IO (QR.Result rsp)
1049mainlineSend meth unwrap msg client nid addr = do 1049mainlineSend meth unwrap msg client nid addr = do
1050 reply <- sendQuery client serializer (msg nid) addr 1050 reply <- sendQuery client serializer (msg nid) addr
1051 return $ case reply of 1051 return $ case reply of
1052 Success (Right x) -> Just x 1052 Success (Right x) -> Success x
1053 Success (Left e) -> Nothing -- TODO: Do something with parse errors. 1053 Success (Left e) -> Canceled -- TODO: Do something with parse errors.
1054 Canceled -> Nothing 1054 Canceled -> Canceled
1055 TimedOut -> Nothing 1055 TimedOut -> TimedOut
1056 where 1056 where
1057 serializer = MethodSerializer 1057 serializer = MethodSerializer
1058 { methodTimeout = \ni -> return (ni, 5000000) 1058 { methodTimeout = \ni -> return (ni, 5000000)
@@ -1066,23 +1066,23 @@ mainlineSend meth unwrap msg client nid addr = do
1066 1066
1067ping :: MainlineClient -> NodeInfo -> IO Bool 1067ping :: MainlineClient -> NodeInfo -> IO Bool
1068ping client addr = 1068ping client addr =
1069 fromMaybe False 1069 fromMaybe False . resultToMaybe
1070 <$> mainlineSend (Method "ping") (\Pong -> True) (const Ping) client () addr 1070 <$> mainlineSend (Method "ping") (\Pong -> True) (const Ping) client () addr
1071 1071
1072-- searchQuery :: ni -> IO (Maybe [ni], [r], tok)) 1072-- searchQuery :: ni -> IO (Maybe [ni], [r], tok))
1073getNodes :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ())) 1073getNodes :: MainlineClient -> NodeId -> NodeInfo -> IO (QR.Result ([NodeInfo],[NodeInfo],Maybe ()))
1074getNodes = mainlineSend (Method "find_node") unwrapNodes $ flip FindNode (Just Want_Both) 1074getNodes = mainlineSend (Method "find_node") unwrapNodes $ flip FindNode (Just Want_Both)
1075 1075
1076unwrapNodes :: NodeFound -> ([NodeInfo], [NodeInfo], Maybe ()) 1076unwrapNodes :: NodeFound -> ([NodeInfo], [NodeInfo], Maybe ())
1077unwrapNodes (NodeFound ns4 ns6) = (ns4++ns6, ns4++ns6, Just ()) 1077unwrapNodes (NodeFound ns4 ns6) = (ns4++ns6, ns4++ns6, Just ())
1078 1078
1079getPeers :: MainlineClient -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[PeerAddr],Maybe Token)) 1079getPeers :: MainlineClient -> NodeId -> NodeInfo -> IO (QR.Result ([NodeInfo],[PeerAddr],Maybe Token))
1080getPeers = mainlineSend (Method "get_peers") unwrapPeers $ flip GetPeers (Just Want_Both) . coerce 1080getPeers = mainlineSend (Method "get_peers") unwrapPeers $ flip GetPeers (Just Want_Both) . coerce
1081 1081
1082unwrapPeers :: GotPeers -> ([NodeInfo], [PeerAddr], Maybe Token) 1082unwrapPeers :: GotPeers -> ([NodeInfo], [PeerAddr], Maybe Token)
1083unwrapPeers (GotPeers ps (NodeFound ns4 ns6) tok) = (ns4++ns6, ps, Just tok) 1083unwrapPeers (GotPeers ps (NodeFound ns4 ns6) tok) = (ns4++ns6, ps, Just tok)
1084 1084
1085mainlineSearch :: (NodeId -> NodeInfo -> IO (Maybe ([NodeInfo], [r], Maybe tok))) 1085mainlineSearch :: (NodeId -> NodeInfo -> IO (QR.Result ([NodeInfo], [r], Maybe tok)))
1086 -> Search NodeId (IP, PortNumber) tok NodeInfo r 1086 -> Search NodeId (IP, PortNumber) tok NodeInfo r
1087mainlineSearch qry = Search 1087mainlineSearch qry = Search
1088 { searchSpace = mainlineSpace 1088 { searchSpace = mainlineSpace
@@ -1140,5 +1140,5 @@ resolve want hostAndPort = do
1140 1140
1141 1141
1142announce :: MainlineClient -> Announce -> NodeInfo -> IO (Maybe Announced) 1142announce :: MainlineClient -> Announce -> NodeInfo -> IO (Maybe Announced)
1143announce client msg addr = do 1143announce client msg addr =
1144 mainlineSend (Method "announce_peer") id (\() -> msg) client () addr 1144 resultToMaybe <$> mainlineSend (Method "announce_peer") id (\() -> msg) client () addr
diff --git a/dht/src/Network/Tox.hs b/dht/src/Network/Tox.hs
index f17bad2c..f9f35ea4 100644
--- a/dht/src/Network/Tox.hs
+++ b/dht/src/Network/Tox.hs
@@ -349,7 +349,7 @@ newToxOverTransport keydb addr onNewSession (crypto,roster) udp tcp = do
349 -- TODO: Refactor so that these threads are forked when 'forkTox' is invoked. 349 -- TODO: Refactor so that these threads are forked when 'forkTox' is invoked.
350 -- This function should only initialize state. 350 -- This function should only initialize state.
351 orouter' <- forkRouteBuilder orouter 351 orouter' <- forkRouteBuilder orouter
352 $ \nid ni -> fmap (\(_,ns,_)->ns) 352 $ \nid ni -> fmap (\(_,ns,_)->ns) . resultToMaybe
353 <$> DHT.getNodes dhtclient (DHT.nodesOfInterest $ mkrouting dhtclient) nid (Multi.UDP ==> ni) 353 <$> DHT.getNodes dhtclient (DHT.nodesOfInterest $ mkrouting dhtclient) nid (Multi.UDP ==> ni)
354 354
355 toks <- do 355 toks <- do
diff --git a/dht/src/Network/Tox/DHT/Handlers.hs b/dht/src/Network/Tox/DHT/Handlers.hs
index dc4ca5fa..d132da88 100644
--- a/dht/src/Network/Tox/DHT/Handlers.hs
+++ b/dht/src/Network/Tox/DHT/Handlers.hs
@@ -198,7 +198,7 @@ newRouting addr crypto update4 update6 = do
198 nullSearch = Search 198 nullSearch = Search
199 { searchSpace = toxSpace 199 { searchSpace = toxSpace
200 , searchNodeAddress = nodeIP &&& nodePort 200 , searchNodeAddress = nodeIP &&& nodePort
201 , searchQuery = \_ _ -> return Nothing 201 , searchQuery = \_ _ -> return Canceled
202 , searchAlpha = 1 202 , searchAlpha = 1
203 , searchK = 2 203 , searchK = 2
204 } 204 }
@@ -410,7 +410,8 @@ unsendNodes _ = Nothing
410unwrapNodes :: SendNodes -> ( [NodeInfo], [NodeInfo], Maybe () ) 410unwrapNodes :: SendNodes -> ( [NodeInfo], [NodeInfo], Maybe () )
411unwrapNodes (SendNodes ns) = (map udpNodeInfo ns,map udpNodeInfo ns,Just ()) 411unwrapNodes (SendNodes ns) = (map udpNodeInfo ns,map udpNodeInfo ns,Just ())
412 412
413getNodes :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> NodeId -> Multi.NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ())) 413getNodes :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> NodeId -> Multi.NodeInfo
414 -> IO (QR.Result ([NodeInfo],[NodeInfo],Maybe ()))
414getNodes client cbvar nid addr = do 415getNodes client cbvar nid addr = do
415 -- dput XMisc $ show addr ++ " <-- getnodes " ++ show nid 416 -- dput XMisc $ show addr ++ " <-- getnodes " ++ show nid
416 reply <- QR.sendQuery client (serializer GetNodesType DHTGetNodes unsendNodes) (GetNodes nid) addr 417 reply <- QR.sendQuery client (serializer GetNodesType DHTGetNodes unsendNodes) (GetNodes nid) addr
@@ -423,9 +424,12 @@ getNodes client cbvar nid addr = do
423 forM_ mcbs $ \cbs -> do 424 forM_ mcbs $ \cbs -> do
424 forM_ cbs $ \cb -> do 425 forM_ cbs $ \cb -> do
425 rumoredAddress cb now addr (udpNodeInfo n) 426 rumoredAddress cb now addr (udpNodeInfo n)
426 return $ fmap unwrapNodes $ join $ resultToMaybe reply 427 return $ case reply of
428 Success x -> maybe Canceled (Success . unwrapNodes) x
429 _ -> fmap (error "Network.Tox.DHT.Handlers.getNodes: the impossible happened!") reply
427 430
428getNodesUDP :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ())) 431getNodesUDP :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> NodeId -> NodeInfo
432 -> IO (QR.Result ([NodeInfo],[NodeInfo],Maybe ()))
429getNodesUDP client cbvar nid addr = getNodes client cbvar nid (Multi.UDP ==> addr) 433getNodesUDP client cbvar nid addr = getNodes client cbvar nid (Multi.UDP ==> addr)
430 434
431updateRouting :: Client -> Routing 435updateRouting :: Client -> Routing
diff --git a/dht/src/Network/Tox/Onion/Handlers.hs b/dht/src/Network/Tox/Onion/Handlers.hs
index fa7bc83c..015c758c 100644
--- a/dht/src/Network/Tox/Onion/Handlers.hs
+++ b/dht/src/Network/Tox/Onion/Handlers.hs
@@ -277,15 +277,17 @@ sendOnion :: (OnionDestination r -> STM (OnionDestination r, Int))
277 -> AnnounceRequest 277 -> AnnounceRequest
278 -> OnionDestination r 278 -> OnionDestination r
279 -> (NodeInfo -> AnnounceResponse -> t) 279 -> (NodeInfo -> AnnounceResponse -> t)
280 -> IO (Maybe t) 280 -> IO (QR.Result t)
281sendOnion getTimeout client req oaddr unwrap = 281sendOnion getTimeout client req oaddr unwrap =
282 -- Four tries and then we tap out. 282 -- Four tries and then we tap out.
283 flip fix 4 $ \loop n -> do 283 flip fix 4 $ \loop n -> do
284 mb <- QR.sendQuery client (announceSerializer getTimeout) req oaddr 284 mb <- QR.sendQuery client (announceSerializer getTimeout) req oaddr
285 forM_ mb $ \r -> dput XAnnounce $ show (onionNodeInfo oaddr) ++ " sent response: " ++ show r 285 forM_ mb $ \r -> dput XAnnounce $ show (onionNodeInfo oaddr) ++ " sent response: " ++ show r
286 maybe (if n>0 then loop $! n - 1 else return Nothing) 286 let re = if n>0 then loop $! n - 1 else return Canceled
287 (return . Just . unwrap (onionNodeInfo oaddr)) 287 case mb of
288 $ join $ resultToMaybe mb 288 Success x -> maybe re (return . Success . unwrap (onionNodeInfo oaddr)) x
289 Canceled -> return Canceled
290 TimedOut -> re
289 291
290 292
291-- | Lookup the secret counterpart for a given alias key. 293-- | Lookup the secret counterpart for a given alias key.
@@ -294,7 +296,7 @@ getRendezvous :: (OnionDestination r -> STM (OnionDestination r, Int))
294 -> Client r 296 -> Client r
295 -> NodeId 297 -> NodeId
296 -> NodeInfo 298 -> NodeInfo
297 -> IO (Maybe ([NodeInfo],[Rendezvous],Maybe Nonce32)) 299 -> IO (Result ([NodeInfo],[Rendezvous],Maybe Nonce32))
298getRendezvous getTimeout crypto client nid ni = do 300getRendezvous getTimeout crypto client nid ni = do
299 asel <- atomically $ selectAlias crypto nid 301 asel <- atomically $ selectAlias crypto nid
300 let oaddr = OnionDestination asel ni Nothing 302 let oaddr = OnionDestination asel ni Nothing
@@ -319,5 +321,6 @@ putRendezvous getTimeout crypto client pubkey nonce32 ni = do
319 rendezvousKey = key2id rkey 321 rendezvousKey = key2id rkey
320 asel <- atomically $ selectAlias crypto longTermKey 322 asel <- atomically $ selectAlias crypto longTermKey
321 let oaddr = OnionDestination asel ni Nothing 323 let oaddr = OnionDestination asel ni Nothing
322 sendOnion getTimeout client (AnnounceRequest nonce32 longTermKey rendezvousKey) oaddr 324 fmap resultToMaybe
325 $ sendOnion getTimeout client (AnnounceRequest nonce32 longTermKey rendezvousKey) oaddr
323 $ \ni resp -> (Rendezvous rkey ni, resp) 326 $ \ni resp -> (Rendezvous rkey ni, resp)
diff --git a/dht/src/Network/Tox/TCP.hs b/dht/src/Network/Tox/TCP.hs
index 385da35b..932b4ab3 100644
--- a/dht/src/Network/Tox/TCP.hs
+++ b/dht/src/Network/Tox/TCP.hs
@@ -221,12 +221,14 @@ getTCPNodes tcp seeking dst = do
221-} 221-}
222 222
223getUDPNodes :: TCPClient err Nonce8 -> NodeId -> UDP.NodeInfo -> IO (Maybe ([UDP.NodeInfo], [UDP.NodeInfo], Maybe ())) 223getUDPNodes :: TCPClient err Nonce8 -> NodeId -> UDP.NodeInfo -> IO (Maybe ([UDP.NodeInfo], [UDP.NodeInfo], Maybe ()))
224getUDPNodes tcp seeking dst = fmap fst <$> getUDPNodes' tcp seeking dst 224getUDPNodes tcp seeking dst = fmap fst . resultToMaybe <$> getUDPNodes' tcp seeking dst
225 225
226getUDPNodes' :: TCPClient err Nonce8 -> NodeId -> UDP.NodeInfo -> IO (Maybe (([UDP.NodeInfo], [UDP.NodeInfo], Maybe ()), NodeInfo)) 226getUDPNodes' :: TCPClient err Nonce8 -> NodeId -> UDP.NodeInfo -> IO (QR.Result (([UDP.NodeInfo], [UDP.NodeInfo], Maybe ()), NodeInfo))
227getUDPNodes' tcp seeking dst0 = do 227getUDPNodes' tcp seeking dst0 = do
228 mgateway <- atomically $ tcpGetGateway tcp dst0 228 mgateway <- atomically $ tcpGetGateway tcp dst0
229 fmap (join . fmap resultToMaybe) $ forM mgateway $ \gateway -> do 229 case mgateway of
230 Nothing -> return Canceled
231 Just gateway -> do
230 (b,c,n24) <- atomically $ do 232 (b,c,n24) <- atomically $ do
231 b <- transportNewKey (tcpCrypto tcp) 233 b <- transportNewKey (tcpCrypto tcp)
232 c <- transportNewKey (tcpCrypto tcp) 234 c <- transportNewKey (tcpCrypto tcp)
diff --git a/kad/kad.cabal b/kad/kad.cabal
index 4a86bc4f..7c92f809 100644
--- a/kad/kad.cabal
+++ b/kad/kad.cabal
@@ -86,6 +86,7 @@ library
86 , network-addr 86 , network-addr
87 , cereal 87 , cereal
88 , tasks 88 , tasks
89 , server
89 hs-source-dirs: src 90 hs-source-dirs: src
90 default-language: Haskell2010 91 default-language: Haskell2010
91 92
diff --git a/kad/src/Network/Kademlia/Search.hs b/kad/src/Network/Kademlia/Search.hs
index 03c18d0e..8d9c997b 100644
--- a/kad/src/Network/Kademlia/Search.hs
+++ b/kad/src/Network/Kademlia/Search.hs
@@ -29,7 +29,8 @@ import qualified Data.MinMaxPSQ as MM
29 ;import Data.MinMaxPSQ (MinMaxPSQ, MinMaxPSQ') 29 ;import Data.MinMaxPSQ (MinMaxPSQ, MinMaxPSQ')
30import qualified Data.Wrapper.PSQ as PSQ 30import qualified Data.Wrapper.PSQ as PSQ
31 ;import Data.Wrapper.PSQ (pattern (:->), Binding, pattern Binding, Binding', PSQKey) 31 ;import Data.Wrapper.PSQ (pattern (:->), Binding, pattern Binding, Binding', PSQKey)
32import Network.Kademlia.Routing as R 32import Network.Kademlia.Routing as R
33import Network.QueryResponse (Result(..))
33#ifdef THREAD_DEBUG 34#ifdef THREAD_DEBUG
34import Control.Concurrent.Lifted.Instrument 35import Control.Concurrent.Lifted.Instrument
35#else 36#else
@@ -40,7 +41,7 @@ import GHC.Conc (labelThread)
40data Search nid addr tok ni r = Search 41data Search nid addr tok ni r = Search
41 { searchSpace :: KademliaSpace nid ni 42 { searchSpace :: KademliaSpace nid ni
42 , searchNodeAddress :: ni -> addr 43 , searchNodeAddress :: ni -> addr
43 , searchQuery :: nid -> ni -> IO (Maybe ([ni], [r], Maybe tok)) 44 , searchQuery :: nid -> ni -> IO (Result ([ni], [r], Maybe tok))
44 , searchAlpha :: Int -- α = 8 45 , searchAlpha :: Int -- α = 8
45 -- | 'searchK' should be larger than 'searchAlpha'. How much larger depends on 46 -- | 'searchK' should be larger than 'searchAlpha'. How much larger depends on
46 -- how fast the queries are. For Tox's much slower onion-routed queries, we 47 -- how fast the queries are. For Tox's much slower onion-routed queries, we
@@ -138,12 +139,14 @@ sendQuery :: forall addr nid tok ni r.
138 -> IO () 139 -> IO ()
139sendQuery Search{..} searchTarget searchResult sch@SearchState{..} (ni :-> d) = do 140sendQuery Search{..} searchTarget searchResult sch@SearchState{..} (ni :-> d) = do
140 myThreadId >>= flip labelThread ("searchQuery." ++ show searchTarget) 141 myThreadId >>= flip labelThread ("searchQuery." ++ show searchTarget)
141 reply <- searchQuery searchTarget ni `catchIOError` const (return Nothing) 142 reply <- searchQuery searchTarget ni `catchIOError` const (return Canceled)
142 -- (ns,rs) 143 -- (ns,rs)
143 let tok = error "TODO: token" 144 let tok = error "TODO: token"
144 atomically $ do 145 atomically $ do
145 modifyTVar searchPendingCount pred 146 modifyTVar searchPendingCount pred
146 maybe (return ()) go reply 147 case reply of
148 Success x -> go x
149 _ -> return ()
147 where 150 where
148 go (ns,rs,tok) = do 151 go (ns,rs,tok) = do
149 vs <- readTVar searchVisited 152 vs <- readTVar searchVisited