summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CryptoTransport.hs2
-rw-r--r--DHTHandlers.hs2
-rw-r--r--OnionHandlers.hs148
-rw-r--r--OnionTransport.hs4
-rw-r--r--Tox.hs2
-rw-r--r--ToxTransport.hs2
-rw-r--r--examples/dhtd.hs2
-rw-r--r--src/Network/Tox/DHT/Transport.hs (renamed from DHTTransport.hs)6
8 files changed, 158 insertions, 10 deletions
diff --git a/CryptoTransport.hs b/CryptoTransport.hs
index 203d4d82..9d4b3d84 100644
--- a/CryptoTransport.hs
+++ b/CryptoTransport.hs
@@ -12,7 +12,7 @@ module CryptoTransport
12 ) where 12 ) where
13 13
14import Crypto.Tox 14import Crypto.Tox
15import DHTTransport (Cookie) 15import Network.Tox.DHT.Transport (Cookie)
16 16
17import Network.Socket 17import Network.Socket
18import Data.ByteString 18import Data.ByteString
diff --git a/DHTHandlers.hs b/DHTHandlers.hs
index b98a4d6e..87f5e1b6 100644
--- a/DHTHandlers.hs
+++ b/DHTHandlers.hs
@@ -3,7 +3,7 @@
3{-# LANGUAGE TupleSections #-} 3{-# LANGUAGE TupleSections #-}
4module DHTHandlers where 4module DHTHandlers where
5 5
6import DHTTransport 6import Network.Tox.DHT.Transport as DHTTransport
7import Network.QueryResponse as QR hiding (Client) 7import Network.QueryResponse as QR hiding (Client)
8import qualified Network.QueryResponse as QR (Client) 8import qualified Network.QueryResponse as QR (Client)
9import Crypto.Tox 9import Crypto.Tox
diff --git a/OnionHandlers.hs b/OnionHandlers.hs
new file mode 100644
index 00000000..5e0951e8
--- /dev/null
+++ b/OnionHandlers.hs
@@ -0,0 +1,148 @@
1{-# LANGUAGE PatternSynonyms #-}
2module OnionHandlers where
3
4import Network.Tox.DHT.Transport
5import DHTHandlers hiding (Message,Client)
6import OnionTransport
7import Network.QueryResponse as QR hiding (Client)
8import qualified Network.QueryResponse as QR (Client)
9import Crypto.Tox
10import qualified Data.Wrapper.PSQ as PSQ
11 ;import Data.Wrapper.PSQ (PSQ)
12import Crypto.Error.Types (CryptoFailable (..),
13 throwCryptoError)
14
15import System.IO
16import qualified Data.ByteArray as BA
17import Data.Serialize as S
18import qualified Data.Wrapper.PSQInt as Int
19import Network.Kademlia
20import Network.Address (WantIP (..), ipFamily, testIdBit)
21import qualified Network.DHT.Routing as R
22import Control.TriadCommittee
23import qualified Data.MinMaxPSQ as MinMaxPSQ
24 ;import Data.MinMaxPSQ (MinMaxPSQ')
25import Network.BitTorrent.DHT.Token as Token
26
27import Control.Exception hiding (Handler)
28import Control.Monad
29import Control.Concurrent.STM
30import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime)
31import Network.Socket
32import Data.IP
33import Data.Maybe
34import Data.Bits
35import Data.Ord
36import Data.Functor.Identity
37
38type Client = QR.Client String PacketKind TransactionId OnionToOwner Message
39type Message = OnionMessage Identity
40
41classify :: Message -> MessageClass String PacketKind TransactionId
42classify msg = go msg
43 where
44 go (OnionAnnounce announce) = IsQuery AnnounceType
45 $ TransactionId (snd $ runIdentity $ assymData announce)
46 (assymNonce announce)
47 go (OnionAnnounceResponse n8 n24 resp) = IsResponse (TransactionId n8 n24)
48 go (OnionToRoute {}) = IsQuery DataRequestType (TransactionId (Nonce8 0) (Nonce24 zeros24))
49 go (OnionToRouteResponse {}) = IsResponse (TransactionId (Nonce8 0) (Nonce24 zeros24))
50
51-- Toxcore generates `ping_id`s by taking a 32 byte sha hash of the current time,
52-- some secret bytes generated when the instance is created, the current time
53-- divided by a 20 second timeout, the public key of the requester and the source
54-- ip/port that the packet was received from. Since the ip/port that the packet
55-- was received from is in the `ping_id`, the announce packets being sent with a
56-- ping id must be sent using the same path as the packet that we received the
57-- `ping_id` from or announcing will fail.
58--
59-- The reason for this 20 second timeout in toxcore is that it gives a reasonable
60-- time (20 to 40 seconds) for a peer to announce himself while taking in count
61-- all the possible delays with some extra seconds.
62announceH :: Routing -> TVar SessionTokens -> TVar AnnouncedKeys -> OnionToOwner -> AnnounceRequest -> IO AnnounceResponse
63announceH routing toks keydb (OnionToOwner naddr retpath) req = do
64 case () of
65 _ | announcePingId req == zeros32
66 -> go False
67
68 _ -> let Nonce32 bs = announcePingId req
69 tok = fromPaddedByteString 32 bs
70 in checkToken toks naddr tok >>= go
71 `catch` (\(SomeException e) -> hPutStrLn stderr ("announceH Exception! "++show e) >> throw e)
72 where
73 go withTok = do
74 ns <- getNodesH routing naddr (GetNodes (announceSeeking req))
75 tm <- getPOSIXTime
76 let storing = (nodeId naddr == announceSeeking req)
77 record <- atomically $ do
78 when (withTok && storing) $ do
79 let toxpath = OnionToOwner naddr{ nodeId = announceKey req } retpath
80 -- Note: The following distance calculation assumes that
81 -- our nodeid doesn't change and is the same for both
82 -- routing4 and routing6.
83 d = xorNodeId (nodeId (tentativeId routing))
84 (announceSeeking req)
85 modifyTVar' keydb (insertKey tm (announceSeeking req) toxpath d)
86 ks <- readTVar keydb
87 return $ snd . snd <$> MinMaxPSQ.lookup' (announceSeeking req) (keyAssoc ks)
88 newtok <- if storing
89 then Nonce32 . toPaddedByteString 32 <$> grantToken toks naddr
90 else return $ zeros32
91 let k = case record of
92 Nothing -> NotStored newtok
93 Just (OnionToOwner {}) | storing -> Acknowledged newtok
94 Just (OnionToOwner ni _) -> SendBackKey $ id2key (nodeId ni)
95 let response = AnnounceResponse k ns
96 hPutStrLn stderr $ unwords ["Announce:", show req, "-reply->", show response]
97 return response
98
99dataToRouteH ::
100 TVar AnnouncedKeys
101 -> Transport err OnionToOwner (OnionMessage f)
102 -> addr
103 -> OnionMessage f
104 -> IO ()
105dataToRouteH keydb udp _ (OnionToRoute pub assym) = do
106 let k = key2id pub
107 mb <- atomically $ do
108 ks <- readTVar keydb
109 forM (MinMaxPSQ.lookup' k (keyAssoc ks)) $ \(p,(cnt,rpath)) -> do
110 writeTVar keydb $ ks { keyAssoc = MinMaxPSQ.insert' k (cnt + 1, rpath) p (keyAssoc ks) }
111 return rpath
112 forM_ mb $ \rpath -> do
113 -- forward
114 sendMessage udp rpath $ OnionToRouteResponse assym
115 hPutStrLn stderr $ "Forwarding data-to-route -->"++show k
116
117type NodeDistance = NodeId
118
119data AnnouncedKeys = AnnouncedKeys
120 { keyByAge :: !(PSQ NodeId (Down POSIXTime)) -- timeout of 300 seconds
121 , keyAssoc :: !(MinMaxPSQ' NodeId NodeDistance (Int,OnionToOwner))
122 }
123
124
125insertKey :: POSIXTime -> NodeId -> OnionToOwner -> NodeDistance -> AnnouncedKeys -> AnnouncedKeys
126insertKey tm pub toxpath d keydb = AnnouncedKeys
127 { keyByAge = PSQ.insert pub (Down tm) (keyByAge keydb)
128 , keyAssoc = case MinMaxPSQ.lookup' pub (keyAssoc keydb) of
129 Just (_,(cnt,_)) -> MinMaxPSQ.insert' pub (cnt,toxpath) d (keyAssoc keydb)
130 Nothing -> MinMaxPSQ.insert' pub (0 ,toxpath) d (keyAssoc keydb)
131 }
132
133areq :: Message -> Either String AnnounceRequest
134areq (OnionAnnounce assym) = Right $ fst $ runIdentity $ assymData assym
135areq _ = Left "Unexpected non-announce OnionMessage"
136
137handlers :: Transport err OnionToOwner Message
138 -> Routing
139 -> TVar SessionTokens
140 -> TVar AnnouncedKeys
141 -> PacketKind
142 -> Maybe (MethodHandler String TransactionId OnionToOwner Message)
143handlers net routing toks keydb AnnounceType
144 = Just
145 $ MethodHandler areq (\(TransactionId n8 n24) src dst -> OnionAnnounceResponse n8 n24 . Identity)
146 $ announceH routing toks keydb
147handlers net _ _ keydb _ = Just $ NoReply Right $ dataToRouteH keydb net
148
diff --git a/OnionTransport.hs b/OnionTransport.hs
index 0ba71922..26130a0c 100644
--- a/OnionTransport.hs
+++ b/OnionTransport.hs
@@ -40,8 +40,8 @@ import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort)
40import Network.QueryResponse 40import Network.QueryResponse
41import Crypto.Tox hiding (encrypt,decrypt) 41import Crypto.Tox hiding (encrypt,decrypt)
42import Network.Tox.Address 42import Network.Tox.Address
43import qualified ToxCrypto 43import qualified Crypto.Tox as ToxCrypto
44import DHTTransport (NodeInfo(..),NodeId(..),SendNodes,nodeInfo,DHTPublicKey) 44import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes,nodeInfo,DHTPublicKey)
45 45
46import Debug.Trace 46import Debug.Trace
47import Control.Arrow 47import Control.Arrow
diff --git a/Tox.hs b/Tox.hs
index 44703cbd..a8ae8a84 100644
--- a/Tox.hs
+++ b/Tox.hs
@@ -86,7 +86,7 @@ import GHC.TypeLits
86import Crypto.Tox hiding (Assym) 86import Crypto.Tox hiding (Assym)
87import ToxTransport 87import ToxTransport
88import Network.Tox.Address 88import Network.Tox.Address
89import qualified DHTTransport as DHT 89import qualified Network.Tox.DHT.Transport as DHT
90import qualified DHTHandlers as DHT 90import qualified DHTHandlers as DHT
91import qualified OnionTransport as Onion 91import qualified OnionTransport as Onion
92import qualified OnionHandlers as Onion 92import qualified OnionHandlers as Onion
diff --git a/ToxTransport.hs b/ToxTransport.hs
index ea7f6492..a401638a 100644
--- a/ToxTransport.hs
+++ b/ToxTransport.hs
@@ -10,7 +10,7 @@ module ToxTransport (toxTransport) where
10 10
11import Network.QueryResponse 11import Network.QueryResponse
12import Crypto.Tox 12import Crypto.Tox
13import DHTTransport 13import Network.Tox.DHT.Transport
14import OnionTransport 14import OnionTransport
15import CryptoTransport 15import CryptoTransport
16 16
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index 5d4b3b9f..e52d494c 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -65,7 +65,7 @@ import Data.Wrapper.PSQ as PSQ (pattern (:->))
65import qualified Data.Wrapper.PSQ as PSQ 65import qualified Data.Wrapper.PSQ as PSQ
66import Data.Ord 66import Data.Ord
67import Data.Time.Clock.POSIX 67import Data.Time.Clock.POSIX
68import qualified DHTTransport as Tox 68import qualified Network.Tox.DHT.Transport as Tox
69import qualified DHTHandlers as Tox 69import qualified DHTHandlers as Tox
70import qualified OnionHandlers as Tox 70import qualified OnionHandlers as Tox
71import Data.Typeable 71import Data.Typeable
diff --git a/DHTTransport.hs b/src/Network/Tox/DHT/Transport.hs
index 189ff0ee..5a2d8a84 100644
--- a/DHTTransport.hs
+++ b/src/Network/Tox/DHT/Transport.hs
@@ -6,11 +6,11 @@
6{-# LANGUAGE TupleSections #-} 6{-# LANGUAGE TupleSections #-}
7{-# LANGUAGE TypeOperators #-} 7{-# LANGUAGE TypeOperators #-}
8{-# LANGUAGE UndecidableInstances #-} 8{-# LANGUAGE UndecidableInstances #-}
9module DHTTransport 9module Network.Tox.DHT.Transport
10 ( parseDHTAddr 10 ( parseDHTAddr
11 , encodeDHTAddr 11 , encodeDHTAddr
12 , forwardDHTRequests 12 , forwardDHTRequests
13 , module ToxAddress 13 , module Network.Tox.Address
14 , DHTMessage(..) 14 , DHTMessage(..)
15 , Ping(..) 15 , Ping(..)
16 , Pong(..) 16 , Pong(..)
@@ -28,7 +28,7 @@ module DHTTransport
28 28
29import Network.Tox.Address 29import Network.Tox.Address
30import Crypto.Tox hiding (encrypt,decrypt) 30import Crypto.Tox hiding (encrypt,decrypt)
31import qualified ToxCrypto 31import qualified Crypto.Tox as ToxCrypto
32import Network.QueryResponse 32import Network.QueryResponse
33 33
34import Control.Arrow 34import Control.Arrow