summaryrefslogtreecommitdiff
path: root/src/Network/Tox/Onion/Handlers.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-10-12 05:41:09 -0400
committerjoe <joe@jerkface.net>2017-10-12 05:41:09 -0400
commit37a7fa4978f89072d9231bcc9bd0848bb52c676c (patch)
tree48a2a934e5da1c6754915d5ad27417f604cbfd04 /src/Network/Tox/Onion/Handlers.hs
parent3024b35b05d7f520666af20ced8d1f3080837bb2 (diff)
WIP Onion routing.
Diffstat (limited to 'src/Network/Tox/Onion/Handlers.hs')
-rw-r--r--src/Network/Tox/Onion/Handlers.hs81
1 files changed, 72 insertions, 9 deletions
diff --git a/src/Network/Tox/Onion/Handlers.hs b/src/Network/Tox/Onion/Handlers.hs
index 08f5cabd..91dd843e 100644
--- a/src/Network/Tox/Onion/Handlers.hs
+++ b/src/Network/Tox/Onion/Handlers.hs
@@ -1,6 +1,8 @@
1{-# LANGUAGE PatternSynonyms #-} 1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE PatternSynonyms #-}
2module Network.Tox.Onion.Handlers where 3module Network.Tox.Onion.Handlers where
3 4
5import Network.Kademlia.Search
4import Network.Tox.DHT.Transport 6import Network.Tox.DHT.Transport
5import Network.Tox.DHT.Handlers hiding (Message,Client) 7import Network.Tox.DHT.Handlers hiding (Message,Client)
6import Network.Tox.Onion.Transport 8import Network.Tox.Onion.Transport
@@ -11,9 +13,11 @@ import qualified Data.Wrapper.PSQ as PSQ
11 ;import Data.Wrapper.PSQ (PSQ) 13 ;import Data.Wrapper.PSQ (PSQ)
12import Crypto.Error.Types (CryptoFailable (..), 14import Crypto.Error.Types (CryptoFailable (..),
13 throwCryptoError) 15 throwCryptoError)
16import Control.Arrow
14 17
15import System.IO 18import System.IO
16import qualified Data.ByteArray as BA 19import qualified Data.ByteArray as BA
20import Data.Function
17import Data.Serialize as S 21import Data.Serialize as S
18import qualified Data.Wrapper.PSQInt as Int 22import qualified Data.Wrapper.PSQInt as Int
19import Network.Kademlia 23import Network.Kademlia
@@ -59,23 +63,27 @@ classify msg = go msg
59-- The reason for this 20 second timeout in toxcore is that it gives a reasonable 63-- 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 64-- time (20 to 40 seconds) for a peer to announce himself while taking in count
61-- all the possible delays with some extra seconds. 65-- all the possible delays with some extra seconds.
66-- dhtd: src/Network/Tox/Onion/Handlers.hs:(67,1)-(101,23): Non-exhaustive patterns in function announceH
62announceH :: Routing -> TVar SessionTokens -> TVar AnnouncedKeys -> OnionDestination r -> AnnounceRequest -> IO AnnounceResponse 67announceH :: Routing -> TVar SessionTokens -> TVar AnnouncedKeys -> OnionDestination r -> AnnounceRequest -> IO AnnounceResponse
63announceH routing toks keydb (OnionToOwner naddr retpath) req = do 68announceH routing toks keydb oaddr req = do
64 case () of 69 case () of
65 _ | announcePingId req == zeros32 70 _ | announcePingId req == zeros32
66 -> go False 71 -> go False
67 72
68 _ -> let Nonce32 bs = announcePingId req 73 _ -> let Nonce32 bs = announcePingId req
69 tok = fromPaddedByteString 32 bs 74 tok = fromPaddedByteString 32 bs
70 in checkToken toks naddr tok >>= go 75 in checkToken toks (onionNodeInfo oaddr) tok >>= go
71 `catch` (\(SomeException e) -> hPutStrLn stderr ("announceH Exception! "++show e) >> throw e) 76 `catch` (\(SomeException e) -> hPutStrLn stderr ("announceH Exception! "++show e) >> throw e)
72 where 77 where
73 go withTok = do 78 go withTok = do
79 let naddr = onionNodeInfo oaddr
74 ns <- getNodesH routing naddr (GetNodes (announceSeeking req)) 80 ns <- getNodesH routing naddr (GetNodes (announceSeeking req))
75 tm <- getPOSIXTime 81 tm <- getPOSIXTime
76 let storing = (nodeId naddr == announceSeeking req) 82 let storing = case oaddr of
83 OnionToOwner _ pth -> guard (nodeId naddr == announceSeeking req) >> Just pth
84 _ -> Nothing
77 record <- atomically $ do 85 record <- atomically $ do
78 when (withTok && storing) $ do 86 forM_ storing $ \retpath -> when withTok $ do
79 let toxpath = AnnouncedRoute naddr{ nodeId = announceKey req } retpath 87 let toxpath = AnnouncedRoute naddr{ nodeId = announceKey req } retpath
80 -- Note: The following distance calculation assumes that 88 -- Note: The following distance calculation assumes that
81 -- our nodeid doesn't change and is the same for both 89 -- our nodeid doesn't change and is the same for both
@@ -85,12 +93,12 @@ announceH routing toks keydb (OnionToOwner naddr retpath) req = do
85 modifyTVar' keydb (insertKey tm (announceSeeking req) toxpath d) 93 modifyTVar' keydb (insertKey tm (announceSeeking req) toxpath d)
86 ks <- readTVar keydb 94 ks <- readTVar keydb
87 return $ snd . snd <$> MinMaxPSQ.lookup' (announceSeeking req) (keyAssoc ks) 95 return $ snd . snd <$> MinMaxPSQ.lookup' (announceSeeking req) (keyAssoc ks)
88 newtok <- if storing 96 newtok <- maybe (return $ zeros32)
89 then Nonce32 . toPaddedByteString 32 <$> grantToken toks naddr 97 (const $ Nonce32 . toPaddedByteString 32 <$> grantToken toks naddr)
90 else return $ zeros32 98 storing
91 let k = case record of 99 let k = case record of
92 Nothing -> NotStored newtok 100 Nothing -> NotStored newtok
93 Just _ | storing -> Acknowledged newtok 101 Just _ | isJust storing -> Acknowledged newtok
94 Just (AnnouncedRoute ni _) -> SendBackKey $ id2key (nodeId ni) 102 Just (AnnouncedRoute ni _) -> SendBackKey $ id2key (nodeId ni)
95 let response = AnnounceResponse k ns 103 let response = AnnounceResponse k ns
96 hPutStrLn stderr $ unwords ["Announce:", show req, "-reply->", show response] 104 hPutStrLn stderr $ unwords ["Announce:", show req, "-reply->", show response]
@@ -151,3 +159,58 @@ handlers net routing toks keydb AnnounceType
151 $ announceH routing toks keydb 159 $ announceH routing toks keydb
152handlers net _ _ keydb _ = Just $ NoReply Right $ dataToRouteH keydb net 160handlers net _ _ keydb _ = Just $ NoReply Right $ dataToRouteH keydb net
153 161
162toxidSearch :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int))
163 -> Client r
164 -> Search NodeId (IP, PortNumber) (Maybe Nonce32) NodeInfo PublicKey
165toxidSearch getTimeout client = Search
166 { searchSpace = toxSpace
167 , searchNodeAddress = nodeIP &&& nodePort
168 , searchQuery = announce getTimeout client
169 }
170
171announceSerializer :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int))
172 -> MethodSerializer
173 TransactionId
174 (OnionDestination r)
175 (OnionMessage Identity)
176 PacketKind
177 AnnounceRequest
178 (Maybe AnnounceResponse)
179announceSerializer getTimeout = MethodSerializer
180 { methodTimeout = getTimeout
181 , method = AnnounceType
182 , wrapQuery = \(TransactionId n8 n24) src dst req ->
183 -- :: tid -> addr -> addr -> a -> OnionMessage Identity
184 OnionAnnounce $ Assym
185 { -- The public key is our real long term public key if we want to
186 -- announce ourselves, a temporary one if we are searching for
187 -- friends.
188 senderKey = fromJust $ onionKey src -- TODO: FIXME: this should be a temporary alias key
189 , assymNonce = n24
190 , assymData = Identity (req, n8)
191 }
192 , unwrapResponse = \case -- :: OnionMessage Identity -> b
193 OnionAnnounceResponse _ _ resp -> Just $ runIdentity resp
194 _ -> Nothing
195 }
196
197unwrapAnnounceResponse :: AnnounceResponse -> ([NodeInfo], [PublicKey], Maybe Nonce32)
198unwrapAnnounceResponse (AnnounceResponse is_stored (SendNodes ns))
199 = case is_stored of
200 NotStored n32 -> (ns, [], Just n32)
201 SendBackKey k -> (ns, [k], Nothing)
202 Acknowledged n32 -> (ns, [], Just n32)
203
204announce :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int))
205 -> Client r
206 -> NodeId
207 -> NodeInfo
208 -> IO (Maybe ([NodeInfo],[PublicKey],Maybe Nonce32))
209announce getTimeout client nid ni =
210 -- Four tries and then we tap out.
211 flip fix 4 $ \loop n -> do
212 let oaddr = OnionDestination ni Nothing
213 mb <- QR.sendQuery client (announceSerializer getTimeout) (AnnounceRequest zeros32 nid zeroID) oaddr
214 maybe (if n>0 then loop $! n - 1 else return Nothing)
215 (return . Just . unwrapAnnounceResponse)
216 $ join mb