summaryrefslogtreecommitdiff
path: root/src/Network/Tox/Onion
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-09-20 20:47:10 -0400
committerjoe <joe@jerkface.net>2017-09-20 20:47:10 -0400
commit6b822e47e4995e4aaf4cb1cc034c34314bd51da2 (patch)
tree5e83ab1f500ba850b25bcdd5f4d54bf03809dd22 /src/Network/Tox/Onion
parent447e9e53661edd7c633f757eb3403298849e4c35 (diff)
Added outbound initiation addresses to the Onion transport.
Diffstat (limited to 'src/Network/Tox/Onion')
-rw-r--r--src/Network/Tox/Onion/Handlers.hs20
-rw-r--r--src/Network/Tox/Onion/Transport.hs57
2 files changed, 42 insertions, 35 deletions
diff --git a/src/Network/Tox/Onion/Handlers.hs b/src/Network/Tox/Onion/Handlers.hs
index 9dc6177c..72398735 100644
--- a/src/Network/Tox/Onion/Handlers.hs
+++ b/src/Network/Tox/Onion/Handlers.hs
@@ -35,7 +35,7 @@ import Data.Bits
35import Data.Ord 35import Data.Ord
36import Data.Functor.Identity 36import Data.Functor.Identity
37 37
38type Client = QR.Client String PacketKind TransactionId OnionToOwner Message 38type Client = QR.Client String PacketKind TransactionId OnionDestination Message
39type Message = OnionMessage Identity 39type Message = OnionMessage Identity
40 40
41classify :: Message -> MessageClass String PacketKind TransactionId 41classify :: Message -> MessageClass String PacketKind TransactionId
@@ -59,7 +59,7 @@ classify msg = go msg
59-- The reason for this 20 second timeout in toxcore is that it gives a reasonable 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 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. 61-- all the possible delays with some extra seconds.
62announceH :: Routing -> TVar SessionTokens -> TVar AnnouncedKeys -> OnionToOwner -> AnnounceRequest -> IO AnnounceResponse 62announceH :: Routing -> TVar SessionTokens -> TVar AnnouncedKeys -> OnionDestination -> AnnounceRequest -> IO AnnounceResponse
63announceH routing toks keydb (OnionToOwner naddr retpath) req = do 63announceH routing toks keydb (OnionToOwner naddr retpath) req = do
64 case () of 64 case () of
65 _ | announcePingId req == zeros32 65 _ | announcePingId req == zeros32
@@ -89,16 +89,16 @@ announceH routing toks keydb (OnionToOwner naddr retpath) req = do
89 then Nonce32 . toPaddedByteString 32 <$> grantToken toks naddr 89 then Nonce32 . toPaddedByteString 32 <$> grantToken toks naddr
90 else return $ zeros32 90 else return $ zeros32
91 let k = case record of 91 let k = case record of
92 Nothing -> NotStored newtok 92 Nothing -> NotStored newtok
93 Just (OnionToOwner {}) | storing -> Acknowledged newtok 93 Just (OnionDestination {}) | storing -> Acknowledged newtok
94 Just (OnionToOwner ni _) -> SendBackKey $ id2key (nodeId ni) 94 Just (OnionToOwner ni _) -> SendBackKey $ id2key (nodeId ni)
95 let response = AnnounceResponse k ns 95 let response = AnnounceResponse k ns
96 hPutStrLn stderr $ unwords ["Announce:", show req, "-reply->", show response] 96 hPutStrLn stderr $ unwords ["Announce:", show req, "-reply->", show response]
97 return response 97 return response
98 98
99dataToRouteH :: 99dataToRouteH ::
100 TVar AnnouncedKeys 100 TVar AnnouncedKeys
101 -> Transport err OnionToOwner (OnionMessage f) 101 -> Transport err OnionDestination (OnionMessage f)
102 -> addr 102 -> addr
103 -> OnionMessage f 103 -> OnionMessage f
104 -> IO () 104 -> IO ()
@@ -118,11 +118,11 @@ type NodeDistance = NodeId
118 118
119data AnnouncedKeys = AnnouncedKeys 119data AnnouncedKeys = AnnouncedKeys
120 { keyByAge :: !(PSQ NodeId (Down POSIXTime)) -- timeout of 300 seconds 120 { keyByAge :: !(PSQ NodeId (Down POSIXTime)) -- timeout of 300 seconds
121 , keyAssoc :: !(MinMaxPSQ' NodeId NodeDistance (Int,OnionToOwner)) 121 , keyAssoc :: !(MinMaxPSQ' NodeId NodeDistance (Int,OnionDestination))
122 } 122 }
123 123
124 124
125insertKey :: POSIXTime -> NodeId -> OnionToOwner -> NodeDistance -> AnnouncedKeys -> AnnouncedKeys 125insertKey :: POSIXTime -> NodeId -> OnionDestination -> NodeDistance -> AnnouncedKeys -> AnnouncedKeys
126insertKey tm pub toxpath d keydb = AnnouncedKeys 126insertKey tm pub toxpath d keydb = AnnouncedKeys
127 { keyByAge = PSQ.insert pub (Down tm) (keyByAge keydb) 127 { keyByAge = PSQ.insert pub (Down tm) (keyByAge keydb)
128 , keyAssoc = case MinMaxPSQ.lookup' pub (keyAssoc keydb) of 128 , keyAssoc = case MinMaxPSQ.lookup' pub (keyAssoc keydb) of
@@ -134,12 +134,12 @@ areq :: Message -> Either String AnnounceRequest
134areq (OnionAnnounce assym) = Right $ fst $ runIdentity $ assymData assym 134areq (OnionAnnounce assym) = Right $ fst $ runIdentity $ assymData assym
135areq _ = Left "Unexpected non-announce OnionMessage" 135areq _ = Left "Unexpected non-announce OnionMessage"
136 136
137handlers :: Transport err OnionToOwner Message 137handlers :: Transport err OnionDestination Message
138 -> Routing 138 -> Routing
139 -> TVar SessionTokens 139 -> TVar SessionTokens
140 -> TVar AnnouncedKeys 140 -> TVar AnnouncedKeys
141 -> PacketKind 141 -> PacketKind
142 -> Maybe (MethodHandler String TransactionId OnionToOwner Message) 142 -> Maybe (MethodHandler String TransactionId OnionDestination Message)
143handlers net routing toks keydb AnnounceType 143handlers net routing toks keydb AnnounceType
144 = Just 144 = Just
145 $ MethodHandler areq (\(TransactionId n8 n24) src dst -> OnionAnnounceResponse n8 n24 . Identity) 145 $ MethodHandler areq (\(TransactionId n8 n24) src dst -> OnionAnnounceResponse n8 n24 . Identity)
diff --git a/src/Network/Tox/Onion/Transport.hs b/src/Network/Tox/Onion/Transport.hs
index 8c4df694..a521c39e 100644
--- a/src/Network/Tox/Onion/Transport.hs
+++ b/src/Network/Tox/Onion/Transport.hs
@@ -19,7 +19,7 @@ module Network.Tox.Onion.Transport
19 ( parseOnionAddr 19 ( parseOnionAddr
20 , encodeOnionAddr 20 , encodeOnionAddr
21 , forwardOnions 21 , forwardOnions
22 , OnionToOwner(..) 22 , OnionDestination(..)
23 , OnionMessage(..) 23 , OnionMessage(..)
24 , DataToRoute(..) 24 , DataToRoute(..)
25 , AnnounceResponse(..) 25 , AnnounceResponse(..)
@@ -41,7 +41,7 @@ import Network.QueryResponse
41import Crypto.Tox hiding (encrypt,decrypt) 41import Crypto.Tox hiding (encrypt,decrypt)
42import Network.Tox.NodeId 42import Network.Tox.NodeId
43import qualified Crypto.Tox as ToxCrypto 43import qualified Crypto.Tox as ToxCrypto
44import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes,nodeInfo,DHTPublicKey) 44import Network.Tox.DHT.Transport (NodeInfo(..),NodeId(..),SendNodes,nodeInfo,DHTPublicKey,asymNodeInfo)
45 45
46import Debug.Trace 46import Debug.Trace
47import Control.Arrow 47import Control.Arrow
@@ -87,11 +87,11 @@ deriving instance ( Show (f (AnnounceRequest, Nonce8))
87 , Show (f DataToRoute) 87 , Show (f DataToRoute)
88 ) => Show (OnionMessage f) 88 ) => Show (OnionMessage f)
89 89
90data OnionToOwner = OnionToOwner NodeInfo (ReturnPath N3) 90data OnionDestination = OnionToOwner NodeInfo (ReturnPath N3) -- ^ Somebody else's path to us.
91 | OnionToMe SockAddr -- SockAddr is immediate peer in route 91 | OnionDestination NodeInfo -- ^ Our own onion-path.
92 deriving Show 92 deriving Show
93 93
94onionKey :: OnionToOwner -> Maybe PublicKey 94onionKey :: OnionDestination -> Maybe PublicKey
95onionKey (OnionToOwner ni _) = Just $ id2key (nodeId ni) 95onionKey (OnionToOwner ni _) = Just $ id2key (nodeId ni)
96onionKey _ = Nothing 96onionKey _ = Nothing
97 97
@@ -120,7 +120,7 @@ instance Serialize (OnionMessage Encrypted) where
120 put (OnionAnnounceResponse n8 n24 x) = putWord8 0x84 >> put n8 >> put n24 >> put x 120 put (OnionAnnounceResponse n8 n24 x) = putWord8 0x84 >> put n8 >> put n24 >> put x
121 put (OnionToRouteResponse a) = putWord8 0x86 >> putAliasedAssym a 121 put (OnionToRouteResponse a) = putWord8 0x86 >> putAliasedAssym a
122 122
123onionToOwner :: Assym a -> ReturnPath N3 -> SockAddr -> Either String OnionToOwner 123onionToOwner :: Assym a -> ReturnPath N3 -> SockAddr -> Either String OnionDestination
124onionToOwner assym ret3 saddr = do 124onionToOwner assym ret3 saddr = do
125 ni <- nodeInfo (key2id $ senderKey assym) saddr 125 ni <- nodeInfo (key2id $ senderKey assym) saddr
126 return $ OnionToOwner ni ret3 126 return $ OnionToOwner ni ret3
@@ -131,18 +131,18 @@ onion :: Sized msg =>
131 ByteString 131 ByteString
132 -> SockAddr 132 -> SockAddr
133 -> Get (Assym (Encrypted msg) -> t) 133 -> Get (Assym (Encrypted msg) -> t)
134 -> Either String (t, OnionToOwner) 134 -> Either String (t, OnionDestination)
135onion bs saddr getf = do (f,(assym,ret3)) <- runGet ((,) <$> getf <*> getOnionRequest) bs 135onion bs saddr getf = do (f,(assym,ret3)) <- runGet ((,) <$> getf <*> getOnionRequest) bs
136 oaddr <- onionToOwner assym ret3 saddr 136 oaddr <- onionToOwner assym ret3 saddr
137 return (f assym, oaddr) 137 return (f assym, oaddr)
138 138
139 139
140parseOnionAddr :: (ByteString, SockAddr) -> Either (OnionMessage Encrypted,OnionToOwner) (ByteString,SockAddr) 140parseOnionAddr :: (ByteString, SockAddr) -> Either (OnionMessage Encrypted,OnionDestination) (ByteString,SockAddr)
141parseOnionAddr (msg,saddr) 141parseOnionAddr (msg,saddr)
142 | Just (typ,bs) <- B.uncons msg 142 | Just (typ,bs) <- B.uncons msg
143 , let right = Right (msg,saddr) 143 , let right = Right (msg,saddr)
144 query = either (const right) Left 144 query = either (const right) Left
145 response = either (const right) (Left . (, OnionToMe saddr)) 145 response = either (const right) (Left . \msg -> ( msg , replyAlias saddr msg ))
146 = case typ of 146 = case typ of
147 0x83 -> query $ onion bs saddr (pure OnionAnnounce) -- Announce Request 147 0x83 -> query $ onion bs saddr (pure OnionAnnounce) -- Announce Request
148 0x85 -> query $ onion bs saddr (OnionToRoute <$> getPublicKey) -- Onion Data Request 148 0x85 -> query $ onion bs saddr (OnionToRoute <$> getPublicKey) -- Onion Data Request
@@ -154,22 +154,28 @@ getOnionReply :: Word8 -> Get (OnionMessage Encrypted)
154getOnionReply 0x84 = OnionAnnounceResponse <$> get <*> get <*> get 154getOnionReply 0x84 = OnionAnnounceResponse <$> get <*> get <*> get
155getOnionReply 0x86 = OnionToRouteResponse <$> getOnionAssym 155getOnionReply 0x86 = OnionToRouteResponse <$> getOnionAssym
156 156
157replyAlias :: SockAddr -> OnionMessage Encrypted -> OnionDestination
158replyAlias saddr (OnionAnnounceResponse _ _ _)
159 = OnionDestination
160 $ either (error "replyAlias: bad protocol") id
161 $ nodeInfo zeroID saddr -- TODO OnionAnnounceResponse has no sender key
162replyAlias saddr (OnionToRouteResponse asym)
163 = OnionDestination $ asymNodeInfo saddr asym
164
157putOnionMsg :: OnionMessage Encrypted -> Put 165putOnionMsg :: OnionMessage Encrypted -> Put
158putOnionMsg (OnionAnnounce a) = putOnionAssym 0x83 (return ()) a 166putOnionMsg (OnionAnnounce a) = putOnionAssym 0x83 (return ()) a
159putOnionMsg (OnionToRoute pubkey a) = putOnionAssym 0x85 (putPublicKey pubkey) a 167putOnionMsg (OnionToRoute pubkey a) = putOnionAssym 0x85 (putPublicKey pubkey) a
160putOnionMsg (OnionAnnounceResponse n8 n24 x) = put (0x84 :: Word8) >> put n8 >> put n24 >> put x 168putOnionMsg (OnionAnnounceResponse n8 n24 x) = put (0x84 :: Word8) >> put n8 >> put n24 >> put x
161putOnionMsg (OnionToRouteResponse a) = putOnionAssym 0x86 (return ()) a 169putOnionMsg (OnionToRouteResponse a) = putOnionAssym 0x86 (return ()) a
162 170
163encodeOnionAddr :: (OnionMessage Encrypted,OnionToOwner) -> (ByteString, SockAddr) 171encodeOnionAddr :: (OnionMessage Encrypted,OnionDestination) -> (ByteString, SockAddr)
164encodeOnionAddr (msg,OnionToOwner ni p) = ( runPut $ putResponse (OnionResponse p msg) 172encodeOnionAddr (msg,OnionToOwner ni p) = ( runPut $ putResponse (OnionResponse p msg)
165 , nodeAddr ni ) 173 , nodeAddr ni )
166encodeOnionAddr (msg,OnionToMe a) = ( runPut (putOnionMsg msg), a) 174encodeOnionAddr (msg,OnionDestination a) = ( runPut (putOnionMsg msg), nodeAddr a) -- TODO: Construct (OnionRequest N0)?
167 175
168forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport -- HandleHi a -> IO a -> HandleLo a 176forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport
169forwardOnions crypto udp = udp { awaitMessage = forwardAwait crypto udp } 177forwardOnions crypto udp = udp { awaitMessage = forwardAwait crypto udp }
170 178
171-- forMe :: HandleHi
172-- forThem :: handleLo
173forwardAwait :: TransportCrypto -> UDPTransport -> HandleLo a -> IO a 179forwardAwait :: TransportCrypto -> UDPTransport -> HandleLo a -> IO a
174forwardAwait crypto udp kont = do 180forwardAwait crypto udp kont = do
175 fix $ \another -> do 181 fix $ \another -> do
@@ -520,26 +526,27 @@ instance Sized OnionData where
520 -- should be treated as variable sized. 526 -- should be treated as variable sized.
521 VarSize f -> f dhtpk 527 VarSize f -> f dhtpk
522 528
523encrypt :: TransportCrypto -> OnionMessage Identity -> OnionToOwner -> (OnionMessage Encrypted, OnionToOwner) 529encrypt :: TransportCrypto -> OnionMessage Identity -> OnionDestination -> (OnionMessage Encrypted, OnionDestination)
524encrypt crypto msg rpath = ( transcode (encryptMessage crypto okey) msg 530encrypt crypto msg rpath = ( transcode ( (. (runIdentity . either id assymData))
531 . encryptMessage skey okey)
532 msg
525 , rpath) 533 , rpath)
526 where 534 where
535 skey = transportSecret crypto
536
527 -- The OnionToMe case shouldn't happen, but we'll use our own public 537 -- The OnionToMe case shouldn't happen, but we'll use our own public
528 -- key in this situation. 538 -- key in this situation.
529 okey = fromMaybe (transportPublic crypto) $ onionKey rpath 539 okey = fromMaybe (transportPublic crypto) $ onionKey rpath
530 540
541
531encryptMessage :: Serialize a => 542encryptMessage :: Serialize a =>
532 TransportCrypto -> PublicKey -> Nonce24 -> Either (Identity a) (Assym (Identity a)) -> Encrypted a 543 SecretKey -> PublicKey -> Nonce24 -> a -> Encrypted a
533encryptMessage crypto destKey n (Right a) = ToxCrypto.encrypt secret plain 544encryptMessage skey destKey n a = ToxCrypto.encrypt secret plain
534 where
535 secret = computeSharedSecret (transportSecret crypto) destKey n
536 plain = encodePlain $ runIdentity $ assymData a
537encryptMessage crypto destKey n (Left x) = ToxCrypto.encrypt secret plain
538 where 545 where
539 secret = computeSharedSecret (transportSecret crypto) destKey n 546 secret = computeSharedSecret skey destKey n
540 plain = encodePlain $ runIdentity $ x 547 plain = encodePlain a
541 548
542decrypt :: TransportCrypto -> OnionMessage Encrypted -> OnionToOwner -> Either String (OnionMessage Identity, OnionToOwner) 549decrypt :: TransportCrypto -> OnionMessage Encrypted -> OnionDestination -> Either String (OnionMessage Identity, OnionDestination)
543decrypt crypto msg addr = (, addr) <$> (sequenceMessage $ transcode (decryptMessage crypto) msg) 550decrypt crypto msg addr = (, addr) <$> (sequenceMessage $ transcode (decryptMessage crypto) msg)
544 551
545decryptMessage :: Serialize x => 552decryptMessage :: Serialize x =>