diff options
author | joe <joe@jerkface.net> | 2017-08-31 15:42:27 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-08-31 15:42:49 -0400 |
commit | eba3cdcc646211cc152c16d0813cc7e9b1c3111b (patch) | |
tree | e90c45a86d11b16da4eee5f21bb8ee618d7d94d6 | |
parent | a6b55a29ff656f105ca79c7d4f060920a37c7c70 (diff) |
Separated module OnionTransport from ToxTransport.
-rw-r--r-- | DHTTransport.hs | 18 | ||||
-rw-r--r-- | OnionTransport.hs | 196 | ||||
-rw-r--r-- | ToxCrypto.hs | 11 | ||||
-rw-r--r-- | ToxTransport.hs | 194 |
4 files changed, 226 insertions, 193 deletions
diff --git a/DHTTransport.hs b/DHTTransport.hs index 6b3af2fc..3de276f1 100644 --- a/DHTTransport.hs +++ b/DHTTransport.hs | |||
@@ -1,8 +1,10 @@ | |||
1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | 1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} |
2 | {-# LANGUAGE KindSignatures #-} | 2 | {-# LANGUAGE KindSignatures #-} |
3 | {-# LANGUAGE LambdaCase #-} | ||
3 | module DHTTransport | 4 | module DHTTransport |
4 | ( parseDHTAddr | 5 | ( parseDHTAddr |
5 | , encodeDHTAddr | 6 | , encodeDHTAddr |
7 | , forwardDHTRequests | ||
6 | , module ToxAddress | 8 | , module ToxAddress |
7 | , DHTMessage(..) | 9 | , DHTMessage(..) |
8 | , Ping | 10 | , Ping |
@@ -16,6 +18,7 @@ module DHTTransport | |||
16 | 18 | ||
17 | import ToxAddress | 19 | import ToxAddress |
18 | import ToxCrypto | 20 | import ToxCrypto |
21 | import Network.QueryResponse | ||
19 | 22 | ||
20 | import Control.Arrow | 23 | import Control.Arrow |
21 | import qualified Data.ByteString as B | 24 | import qualified Data.ByteString as B |
@@ -24,6 +27,8 @@ import Data.Serialize as S (Get, Serialize, get, put, runGet) | |||
24 | import Data.Word | 27 | import Data.Word |
25 | import Network.Socket | 28 | import Network.Socket |
26 | 29 | ||
30 | type DHTTransport = Transport String NodeInfo (DHTMessage Encrypted8) | ||
31 | type HandleHi a = Maybe (Either String (DHTMessage Encrypted8, NodeInfo)) -> IO a | ||
27 | 32 | ||
28 | 33 | ||
29 | data DHTMessage (f :: * -> *) | 34 | data DHTMessage (f :: * -> *) |
@@ -175,3 +180,16 @@ data CookieData = CookieData -- 16 (mac) | |||
175 | 180 | ||
176 | instance Sized CookieRequest where | 181 | instance Sized CookieRequest where |
177 | size = ConstSize 64 -- 32 byte key + 32 byte padding | 182 | size = ConstSize 64 -- 32 byte key + 32 byte padding |
183 | |||
184 | forwardDHTRequests :: TransportCrypto -> (PublicKey -> IO (Maybe NodeInfo)) -> DHTTransport -> DHTTransport | ||
185 | forwardDHTRequests crypto closeLookup dht = dht { awaitMessage = await' } | ||
186 | where | ||
187 | await' :: HandleHi a -> IO a | ||
188 | await' pass = awaitMessage dht $ \case | ||
189 | Just (Right (m@(DHTDHTRequest target payload),src)) | target /= transportPublic crypto | ||
190 | -> do mni <- closeLookup target | ||
191 | -- Forward the message if the target is in our close list. | ||
192 | forM_ mni $ \ni -> sendMessage dht ni m | ||
193 | await' pass | ||
194 | m -> pass m | ||
195 | |||
diff --git a/OnionTransport.hs b/OnionTransport.hs new file mode 100644 index 00000000..804c444e --- /dev/null +++ b/OnionTransport.hs | |||
@@ -0,0 +1,196 @@ | |||
1 | {-# LANGUAGE DataKinds #-} | ||
2 | {-# LANGUAGE GADTs #-} | ||
3 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
4 | {-# LANGUAGE KindSignatures #-} | ||
5 | {-# LANGUAGE LambdaCase #-} | ||
6 | {-# LANGUAGE ScopedTypeVariables #-} | ||
7 | {-# LANGUAGE TupleSections #-} | ||
8 | {-# LANGUAGE TypeOperators #-} | ||
9 | module OnionTransport | ||
10 | ( parseOnionAddr | ||
11 | , encodeOnionAddr | ||
12 | , forwardOnions | ||
13 | , OnionToOwner(..) | ||
14 | , OnionMessage(..) | ||
15 | , DataToRoute(..) | ||
16 | , AnnounceResponse(..) | ||
17 | , AnnounceRequest(..) | ||
18 | , Forwarding(..) | ||
19 | , ReturnPath(..) | ||
20 | , OnionRequest(..) | ||
21 | , OnionResponse(..) | ||
22 | , Addressed(..) | ||
23 | , UDPTransport | ||
24 | ) where | ||
25 | |||
26 | import Network.QueryResponse | ||
27 | import ToxCrypto | ||
28 | import DHTTransport (NodeInfo(..),NodeId(..),SendNodes,nodeInfo) | ||
29 | |||
30 | import Control.Arrow | ||
31 | import qualified Data.ByteString as B | ||
32 | ;import Data.ByteString (ByteString) | ||
33 | import Data.Serialize as S (Get, Put, Serialize, get, put, runGet) | ||
34 | import Data.Typeable | ||
35 | import Data.Word | ||
36 | import GHC.TypeLits | ||
37 | import Network.Socket | ||
38 | |||
39 | type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a | ||
40 | |||
41 | type UDPTransport = Transport String SockAddr ByteString | ||
42 | |||
43 | |||
44 | getOnionAssym :: Get (Assym (Encrypted DataToRoute)) | ||
45 | getOnionAssym = _todo | ||
46 | |||
47 | data OnionMessage (f :: * -> *) | ||
48 | = OnionAnnounce (Assym (f (AnnounceRequest,Nonce8))) | ||
49 | | OnionAnnounceResponse Nonce8 Nonce24 (f AnnounceResponse) | ||
50 | | OnionToRoute PublicKey (Assym (f DataToRoute)) -- destination key, aliased Assym | ||
51 | | OnionToRouteResponse (Assym (f DataToRoute)) | ||
52 | |||
53 | data OnionToOwner = OnionToOwner NodeInfo (ReturnPath 3) | ||
54 | | OnionToMe SockAddr -- SockAddr is immediate peer in route | ||
55 | |||
56 | |||
57 | onionToOwner assym ret3 saddr = do | ||
58 | ni <- nodeInfo (NodeId $ senderKey assym) saddr | ||
59 | return $ OnionToOwner ni ret3 | ||
60 | -- data CookieAddress = WithoutCookie NodeInfo | CookieAddress Cookie SockAddr | ||
61 | |||
62 | |||
63 | onion bs saddr getf = do (f,(assym,ret3)) <- runGet ((,) <$> getf <*> getOnionRequest) bs | ||
64 | oaddr <- onionToOwner assym ret3 saddr | ||
65 | return (f assym, oaddr) | ||
66 | |||
67 | |||
68 | parseOnionAddr :: (ByteString, SockAddr) -> Either (OnionMessage Encrypted,OnionToOwner) (ByteString,SockAddr) | ||
69 | parseOnionAddr (msg,saddr) | ||
70 | | Just (typ,bs) <- B.uncons msg | ||
71 | , let right = Right (msg,saddr) | ||
72 | query = either (const right) Left | ||
73 | response = either (const right) (Left . (, OnionToMe saddr)) | ||
74 | = case typ of | ||
75 | 0x83 -> query $ onion bs saddr (pure OnionAnnounce) -- Announce Request | ||
76 | 0x85 -> query $ onion bs saddr (OnionToRoute <$> getPublicKey) -- Onion Data Request | ||
77 | 0x84 -> response $ runGet (OnionAnnounceResponse <$> get <*> get <*> get) bs -- Announce Response | ||
78 | 0x86 -> response $ runGet (OnionToRouteResponse <$> getOnionAssym) bs -- Onion Data Response | ||
79 | _ -> right | ||
80 | |||
81 | encodeOnionAddr :: (OnionMessage Encrypted,OnionToOwner) -> (ByteString, SockAddr) | ||
82 | encodeOnionAddr = _todo | ||
83 | |||
84 | forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport -- HandleHi a -> IO a -> HandleLo a | ||
85 | forwardOnions crypto udp = udp { awaitMessage = await' } | ||
86 | where | ||
87 | -- forMe :: HandleHi | ||
88 | -- forThem :: handleLo | ||
89 | await' :: HandleLo a -> IO a | ||
90 | await' forThem = awaitMessage udp $ \case | ||
91 | m@(Just (Right (bs,saddr))) -> case B.head bs of | ||
92 | 0x80 -> forward forThem bs $ handleOnionRequest (Proxy :: Proxy 0) crypto saddr (forThem m) | ||
93 | 0x81 -> forward forThem bs $ handleOnionRequest (Proxy :: Proxy 1) crypto saddr (forThem m) | ||
94 | 0x82 -> forward forThem bs $ handleOnionRequest (Proxy :: Proxy 2) crypto saddr (forThem m) | ||
95 | 0x8c -> forward forThem bs $ handleOnionResponse (Proxy :: Proxy 3) crypto saddr (forThem m) | ||
96 | 0x8d -> forward forThem bs $ handleOnionResponse (Proxy :: Proxy 2) crypto saddr (forThem m) | ||
97 | 0x8e -> forward forThem bs $ handleOnionResponse (Proxy :: Proxy 1) crypto saddr (forThem m) | ||
98 | _ -> forThem m | ||
99 | m -> forThem m | ||
100 | |||
101 | forward :: forall c b b1. | ||
102 | Serialize b => | ||
103 | (Maybe (Either String b1) -> c) -> ByteString -> (b -> c) -> c | ||
104 | forward forMe bs f = either (forMe . Just . Left) f $ decode $ B.tail bs | ||
105 | |||
106 | -- n = 0, 1, 2 | ||
107 | data OnionRequest (n :: Nat) = OnionRequest | ||
108 | { onionNonce :: Nonce24 | ||
109 | , onionForward :: Forwarding (3 - n) (OnionMessage Encrypted) | ||
110 | , pathFromOwner :: ReturnPath n | ||
111 | } | ||
112 | |||
113 | instance Serialize (OnionRequest n) where { get = _todo; put = _todo } | ||
114 | instance Serialize (OnionResponse n) where { get = _todo; put = _todo } | ||
115 | |||
116 | -- n = 1, 2, 3 | ||
117 | -- Attributed (Encrypted ( | ||
118 | |||
119 | data OnionResponse (n :: Nat) = OnionResponse | ||
120 | { pathToOwner :: ReturnPath n | ||
121 | , msgToOwner :: OnionMessage Encrypted | ||
122 | } | ||
123 | |||
124 | data Addressed a = Addressed { sockAddr :: SockAddr, unaddressed :: a } | ||
125 | |||
126 | data ReturnPath (n :: Nat) where | ||
127 | NoReturnPath :: ReturnPath 0 | ||
128 | ReturnPath :: Nonce24 -> Encrypted (Addressed (ReturnPath n)) -> ReturnPath (n + 1) | ||
129 | |||
130 | -- instance KnownNat n => Serialize (ReturnPath n) where | ||
131 | -- -- Size: 59 = 1(family) + 16(ip) + 2(port) +16(mac) + 24(nonce) | ||
132 | -- get = ReturnPath <$> getBytes ( 59 * (fromIntegral $ natVal $ Proxy @n) ) | ||
133 | -- put (ReturnPath bs) = putByteString bs | ||
134 | |||
135 | |||
136 | data Forwarding (n :: Nat) msg where | ||
137 | NotForwarded :: msg -> Forwarding 0 msg | ||
138 | Forwarding :: Assym (Encrypted (Addressed (Forwarding n msg))) -> Forwarding (n + 1) msg | ||
139 | |||
140 | handleOnionRequest :: KnownNat n => proxy n -> TransportCrypto -> SockAddr -> IO a -> OnionRequest n -> IO a | ||
141 | handleOnionRequest = _todo | ||
142 | |||
143 | handleOnionResponse :: KnownNat n => proxy n -> TransportCrypto -> SockAddr -> IO a -> OnionResponse n -> IO a | ||
144 | handleOnionResponse = _todo | ||
145 | |||
146 | data AnnounceRequest = AnnounceRequest | ||
147 | { announcePingId :: Nonce32 -- Ping ID | ||
148 | , announceSeeking :: NodeId -- Public key we are searching for | ||
149 | , announceKey :: NodeId -- Public key that we want those sending back data packets to use | ||
150 | } | ||
151 | |||
152 | instance S.Serialize AnnounceRequest where | ||
153 | get = AnnounceRequest <$> S.get <*> S.get <*> S.get | ||
154 | put (AnnounceRequest p s k) = S.put (p,s,k) | ||
155 | |||
156 | getOnionRequest :: Get (Assym (Encrypted msg), ReturnPath 3) | ||
157 | getOnionRequest = _todo | ||
158 | |||
159 | data KeyRecord = NotStored Nonce32 | ||
160 | | SendBackKey PublicKey | ||
161 | | Acknowledged Nonce32 | ||
162 | |||
163 | getPublicKey :: Get PublicKey | ||
164 | getPublicKey = _todo | ||
165 | |||
166 | putPublicKey :: PublicKey -> Put | ||
167 | putPublicKey = _todo | ||
168 | |||
169 | instance S.Serialize KeyRecord where | ||
170 | get = do | ||
171 | is_stored <- S.get :: S.Get Word8 | ||
172 | case is_stored of | ||
173 | 1 -> SendBackKey <$> getPublicKey | ||
174 | 2 -> Acknowledged <$> S.get | ||
175 | _ -> NotStored <$> S.get | ||
176 | put (NotStored n32) = S.put (0 :: Word8) >> S.put n32 | ||
177 | put (SendBackKey key) = S.put (1 :: Word8) >> putPublicKey key | ||
178 | put (Acknowledged n32) = S.put (2 :: Word8) >> S.put n32 | ||
179 | |||
180 | data AnnounceResponse = AnnounceResponse | ||
181 | { is_stored :: KeyRecord | ||
182 | , announceNodes :: SendNodes | ||
183 | } | ||
184 | |||
185 | instance Sized AnnounceResponse where | ||
186 | size = VarSize $ \AnnounceResponse {} -> _todo | ||
187 | |||
188 | instance S.Serialize AnnounceResponse where | ||
189 | get = AnnounceResponse <$> S.get <*> S.get | ||
190 | put (AnnounceResponse st ns) = S.put st >> S.put ns | ||
191 | |||
192 | data DataToRoute = DataToRoute | ||
193 | { dataFromKey :: PublicKey | ||
194 | , dataToRoute :: Encrypted (Word8,ByteString) | ||
195 | } | ||
196 | |||
diff --git a/ToxCrypto.hs b/ToxCrypto.hs index 6f0fcf1a..4a8de635 100644 --- a/ToxCrypto.hs +++ b/ToxCrypto.hs | |||
@@ -6,6 +6,8 @@ module ToxCrypto | |||
6 | ( PublicKey | 6 | ( PublicKey |
7 | , publicKey | 7 | , publicKey |
8 | , SecretKey | 8 | , SecretKey |
9 | , SymmetricKey(..) | ||
10 | , TransportCrypto(..) | ||
9 | , Encrypted | 11 | , Encrypted |
10 | , Encrypted8 | 12 | , Encrypted8 |
11 | , Assym(..) | 13 | , Assym(..) |
@@ -44,6 +46,7 @@ import Foreign.Ptr | |||
44 | import Foreign.Storable | 46 | import Foreign.Storable |
45 | import System.Endian | 47 | import System.Endian |
46 | import qualified Data.ByteString.Internal | 48 | import qualified Data.ByteString.Internal |
49 | import Control.Concurrent.STM | ||
47 | 50 | ||
48 | -- | A 16-byte mac and an arbitrary-length encrypted stream. | 51 | -- | A 16-byte mac and an arbitrary-length encrypted stream. |
49 | newtype Encrypted a = Encrypted ByteString | 52 | newtype Encrypted a = Encrypted ByteString |
@@ -226,3 +229,11 @@ data Assym a = Assym | |||
226 | , assymData :: a | 229 | , assymData :: a |
227 | } | 230 | } |
228 | 231 | ||
232 | newtype SymmetricKey = SymmetricKey ByteString | ||
233 | |||
234 | data TransportCrypto = TransportCrypto | ||
235 | { transportSecret :: SecretKey | ||
236 | , transportPublic :: PublicKey | ||
237 | , transportSymmetric :: STM SymmetricKey | ||
238 | } | ||
239 | |||
diff --git a/ToxTransport.hs b/ToxTransport.hs index 3e442d49..62081df5 100644 --- a/ToxTransport.hs +++ b/ToxTransport.hs | |||
@@ -9,24 +9,8 @@ | |||
9 | module ToxTransport | 9 | module ToxTransport |
10 | ( toxTransport | 10 | ( toxTransport |
11 | 11 | ||
12 | , TransportCrypto(..) | ||
13 | , SymmetricKey(..) | ||
14 | , Encrypted8(..) | 12 | , Encrypted8(..) |
15 | 13 | ||
16 | , UDPTransport | ||
17 | |||
18 | -- OnionTransport | ||
19 | , OnionToOwner(..) | ||
20 | , OnionMessage(..) | ||
21 | , DataToRoute(..) | ||
22 | , AnnounceResponse(..) | ||
23 | , AnnounceRequest(..) | ||
24 | , Forwarding(..) | ||
25 | , ReturnPath(..) | ||
26 | , OnionRequest(..) | ||
27 | , OnionResponse(..) | ||
28 | , Addressed(..) | ||
29 | |||
30 | -- CryptoTransport | 14 | -- CryptoTransport |
31 | , NetCrypto(..) | 15 | , NetCrypto(..) |
32 | , CryptoData(..) | 16 | , CryptoData(..) |
@@ -40,6 +24,7 @@ module ToxTransport | |||
40 | import Network.QueryResponse | 24 | import Network.QueryResponse |
41 | import ToxCrypto | 25 | import ToxCrypto |
42 | import DHTTransport | 26 | import DHTTransport |
27 | import OnionTransport | ||
43 | 28 | ||
44 | import Control.Applicative | 29 | import Control.Applicative |
45 | import Control.Arrow | 30 | import Control.Arrow |
@@ -56,17 +41,6 @@ import Data.Word | |||
56 | import GHC.TypeLits | 41 | import GHC.TypeLits |
57 | import Network.Socket | 42 | import Network.Socket |
58 | 43 | ||
59 | newtype SymmetricKey = SymmetricKey ByteString | ||
60 | |||
61 | data TransportCrypto = TransportCrypto | ||
62 | { transportSecret :: SecretKey | ||
63 | , transportPublic :: PublicKey | ||
64 | , transportSymmetric :: STM SymmetricKey | ||
65 | } | ||
66 | |||
67 | type UDPTransport = Transport String SockAddr ByteString | ||
68 | type DHTTransport = Transport String NodeInfo (DHTMessage Encrypted8) | ||
69 | |||
70 | toxTransport :: | 44 | toxTransport :: |
71 | TransportCrypto | 45 | TransportCrypto |
72 | -> (PublicKey -> IO (Maybe NodeInfo)) | 46 | -> (PublicKey -> IO (Maybe NodeInfo)) |
@@ -84,50 +58,8 @@ toxTransport crypto closeLookup udp = do | |||
84 | ) | 58 | ) |
85 | 59 | ||
86 | 60 | ||
87 | type HandleHi a = Maybe (Either String (DHTMessage Encrypted8, NodeInfo)) -> IO a | ||
88 | type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a | ||
89 | |||
90 | -- instance (Sized a, Sized b) => Sized (a,b) where size = _todo | 61 | -- instance (Sized a, Sized b) => Sized (a,b) where size = _todo |
91 | 62 | ||
92 | getOnionAssym :: Get (Assym (Encrypted DataToRoute)) | ||
93 | getOnionAssym = _todo | ||
94 | |||
95 | |||
96 | data OnionMessage (f :: * -> *) | ||
97 | = OnionAnnounce (Assym (f (AnnounceRequest,Nonce8))) | ||
98 | | OnionAnnounceResponse Nonce8 Nonce24 (f AnnounceResponse) | ||
99 | | OnionToRoute PublicKey (Assym (f DataToRoute)) -- destination key, aliased Assym | ||
100 | | OnionToRouteResponse (Assym (f DataToRoute)) | ||
101 | |||
102 | data OnionToOwner = OnionToOwner NodeInfo (ReturnPath 3) | ||
103 | | OnionToMe SockAddr -- SockAddr is immediate peer in route | ||
104 | |||
105 | onionToOwner assym ret3 saddr = do | ||
106 | ni <- nodeInfo (NodeId $ senderKey assym) saddr | ||
107 | return $ OnionToOwner ni ret3 | ||
108 | |||
109 | onion bs saddr getf = do (f,(assym,ret3)) <- runGet ((,) <$> getf <*> getOnionRequest) bs | ||
110 | oaddr <- onionToOwner assym ret3 saddr | ||
111 | return (f assym, oaddr) | ||
112 | |||
113 | parseOnionAddr :: (ByteString, SockAddr) -> Either (OnionMessage Encrypted,OnionToOwner) (ByteString,SockAddr) | ||
114 | parseOnionAddr (msg,saddr) | ||
115 | | Just (typ,bs) <- B.uncons msg | ||
116 | , let right = Right (msg,saddr) | ||
117 | query = either (const right) Left | ||
118 | response = either (const right) (Left . (, OnionToMe saddr)) | ||
119 | = case typ of | ||
120 | 0x83 -> query $ onion bs saddr (pure OnionAnnounce) -- Announce Request | ||
121 | 0x85 -> query $ onion bs saddr (OnionToRoute <$> getPublicKey) -- Onion Data Request | ||
122 | 0x84 -> response $ runGet (OnionAnnounceResponse <$> get <*> get <*> get) bs -- Announce Response | ||
123 | 0x86 -> response $ runGet (OnionToRouteResponse <$> getOnionAssym) bs -- Onion Data Response | ||
124 | _ -> right | ||
125 | |||
126 | encodeOnionAddr :: (OnionMessage Encrypted,OnionToOwner) -> (ByteString, SockAddr) | ||
127 | encodeOnionAddr = _todo | ||
128 | |||
129 | |||
130 | -- data CookieAddress = WithoutCookie NodeInfo | CookieAddress Cookie SockAddr | ||
131 | 63 | ||
132 | data NetCrypto | 64 | data NetCrypto |
133 | = NetHandshake (Handshake Encrypted) | 65 | = NetHandshake (Handshake Encrypted) |
@@ -260,129 +192,5 @@ data CryptoMessage -- First byte indicates data | |||
260 | -- `0x8d` Onion Response 2 -return | 192 | -- `0x8d` Onion Response 2 -return |
261 | -- `0x8e` Onion Response 1 -return | 193 | -- `0x8e` Onion Response 1 -return |
262 | 194 | ||
263 | forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport -- HandleHi a -> IO a -> HandleLo a | ||
264 | forwardOnions crypto udp = udp { awaitMessage = await' } | ||
265 | where | ||
266 | -- forMe :: HandleHi | ||
267 | -- forThem :: handleLo | ||
268 | await' :: HandleLo a -> IO a | ||
269 | await' forThem = awaitMessage udp $ \case | ||
270 | m@(Just (Right (bs,saddr))) -> case B.head bs of | ||
271 | 0x80 -> forward forThem bs $ handleOnionRequest (Proxy :: Proxy 0) crypto saddr (forThem m) | ||
272 | 0x81 -> forward forThem bs $ handleOnionRequest (Proxy :: Proxy 1) crypto saddr (forThem m) | ||
273 | 0x82 -> forward forThem bs $ handleOnionRequest (Proxy :: Proxy 2) crypto saddr (forThem m) | ||
274 | 0x8c -> forward forThem bs $ handleOnionResponse (Proxy :: Proxy 3) crypto saddr (forThem m) | ||
275 | 0x8d -> forward forThem bs $ handleOnionResponse (Proxy :: Proxy 2) crypto saddr (forThem m) | ||
276 | 0x8e -> forward forThem bs $ handleOnionResponse (Proxy :: Proxy 1) crypto saddr (forThem m) | ||
277 | _ -> forThem m | ||
278 | m -> forThem m | ||
279 | |||
280 | forward :: forall c b b1. | ||
281 | Serialize b => | ||
282 | (Maybe (Either String b1) -> c) -> ByteString -> (b -> c) -> c | ||
283 | forward forMe bs f = either (forMe . Just . Left) f $ decode $ B.tail bs | ||
284 | |||
285 | |||
286 | forwardDHTRequests :: TransportCrypto -> (PublicKey -> IO (Maybe NodeInfo)) -> DHTTransport -> DHTTransport | ||
287 | forwardDHTRequests crypto closeLookup dht = dht { awaitMessage = await' } | ||
288 | where | ||
289 | await' :: HandleHi a -> IO a | ||
290 | await' pass = awaitMessage dht $ \case | ||
291 | Just (Right (m@(DHTDHTRequest target payload),src)) | target /= transportPublic crypto | ||
292 | -> do mni <- closeLookup target | ||
293 | -- Forward the message if the target is in our close list. | ||
294 | forM_ mni $ \ni -> sendMessage dht ni m | ||
295 | await' pass | ||
296 | m -> pass m | ||
297 | |||
298 | |||
299 | -- n = 0, 1, 2 | ||
300 | data OnionRequest (n :: Nat) = OnionRequest | ||
301 | { onionNonce :: Nonce24 | ||
302 | , onionForward :: Forwarding (3 - n) (OnionMessage Encrypted) | ||
303 | , pathFromOwner :: ReturnPath n | ||
304 | } | ||
305 | |||
306 | instance Serialize (OnionRequest n) where { get = _todo; put = _todo } | ||
307 | instance Serialize (OnionResponse n) where { get = _todo; put = _todo } | ||
308 | 195 | ||
309 | -- n = 1, 2, 3 | ||
310 | -- Attributed (Encrypted ( | ||
311 | 196 | ||
312 | data OnionResponse (n :: Nat) = OnionResponse | ||
313 | { pathToOwner :: ReturnPath n | ||
314 | , msgToOwner :: OnionMessage Encrypted | ||
315 | } | ||
316 | |||
317 | data Addressed a = Addressed { sockAddr :: SockAddr, unaddressed :: a } | ||
318 | |||
319 | data ReturnPath (n :: Nat) where | ||
320 | NoReturnPath :: ReturnPath 0 | ||
321 | ReturnPath :: Nonce24 -> Encrypted (Addressed (ReturnPath n)) -> ReturnPath (n + 1) | ||
322 | |||
323 | -- instance KnownNat n => Serialize (ReturnPath n) where | ||
324 | -- -- Size: 59 = 1(family) + 16(ip) + 2(port) +16(mac) + 24(nonce) | ||
325 | -- get = ReturnPath <$> getBytes ( 59 * (fromIntegral $ natVal $ Proxy @n) ) | ||
326 | -- put (ReturnPath bs) = putByteString bs | ||
327 | |||
328 | |||
329 | data Forwarding (n :: Nat) msg where | ||
330 | NotForwarded :: msg -> Forwarding 0 msg | ||
331 | Forwarding :: Assym (Encrypted (Addressed (Forwarding n msg))) -> Forwarding (n + 1) msg | ||
332 | |||
333 | handleOnionRequest :: KnownNat n => proxy n -> TransportCrypto -> SockAddr -> IO a -> OnionRequest n -> IO a | ||
334 | handleOnionRequest = _todo | ||
335 | |||
336 | handleOnionResponse :: KnownNat n => proxy n -> TransportCrypto -> SockAddr -> IO a -> OnionResponse n -> IO a | ||
337 | handleOnionResponse = _todo | ||
338 | |||
339 | data AnnounceRequest = AnnounceRequest | ||
340 | { announcePingId :: Nonce32 -- Ping ID | ||
341 | , announceSeeking :: NodeId -- Public key we are searching for | ||
342 | , announceKey :: NodeId -- Public key that we want those sending back data packets to use | ||
343 | } | ||
344 | |||
345 | instance S.Serialize AnnounceRequest where | ||
346 | get = AnnounceRequest <$> S.get <*> S.get <*> S.get | ||
347 | put (AnnounceRequest p s k) = S.put (p,s,k) | ||
348 | |||
349 | getOnionRequest :: Get (Assym (Encrypted msg), ReturnPath 3) | ||
350 | getOnionRequest = _todo | ||
351 | |||
352 | data KeyRecord = NotStored Nonce32 | ||
353 | | SendBackKey PublicKey | ||
354 | | Acknowledged Nonce32 | ||
355 | |||
356 | getPublicKey :: Get PublicKey | ||
357 | getPublicKey = _todo | ||
358 | |||
359 | putPublicKey :: PublicKey -> Put | ||
360 | putPublicKey = _todo | ||
361 | |||
362 | instance S.Serialize KeyRecord where | ||
363 | get = do | ||
364 | is_stored <- S.get :: S.Get Word8 | ||
365 | case is_stored of | ||
366 | 1 -> SendBackKey <$> getPublicKey | ||
367 | 2 -> Acknowledged <$> S.get | ||
368 | _ -> NotStored <$> S.get | ||
369 | put (NotStored n32) = S.put (0 :: Word8) >> S.put n32 | ||
370 | put (SendBackKey key) = S.put (1 :: Word8) >> putPublicKey key | ||
371 | put (Acknowledged n32) = S.put (2 :: Word8) >> S.put n32 | ||
372 | |||
373 | data AnnounceResponse = AnnounceResponse | ||
374 | { is_stored :: KeyRecord | ||
375 | , announceNodes :: SendNodes | ||
376 | } | ||
377 | |||
378 | instance Sized AnnounceResponse where | ||
379 | size = VarSize $ \AnnounceResponse {} -> _todo | ||
380 | |||
381 | instance S.Serialize AnnounceResponse where | ||
382 | get = AnnounceResponse <$> S.get <*> S.get | ||
383 | put (AnnounceResponse st ns) = S.put st >> S.put ns | ||
384 | |||
385 | data DataToRoute = DataToRoute | ||
386 | { dataFromKey :: PublicKey | ||
387 | , dataToRoute :: Encrypted (Word8,ByteString) | ||
388 | } | ||