diff options
Diffstat (limited to 'src/Network/Tox')
-rw-r--r-- | src/Network/Tox/DHT/Handlers.hs | 26 | ||||
-rw-r--r-- | src/Network/Tox/NodeId.hs | 5 | ||||
-rw-r--r-- | src/Network/Tox/Onion/Handlers.hs | 81 | ||||
-rw-r--r-- | src/Network/Tox/Onion/Transport.hs | 61 |
4 files changed, 136 insertions, 37 deletions
diff --git a/src/Network/Tox/DHT/Handlers.hs b/src/Network/Tox/DHT/Handlers.hs index c9adc860..a3f13ac7 100644 --- a/src/Network/Tox/DHT/Handlers.hs +++ b/src/Network/Tox/DHT/Handlers.hs | |||
@@ -105,7 +105,6 @@ data Routing = Routing | |||
105 | , sched6 :: !( TVar (Int.PSQ POSIXTime) ) | 105 | , sched6 :: !( TVar (Int.PSQ POSIXTime) ) |
106 | , routing6 :: !( TVar (R.BucketList NodeInfo) ) | 106 | , routing6 :: !( TVar (R.BucketList NodeInfo) ) |
107 | , committee6 :: TriadCommittee NodeId SockAddr | 107 | , committee6 :: TriadCommittee NodeId SockAddr |
108 | , orouter :: OnionRouter | ||
109 | } | 108 | } |
110 | 109 | ||
111 | newRouting :: SockAddr -> TransportCrypto | 110 | newRouting :: SockAddr -> TransportCrypto |
@@ -124,8 +123,9 @@ newRouting addr crypto update4 update6 = do | |||
124 | tentative_info6 <- | 123 | tentative_info6 <- |
125 | maybe (tentative_info { nodeIP = tentative_ip6 }) | 124 | maybe (tentative_info { nodeIP = tentative_ip6 }) |
126 | (\ip6 -> tentative_info { nodeIP = IPv6 ip6 }) | 125 | (\ip6 -> tentative_info { nodeIP = IPv6 ip6 }) |
127 | <$> global6 | 126 | <$> case addr of |
128 | orouter <- newOnionRouter | 127 | SockAddrInet {} -> return Nothing |
128 | _ -> global6 | ||
129 | atomically $ do | 129 | atomically $ do |
130 | let nobkts = R.defaultBucketCount :: Int | 130 | let nobkts = R.defaultBucketCount :: Int |
131 | tbl4 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info4 nobkts | 131 | tbl4 <- newTVar $ R.nullTable (comparing nodeId) (\s -> hashWithSalt s . nodeId) tentative_info4 nobkts |
@@ -134,7 +134,7 @@ newRouting addr crypto update4 update6 = do | |||
134 | committee6 <- newTriadCommittee (update6 tbl6) -- updateIPVote tbl6 addr6 | 134 | committee6 <- newTriadCommittee (update6 tbl6) -- updateIPVote tbl6 addr6 |
135 | sched4 <- newTVar Int.empty | 135 | sched4 <- newTVar Int.empty |
136 | sched6 <- newTVar Int.empty | 136 | sched6 <- newTVar Int.empty |
137 | return $ Routing tentative_info sched4 tbl4 committee4 sched6 tbl6 committee6 orouter | 137 | return $ Routing tentative_info sched4 tbl4 committee4 sched6 tbl6 committee6 |
138 | 138 | ||
139 | 139 | ||
140 | -- TODO: This should cover more cases | 140 | -- TODO: This should cover more cases |
@@ -200,7 +200,7 @@ serializer :: PacketKind | |||
200 | -> (Message -> Maybe (Assym (Nonce8,pong))) | 200 | -> (Message -> Maybe (Assym (Nonce8,pong))) |
201 | -> MethodSerializer TransactionId NodeInfo Message PacketKind ping (Maybe pong) | 201 | -> MethodSerializer TransactionId NodeInfo Message PacketKind ping (Maybe pong) |
202 | serializer pktkind mkping mkpong = MethodSerializer | 202 | serializer pktkind mkping mkpong = MethodSerializer |
203 | { methodTimeout = 5 | 203 | { methodTimeout = \tid addr -> return (addr, 5000000) |
204 | , method = pktkind | 204 | , method = pktkind |
205 | -- wrapQuery :: tid -> addr -> addr -> qry -> x | 205 | -- wrapQuery :: tid -> addr -> addr -> qry -> x |
206 | , wrapQuery = \tid src dst ping -> mkping $ wrapAssym tid src dst (, ping) | 206 | , wrapQuery = \tid src dst ping -> mkping $ wrapAssym tid src dst (, ping) |
@@ -232,20 +232,20 @@ unwrapNodes (SendNodes ns) = (ns,ns,()) | |||
232 | 232 | ||
233 | getNodes :: Client -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],())) | 233 | getNodes :: Client -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],())) |
234 | getNodes client nid addr = do | 234 | getNodes client nid addr = do |
235 | hPutStrLn stderr $ show addr ++ " <-- getnodes " ++ show nid | 235 | -- hPutStrLn stderr $ show addr ++ " <-- getnodes " ++ show nid |
236 | reply <- QR.sendQuery client (serializer GetNodesType DHTGetNodes unsendNodes) (GetNodes nid) addr | 236 | reply <- QR.sendQuery client (serializer GetNodesType DHTGetNodes unsendNodes) (GetNodes nid) addr |
237 | hPutStrLn stderr $ show addr ++ " -sendnodes-> " ++ show reply | 237 | -- hPutStrLn stderr $ show addr ++ " -sendnodes-> " ++ show reply |
238 | return $ fmap unwrapNodes $ join reply | 238 | return $ fmap unwrapNodes $ join reply |
239 | 239 | ||
240 | updateRouting :: Client -> Routing -> NodeInfo -> Message -> IO () | 240 | updateRouting :: Client -> Routing -> OnionRouter -> NodeInfo -> Message -> IO () |
241 | updateRouting client routing naddr msg = do | 241 | updateRouting client routing orouter naddr msg = do |
242 | let typ = fst $ dhtMessageType $ fst $ DHTTransport.encrypt (error "updateRouting") msg naddr | 242 | let typ = fst $ dhtMessageType $ fst $ DHTTransport.encrypt (error "updateRouting") msg naddr |
243 | tid = mapMessage (\n24 (n8,_) -> TransactionId n8 n24) msg | 243 | tid = mapMessage (\n24 (n8,_) -> TransactionId n8 n24) msg |
244 | hPutStrLn stderr $ "updateRouting "++show (typ,tid) | 244 | -- hPutStrLn stderr $ "updateRouting "++show (typ,tid) |
245 | -- TODO: check msg type | 245 | -- TODO: check msg type |
246 | case prefer4or6 naddr Nothing of | 246 | case prefer4or6 naddr Nothing of |
247 | Want_IP4 -> updateTable client naddr (orouter routing) (routing4 routing) (committee4 routing) (sched4 routing) | 247 | Want_IP4 -> updateTable client naddr orouter (routing4 routing) (committee4 routing) (sched4 routing) |
248 | Want_IP6 -> updateTable client naddr (orouter routing) (routing6 routing) (committee6 routing) (sched6 routing) | 248 | Want_IP6 -> updateTable client naddr orouter (routing6 routing) (committee6 routing) (sched6 routing) |
249 | 249 | ||
250 | updateTable :: Client -> NodeInfo -> OnionRouter -> TVar (R.BucketList NodeInfo) -> TriadCommittee NodeId SockAddr -> TVar (Int.PSQ POSIXTime) -> IO () | 250 | updateTable :: Client -> NodeInfo -> OnionRouter -> TVar (R.BucketList NodeInfo) -> TriadCommittee NodeId SockAddr -> TVar (Int.PSQ POSIXTime) -> IO () |
251 | updateTable client naddr orouter tbl committee sched = do | 251 | updateTable client naddr orouter tbl committee sched = do |
@@ -262,7 +262,7 @@ toxKademlia client committee orouter var sched | |||
262 | { tblTransition = \tr -> do | 262 | { tblTransition = \tr -> do |
263 | io1 <- transitionCommittee committee tr | 263 | io1 <- transitionCommittee committee tr |
264 | io2 <- touchBucket toxSpace (15*60) var sched tr | 264 | io2 <- touchBucket toxSpace (15*60) var sched tr |
265 | hookBucketList orouter tr | 265 | hookBucketList toxSpace var orouter tr |
266 | return $ do | 266 | return $ do |
267 | io1 >> io2 | 267 | io1 >> io2 |
268 | {- | 268 | {- |
diff --git a/src/Network/Tox/NodeId.hs b/src/Network/Tox/NodeId.hs index 959d689c..d0c57416 100644 --- a/src/Network/Tox/NodeId.hs +++ b/src/Network/Tox/NodeId.hs | |||
@@ -223,7 +223,10 @@ instance Sized NodeInfo where | |||
223 | instance S.Serialize NodeInfo where | 223 | instance S.Serialize NodeInfo where |
224 | get = do | 224 | get = do |
225 | addrfam <- S.get :: S.Get Word8 | 225 | addrfam <- S.get :: S.Get Word8 |
226 | ip <- getIP addrfam | 226 | let fallback = do -- FIXME: Handle unrecognized address families. |
227 | IPv6 <$> S.get | ||
228 | return $ IPv6 (read "::" :: IPv6) | ||
229 | ip <- getIP addrfam <|> fallback | ||
227 | port <- S.get :: S.Get PortNumber | 230 | port <- S.get :: S.Get PortNumber |
228 | nid <- S.get | 231 | nid <- S.get |
229 | return $ NodeInfo nid ip port | 232 | return $ NodeInfo nid ip port |
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 #-} | ||
2 | module Network.Tox.Onion.Handlers where | 3 | module Network.Tox.Onion.Handlers where |
3 | 4 | ||
5 | import Network.Kademlia.Search | ||
4 | import Network.Tox.DHT.Transport | 6 | import Network.Tox.DHT.Transport |
5 | import Network.Tox.DHT.Handlers hiding (Message,Client) | 7 | import Network.Tox.DHT.Handlers hiding (Message,Client) |
6 | import Network.Tox.Onion.Transport | 8 | import 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) |
12 | import Crypto.Error.Types (CryptoFailable (..), | 14 | import Crypto.Error.Types (CryptoFailable (..), |
13 | throwCryptoError) | 15 | throwCryptoError) |
16 | import Control.Arrow | ||
14 | 17 | ||
15 | import System.IO | 18 | import System.IO |
16 | import qualified Data.ByteArray as BA | 19 | import qualified Data.ByteArray as BA |
20 | import Data.Function | ||
17 | import Data.Serialize as S | 21 | import Data.Serialize as S |
18 | import qualified Data.Wrapper.PSQInt as Int | 22 | import qualified Data.Wrapper.PSQInt as Int |
19 | import Network.Kademlia | 23 | import 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 | ||
62 | announceH :: Routing -> TVar SessionTokens -> TVar AnnouncedKeys -> OnionDestination r -> AnnounceRequest -> IO AnnounceResponse | 67 | announceH :: Routing -> TVar SessionTokens -> TVar AnnouncedKeys -> OnionDestination r -> AnnounceRequest -> IO AnnounceResponse |
63 | announceH routing toks keydb (OnionToOwner naddr retpath) req = do | 68 | announceH 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 |
152 | handlers net _ _ keydb _ = Just $ NoReply Right $ dataToRouteH keydb net | 160 | handlers net _ _ keydb _ = Just $ NoReply Right $ dataToRouteH keydb net |
153 | 161 | ||
162 | toxidSearch :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int)) | ||
163 | -> Client r | ||
164 | -> Search NodeId (IP, PortNumber) (Maybe Nonce32) NodeInfo PublicKey | ||
165 | toxidSearch getTimeout client = Search | ||
166 | { searchSpace = toxSpace | ||
167 | , searchNodeAddress = nodeIP &&& nodePort | ||
168 | , searchQuery = announce getTimeout client | ||
169 | } | ||
170 | |||
171 | announceSerializer :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int)) | ||
172 | -> MethodSerializer | ||
173 | TransactionId | ||
174 | (OnionDestination r) | ||
175 | (OnionMessage Identity) | ||
176 | PacketKind | ||
177 | AnnounceRequest | ||
178 | (Maybe AnnounceResponse) | ||
179 | announceSerializer 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 | |||
197 | unwrapAnnounceResponse :: AnnounceResponse -> ([NodeInfo], [PublicKey], Maybe Nonce32) | ||
198 | unwrapAnnounceResponse (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 | |||
204 | announce :: (TransactionId -> OnionDestination r -> STM (OnionDestination r, Int)) | ||
205 | -> Client r | ||
206 | -> NodeId | ||
207 | -> NodeInfo | ||
208 | -> IO (Maybe ([NodeInfo],[PublicKey],Maybe Nonce32)) | ||
209 | announce 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 | ||
diff --git a/src/Network/Tox/Onion/Transport.hs b/src/Network/Tox/Onion/Transport.hs index a3c1950f..b5ac748a 100644 --- a/src/Network/Tox/Onion/Transport.hs +++ b/src/Network/Tox/Onion/Transport.hs | |||
@@ -35,6 +35,8 @@ module Network.Tox.Onion.Transport | |||
35 | , peelSymmetric | 35 | , peelSymmetric |
36 | , OnionRoute(..) | 36 | , OnionRoute(..) |
37 | , N3 | 37 | , N3 |
38 | , onionKey | ||
39 | , onionNodeInfo | ||
38 | ) where | 40 | ) where |
39 | 41 | ||
40 | import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort) | 42 | import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort) |
@@ -42,10 +44,11 @@ import Network.QueryResponse | |||
42 | import Crypto.Tox hiding (encrypt,decrypt) | 44 | import Crypto.Tox hiding (encrypt,decrypt) |
43 | import Network.Tox.NodeId | 45 | import Network.Tox.NodeId |
44 | import qualified Crypto.Tox as ToxCrypto | 46 | import qualified Crypto.Tox as ToxCrypto |
45 | import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes,nodeInfo,DHTPublicKey,asymNodeInfo) | 47 | import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes(..),nodeInfo,DHTPublicKey,asymNodeInfo) |
46 | 48 | ||
47 | import Debug.Trace | 49 | import Debug.Trace |
48 | import Control.Arrow | 50 | import Control.Arrow |
51 | import Control.Applicative | ||
49 | import Control.Concurrent.STM | 52 | import Control.Concurrent.STM |
50 | import Control.Monad | 53 | import Control.Monad |
51 | import qualified Data.ByteString as B | 54 | import qualified Data.ByteString as B |
@@ -88,14 +91,23 @@ deriving instance ( Show (f (AnnounceRequest, Nonce8)) | |||
88 | , Show (f DataToRoute) | 91 | , Show (f DataToRoute) |
89 | ) => Show (OnionMessage f) | 92 | ) => Show (OnionMessage f) |
90 | 93 | ||
94 | msgNonce :: OnionMessage f -> Nonce24 | ||
95 | msgNonce (OnionAnnounce a) = assymNonce a | ||
96 | msgNonce (OnionAnnounceResponse _ n24 _) = n24 | ||
97 | msgNonce (OnionToRoute _ a) = assymNonce a | ||
98 | msgNonce (OnionToRouteResponse a) = assymNonce a | ||
99 | |||
91 | data OnionDestination r | 100 | data OnionDestination r |
92 | = OnionToOwner NodeInfo (ReturnPath N3) -- ^ Somebody else's path to us. | 101 | = OnionToOwner NodeInfo (ReturnPath N3) -- ^ Somebody else's path to us. |
93 | | OnionDestination NodeInfo (Maybe r) -- ^ Our own onion-path. | 102 | | OnionDestination NodeInfo (Maybe r) -- ^ Our own onion-path. |
94 | deriving Show | 103 | deriving Show |
95 | 104 | ||
105 | onionNodeInfo :: OnionDestination r -> NodeInfo | ||
106 | onionNodeInfo (OnionToOwner ni _) = ni | ||
107 | onionNodeInfo (OnionDestination ni _) = ni | ||
108 | |||
96 | onionKey :: OnionDestination r -> Maybe PublicKey | 109 | onionKey :: OnionDestination r -> Maybe PublicKey |
97 | onionKey (OnionToOwner ni _) = Just $ id2key (nodeId ni) | 110 | onionKey od = Just $ id2key . nodeId $ onionNodeInfo od |
98 | onionKey (OnionDestination ni _) = Just $ id2key (nodeId ni) | ||
99 | 111 | ||
100 | instance Sized (OnionMessage Encrypted) where | 112 | instance Sized (OnionMessage Encrypted) where |
101 | size = VarSize $ \case | 113 | size = VarSize $ \case |
@@ -176,11 +188,19 @@ encodeOnionAddr :: (NodeInfo -> r -> IO (Maybe OnionRoute)) | |||
176 | encodeOnionAddr _ (msg,OnionToOwner ni p) = | 188 | encodeOnionAddr _ (msg,OnionToOwner ni p) = |
177 | return $ Just ( runPut $ putResponse (OnionResponse p msg) | 189 | return $ Just ( runPut $ putResponse (OnionResponse p msg) |
178 | , nodeAddr ni ) | 190 | , nodeAddr ni ) |
179 | encodeOnionAddr _ (msg,OnionDestination _ Nothing ) = return Nothing | 191 | encodeOnionAddr _ (msg,OnionDestination _ Nothing ) = do |
192 | hPutStrLn stderr $ "ONION encode missing routeid" | ||
193 | return Nothing | ||
180 | encodeOnionAddr getRoute (msg,OnionDestination ni (Just rid)) = do | 194 | encodeOnionAddr getRoute (msg,OnionDestination ni (Just rid)) = do |
181 | let go route = do | 195 | let go route0 = do |
182 | return (runPut $ putRequest $ wrapForRoute msg ni route, nodeAddr ni) | 196 | let route = route0 { routeNonce = msgNonce msg } -- TODO: This necessary? |
183 | getRoute ni rid >>= mapM go | 197 | return ( runPut $ putRequest $ wrapForRoute msg ni route |
198 | , nodeAddr $ routeNodeA route) | ||
199 | mapM' f x = do | ||
200 | hPutStrLn stderr $ "ONION encode sending to " ++ show ni | ||
201 | hPutStrLn stderr $ "ONION encode getRoute -> " ++ show (mapM (\y -> map ($ y) [routeNodeA,routeNodeB,routeNodeC]) x) | ||
202 | mapM f x | ||
203 | getRoute ni rid >>= mapM' go | ||
184 | 204 | ||
185 | 205 | ||
186 | forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport | 206 | forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport |
@@ -239,16 +259,19 @@ deriving instance ( Show (Forwarding (ThreeMinus n) (OnionMessage Encrypted)) | |||
239 | instance ( Serialize (Forwarding (ThreeMinus n) (OnionMessage Encrypted)) | 259 | instance ( Serialize (Forwarding (ThreeMinus n) (OnionMessage Encrypted)) |
240 | , Sized (ReturnPath n) | 260 | , Sized (ReturnPath n) |
241 | , Serialize (ReturnPath n) | 261 | , Serialize (ReturnPath n) |
262 | , Typeable n | ||
242 | ) => Serialize (OnionRequest n) where | 263 | ) => Serialize (OnionRequest n) where |
243 | get = do | 264 | get = do |
244 | -- TODO share code with 'getOnionRequest' | 265 | -- TODO share code with 'getOnionRequest' |
245 | n24 <- get | 266 | n24 <- case eqT :: Maybe (n :~: N3) of |
267 | Just Refl -> return $ Nonce24 zeros24 | ||
268 | Nothing -> get | ||
246 | cnt <- remaining | 269 | cnt <- remaining |
247 | let fwdsize = case size :: Size (ReturnPath n) of ConstSize n -> cnt - n | 270 | let fwdsize = case size :: Size (ReturnPath n) of ConstSize n -> cnt - n |
248 | fwd <- isolate fwdsize get | 271 | fwd <- isolate fwdsize get |
249 | rpath <- get | 272 | rpath <- get |
250 | return $ OnionRequest n24 fwd rpath | 273 | return $ OnionRequest n24 fwd rpath |
251 | put (OnionRequest n f p) = put n >> put f >> put p | 274 | put (OnionRequest n f p) = maybe (put n) (\Refl -> return ()) (eqT :: Maybe (n :~: N3)) >> put f >> put p |
252 | 275 | ||
253 | -- getRequest :: _ | 276 | -- getRequest :: _ |
254 | -- getRequest = OnionRequest <$> get <*> get <*> get | 277 | -- getRequest = OnionRequest <$> get <*> get <*> get |
@@ -402,6 +425,7 @@ handleOnionRequest :: forall a proxy n. | |||
402 | ( LessThanThree n | 425 | ( LessThanThree n |
403 | , KnownPeanoNat n | 426 | , KnownPeanoNat n |
404 | , Sized (ReturnPath n) | 427 | , Sized (ReturnPath n) |
428 | , Typeable n | ||
405 | ) => proxy n -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionRequest n -> IO a | 429 | ) => proxy n -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionRequest n -> IO a |
406 | handleOnionRequest proxy crypto saddr udp kont (OnionRequest nonce msg rpath) = do | 430 | handleOnionRequest proxy crypto saddr udp kont (OnionRequest nonce msg rpath) = do |
407 | let n = peanoVal rpath | 431 | let n = peanoVal rpath |
@@ -414,7 +438,7 @@ handleOnionRequest proxy crypto saddr udp kont (OnionRequest nonce msg rpath) = | |||
414 | hPutStrLn stderr $ unwords [ "peelOnion:", show n, either show show (either4or6 saddr), e] | 438 | hPutStrLn stderr $ unwords [ "peelOnion:", show n, either show show (either4or6 saddr), e] |
415 | kont | 439 | kont |
416 | Right (Addressed dst msg') -> do | 440 | Right (Addressed dst msg') -> do |
417 | hPutStrLn stderr $ unwords [ "peelOnion:", show n, either show show (either4or6 saddr), "SUCCESS"] | 441 | hPutStrLn stderr $ unwords [ "peelOnion:", show n, either show show (either4or6 saddr), "-->", either show show (either4or6 dst), "SUCCESS"] |
418 | sendMessage udp dst (runPut $ putRequest $ OnionRequest nonce msg' $ wrapSymmetric sym snonce saddr rpath) | 442 | sendMessage udp dst (runPut $ putRequest $ OnionRequest nonce msg' $ wrapSymmetric sym snonce saddr rpath) |
419 | kont | 443 | kont |
420 | 444 | ||
@@ -472,9 +496,13 @@ getOnionRequest = do | |||
472 | path <- get | 496 | path <- get |
473 | return (a,path) | 497 | return (a,path) |
474 | 498 | ||
475 | putRequest :: (KnownPeanoNat n, Serialize (OnionRequest n)) => OnionRequest n -> Put | 499 | putRequest :: ( KnownPeanoNat n |
500 | , Serialize (OnionRequest n) | ||
501 | , Typeable n | ||
502 | ) => OnionRequest n -> Put | ||
476 | putRequest req = do | 503 | putRequest req = do |
477 | putWord8 $ 0x80 + fromIntegral (peanoVal req) | 504 | let tag = 0x80 + fromIntegral (peanoVal req) |
505 | when (tag <= 0x82) (putWord8 tag) | ||
478 | put req | 506 | put req |
479 | 507 | ||
480 | putResponse :: (KnownPeanoNat n, Serialize (OnionResponse n)) => OnionResponse n -> Put | 508 | putResponse :: (KnownPeanoNat n, Serialize (OnionResponse n)) => OnionResponse n -> Put |
@@ -513,9 +541,14 @@ data AnnounceResponse = AnnounceResponse | |||
513 | instance Sized AnnounceResponse where | 541 | instance Sized AnnounceResponse where |
514 | size = contramap is_stored size <> contramap announceNodes size | 542 | size = contramap is_stored size <> contramap announceNodes size |
515 | 543 | ||
544 | getNodeList :: S.Get [NodeInfo] | ||
545 | getNodeList = do | ||
546 | n <- S.get | ||
547 | (:) n <$> (getNodeList <|> pure []) | ||
548 | |||
516 | instance S.Serialize AnnounceResponse where | 549 | instance S.Serialize AnnounceResponse where |
517 | get = AnnounceResponse <$> S.get <*> S.get | 550 | get = AnnounceResponse <$> S.get <*> (SendNodes <$> getNodeList) |
518 | put (AnnounceResponse st ns) = S.put st >> S.put ns | 551 | put (AnnounceResponse st (SendNodes ns)) = S.put st >> mapM_ S.put ns |
519 | 552 | ||
520 | data DataToRoute = DataToRoute | 553 | data DataToRoute = DataToRoute |
521 | { dataFromKey :: PublicKey -- Real public key of sender | 554 | { dataFromKey :: PublicKey -- Real public key of sender |