summaryrefslogtreecommitdiff
path: root/src/Network/Tox
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/Tox')
-rw-r--r--src/Network/Tox/DHT/Handlers.hs26
-rw-r--r--src/Network/Tox/NodeId.hs5
-rw-r--r--src/Network/Tox/Onion/Handlers.hs81
-rw-r--r--src/Network/Tox/Onion/Transport.hs61
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
111newRouting :: SockAddr -> TransportCrypto 110newRouting :: 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)
202serializer pktkind mkping mkpong = MethodSerializer 202serializer 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
233getNodes :: Client -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],())) 233getNodes :: Client -> NodeId -> NodeInfo -> IO (Maybe ([NodeInfo],[NodeInfo],()))
234getNodes client nid addr = do 234getNodes 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
240updateRouting :: Client -> Routing -> NodeInfo -> Message -> IO () 240updateRouting :: Client -> Routing -> OnionRouter -> NodeInfo -> Message -> IO ()
241updateRouting client routing naddr msg = do 241updateRouting 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
250updateTable :: Client -> NodeInfo -> OnionRouter -> TVar (R.BucketList NodeInfo) -> TriadCommittee NodeId SockAddr -> TVar (Int.PSQ POSIXTime) -> IO () 250updateTable :: Client -> NodeInfo -> OnionRouter -> TVar (R.BucketList NodeInfo) -> TriadCommittee NodeId SockAddr -> TVar (Int.PSQ POSIXTime) -> IO ()
251updateTable client naddr orouter tbl committee sched = do 251updateTable 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
223instance S.Serialize NodeInfo where 223instance 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 #-}
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
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
40import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort) 42import Network.Address (fromSockAddr,toSockAddr,setPort,either4or6,sockAddrPort)
@@ -42,10 +44,11 @@ import Network.QueryResponse
42import Crypto.Tox hiding (encrypt,decrypt) 44import Crypto.Tox hiding (encrypt,decrypt)
43import Network.Tox.NodeId 45import Network.Tox.NodeId
44import qualified Crypto.Tox as ToxCrypto 46import qualified Crypto.Tox as ToxCrypto
45import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes,nodeInfo,DHTPublicKey,asymNodeInfo) 47import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes(..),nodeInfo,DHTPublicKey,asymNodeInfo)
46 48
47import Debug.Trace 49import Debug.Trace
48import Control.Arrow 50import Control.Arrow
51import Control.Applicative
49import Control.Concurrent.STM 52import Control.Concurrent.STM
50import Control.Monad 53import Control.Monad
51import qualified Data.ByteString as B 54import 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
94msgNonce :: OnionMessage f -> Nonce24
95msgNonce (OnionAnnounce a) = assymNonce a
96msgNonce (OnionAnnounceResponse _ n24 _) = n24
97msgNonce (OnionToRoute _ a) = assymNonce a
98msgNonce (OnionToRouteResponse a) = assymNonce a
99
91data OnionDestination r 100data 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
105onionNodeInfo :: OnionDestination r -> NodeInfo
106onionNodeInfo (OnionToOwner ni _) = ni
107onionNodeInfo (OnionDestination ni _) = ni
108
96onionKey :: OnionDestination r -> Maybe PublicKey 109onionKey :: OnionDestination r -> Maybe PublicKey
97onionKey (OnionToOwner ni _) = Just $ id2key (nodeId ni) 110onionKey od = Just $ id2key . nodeId $ onionNodeInfo od
98onionKey (OnionDestination ni _) = Just $ id2key (nodeId ni)
99 111
100instance Sized (OnionMessage Encrypted) where 112instance Sized (OnionMessage Encrypted) where
101 size = VarSize $ \case 113 size = VarSize $ \case
@@ -176,11 +188,19 @@ encodeOnionAddr :: (NodeInfo -> r -> IO (Maybe OnionRoute))
176encodeOnionAddr _ (msg,OnionToOwner ni p) = 188encodeOnionAddr _ (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 )
179encodeOnionAddr _ (msg,OnionDestination _ Nothing ) = return Nothing 191encodeOnionAddr _ (msg,OnionDestination _ Nothing ) = do
192 hPutStrLn stderr $ "ONION encode missing routeid"
193 return Nothing
180encodeOnionAddr getRoute (msg,OnionDestination ni (Just rid)) = do 194encodeOnionAddr 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
186forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport 206forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport
@@ -239,16 +259,19 @@ deriving instance ( Show (Forwarding (ThreeMinus n) (OnionMessage Encrypted))
239instance ( Serialize (Forwarding (ThreeMinus n) (OnionMessage Encrypted)) 259instance ( 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
406handleOnionRequest proxy crypto saddr udp kont (OnionRequest nonce msg rpath) = do 430handleOnionRequest 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
475putRequest :: (KnownPeanoNat n, Serialize (OnionRequest n)) => OnionRequest n -> Put 499putRequest :: ( KnownPeanoNat n
500 , Serialize (OnionRequest n)
501 , Typeable n
502 ) => OnionRequest n -> Put
476putRequest req = do 503putRequest 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
480putResponse :: (KnownPeanoNat n, Serialize (OnionResponse n)) => OnionResponse n -> Put 508putResponse :: (KnownPeanoNat n, Serialize (OnionResponse n)) => OnionResponse n -> Put
@@ -513,9 +541,14 @@ data AnnounceResponse = AnnounceResponse
513instance Sized AnnounceResponse where 541instance Sized AnnounceResponse where
514 size = contramap is_stored size <> contramap announceNodes size 542 size = contramap is_stored size <> contramap announceNodes size
515 543
544getNodeList :: S.Get [NodeInfo]
545getNodeList = do
546 n <- S.get
547 (:) n <$> (getNodeList <|> pure [])
548
516instance S.Serialize AnnounceResponse where 549instance 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
520data DataToRoute = DataToRoute 553data DataToRoute = DataToRoute
521 { dataFromKey :: PublicKey -- Real public key of sender 554 { dataFromKey :: PublicKey -- Real public key of sender