diff options
Diffstat (limited to 'dht/src/Network/Tox/DHT/Handlers.hs')
-rw-r--r-- | dht/src/Network/Tox/DHT/Handlers.hs | 189 |
1 files changed, 107 insertions, 82 deletions
diff --git a/dht/src/Network/Tox/DHT/Handlers.hs b/dht/src/Network/Tox/DHT/Handlers.hs index 323d5f5e..5156ec44 100644 --- a/dht/src/Network/Tox/DHT/Handlers.hs +++ b/dht/src/Network/Tox/DHT/Handlers.hs | |||
@@ -5,22 +5,24 @@ | |||
5 | {-# LANGUAGE TupleSections #-} | 5 | {-# LANGUAGE TupleSections #-} |
6 | module Network.Tox.DHT.Handlers where | 6 | module Network.Tox.DHT.Handlers where |
7 | 7 | ||
8 | import Debug.Trace | 8 | import Control.TriadCommittee |
9 | import Network.Tox.DHT.Transport as DHTTransport | ||
10 | import Network.Tox.TCP.NodeId as TCP (fromUDPNode, udpNodeInfo) | ||
11 | import Network.QueryResponse as QR hiding (Client) | ||
12 | import qualified Network.QueryResponse as QR (Client) | ||
13 | import Crypto.Tox | 9 | import Crypto.Tox |
14 | import Network.Kademlia.Search | 10 | import qualified Data.Tox.DHT.Multi as Multi |
15 | import qualified Data.Wrapper.PSQInt as Int | 11 | import qualified Data.Wrapper.PSQInt as Int |
12 | import Debug.Trace | ||
13 | import DebugTag | ||
14 | import DPut | ||
15 | import Network.Address (WantIP (..), fromSockAddr, ipFamily, | ||
16 | sockAddrPort) | ||
16 | import Network.Kademlia | 17 | import Network.Kademlia |
17 | import Network.Kademlia.Bootstrap | 18 | import Network.Kademlia.Bootstrap |
18 | import Network.Address (WantIP (..), ipFamily, fromSockAddr, sockAddrPort) | ||
19 | import qualified Network.Kademlia.Routing as R | 19 | import qualified Network.Kademlia.Routing as R |
20 | import Control.TriadCommittee | 20 | import Network.Kademlia.Search |
21 | import qualified Network.QueryResponse as QR (Client) | ||
22 | ;import Network.QueryResponse as QR hiding (Client) | ||
23 | import Network.Tox.DHT.Transport as DHTTransport | ||
24 | import Network.Tox.TCP.NodeId as TCP (fromUDPNode, udpNodeInfo) | ||
21 | import System.Global6 | 25 | import System.Global6 |
22 | import DPut | ||
23 | import DebugTag | ||
24 | 26 | ||
25 | import qualified Data.ByteArray as BA | 27 | import qualified Data.ByteArray as BA |
26 | import qualified Data.ByteString.Char8 as C8 | 28 | import qualified Data.ByteString.Char8 as C8 |
@@ -29,6 +31,7 @@ import Control.Arrow | |||
29 | import Control.Monad | 31 | import Control.Monad |
30 | import Control.Concurrent.Lifted.Instrument | 32 | import Control.Concurrent.Lifted.Instrument |
31 | import Control.Concurrent.STM | 33 | import Control.Concurrent.STM |
34 | import Data.Dependent.Sum ((==>)) | ||
32 | import Data.Hashable | 35 | import Data.Hashable |
33 | import Data.Ord | 36 | import Data.Ord |
34 | import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime) | 37 | import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime) |
@@ -80,21 +83,21 @@ pattern SendNodesType = PacketKind 4 -- 0x04 Nodes Response | |||
80 | 83 | ||
81 | 84 | ||
82 | instance Show PacketKind where | 85 | instance Show PacketKind where |
83 | showsPrec d PingType = mappend "PingType" | 86 | showsPrec d PingType = mappend "PingType" |
84 | showsPrec d PongType = mappend "PongType" | 87 | showsPrec d PongType = mappend "PongType" |
85 | showsPrec d GetNodesType = mappend "GetNodesType" | 88 | showsPrec d GetNodesType = mappend "GetNodesType" |
86 | showsPrec d SendNodesType = mappend "SendNodesType" | 89 | showsPrec d SendNodesType = mappend "SendNodesType" |
87 | showsPrec d DHTRequestType = mappend "DHTRequestType" | 90 | showsPrec d DHTRequestType = mappend "DHTRequestType" |
88 | showsPrec d OnionRequest0Type = mappend "OnionRequest0Type" | 91 | showsPrec d OnionRequest0Type = mappend "OnionRequest0Type" |
89 | showsPrec d OnionResponse1Type = mappend "OnionResponse1Type" | 92 | showsPrec d OnionResponse1Type = mappend "OnionResponse1Type" |
90 | showsPrec d OnionResponse3Type = mappend "OnionResponse3Type" | 93 | showsPrec d OnionResponse3Type = mappend "OnionResponse3Type" |
91 | showsPrec d AnnounceType = mappend "AnnounceType" | 94 | showsPrec d AnnounceType = mappend "AnnounceType" |
92 | showsPrec d AnnounceResponseType = mappend "AnnounceResponseType" | 95 | showsPrec d AnnounceResponseType = mappend "AnnounceResponseType" |
93 | showsPrec d DataRequestType = mappend "DataRequestType" | 96 | showsPrec d DataRequestType = mappend "DataRequestType" |
94 | showsPrec d DataResponseType = mappend "DataResponseType" | 97 | showsPrec d DataResponseType = mappend "DataResponseType" |
95 | showsPrec d CookieRequestType = mappend "CookieRequestType" | 98 | showsPrec d CookieRequestType = mappend "CookieRequestType" |
96 | showsPrec d CookieResponseType = mappend "CookieResponseType" | 99 | showsPrec d CookieResponseType = mappend "CookieResponseType" |
97 | showsPrec d (PacketKind x) = mappend "PacketKind " . showsPrec (d+1) x | 100 | showsPrec d (PacketKind x) = mappend "PacketKind " . showsPrec (d+1) x |
98 | 101 | ||
99 | msgType :: ( Serialize (f DHTRequest) | 102 | msgType :: ( Serialize (f DHTRequest) |
100 | , Serialize (f (Cookie Encrypted)), Serialize (f CookieRequest) | 103 | , Serialize (f (Cookie Encrypted)), Serialize (f CookieRequest) |
@@ -103,7 +106,7 @@ msgType :: ( Serialize (f DHTRequest) | |||
103 | ) => DHTMessage f -> PacketKind | 106 | ) => DHTMessage f -> PacketKind |
104 | msgType msg = PacketKind $ fst $ dhtMessageType msg | 107 | msgType msg = PacketKind $ fst $ dhtMessageType msg |
105 | 108 | ||
106 | classify :: Client -> Message -> MessageClass String PacketKind TransactionId NodeInfo Message | 109 | classify :: Client -> Message -> MessageClass String PacketKind TransactionId Multi.NodeInfo Message |
107 | classify client (DHTLanDiscovery {}) = IsUnsolicited (lanDiscoveryH client) | 110 | classify client (DHTLanDiscovery {}) = IsUnsolicited (lanDiscoveryH client) |
108 | classify client msg = fromMaybe (IsUnknown "unknown") | 111 | classify client msg = fromMaybe (IsUnknown "unknown") |
109 | $ mapMessage (\nonce24 (nonce8,_) -> go msg (TransactionId nonce8 nonce24)) msg | 112 | $ mapMessage (\nonce24 (nonce8,_) -> go msg (TransactionId nonce8 nonce24)) msg |
@@ -121,7 +124,7 @@ data NodeInfoCallback = NodeInfoCallback | |||
121 | , listenerId :: Int | 124 | , listenerId :: Int |
122 | , observedAddress :: POSIXTime -> NodeInfo -- Address and port for interestingNodeId | 125 | , observedAddress :: POSIXTime -> NodeInfo -- Address and port for interestingNodeId |
123 | -> STM () | 126 | -> STM () |
124 | , rumoredAddress :: POSIXTime -> SockAddr -- source of information | 127 | , rumoredAddress :: POSIXTime -> Multi.NodeInfo -- source of information |
125 | -> NodeInfo -- Address and port for interestingNodeId | 128 | -> NodeInfo -- Address and port for interestingNodeId |
126 | -> STM () | 129 | -> STM () |
127 | } | 130 | } |
@@ -208,7 +211,7 @@ newRouting addr crypto update4 update6 = do | |||
208 | cbvar <- newTVar HashMap.empty | 211 | cbvar <- newTVar HashMap.empty |
209 | return $ \client -> | 212 | return $ \client -> |
210 | -- Now we have a client, so tell the BucketRefresher how to search and ping. | 213 | -- Now we have a client, so tell the BucketRefresher how to search and ping. |
211 | let updIO r = updateRefresherIO (nodeSearch client cbvar) (ping client) r | 214 | let updIO r = updateRefresherIO (nodeSearch client cbvar) (pingUDP client) r |
212 | in Routing { tentativeId = tentative_info | 215 | in Routing { tentativeId = tentative_info |
213 | , committee4 = committee4 | 216 | , committee4 = committee4 |
214 | , committee6 = committee6 | 217 | , committee6 = committee6 |
@@ -226,32 +229,28 @@ isLocal (IPv4 ip4) = (ip4 == toEnum 0) | |||
226 | isGlobal :: IP -> Bool | 229 | isGlobal :: IP -> Bool |
227 | isGlobal = not . isLocal | 230 | isGlobal = not . isLocal |
228 | 231 | ||
229 | prefer4or6 :: NodeInfo -> Maybe WantIP -> WantIP | 232 | prefer4or6 :: Multi.NodeInfo -> Maybe WantIP -> WantIP |
230 | prefer4or6 addr iptyp = fromMaybe (ipFamily $ nodeIP addr) iptyp | 233 | prefer4or6 addr iptyp = fromMaybe fallback iptyp |
231 | 234 | where | |
232 | toxSpace :: R.KademliaSpace NodeId NodeInfo | 235 | fallback = case Multi.udpNode addr of |
233 | toxSpace = R.KademliaSpace | 236 | Just ni -> ipFamily $ nodeIP ni |
234 | { R.kademliaLocation = nodeId | 237 | Nothing -> Want_Both |
235 | , R.kademliaTestBit = testNodeIdBit | ||
236 | , R.kademliaXor = xorNodeId | ||
237 | , R.kademliaSample = sampleNodeId | ||
238 | } | ||
239 | 238 | ||
240 | 239 | ||
241 | pingH :: NodeInfo -> Ping -> IO Pong | 240 | pingH :: ni -> Ping -> IO Pong |
242 | pingH _ Ping = return Pong | 241 | pingH _ Ping = return Pong |
243 | 242 | ||
244 | getNodesH :: Routing -> NodeInfo -> GetNodes -> IO SendNodes | 243 | getNodesH :: Routing -> Multi.NodeInfo -> GetNodes -> IO SendNodes |
245 | getNodesH routing addr (GetNodes nid) = do | 244 | getNodesH routing addr (GetNodes nid) = do |
246 | let preferred = prefer4or6 addr Nothing | 245 | let preferred = prefer4or6 addr Nothing |
247 | 246 | ||
248 | (append4,append6) <- atomically $ do | 247 | (append4,append6) <- atomically $ do |
249 | ni4 <- R.thisNode <$> readTVar (routing4 routing) | 248 | ni4 <- R.thisNode <$> readTVar (routing4 routing) |
250 | ni6 <- R.thisNode <$> readTVar (routing6 routing) | 249 | ni6 <- R.thisNode <$> readTVar (routing6 routing) |
251 | return $ case ipFamily (nodeIP addr) of | 250 | return $ case ipFamily . nodeIP <$> Multi.udpNode addr of |
252 | Want_IP4 | isGlobal (nodeIP ni6) -> (id, (++ [ni6])) | 251 | Just Want_IP4 | isGlobal (nodeIP ni6) -> (id, (++ [ni6])) |
253 | Want_IP6 | isGlobal (nodeIP ni4) -> ((++ [ni4]), id) | 252 | Just Want_IP6 | isGlobal (nodeIP ni4) -> ((++ [ni4]), id) |
254 | _ -> (id, id) | 253 | _ -> (id, id) |
255 | ks <- go append4 $ routing4 routing | 254 | ks <- go append4 $ routing4 routing |
256 | ks6 <- go append6 $ routing6 routing | 255 | ks6 <- go append6 $ routing6 routing |
257 | let (ns1,ns2) = case preferred of Want_IP6 -> (ks6,ks) | 256 | let (ns1,ns2) = case preferred of Want_IP6 -> (ks6,ks) |
@@ -266,7 +265,7 @@ getNodesH routing addr (GetNodes nid) = do | |||
266 | 265 | ||
267 | k = 4 | 266 | k = 4 |
268 | 267 | ||
269 | createCookie :: TransportCrypto -> NodeInfo -> PublicKey -> IO (Cookie Encrypted) | 268 | createCookie :: TransportCrypto -> Multi.NodeInfo -> PublicKey -> IO (Cookie Encrypted) |
270 | createCookie crypto ni remoteUserKey = do | 269 | createCookie crypto ni remoteUserKey = do |
271 | (n24,sym) <- atomically $ do | 270 | (n24,sym) <- atomically $ do |
272 | n24 <- transportNewNonce crypto | 271 | n24 <- transportNewNonce crypto |
@@ -276,12 +275,12 @@ createCookie crypto ni remoteUserKey = do | |||
276 | let dta = encodePlain $ CookieData | 275 | let dta = encodePlain $ CookieData |
277 | { cookieTime = timestamp | 276 | { cookieTime = timestamp |
278 | , longTermKey = remoteUserKey | 277 | , longTermKey = remoteUserKey |
279 | , dhtKey = id2key $ nodeId ni -- transportPublic crypto | 278 | , dhtKey = id2key $ Multi.nodeId ni -- transportPublic crypto |
280 | } | 279 | } |
281 | edta = encryptSymmetric sym n24 dta | 280 | edta = encryptSymmetric sym n24 dta |
282 | return $ Cookie n24 edta | 281 | return $ Cookie n24 edta |
283 | 282 | ||
284 | createCookieSTM :: POSIXTime -> TransportCrypto -> NodeInfo -> PublicKey -> STM (Cookie Encrypted) | 283 | createCookieSTM :: POSIXTime -> TransportCrypto -> Multi.NodeInfo -> PublicKey -> STM (Cookie Encrypted) |
285 | createCookieSTM now crypto ni remoteUserKey = do | 284 | createCookieSTM now crypto ni remoteUserKey = do |
286 | let dmsg msg = trace msg (return ()) | 285 | let dmsg msg = trace msg (return ()) |
287 | (n24,sym) <- do | 286 | (n24,sym) <- do |
@@ -292,37 +291,38 @@ createCookieSTM now crypto ni remoteUserKey = do | |||
292 | let dta = encodePlain $ CookieData | 291 | let dta = encodePlain $ CookieData |
293 | { cookieTime = timestamp | 292 | { cookieTime = timestamp |
294 | , longTermKey = remoteUserKey | 293 | , longTermKey = remoteUserKey |
295 | , dhtKey = id2key $ nodeId ni -- transportPublic crypto | 294 | , dhtKey = id2key $ Multi.nodeId ni -- transportPublic crypto |
296 | } | 295 | } |
297 | edta = encryptSymmetric sym n24 dta | 296 | edta = encryptSymmetric sym n24 dta |
298 | return $ Cookie n24 edta | 297 | return $ Cookie n24 edta |
299 | 298 | ||
300 | cookieRequestH :: TransportCrypto -> NodeInfo -> CookieRequest -> IO (Cookie Encrypted) | 299 | cookieRequestH :: TransportCrypto -> Multi.NodeInfo -> CookieRequest -> IO (Cookie Encrypted) |
301 | cookieRequestH crypto ni (CookieRequest remoteUserKey) = do | 300 | cookieRequestH crypto ni (CookieRequest remoteUserKey) = do |
302 | dput XNetCrypto $ unlines | 301 | dput XNetCrypto $ unlines |
303 | [ show (nodeAddr ni) ++ " --> request cookie: remoteUserKey=" ++ show (key2id remoteUserKey) | 302 | [ show ni ++ " --> request cookie: remoteUserKey=" ++ show (key2id remoteUserKey) |
304 | , show (nodeAddr ni) ++ " --> sender=" ++ show (nodeId ni) ] | 303 | , show ni ++ " --> sender=" ++ show (Multi.nodeId ni) ] |
305 | x <- createCookie crypto ni remoteUserKey | 304 | x <- createCookie crypto ni remoteUserKey |
306 | dput XNetCrypto $ show (nodeAddr ni) ++ " <-- cookie " ++ show (key2id remoteUserKey) | 305 | dput XNetCrypto $ show ni ++ " <-- cookie " ++ show (key2id remoteUserKey) |
307 | return x | 306 | return x |
308 | 307 | ||
309 | lanDiscoveryH :: Client -> NodeInfo -> NodeInfo -> IO (Maybe (Message -> Message)) | 308 | lanDiscoveryH :: Client -> Multi.NodeInfo -> Multi.NodeInfo -> IO (Maybe (Message -> Message)) |
310 | lanDiscoveryH client _ ni = do | 309 | lanDiscoveryH client _ ni = do |
311 | dput XLan $ show (nodeAddr ni) ++ " --> LanAnnounce " ++ show (nodeId ni) | 310 | forM_ (Multi.udpNode ni) $ \uni -> do |
312 | forkIO $ do | 311 | dput XLan $ show (nodeAddr uni) ++ " --> LanAnnounce " ++ show (nodeId uni) |
313 | myThreadId >>= flip labelThread "lan-discover-ping" | 312 | forkIO $ do |
314 | ping client ni | 313 | myThreadId >>= flip labelThread "lan-discover-ping" |
315 | return () | 314 | pingUDP client uni |
315 | return () | ||
316 | return Nothing | 316 | return Nothing |
317 | 317 | ||
318 | type Message = DHTMessage ((,) Nonce8) | 318 | type Message = DHTMessage ((,) Nonce8) |
319 | 319 | ||
320 | type Client = QR.Client String PacketKind TransactionId NodeInfo Message | 320 | type Client = QR.Client String PacketKind TransactionId Multi.NodeInfo Message |
321 | 321 | ||
322 | 322 | ||
323 | wrapAsymm :: TransactionId -> NodeInfo -> NodeInfo -> (Nonce8 -> dta) -> Asymm dta | 323 | wrapAsymm :: TransactionId -> Multi.NodeInfo -> Multi.NodeInfo -> (Nonce8 -> dta) -> Asymm dta |
324 | wrapAsymm (TransactionId n8 n24) src dst dta = Asymm | 324 | wrapAsymm (TransactionId n8 n24) src dst dta = Asymm |
325 | { senderKey = id2key $ nodeId src | 325 | { senderKey = id2key $ Multi.nodeId src |
326 | , asymmNonce = n24 | 326 | , asymmNonce = n24 |
327 | , asymmData = dta n8 | 327 | , asymmData = dta n8 |
328 | } | 328 | } |
@@ -330,7 +330,7 @@ wrapAsymm (TransactionId n8 n24) src dst dta = Asymm | |||
330 | serializer :: PacketKind | 330 | serializer :: PacketKind |
331 | -> (Asymm (Nonce8,ping) -> Message) | 331 | -> (Asymm (Nonce8,ping) -> Message) |
332 | -> (Message -> Maybe (Asymm (Nonce8,pong))) | 332 | -> (Message -> Maybe (Asymm (Nonce8,pong))) |
333 | -> MethodSerializer TransactionId NodeInfo Message PacketKind ping (Maybe pong) | 333 | -> MethodSerializer TransactionId Multi.NodeInfo Message PacketKind ping (Maybe pong) |
334 | serializer pktkind mkping mkpong = MethodSerializer | 334 | serializer pktkind mkping mkpong = MethodSerializer |
335 | { methodTimeout = \addr -> return (addr, 5000000) | 335 | { methodTimeout = \addr -> return (addr, 5000000) |
336 | , method = pktkind | 336 | , method = pktkind |
@@ -345,7 +345,10 @@ unpong :: Message -> Maybe (Asymm (Nonce8,Pong)) | |||
345 | unpong (DHTPong asymm) = Just asymm | 345 | unpong (DHTPong asymm) = Just asymm |
346 | unpong _ = Nothing | 346 | unpong _ = Nothing |
347 | 347 | ||
348 | ping :: Client -> NodeInfo -> IO Bool | 348 | pingUDP :: Client -> NodeInfo -> IO Bool |
349 | pingUDP client ni = ping client (Multi.UDP ==> ni) | ||
350 | |||
351 | ping :: Client -> Multi.NodeInfo -> IO Bool | ||
349 | ping client addr = do | 352 | ping client addr = do |
350 | dput XPing $ show addr ++ " <-- ping" | 353 | dput XPing $ show addr ++ " <-- ping" |
351 | reply <- QR.sendQuery client (serializer PingType DHTPing unpong) Ping addr | 354 | reply <- QR.sendQuery client (serializer PingType DHTPing unpong) Ping addr |
@@ -372,10 +375,14 @@ loseCookieKey var saddr pk = do | |||
372 | _ -> return () -- unreachable? | 375 | _ -> return () -- unreachable? |
373 | 376 | ||
374 | 377 | ||
375 | cookieRequest :: TransportCrypto -> Client -> PublicKey -> NodeInfo -> IO (Maybe (Cookie Encrypted)) | 378 | cookieRequest :: TransportCrypto -> Client -> PublicKey -> Multi.NodeInfo -> IO (Maybe (Cookie Encrypted)) |
376 | cookieRequest crypto client localUserKey addr = do | 379 | cookieRequest crypto client localUserKey addr = do |
377 | let sockAddr = nodeAddr addr | 380 | let (runfirst,runlast) = case Multi.udpNode addr of |
378 | nid = id2key $ nodeId addr | 381 | Just ni -> let sockAddr = nodeAddr ni |
382 | nid = id2key $ nodeId ni | ||
383 | in ( atomically $ saveCookieKey (pendingCookies crypto) sockAddr nid | ||
384 | , atomically $ loseCookieKey (pendingCookies crypto) sockAddr nid ) | ||
385 | Nothing -> (return (), return ()) | ||
379 | cookieSerializer | 386 | cookieSerializer |
380 | = MethodSerializer | 387 | = MethodSerializer |
381 | { methodTimeout = \addr -> return (addr, 5000000) | 388 | { methodTimeout = \addr -> return (addr, 5000000) |
@@ -384,10 +391,10 @@ cookieRequest crypto client localUserKey addr = do | |||
384 | , unwrapResponse = fmap snd . unCookie | 391 | , unwrapResponse = fmap snd . unCookie |
385 | } | 392 | } |
386 | cookieRequest = CookieRequest localUserKey | 393 | cookieRequest = CookieRequest localUserKey |
387 | atomically $ saveCookieKey (pendingCookies crypto) sockAddr nid | 394 | runfirst |
388 | dput XNetCrypto $ show addr ++ " <-- cookieRequest" | 395 | dput XNetCrypto $ show addr ++ " <-- cookieRequest" |
389 | reply <- QR.sendQuery client cookieSerializer cookieRequest addr | 396 | reply <- QR.sendQuery client cookieSerializer cookieRequest addr |
390 | atomically $ loseCookieKey (pendingCookies crypto) sockAddr nid | 397 | runlast |
391 | dput XNetCrypto $ show addr ++ " -cookieResponse-> " ++ show reply | 398 | dput XNetCrypto $ show addr ++ " -cookieResponse-> " ++ show reply |
392 | return $ join reply | 399 | return $ join reply |
393 | 400 | ||
@@ -403,39 +410,42 @@ unsendNodes _ = Nothing | |||
403 | unwrapNodes :: SendNodes -> ( [NodeInfo], [NodeInfo], Maybe () ) | 410 | unwrapNodes :: SendNodes -> ( [NodeInfo], [NodeInfo], Maybe () ) |
404 | unwrapNodes (SendNodes ns) = (map udpNodeInfo ns,map udpNodeInfo ns,Just ()) | 411 | unwrapNodes (SendNodes ns) = (map udpNodeInfo ns,map udpNodeInfo ns,Just ()) |
405 | 412 | ||
406 | getNodes :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ())) | 413 | getNodes :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> NodeId -> Multi.NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ())) |
407 | getNodes client cbvar nid addr = do | 414 | getNodes client cbvar nid addr = do |
408 | -- dput XMisc $ show addr ++ " <-- getnodes " ++ show nid | 415 | -- dput XMisc $ show addr ++ " <-- getnodes " ++ show nid |
409 | reply <- QR.sendQuery client (serializer GetNodesType DHTGetNodes unsendNodes) (GetNodes nid) addr | 416 | reply <- QR.sendQuery client (serializer GetNodesType DHTGetNodes unsendNodes) (GetNodes nid) addr |
410 | -- dput XMisc $ show addr ++ " -sendnodes-> " ++ show reply | 417 | -- dput XMisc $ show addr ++ " -sendnodes-> " ++ show reply |
411 | forM_ (join reply) $ \(SendNodes ns) -> | 418 | forM_ (join reply) $ \(SendNodes ns) -> |
412 | forM_ ns $ \n -> do | 419 | forM_ ns $ \n -> do |
413 | now <- getPOSIXTime | 420 | now <- getPOSIXTime |
414 | atomically $ do | 421 | atomically $ do |
415 | mcbs <- HashMap.lookup (nodeId . udpNodeInfo $ n) <$> readTVar cbvar | 422 | mcbs <- HashMap.lookup (nodeId . udpNodeInfo $ n) <$> readTVar cbvar |
416 | forM_ mcbs $ \cbs -> do | 423 | forM_ mcbs $ \cbs -> do |
417 | forM_ cbs $ \cb -> do | 424 | forM_ cbs $ \cb -> do |
418 | rumoredAddress cb now (nodeAddr addr) (udpNodeInfo n) | 425 | rumoredAddress cb now addr (udpNodeInfo n) |
419 | return $ fmap unwrapNodes $ join reply | 426 | return $ fmap unwrapNodes $ join reply |
420 | 427 | ||
428 | getNodesUDP :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ())) | ||
429 | getNodesUDP client cbvar nid addr = getNodes client cbvar nid (Multi.UDP ==> addr) | ||
430 | |||
421 | updateRouting :: Client -> Routing | 431 | updateRouting :: Client -> Routing |
422 | -> (TVar (R.BucketList NodeInfo) -> RoutingTransition NodeInfo -> STM ()) | 432 | -> (TVar (R.BucketList NodeInfo) -> RoutingTransition NodeInfo -> STM ()) |
423 | -> NodeInfo | 433 | -> Multi.NodeInfo |
424 | -> Message | 434 | -> Message |
425 | -> IO () | 435 | -> IO () |
426 | updateRouting client routing orouter naddr msg | 436 | updateRouting client routing orouter naddr0 msg |
427 | | PacketKind 0x21 <- msgType msg = -- dput XLan "(tox)updateRouting: ignoring lan discovery" -- ignore lan discovery | 437 | | PacketKind 0x21 <- msgType msg = -- dput XLan "(tox)updateRouting: ignoring lan discovery" -- ignore lan discovery |
428 | -- Ignore lan announcements until they reply to our ping. | 438 | -- Ignore lan announcements until they reply to our ping. |
429 | -- We do this because the lan announce is not authenticated. | 439 | -- We do this because the lan announce is not authenticated. |
430 | return () | 440 | return () |
431 | | otherwise = do | 441 | | otherwise = forM_ (Multi.udpNode naddr0) $ \naddr -> do |
432 | now <- getPOSIXTime | 442 | now <- getPOSIXTime |
433 | atomically $ do | 443 | atomically $ do |
434 | m <- HashMap.lookup (nodeId naddr) <$> readTVar (nodesOfInterest routing) | 444 | m <- HashMap.lookup (nodeId naddr) <$> readTVar (nodesOfInterest routing) |
435 | forM_ m $ mapM_ $ \NodeInfoCallback{interestingNodeId,observedAddress} -> do | 445 | forM_ m $ mapM_ $ \NodeInfoCallback{interestingNodeId,observedAddress} -> do |
436 | when (interestingNodeId == nodeId naddr) | 446 | when (interestingNodeId == nodeId naddr) |
437 | $ observedAddress now naddr | 447 | $ observedAddress now naddr |
438 | case prefer4or6 naddr Nothing of | 448 | case prefer4or6 (Multi.UDP ==> naddr) Nothing of |
439 | Want_IP4 -> updateTable client naddr orouter (committee4 routing) (refresher4 routing) | 449 | Want_IP4 -> updateTable client naddr orouter (committee4 routing) (refresher4 routing) |
440 | Want_IP6 -> updateTable client naddr orouter (committee6 routing) (refresher6 routing) | 450 | Want_IP6 -> updateTable client naddr orouter (committee6 routing) (refresher6 routing) |
441 | Want_Both -> do dput XMisc "BUG:unreachable" | 451 | Want_Both -> do dput XMisc "BUG:unreachable" |
@@ -461,7 +471,7 @@ toxKademlia :: Client | |||
461 | toxKademlia client committee orouter refresher | 471 | toxKademlia client committee orouter refresher |
462 | = Kademlia quietInsertions | 472 | = Kademlia quietInsertions |
463 | toxSpace | 473 | toxSpace |
464 | (vanillaIO (refreshBuckets refresher) $ ping client) | 474 | (vanillaIO (refreshBuckets refresher) $ pingUDP client) |
465 | { tblTransition = \tr -> do | 475 | { tblTransition = \tr -> do |
466 | io1 <- transitionCommittee committee tr | 476 | io1 <- transitionCommittee committee tr |
467 | io2 <- touchBucket refresher tr -- toxSpace (15*60) var sched tr | 477 | io2 <- touchBucket refresher tr -- toxSpace (15*60) var sched tr |
@@ -486,34 +496,34 @@ transitionCommittee committee (RoutingTransition ni Stranger) = do | |||
486 | return () | 496 | return () |
487 | transitionCommittee committee _ = return $ return () | 497 | transitionCommittee committee _ = return $ return () |
488 | 498 | ||
489 | type Handler = MethodHandler String TransactionId NodeInfo Message | 499 | type Handler = MethodHandler String TransactionId Multi.NodeInfo Message |
490 | 500 | ||
491 | isPing :: (f Ping -> Ping) -> DHTMessage f -> Either String Ping | 501 | isPing :: (f Ping -> Ping) -> DHTMessage f -> Either String Ping |
492 | isPing unpack (DHTPing a) = Right $ unpack $ asymmData a | 502 | isPing unpack (DHTPing a) = Right $ unpack $ asymmData a |
493 | isPing _ _ = Left "Bad ping" | 503 | isPing _ _ = Left "Bad ping" |
494 | 504 | ||
495 | mkPong :: TransactionId -> NodeInfo -> NodeInfo -> Pong -> DHTMessage ((,) Nonce8) | 505 | mkPong :: TransactionId -> Multi.NodeInfo -> Multi.NodeInfo -> Pong -> DHTMessage ((,) Nonce8) |
496 | mkPong tid src dst pong = DHTPong $ wrapAsymm tid src dst (, pong) | 506 | mkPong tid src dst pong = DHTPong $ wrapAsymm tid src dst (, pong) |
497 | 507 | ||
498 | isGetNodes :: (f GetNodes -> GetNodes) -> DHTMessage f -> Either String GetNodes | 508 | isGetNodes :: (f GetNodes -> GetNodes) -> DHTMessage f -> Either String GetNodes |
499 | isGetNodes unpack (DHTGetNodes a) = Right $ unpack $ asymmData a | 509 | isGetNodes unpack (DHTGetNodes a) = Right $ unpack $ asymmData a |
500 | isGetNodes _ _ = Left "Bad GetNodes" | 510 | isGetNodes _ _ = Left "Bad GetNodes" |
501 | 511 | ||
502 | mkSendNodes :: TransactionId -> NodeInfo -> NodeInfo -> SendNodes -> DHTMessage ((,) Nonce8) | 512 | mkSendNodes :: TransactionId -> Multi.NodeInfo -> Multi.NodeInfo -> SendNodes -> DHTMessage ((,) Nonce8) |
503 | mkSendNodes tid src dst sendnodes = DHTSendNodes $ wrapAsymm tid src dst (, sendnodes) | 513 | mkSendNodes tid src dst sendnodes = DHTSendNodes $ wrapAsymm tid src dst (, sendnodes) |
504 | 514 | ||
505 | isCookieRequest :: (f CookieRequest -> CookieRequest) -> DHTMessage f -> Either String CookieRequest | 515 | isCookieRequest :: (f CookieRequest -> CookieRequest) -> DHTMessage f -> Either String CookieRequest |
506 | isCookieRequest unpack (DHTCookieRequest a) = Right $ unpack $ asymmData a | 516 | isCookieRequest unpack (DHTCookieRequest a) = Right $ unpack $ asymmData a |
507 | isCookieRequest _ _ = Left "Bad cookie request" | 517 | isCookieRequest _ _ = Left "Bad cookie request" |
508 | 518 | ||
509 | mkCookie :: TransactionId -> NodeInfo -> NodeInfo -> Cookie Encrypted -> DHTMessage ((,) Nonce8) | 519 | mkCookie :: TransactionId -> ni -> ni -> Cookie Encrypted -> DHTMessage ((,) Nonce8) |
510 | mkCookie (TransactionId n8 n24) src dst cookie = DHTCookie n24 (n8,cookie) | 520 | mkCookie (TransactionId n8 n24) src dst cookie = DHTCookie n24 (n8,cookie) |
511 | 521 | ||
512 | isDHTRequest :: (f DHTRequest -> DHTRequest) -> DHTMessage f -> Either String DHTRequest | 522 | isDHTRequest :: (f DHTRequest -> DHTRequest) -> DHTMessage f -> Either String DHTRequest |
513 | isDHTRequest unpack (DHTDHTRequest pubkey a) = Right $ unpack $ asymmData a | 523 | isDHTRequest unpack (DHTDHTRequest pubkey a) = Right $ unpack $ asymmData a |
514 | isDHTRequest _ _ = Left "Bad dht relay request" | 524 | isDHTRequest _ _ = Left "Bad dht relay request" |
515 | 525 | ||
516 | dhtRequestH :: NodeInfo -> DHTRequest -> IO () | 526 | dhtRequestH :: Multi.NodeInfo -> DHTRequest -> IO () |
517 | dhtRequestH ni req = do | 527 | dhtRequestH ni req = do |
518 | dput XMisc $ "Unhandled DHT Request: " ++ show req | 528 | dput XMisc $ "Unhandled DHT Request: " ++ show req |
519 | 529 | ||
@@ -528,8 +538,23 @@ nodeSearch :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> Search NodeI | |||
528 | nodeSearch client cbvar = Search | 538 | nodeSearch client cbvar = Search |
529 | { searchSpace = toxSpace | 539 | { searchSpace = toxSpace |
530 | , searchNodeAddress = nodeIP &&& nodePort | 540 | , searchNodeAddress = nodeIP &&& nodePort |
531 | , searchQuery = Left $ getNodes client cbvar | 541 | -- searchQuery :: Either (nid -> ni -> IO (Maybe ([ni], [r], Maybe tok))) |
542 | -- (nid -> ni -> (Maybe ([ni],[r],Maybe tok) -> IO ()) -> IO ()) | ||
543 | , searchQuery = Left $ getNodesUDP client cbvar | ||
532 | , searchAlpha = 8 | 544 | , searchAlpha = 8 |
533 | , searchK = 16 | 545 | , searchK = 16 |
546 | } | ||
534 | 547 | ||
548 | {- | ||
549 | nodeSearchMulti :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> Search NodeId (IP,PortNumber) () Multi.NodeInfo Multi.NodeInfo | ||
550 | nodeSearchMulti client cbvar = Search | ||
551 | { searchSpace = toxSpace | ||
552 | , searchNodeAddress = nodeIP &&& nodePort | ||
553 | -- searchQuery :: Either (nid -> ni -> IO (Maybe ([ni], [r], Maybe tok))) | ||
554 | -- (nid -> ni -> (Maybe ([ni],[r],Maybe tok) -> IO ()) -> IO ()) | ||
555 | , searchQuery = Left $ \nid ni -> fmap fixupUDP <$> getNodes client cbvar nid ni | ||
556 | , searchAlpha = 8 | ||
557 | , searchK = 16 | ||
535 | } | 558 | } |
559 | where fixupUDP (xs,ys,m) = (map (Multi.UDP ==>) xs, map (Multi.UDP ==>) ys, m) | ||
560 | -} | ||