summaryrefslogtreecommitdiff
path: root/OnionTransport.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-08-31 15:42:27 -0400
committerjoe <joe@jerkface.net>2017-08-31 15:42:49 -0400
commiteba3cdcc646211cc152c16d0813cc7e9b1c3111b (patch)
treee90c45a86d11b16da4eee5f21bb8ee618d7d94d6 /OnionTransport.hs
parenta6b55a29ff656f105ca79c7d4f060920a37c7c70 (diff)
Separated module OnionTransport from ToxTransport.
Diffstat (limited to 'OnionTransport.hs')
-rw-r--r--OnionTransport.hs196
1 files changed, 196 insertions, 0 deletions
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 #-}
9module 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
26import Network.QueryResponse
27import ToxCrypto
28import DHTTransport (NodeInfo(..),NodeId(..),SendNodes,nodeInfo)
29
30import Control.Arrow
31import qualified Data.ByteString as B
32 ;import Data.ByteString (ByteString)
33import Data.Serialize as S (Get, Put, Serialize, get, put, runGet)
34import Data.Typeable
35import Data.Word
36import GHC.TypeLits
37import Network.Socket
38
39type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a
40
41type UDPTransport = Transport String SockAddr ByteString
42
43
44getOnionAssym :: Get (Assym (Encrypted DataToRoute))
45getOnionAssym = _todo
46
47data 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
53data OnionToOwner = OnionToOwner NodeInfo (ReturnPath 3)
54 | OnionToMe SockAddr -- SockAddr is immediate peer in route
55
56
57onionToOwner 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
63onion bs saddr getf = do (f,(assym,ret3)) <- runGet ((,) <$> getf <*> getOnionRequest) bs
64 oaddr <- onionToOwner assym ret3 saddr
65 return (f assym, oaddr)
66
67
68parseOnionAddr :: (ByteString, SockAddr) -> Either (OnionMessage Encrypted,OnionToOwner) (ByteString,SockAddr)
69parseOnionAddr (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
81encodeOnionAddr :: (OnionMessage Encrypted,OnionToOwner) -> (ByteString, SockAddr)
82encodeOnionAddr = _todo
83
84forwardOnions :: TransportCrypto -> UDPTransport -> UDPTransport -- HandleHi a -> IO a -> HandleLo a
85forwardOnions 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
101forward :: forall c b b1.
102 Serialize b =>
103 (Maybe (Either String b1) -> c) -> ByteString -> (b -> c) -> c
104forward forMe bs f = either (forMe . Just . Left) f $ decode $ B.tail bs
105
106-- n = 0, 1, 2
107data OnionRequest (n :: Nat) = OnionRequest
108 { onionNonce :: Nonce24
109 , onionForward :: Forwarding (3 - n) (OnionMessage Encrypted)
110 , pathFromOwner :: ReturnPath n
111 }
112
113instance Serialize (OnionRequest n) where { get = _todo; put = _todo }
114instance Serialize (OnionResponse n) where { get = _todo; put = _todo }
115
116-- n = 1, 2, 3
117-- Attributed (Encrypted (
118
119data OnionResponse (n :: Nat) = OnionResponse
120 { pathToOwner :: ReturnPath n
121 , msgToOwner :: OnionMessage Encrypted
122 }
123
124data Addressed a = Addressed { sockAddr :: SockAddr, unaddressed :: a }
125
126data 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
136data Forwarding (n :: Nat) msg where
137 NotForwarded :: msg -> Forwarding 0 msg
138 Forwarding :: Assym (Encrypted (Addressed (Forwarding n msg))) -> Forwarding (n + 1) msg
139
140handleOnionRequest :: KnownNat n => proxy n -> TransportCrypto -> SockAddr -> IO a -> OnionRequest n -> IO a
141handleOnionRequest = _todo
142
143handleOnionResponse :: KnownNat n => proxy n -> TransportCrypto -> SockAddr -> IO a -> OnionResponse n -> IO a
144handleOnionResponse = _todo
145
146data 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
152instance 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
156getOnionRequest :: Get (Assym (Encrypted msg), ReturnPath 3)
157getOnionRequest = _todo
158
159data KeyRecord = NotStored Nonce32
160 | SendBackKey PublicKey
161 | Acknowledged Nonce32
162
163getPublicKey :: Get PublicKey
164getPublicKey = _todo
165
166putPublicKey :: PublicKey -> Put
167putPublicKey = _todo
168
169instance 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
180data AnnounceResponse = AnnounceResponse
181 { is_stored :: KeyRecord
182 , announceNodes :: SendNodes
183 }
184
185instance Sized AnnounceResponse where
186 size = VarSize $ \AnnounceResponse {} -> _todo
187
188instance S.Serialize AnnounceResponse where
189 get = AnnounceResponse <$> S.get <*> S.get
190 put (AnnounceResponse st ns) = S.put st >> S.put ns
191
192data DataToRoute = DataToRoute
193 { dataFromKey :: PublicKey
194 , dataToRoute :: Encrypted (Word8,ByteString)
195 }
196