summaryrefslogtreecommitdiff
path: root/dht
diff options
context:
space:
mode:
Diffstat (limited to 'dht')
-rw-r--r--dht/dht-client.cabal1
-rw-r--r--dht/src/Data/Tox/Onion.hs3
-rw-r--r--dht/src/Data/Tox/Relay.hs29
-rw-r--r--dht/src/Network/Tox.hs6
-rw-r--r--dht/src/Network/Tox/DHT/Handlers.hs9
-rw-r--r--dht/src/Network/Tox/DHT/Transport.hs3
-rw-r--r--dht/src/Network/Tox/NodeId.hs4
-rw-r--r--dht/src/Network/Tox/Onion/Handlers.hs3
-rw-r--r--dht/src/Network/Tox/TCP.hs5
-rw-r--r--dht/src/Network/Tox/TCP/NodeId.hs89
10 files changed, 115 insertions, 37 deletions
diff --git a/dht/dht-client.cabal b/dht/dht-client.cabal
index 19f4f2b3..24739767 100644
--- a/dht/dht-client.cabal
+++ b/dht/dht-client.cabal
@@ -98,6 +98,7 @@ library
98 Network.Tox.DHT.Transport 98 Network.Tox.DHT.Transport
99 Network.Tox.Handshake 99 Network.Tox.Handshake
100 Network.Tox.NodeId 100 Network.Tox.NodeId
101 Network.Tox.TCP.NodeId
101 Network.Tox.Avahi 102 Network.Tox.Avahi
102 Network.Tox.RelayPinger 103 Network.Tox.RelayPinger
103 Network.UPNP 104 Network.UPNP
diff --git a/dht/src/Data/Tox/Onion.hs b/dht/src/Data/Tox/Onion.hs
index 258a9f73..d3c8086d 100644
--- a/dht/src/Data/Tox/Onion.hs
+++ b/dht/src/Data/Tox/Onion.hs
@@ -25,6 +25,7 @@ import Crypto.Tox hiding (encrypt,decrypt)
25import Network.Tox.NodeId 25import Network.Tox.NodeId
26import qualified Crypto.Tox as ToxCrypto 26import qualified Crypto.Tox as ToxCrypto
27import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes(..),nodeInfo,DHTPublicKey(..),FriendRequest,asymNodeInfo) 27import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes(..),nodeInfo,DHTPublicKey(..),FriendRequest,asymNodeInfo)
28import Network.Tox.TCP.NodeId (fromUDPNode)
28 29
29import Control.Applicative 30import Control.Applicative
30import Control.Arrow 31import Control.Arrow
@@ -717,7 +718,7 @@ getNodeList = do
717 (:) n <$> (getNodeList <|> pure []) 718 (:) n <$> (getNodeList <|> pure [])
718 719
719instance S.Serialize AnnounceResponse where 720instance S.Serialize AnnounceResponse where
720 get = AnnounceResponse <$> S.get <*> (SendNodes <$> getNodeList) 721 get = AnnounceResponse <$> S.get <*> (SendNodes . map fromUDPNode <$> getNodeList)
721 put (AnnounceResponse st (SendNodes ns)) = S.put st >> mapM_ S.put ns 722 put (AnnounceResponse st (SendNodes ns)) = S.put st >> mapM_ S.put ns
722 723
723data DataToRoute = DataToRoute 724data DataToRoute = DataToRoute
diff --git a/dht/src/Data/Tox/Relay.hs b/dht/src/Data/Tox/Relay.hs
index f28a1685..64c90806 100644
--- a/dht/src/Data/Tox/Relay.hs
+++ b/dht/src/Data/Tox/Relay.hs
@@ -7,7 +7,10 @@
7{-# LANGUAGE PatternSynonyms #-} 7{-# LANGUAGE PatternSynonyms #-}
8{-# LANGUAGE StandaloneDeriving #-} 8{-# LANGUAGE StandaloneDeriving #-}
9{-# LANGUAGE UndecidableInstances #-} 9{-# LANGUAGE UndecidableInstances #-}
10module Data.Tox.Relay where 10module Data.Tox.Relay
11 ( module Network.Tox.TCP.NodeId
12 , module Data.Tox.Relay
13 ) where
11 14
12import Data.Aeson (ToJSON(..),FromJSON(..)) 15import Data.Aeson (ToJSON(..),FromJSON(..))
13import qualified Data.Aeson as JSON 16import qualified Data.Aeson as JSON
@@ -27,8 +30,10 @@ import qualified Rank2
27import qualified Text.ParserCombinators.ReadP as RP 30import qualified Text.ParserCombinators.ReadP as RP
28 31
29import Crypto.Tox 32import Crypto.Tox
33import Network.Tox.TCP.NodeId
30import Data.Tox.Onion 34import Data.Tox.Onion
31import qualified Network.Tox.NodeId as UDP 35import qualified Network.Tox.NodeId as UDP
36import Network.Tox.TCP.NodeId as TCP
32 37
33newtype ConId = ConId Word8 38newtype ConId = ConId Word8
34 deriving (Eq,Show,Ord,Data,Serialize) 39 deriving (Eq,Show,Ord,Data,Serialize)
@@ -196,28 +201,6 @@ instance Serialize (Welcome Encrypted) where
196 get = Welcome <$> get <*> get 201 get = Welcome <$> get <*> get
197 put (Welcome n dta) = put n >> put dta 202 put (Welcome n dta) = put n >> put dta
198 203
199data NodeInfo = NodeInfo
200 { udpNodeInfo :: UDP.NodeInfo
201 , tcpPort :: PortNumber
202 }
203 deriving (Eq,Ord)
204
205instance Read NodeInfo where
206 readsPrec _ = RP.readP_to_S $ do
207 udp <- RP.readS_to_P reads
208 port <- RP.between (RP.char '{') (RP.char '}') $ do
209 mapM_ RP.char ("tcp:" :: String)
210 w16 <- RP.readS_to_P reads
211 return $ fromIntegral (w16 :: Word16)
212 return $ NodeInfo udp port
213
214instance ToJSON NodeInfo where
215 toJSON (NodeInfo udp port) = case (toJSON udp) of
216 JSON.Object tbl -> JSON.Object $ HashMap.insert "tcp_ports"
217 (JSON.Array $ Vector.fromList
218 [JSON.Number (fromIntegral port)])
219 tbl
220 x -> x -- Shouldn't happen.
221 204
222tcpPortScore :: Word16 -> Word16 205tcpPortScore :: Word16 -> Word16
223tcpPortScore 443 = 0 206tcpPortScore 443 = 0
diff --git a/dht/src/Network/Tox.hs b/dht/src/Network/Tox.hs
index c233492d..61a1d117 100644
--- a/dht/src/Network/Tox.hs
+++ b/dht/src/Network/Tox.hs
@@ -47,6 +47,7 @@ import System.IO.Error
47 47
48import Data.TableMethods 48import Data.TableMethods
49import Data.Tox.Onion (substituteLoopback) 49import Data.Tox.Onion (substituteLoopback)
50import Network.Tox.RelayPinger
50import qualified Data.Word64Map 51import qualified Data.Word64Map
51import Network.BitTorrent.DHT.Token as Token 52import Network.BitTorrent.DHT.Token as Token
52import qualified Data.Wrapper.PSQ as PSQ 53import qualified Data.Wrapper.PSQ as PSQ
@@ -194,7 +195,8 @@ data Tox extra = Tox
194 195
195-- | Create a DHTPublicKey packet to send to a remote contact. 196-- | Create a DHTPublicKey packet to send to a remote contact.
196getContactInfo :: Tox extra -> IO DHT.DHTPublicKey 197getContactInfo :: Tox extra -> IO DHT.DHTPublicKey
197getContactInfo Tox{toxCryptoKeys,toxRouting} = join $ atomically $ do 198getContactInfo Tox{toxCryptoKeys,toxRouting,toxOnionRoutes} = join $ atomically $ do
199 (rcnt,relays) <- currentRelays (tcpRelayPinger toxOnionRoutes)
198 r4 <- readTVar $ DHT.routing4 toxRouting 200 r4 <- readTVar $ DHT.routing4 toxRouting
199 r6 <- readTVar $ DHT.routing6 toxRouting 201 r6 <- readTVar $ DHT.routing6 toxRouting
200 nonce <- transportNewNonce toxCryptoKeys 202 nonce <- transportNewNonce toxCryptoKeys
@@ -210,7 +212,7 @@ getContactInfo Tox{toxCryptoKeys,toxRouting} = join $ atomically $ do
210 return DHT.DHTPublicKey 212 return DHT.DHTPublicKey
211 { dhtpkNonce = timestamp 213 { dhtpkNonce = timestamp
212 , dhtpk = id2key self 214 , dhtpk = id2key self
213 , dhtpkNodes = DHT.SendNodes $ take 4 ns 215 , dhtpkNodes = DHT.SendNodes $ take 4 $ relays ++ map TCP.fromUDPNode ns
214 } 216 }
215 217
216isLocalHost :: SockAddr -> Bool 218isLocalHost :: SockAddr -> Bool
diff --git a/dht/src/Network/Tox/DHT/Handlers.hs b/dht/src/Network/Tox/DHT/Handlers.hs
index e93f565b..323d5f5e 100644
--- a/dht/src/Network/Tox/DHT/Handlers.hs
+++ b/dht/src/Network/Tox/DHT/Handlers.hs
@@ -7,6 +7,7 @@ module Network.Tox.DHT.Handlers where
7 7
8import Debug.Trace 8import Debug.Trace
9import Network.Tox.DHT.Transport as DHTTransport 9import Network.Tox.DHT.Transport as DHTTransport
10import Network.Tox.TCP.NodeId as TCP (fromUDPNode, udpNodeInfo)
10import Network.QueryResponse as QR hiding (Client) 11import Network.QueryResponse as QR hiding (Client)
11import qualified Network.QueryResponse as QR (Client) 12import qualified Network.QueryResponse as QR (Client)
12import Crypto.Tox 13import Crypto.Tox
@@ -257,6 +258,7 @@ getNodesH routing addr (GetNodes nid) = do
257 Want_IP4 -> (ks,ks6) 258 Want_IP4 -> (ks,ks6)
258 Want_Both -> error $ "BUG:unreachable at " ++ __FILE__ ++ ":" ++ show __LINE__ 259 Want_Both -> error $ "BUG:unreachable at " ++ __FILE__ ++ ":" ++ show __LINE__
259 return $ SendNodes 260 return $ SendNodes
261 $ map fromUDPNode
260 $ if null ns2 then ns1 262 $ if null ns2 then ns1
261 else take 4 (take 3 ns1 ++ ns2) 263 else take 4 (take 3 ns1 ++ ns2)
262 where 264 where
@@ -397,8 +399,9 @@ unsendNodes :: Message -> Maybe (Asymm (Nonce8,SendNodes))
397unsendNodes (DHTSendNodes asymm) = Just asymm 399unsendNodes (DHTSendNodes asymm) = Just asymm
398unsendNodes _ = Nothing 400unsendNodes _ = Nothing
399 401
402-- XXX: map udpNodeInfo is probably not right
400unwrapNodes :: SendNodes -> ( [NodeInfo], [NodeInfo], Maybe () ) 403unwrapNodes :: SendNodes -> ( [NodeInfo], [NodeInfo], Maybe () )
401unwrapNodes (SendNodes ns) = (ns,ns,Just ()) 404unwrapNodes (SendNodes ns) = (map udpNodeInfo ns,map udpNodeInfo ns,Just ())
402 405
403getNodes :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ())) 406getNodes :: Client -> TVar (HashMap NodeId [NodeInfoCallback]) -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],Maybe ()))
404getNodes client cbvar nid addr = do 407getNodes client cbvar nid addr = do
@@ -409,10 +412,10 @@ getNodes client cbvar nid addr = do
409 forM_ ns $ \n -> do 412 forM_ ns $ \n -> do
410 now <- getPOSIXTime 413 now <- getPOSIXTime
411 atomically $ do 414 atomically $ do
412 mcbs <- HashMap.lookup (nodeId n) <$> readTVar cbvar 415 mcbs <- HashMap.lookup (nodeId . udpNodeInfo $ n) <$> readTVar cbvar
413 forM_ mcbs $ \cbs -> do 416 forM_ mcbs $ \cbs -> do
414 forM_ cbs $ \cb -> do 417 forM_ cbs $ \cb -> do
415 rumoredAddress cb now (nodeAddr addr) n 418 rumoredAddress cb now (nodeAddr addr) (udpNodeInfo n)
416 return $ fmap unwrapNodes $ join reply 419 return $ fmap unwrapNodes $ join reply
417 420
418updateRouting :: Client -> Routing 421updateRouting :: Client -> Routing
diff --git a/dht/src/Network/Tox/DHT/Transport.hs b/dht/src/Network/Tox/DHT/Transport.hs
index b9b63165..7475b3b1 100644
--- a/dht/src/Network/Tox/DHT/Transport.hs
+++ b/dht/src/Network/Tox/DHT/Transport.hs
@@ -36,6 +36,7 @@ module Network.Tox.DHT.Transport
36 ) where 36 ) where
37 37
38import Network.Tox.NodeId 38import Network.Tox.NodeId
39import qualified Network.Tox.TCP.NodeId as TCP
39import Crypto.Tox hiding (encrypt,decrypt) 40import Crypto.Tox hiding (encrypt,decrypt)
40import qualified Crypto.Tox as ToxCrypto 41import qualified Crypto.Tox as ToxCrypto
41import Network.QueryResponse 42import Network.QueryResponse
@@ -315,7 +316,7 @@ newtype GetNodes = GetNodes NodeId
315instance Sized GetNodes where 316instance Sized GetNodes where
316 size = ConstSize 32 -- TODO This right? 317 size = ConstSize 32 -- TODO This right?
317 318
318newtype SendNodes = SendNodes [NodeInfo] 319newtype SendNodes = SendNodes [TCP.NodeInfo]
319 deriving (Eq,Ord,Show,Read) 320 deriving (Eq,Ord,Show,Read)
320 321
321instance Sized SendNodes where 322instance Sized SendNodes where
diff --git a/dht/src/Network/Tox/NodeId.hs b/dht/src/Network/Tox/NodeId.hs
index 6c82ce09..8567e77d 100644
--- a/dht/src/Network/Tox/NodeId.hs
+++ b/dht/src/Network/Tox/NodeId.hs
@@ -252,8 +252,8 @@ nodeInfoFromJSON prefer4 (JSON.Object v) = do
252getIP :: Word8 -> S.Get IP 252getIP :: Word8 -> S.Get IP
253getIP 0x02 = IPv4 <$> S.get 253getIP 0x02 = IPv4 <$> S.get
254getIP 0x0a = IPv6 <$> S.get 254getIP 0x0a = IPv6 <$> S.get
255getIP 0x82 = IPv4 <$> S.get -- TODO: TCP 255getIP 0x82 = IPv4 <$> S.get -- TODO: TCP TOX_TCP_INET
256getIP 0x8a = IPv6 <$> S.get -- TODO: TCP 256getIP 0x8a = IPv6 <$> S.get -- TODO: TCP TOX_TCP_INET6
257getIP x = fail ("unsupported address family ("++show x++")") 257getIP x = fail ("unsupported address family ("++show x++")")
258 258
259instance Sized NodeInfo where 259instance Sized NodeInfo where
diff --git a/dht/src/Network/Tox/Onion/Handlers.hs b/dht/src/Network/Tox/Onion/Handlers.hs
index b35631a3..52dcf536 100644
--- a/dht/src/Network/Tox/Onion/Handlers.hs
+++ b/dht/src/Network/Tox/Onion/Handlers.hs
@@ -4,6 +4,7 @@
4module Network.Tox.Onion.Handlers where 4module Network.Tox.Onion.Handlers where
5 5
6import Network.Kademlia.Search 6import Network.Kademlia.Search
7import Network.Tox.TCP.NodeId (udpNodeInfo)
7import Network.Tox.DHT.Transport 8import Network.Tox.DHT.Transport
8import Network.Tox.DHT.Handlers hiding (Message,Client) 9import Network.Tox.DHT.Handlers hiding (Message,Client)
9import Network.Tox.Onion.Transport 10import Network.Tox.Onion.Transport
@@ -251,7 +252,7 @@ announceSerializer getTimeout = MethodSerializer
251 } 252 }
252 253
253unwrapAnnounceResponse :: Maybe NodeId -> NodeInfo -> AnnounceResponse -> ([NodeInfo], [Rendezvous], Maybe Nonce32) 254unwrapAnnounceResponse :: Maybe NodeId -> NodeInfo -> AnnounceResponse -> ([NodeInfo], [Rendezvous], Maybe Nonce32)
254unwrapAnnounceResponse alias ni (AnnounceResponse is_stored (SendNodes ns)) 255unwrapAnnounceResponse alias ni (AnnounceResponse is_stored (SendNodes ns0)) | let ns = map udpNodeInfo ns0
255 = case is_stored of 256 = case is_stored of
256 NotStored n32 -> ( ns , [] , Just n32) 257 NotStored n32 -> ( ns , [] , Just n32)
257 SendBackKey k -> ( ns , [Rendezvous k ni] , Nothing ) 258 SendBackKey k -> ( ns , [Rendezvous k ni] , Nothing )
diff --git a/dht/src/Network/Tox/TCP.hs b/dht/src/Network/Tox/TCP.hs
index e80a22d1..1531dfb4 100644
--- a/dht/src/Network/Tox/TCP.hs
+++ b/dht/src/Network/Tox/TCP.hs
@@ -44,6 +44,7 @@ import Network.Kademlia.Routing
44import Network.Kademlia.Search hiding (sendQuery) 44import Network.Kademlia.Search hiding (sendQuery)
45import Network.QueryResponse 45import Network.QueryResponse
46import Network.QueryResponse.TCP 46import Network.QueryResponse.TCP
47import Network.Tox.TCP.NodeId ()
47import Network.Tox.DHT.Handlers (toxSpace) 48import Network.Tox.DHT.Handlers (toxSpace)
48import Network.Tox.Onion.Transport hiding (encrypt,decrypt) 49import Network.Tox.Onion.Transport hiding (encrypt,decrypt)
49import Network.Tox.Onion.Handlers (unwrapAnnounceResponse) 50import Network.Tox.Onion.Handlers (unwrapAnnounceResponse)
@@ -57,10 +58,6 @@ withSize f = case size of len -> f len
57 58
58type NodeId = UDP.NodeId 59type NodeId = UDP.NodeId
59 60
60-- example:
61-- KEyW2Bm.S-DpIGp72380BAfgintUWX1KX.6ZU.4m5Ex@80.99.99.99:33400{tcp:443}
62instance Show NodeInfo where
63 show (NodeInfo udp port) = show udp ++ "{tcp:"++show port++"}"
64 61
65nodeId :: NodeInfo -> NodeId 62nodeId :: NodeInfo -> NodeId
66nodeId ni = UDP.nodeId $ udpNodeInfo ni 63nodeId ni = UDP.nodeId $ udpNodeInfo ni
diff --git a/dht/src/Network/Tox/TCP/NodeId.hs b/dht/src/Network/Tox/TCP/NodeId.hs
new file mode 100644
index 00000000..c218c88f
--- /dev/null
+++ b/dht/src/Network/Tox/TCP/NodeId.hs
@@ -0,0 +1,89 @@
1{-# LANGUAGE CPP #-}
2module Network.Tox.TCP.NodeId where
3
4import Crypto.Tox
5import qualified Network.Tox.NodeId as UDP
6
7import qualified Data.Aeson as JSON
8 ;import Data.Aeson (FromJSON (..), ToJSON (..))
9import Data.Functor.Contravariant
10import Data.Hashable
11import qualified Data.HashMap.Strict as HashMap
12import qualified Data.Vector as Vector
13import Data.Word
14import Network.Socket
15import qualified Text.ParserCombinators.ReadP as RP
16import Data.Serialize as S
17
18#if MIN_VERSION_iproute(1,7,4)
19import Data.IP hiding (fromSockAddr)
20#else
21import Data.IP
22#endif
23
24data NodeInfo = NodeInfo
25 { udpNodeInfo :: UDP.NodeInfo
26 , tcpPort :: PortNumber
27 }
28 deriving (Eq,Ord)
29
30instance Read NodeInfo where
31 readsPrec _ = RP.readP_to_S $ do
32 udp <- RP.readS_to_P reads
33 port <- RP.between (RP.char '{') (RP.char '}') $ do
34 mapM_ RP.char ("tcp:" :: String)
35 w16 <- RP.readS_to_P reads
36 return $ fromIntegral (w16 :: Word16)
37 return $ NodeInfo udp port
38
39instance ToJSON NodeInfo where
40 toJSON (NodeInfo udp port) = case (toJSON udp) of
41 JSON.Object tbl -> JSON.Object $ HashMap.insert "tcp_ports"
42 (JSON.Array $ Vector.fromList
43 [JSON.Number (fromIntegral port)])
44 tbl
45 x -> x -- Shouldn't happen.
46
47-- example:
48-- KEyW2Bm.S-DpIGp72380BAfgintUWX1KX.6ZU.4m5Ex@80.99.99.99:33400{tcp:443}
49instance Show NodeInfo where
50 show (NodeInfo udp port) = show udp ++ "{tcp:"++show port++"}"
51
52instance Sized NodeInfo where
53 size = contramap udpNodeInfo size
54
55
56getIP :: Word8 -> S.Get (Bool, IP)
57getIP 0x02 = (,) False . IPv4 <$> S.get -- UDP 4
58getIP 0x0a = (,) False . IPv6 <$> S.get -- UDP 6
59getIP 0x82 = (,) True . IPv4 <$> S.get -- TCP 4
60getIP 0x8a = (,) True . IPv6 <$> S.get -- TCP 6
61getIP x = fail ("unsupported address family ("++show x++")")
62
63instance S.Serialize NodeInfo where
64 get = do
65 addrfam <- S.get :: S.Get Word8
66 (istcp, ip) <- getIP addrfam
67 port <- S.get :: S.Get PortNumber
68 nid <- S.get
69 let (udpport, tcpport) = if istcp
70 then (0, port)
71 else (port, 0)
72 return $ NodeInfo (UDP.NodeInfo nid ip udpport) tcpport
73
74 put (NodeInfo (UDP.NodeInfo nid ip udpport) tcpport) = do
75 if tcpport==0
76 then do
77 case ip of
78 IPv4 ip4 -> S.put (2 :: Word8) >> S.put ip4
79 IPv6 ip6 -> S.put (10 :: Word8) >> S.put ip6
80 S.put udpport
81 else do
82 case ip of
83 IPv4 ip4 -> S.put (0x82 :: Word8) >> S.put ip4
84 IPv6 ip6 -> S.put (0x8a :: Word8) >> S.put ip6
85 S.put tcpport
86 S.put nid
87
88fromUDPNode :: UDP.NodeInfo -> NodeInfo
89fromUDPNode ni = NodeInfo ni 0