summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2018-12-08 23:30:48 -0500
committerJoe Crayne <joe@jerkface.net>2018-12-16 14:08:26 -0500
commit0dd2f5e5d078b735760e097df4204f9778bb193d (patch)
treea752a8f9e97e1aac44b641c928e8d7d32a7178d9 /src
parentdf6292eef942c11b9ac58b337f29641dae404116 (diff)
Integrated cli interface to TCP Kademlia table.
Diffstat (limited to 'src')
-rw-r--r--src/Network/BitTorrent/MainlineDHT.hs10
-rw-r--r--src/Network/Kademlia.hs6
-rw-r--r--src/Network/Kademlia/Bootstrap.hs6
-rw-r--r--src/Network/Tox.hs5
-rw-r--r--src/Network/Tox/DHT/Handlers.hs34
-rw-r--r--src/Network/Tox/NodeId.hs2
6 files changed, 38 insertions, 25 deletions
diff --git a/src/Network/BitTorrent/MainlineDHT.hs b/src/Network/BitTorrent/MainlineDHT.hs
index 573efcba..a29657af 100644
--- a/src/Network/BitTorrent/MainlineDHT.hs
+++ b/src/Network/BitTorrent/MainlineDHT.hs
@@ -563,11 +563,11 @@ newClient swarms addr = do
563 -- have a client to send queries with. 563 -- have a client to send queries with.
564 let nullPing = const $ return False 564 let nullPing = const $ return False
565 nullSearch = mainlineSearch $ \_ _ -> return Nothing 565 nullSearch = mainlineSearch $ \_ _ -> return Nothing
566 refresher4 <- newBucketRefresher tentative_info nullSearch nullPing 566 tbl4 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info R.defaultBucketCount
567 refresher6 <- newBucketRefresher tentative_info6 nullSearch nullPing 567 refresher4 <- newBucketRefresher tbl4 nullSearch nullPing
568 let tbl4 = refreshBuckets refresher4 568 tbl6 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info6 R.defaultBucketCount
569 tbl6 = refreshBuckets refresher6 569 refresher6 <- newBucketRefresher tbl6 nullSearch nullPing
570 updateIPVote tblvar addrvar a = do 570 let updateIPVote tblvar addrvar a = do
571 bkts <- readTVar tblvar 571 bkts <- readTVar tblvar
572 case bep42 a (nodeId $ R.thisNode bkts) of 572 case bep42 a (nodeId $ R.thisNode bkts) of
573 Just nid -> do 573 Just nid -> do
diff --git a/src/Network/Kademlia.hs b/src/Network/Kademlia.hs
index 44ef2ec1..488a53ac 100644
--- a/src/Network/Kademlia.hs
+++ b/src/Network/Kademlia.hs
@@ -66,7 +66,7 @@ contramapIR f ir = InsertionReporter
66 , reportPingResult = \tm ni b -> reportPingResult ir tm (f ni) b 66 , reportPingResult = \tm ni b -> reportPingResult ir tm (f ni) b
67 } 67 }
68 68
69-- | All the IO operations neccessary to maintain a Kademlia routing table. 69-- | All the IO operations necessary to maintain a Kademlia routing table.
70data TableStateIO ni = TableStateIO 70data TableStateIO ni = TableStateIO
71 { -- | Write the routing table. Typically 'writeTVar'. 71 { -- | Write the routing table. Typically 'writeTVar'.
72 tblWrite :: R.BucketList ni -> STM () 72 tblWrite :: R.BucketList ni -> STM ()
@@ -99,7 +99,7 @@ vanillaIO var ping = TableStateIO
99 , tblTransition = const $ return $ return () 99 , tblTransition = const $ return $ return ()
100 } 100 }
101 101
102-- | Everything neccessary to maintain a routing table of /ni/ (node 102-- | Everything necessary to maintain a routing table of /ni/ (node
103-- information) entries. 103-- information) entries.
104data Kademlia nid ni = Kademlia (InsertionReporter ni) 104data Kademlia nid ni = Kademlia (InsertionReporter ni)
105 (KademliaSpace nid ni) 105 (KademliaSpace nid ni)
@@ -109,7 +109,7 @@ data Kademlia nid ni = Kademlia (InsertionReporter ni)
109-- Helper to 'insertNode'. 109-- Helper to 'insertNode'.
110-- 110--
111-- Adapt return value from 'updateForPingResult' into a 111-- Adapt return value from 'updateForPingResult' into a
112-- more easily groked list of transitions. 112-- more easily grokked list of transitions.
113transition :: (ni,Maybe (t,ni)) -> [RoutingTransition ni] 113transition :: (ni,Maybe (t,ni)) -> [RoutingTransition ni]
114transition (x,m) = 114transition (x,m) =
115 -- Just _ <- m = Node transition: Accepted --> Stranger 115 -- Just _ <- m = Node transition: Accepted --> Stranger
diff --git a/src/Network/Kademlia/Bootstrap.hs b/src/Network/Kademlia/Bootstrap.hs
index aad8a81e..0f5d4e4d 100644
--- a/src/Network/Kademlia/Bootstrap.hs
+++ b/src/Network/Kademlia/Bootstrap.hs
@@ -77,14 +77,14 @@ data BucketRefresher nid ni = forall tok addr. Ord addr => BucketRefresher
77 77
78newBucketRefresher :: ( Ord addr, Hashable addr 78newBucketRefresher :: ( Ord addr, Hashable addr
79 , SensibleNodeId nid ni ) 79 , SensibleNodeId nid ni )
80 => ni 80 => TVar (R.BucketList ni)
81 -> Search nid addr tok ni ni 81 -> Search nid addr tok ni ni
82 -> (ni -> IO Bool) 82 -> (ni -> IO Bool)
83 -> STM (BucketRefresher nid ni) 83 -> STM (BucketRefresher nid ni)
84newBucketRefresher template_ni sch ping = do 84newBucketRefresher bkts sch ping = do
85 let spc = searchSpace sch 85 let spc = searchSpace sch
86 nodeId = kademliaLocation spc 86 nodeId = kademliaLocation spc
87 bkts <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) template_ni R.defaultBucketCount 87 -- bkts <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) template_ni R.defaultBucketCount
88 sched <- newTVar Int.empty 88 sched <- newTVar Int.empty
89 lasttouch <- newTVar 0 -- Would use getPOSIXTime here, or minBound, but alas... 89 lasttouch <- newTVar 0 -- Would use getPOSIXTime here, or minBound, but alas...
90 bootstrapVar <- newTVar True -- Start in bootstrapping mode. 90 bootstrapVar <- newTVar True -- Start in bootstrapping mode.
diff --git a/src/Network/Tox.hs b/src/Network/Tox.hs
index b98252d3..1e82c0c4 100644
--- a/src/Network/Tox.hs
+++ b/src/Network/Tox.hs
@@ -285,15 +285,16 @@ newToxOverTransport keydb addr onNewSession suppliedDHTKey udp tcp = do
285 let lookupClose _ = return Nothing 285 let lookupClose _ = return Nothing
286 286
287 mkrouting <- DHT.newRouting addr crypto updateIP updateIP 287 mkrouting <- DHT.newRouting addr crypto updateIP updateIP
288 orouter <- newOnionRouter $ dput XRoutes 288 orouter <- newOnionRouter crypto $ dput XRoutes
289 (cryptonet,dhtcrypt,onioncrypt,dtacrypt,handshakes) <- toxTransport crypto orouter lookupClose udp tcp 289 (cryptonet,dhtcrypt,onioncrypt,dtacrypt,handshakes) <- toxTransport crypto orouter lookupClose udp tcp
290 sessions <- initSessions (sendMessage cryptonet) 290 sessions <- initSessions (sendMessage cryptonet)
291 291
292 let dhtnet0 = layerTransportM (DHT.decrypt crypto) (DHT.encrypt crypto) dhtcrypt 292 let dhtnet0 = layerTransportM (DHT.decrypt crypto) (DHT.encrypt crypto) dhtcrypt
293 tbl4 = DHT.routing4 $ mkrouting (error "missing client") 293 tbl4 = DHT.routing4 $ mkrouting (error "missing client")
294 tbl6 = DHT.routing6 $ mkrouting (error "missing client") 294 tbl6 = DHT.routing6 $ mkrouting (error "missing client")
295 updateOnion bkts tr = hookBucketList DHT.toxSpace bkts orouter tr
295 dhtclient <- newClient drg dhtnet0 DHT.classify (myAddr tbl4 tbl6) (DHT.handlers crypto . mkrouting) id 296 dhtclient <- newClient drg dhtnet0 DHT.classify (myAddr tbl4 tbl6) (DHT.handlers crypto . mkrouting) id
296 $ \client net -> onInbound (DHT.updateRouting client (mkrouting client) orouter) net 297 $ \client net -> onInbound (DHT.updateRouting client (mkrouting client) updateOnion) net
297 298
298 hscache <- newHandshakeCache crypto (sendMessage handshakes) 299 hscache <- newHandshakeCache crypto (sendMessage handshakes)
299 let sparams = SessionParams 300 let sparams = SessionParams
diff --git a/src/Network/Tox/DHT/Handlers.hs b/src/Network/Tox/DHT/Handlers.hs
index 2062b51d..2fbac5d3 100644
--- a/src/Network/Tox/DHT/Handlers.hs
+++ b/src/Network/Tox/DHT/Handlers.hs
@@ -18,7 +18,8 @@ import Network.Address (WantIP (..), ipFamily, fromSockAddr, sockA
18import qualified Network.Kademlia.Routing as R 18import qualified Network.Kademlia.Routing as R
19import Control.TriadCommittee 19import Control.TriadCommittee
20import System.Global6 20import System.Global6
21import OnionRouter 21import DPut
22import DebugTag
22 23
23import qualified Data.ByteArray as BA 24import qualified Data.ByteArray as BA
24import qualified Data.ByteString.Char8 as C8 25import qualified Data.ByteString.Char8 as C8
@@ -27,6 +28,8 @@ import Control.Arrow
27import Control.Monad 28import Control.Monad
28import Control.Concurrent.Lifted.Instrument 29import Control.Concurrent.Lifted.Instrument
29import Control.Concurrent.STM 30import Control.Concurrent.STM
31import Data.Hashable
32import Data.Ord
30import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime) 33import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime)
31import Network.Socket 34import Network.Socket
32import qualified Data.HashMap.Strict as HashMap 35import qualified Data.HashMap.Strict as HashMap
@@ -39,8 +42,6 @@ import Data.IP
39import Data.Maybe 42import Data.Maybe
40import Data.Serialize (Serialize) 43import Data.Serialize (Serialize)
41import Data.Word 44import Data.Word
42import DPut
43import DebugTag
44 45
45data TransactionId = TransactionId 46data TransactionId = TransactionId
46 { transactionKey :: Nonce8 -- ^ Used to lookup pending query. 47 { transactionKey :: Nonce8 -- ^ Used to lookup pending query.
@@ -195,10 +196,10 @@ newRouting addr crypto update4 update6 = do
195 , searchNodeAddress = nodeIP &&& nodePort 196 , searchNodeAddress = nodeIP &&& nodePort
196 , searchQuery = \_ _ -> return Nothing 197 , searchQuery = \_ _ -> return Nothing
197 } 198 }
198 refresher4 <- newBucketRefresher tentative_info4 nullSearch nullPing 199 tbl4 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info4 R.defaultBucketCount
199 refresher6 <- newBucketRefresher tentative_info6 nullSearch nullPing 200 tbl6 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info6 R.defaultBucketCount
200 let tbl4 = refreshBuckets refresher4 201 refresher4 <- newBucketRefresher tbl4 nullSearch nullPing
201 tbl6 = refreshBuckets refresher6 202 refresher6 <- newBucketRefresher tbl6 nullSearch nullPing
202 committee4 <- newTriadCommittee (update4 tbl4) -- updateIPVote tbl4 addr4 203 committee4 <- newTriadCommittee (update4 tbl4) -- updateIPVote tbl4 addr4
203 committee6 <- newTriadCommittee (update6 tbl6) -- updateIPVote tbl6 addr6 204 committee6 <- newTriadCommittee (update6 tbl6) -- updateIPVote tbl6 addr6
204 cbvar <- newTVar HashMap.empty 205 cbvar <- newTVar HashMap.empty
@@ -412,7 +413,11 @@ getNodes client cbvar nid addr = do
412 rumoredAddress cb now (nodeAddr addr) n 413 rumoredAddress cb now (nodeAddr addr) n
413 return $ fmap unwrapNodes $ join reply 414 return $ fmap unwrapNodes $ join reply
414 415
415updateRouting :: Client -> Routing -> OnionRouter -> NodeInfo -> Message -> IO () 416updateRouting :: Client -> Routing
417 -> (TVar (R.BucketList NodeInfo) -> RoutingTransition NodeInfo -> STM ())
418 -> NodeInfo
419 -> Message
420 -> IO ()
416updateRouting client routing orouter naddr msg 421updateRouting client routing orouter naddr msg
417 | PacketKind 0x21 <- msgType msg = -- dput XLan "(tox)updateRouting: ignoring lan discovery" -- ignore lan discovery 422 | PacketKind 0x21 <- msgType msg = -- dput XLan "(tox)updateRouting: ignoring lan discovery" -- ignore lan discovery
418 -- Ignore lan announcements until they reply to our ping. 423 -- Ignore lan announcements until they reply to our ping.
@@ -431,7 +436,11 @@ updateRouting client routing orouter naddr msg
431 Want_Both -> do dput XMisc "BUG:unreachable" 436 Want_Both -> do dput XMisc "BUG:unreachable"
432 error $ "BUG:unreachable at " ++ __FILE__ ++ ":" ++ show __LINE__ 437 error $ "BUG:unreachable at " ++ __FILE__ ++ ":" ++ show __LINE__
433 438
434updateTable :: Client -> NodeInfo -> OnionRouter -> TriadCommittee NodeId SockAddr -> BucketRefresher NodeId NodeInfo -> IO () 439updateTable :: Client -> NodeInfo
440 -> (TVar (R.BucketList NodeInfo) -> RoutingTransition NodeInfo -> STM ())
441 -> TriadCommittee NodeId SockAddr
442 -> BucketRefresher NodeId NodeInfo
443 -> IO ()
435updateTable client naddr orouter committee refresher = do 444updateTable client naddr orouter committee refresher = do
436 self <- atomically $ R.thisNode <$> readTVar (refreshBuckets refresher) 445 self <- atomically $ R.thisNode <$> readTVar (refreshBuckets refresher)
437 -- dput XMisc $ "(tox)updateRouting: " ++ show (nodeIP self, nodeIP naddr) 446 -- dput XMisc $ "(tox)updateRouting: " ++ show (nodeIP self, nodeIP naddr)
@@ -439,7 +448,9 @@ updateTable client naddr orouter committee refresher = do
439 -- TODO: IP address vote? 448 -- TODO: IP address vote?
440 insertNode (toxKademlia client committee orouter refresher) naddr 449 insertNode (toxKademlia client committee orouter refresher) naddr
441 450
442toxKademlia :: Client -> TriadCommittee NodeId SockAddr -> OnionRouter 451toxKademlia :: Client
452 -> TriadCommittee NodeId SockAddr
453 -> (TVar (R.BucketList NodeInfo) -> RoutingTransition NodeInfo -> STM ())
443 -> BucketRefresher NodeId NodeInfo 454 -> BucketRefresher NodeId NodeInfo
444 -> Kademlia NodeId NodeInfo 455 -> Kademlia NodeId NodeInfo
445toxKademlia client committee orouter refresher 456toxKademlia client committee orouter refresher
@@ -449,7 +460,8 @@ toxKademlia client committee orouter refresher
449 { tblTransition = \tr -> do 460 { tblTransition = \tr -> do
450 io1 <- transitionCommittee committee tr 461 io1 <- transitionCommittee committee tr
451 io2 <- touchBucket refresher tr -- toxSpace (15*60) var sched tr 462 io2 <- touchBucket refresher tr -- toxSpace (15*60) var sched tr
452 hookBucketList toxSpace (refreshBuckets refresher) orouter tr 463 -- hookBucketList toxSpace (refreshBuckets refresher) orouter tr
464 orouter (refreshBuckets refresher) tr
453 return $ do 465 return $ do
454 io1 >> io2 466 io1 >> io2
455 {- 467 {-
diff --git a/src/Network/Tox/NodeId.hs b/src/Network/Tox/NodeId.hs
index 98be1e3a..1c68249e 100644
--- a/src/Network/Tox/NodeId.hs
+++ b/src/Network/Tox/NodeId.hs
@@ -320,7 +320,7 @@ instance Read NodeInfo where
320 RP.skipSpaces 320 RP.skipSpaces
321 let n = 43 -- characters in node id. 321 let n = 43 -- characters in node id.
322 parseAddr = RP.between (RP.char '(') (RP.char ')') (RP.munch (/=')')) 322 parseAddr = RP.between (RP.char '(') (RP.char ')') (RP.munch (/=')'))
323 RP.+++ RP.munch (not . isSpace) 323 RP.+++ RP.munch (\c -> not (isSpace c) && not (c `elem` ("{}()"::[Char])))
324 nodeidAt = do hexhash <- sequence $ replicate n (RP.satisfy b64digit) 324 nodeidAt = do hexhash <- sequence $ replicate n (RP.satisfy b64digit)
325 RP.char '@' RP.+++ RP.satisfy isSpace 325 RP.char '@' RP.+++ RP.satisfy isSpace
326 addrstr <- parseAddr 326 addrstr <- parseAddr