summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-08-31 15:19:34 -0400
committerjoe <joe@jerkface.net>2017-08-31 15:19:34 -0400
commita6b55a29ff656f105ca79c7d4f060920a37c7c70 (patch)
treee7dc6bd7dc066626e5460117384d30ffbcd29971
parent74de5c3d86dfdc000f0abab0d465109417932ffe (diff)
Separated module DHTTransport from ToxTransport.
-rw-r--r--DHTTransport.hs177
-rw-r--r--ToxAddress.hs30
-rw-r--r--ToxCrypto.hs16
-rw-r--r--ToxTransport.hs84
4 files changed, 209 insertions, 98 deletions
diff --git a/DHTTransport.hs b/DHTTransport.hs
new file mode 100644
index 00000000..6b3af2fc
--- /dev/null
+++ b/DHTTransport.hs
@@ -0,0 +1,177 @@
1{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE KindSignatures #-}
3module DHTTransport
4 ( parseDHTAddr
5 , encodeDHTAddr
6 , module ToxAddress
7 , DHTMessage(..)
8 , Ping
9 , Pong
10 , GetNodes
11 , SendNodes
12 , CookieRequest
13 , Cookie
14 , DHTRequest
15 ) where
16
17import ToxAddress
18import ToxCrypto
19
20import Control.Arrow
21import qualified Data.ByteString as B
22 ;import Data.ByteString (ByteString)
23import Data.Serialize as S (Get, Serialize, get, put, runGet)
24import Data.Word
25import Network.Socket
26
27
28
29data DHTMessage (f :: * -> *)
30 = DHTPing (Assym (f Ping))
31 | DHTPong (Assym (f Pong))
32 | DHTGetNodes (Assym (f GetNodes))
33 | DHTSendNodes (Assym (f SendNodes))
34 | DHTCookieRequest (Assym (f CookieRequest))
35 | DHTCookie Nonce24 (f Cookie)
36 | DHTDHTRequest PublicKey (Assym (f DHTRequest))
37
38instance Sized GetNodes where
39 size = ConstSize 32 -- TODO This right?
40
41instance Sized SendNodes where
42 size = VarSize $ \(SendNodes ns) -> _nodeFormatSize * length ns
43
44instance Sized Ping where size = ConstSize 1
45instance Sized Pong where size = ConstSize 1
46
47parseDHTAddr :: (ByteString, SockAddr) -> Either (DHTMessage Encrypted8,NodeInfo) (ByteString,SockAddr)
48parseDHTAddr (msg,saddr)
49 | Just (typ,bs) <- B.uncons msg
50 , let right = Right (msg,saddr)
51 left = either (const right) Left
52 = case typ of
53 0x00 -> left $ direct bs saddr DHTPing
54 0x01 -> left $ direct bs saddr DHTPong
55 0x02 -> left $ direct bs saddr DHTGetNodes
56 0x04 -> left $ direct bs saddr DHTSendNodes
57 0x18 -> left $ direct bs saddr DHTCookieRequest
58 0x19 -> left $ fanGet bs getCookie (uncurry DHTCookie) (const $ noReplyAddr saddr)
59 0x20 -> left $ fanGet bs getDHTReqest (uncurry DHTDHTRequest) (asymNodeInfo saddr . snd)
60 _ -> right
61
62encodeDHTAddr :: (DHTMessage Encrypted8,NodeInfo) -> (ByteString, SockAddr)
63encodeDHTAddr = _todo
64
65getCookie :: Get (Nonce24, Encrypted8 Cookie)
66getCookie = get
67
68getDHTReqest :: Get (PublicKey, Assym (Encrypted8 DHTRequest))
69getDHTReqest = _todo
70
71getDHT :: Sized a => Get (Assym (Encrypted8 a))
72getDHT = _todo
73
74
75-- Throws an error if called with a non-internet socket.
76direct :: Sized a => ByteString
77 -> SockAddr
78 -> (Assym (Encrypted8 a)
79 -> DHTMessage Encrypted8)
80 -> Either String (DHTMessage Encrypted8, NodeInfo)
81direct bs saddr f = fanGet bs getDHT f (asymNodeInfo saddr)
82
83-- Throws an error if called with a non-internet socket.
84asymNodeInfo saddr asym = either (error . mappend "asymNodeInfo: ") id $ nodeInfo (NodeId $ senderKey asym) saddr
85
86
87fanGet :: ByteString -> Get x -> (x -> a) -> (x -> b) -> Either String (a,b)
88fanGet bs getIt f nid = fmap (f &&& nid) $ runGet getIt bs
89
90-- Throws an error if called with a non-internet socket.
91noReplyAddr saddr = either (error . mappend "noReplyAddr: ") id $ nodeInfo zeroID saddr
92
93
94-- ## DHT Request packets
95--
96-- | Length | Contents |
97-- |:-------|:--------------------------|
98-- | `1` | `uint8_t` (0x20) |
99-- | `32` | receiver's DHT public key |
100-- ... ...
101
102data DHTRequestPacket = DHTRequestPacket
103 { requestTarget :: PublicKey
104 , request :: Assym (Encrypted DHTRequest)
105 }
106
107instance Serialize DHTRequestPacket where
108 get = _todo
109 put = _todo
110
111
112data DHTRequest
113 = NATPing Nonce8
114 | NATPong Nonce8
115 | DHTPK DHTPublicKey
116
117-- | Length | Contents |
118-- |:------------|:------------------------------------|
119-- | `1` | `uint8_t` (0x9c) |
120-- | `8` | `uint64_t` `no_replay` |
121-- | `32` | Our DHT public key |
122-- | `[39, 204]` | Maximum of 4 nodes in packed format |
123data DHTPublicKey = DHTPublicKey
124 { dhtpkNonce :: Nonce8
125 , dhtpk :: PublicKey
126 , dhtpkNodes :: SendNodes
127 }
128
129newtype GetNodes = GetNodes NodeId
130 deriving (Eq,Ord,Show,Read,S.Serialize)
131
132newtype SendNodes = SendNodes [NodeInfo]
133 deriving (Eq,Ord,Show,Read)
134
135instance S.Serialize SendNodes where
136 get = do
137 cnt <- S.get :: S.Get Word8
138 ns <- sequence $ replicate (fromIntegral cnt) S.get
139 return $ SendNodes ns
140
141 put (SendNodes ns) = do
142 let ns' = take 4 ns
143 S.put (fromIntegral (length ns') :: Word8)
144 mapM_ S.put ns'
145
146data Ping = Ping deriving Show
147data Pong = Pong deriving Show
148
149instance S.Serialize Ping where
150 get = do w8 <- S.get
151 if (w8 :: Word8) /= 0
152 then fail "Malformed ping."
153 else return Ping
154 put Ping = S.put (0 :: Word8)
155
156instance S.Serialize Pong where
157 get = do w8 <- S.get
158 if (w8 :: Word8) /= 1
159 then fail "Malformed pong."
160 else return Pong
161 put Pong = S.put (1 :: Word8)
162
163newtype CookieRequest = CookieRequest PublicKey
164newtype CookieResponse = CookieResponse Cookie
165
166data Cookie = Cookie Nonce24 (Encrypted CookieData)
167
168instance Sized Cookie where size = ConstSize 112 -- 24 byte nonce + 88 byte cookie data
169
170data CookieData = CookieData -- 16 (mac)
171 { cookieTime :: Word64 -- 8
172 , longTermKey :: PublicKey -- 32
173 , dhtKey :: PublicKey -- + 32
174 } -- = 88 bytes when encrypted.
175
176instance Sized CookieRequest where
177 size = ConstSize 64 -- 32 byte key + 32 byte padding
diff --git a/ToxAddress.hs b/ToxAddress.hs
index a0d5345d..9aa7a575 100644
--- a/ToxAddress.hs
+++ b/ToxAddress.hs
@@ -13,16 +13,18 @@
13{-# LANGUAGE ScopedTypeVariables #-} 13{-# LANGUAGE ScopedTypeVariables #-}
14{-# LANGUAGE TupleSections #-} 14{-# LANGUAGE TupleSections #-}
15{-# LANGUAGE TypeApplications #-} 15{-# LANGUAGE TypeApplications #-}
16module ToxAddress where 16module ToxAddress (NodeInfo(..),NodeId(..),nodeInfo) where
17 17
18import Control.Applicative 18import Control.Applicative
19import Control.Monad 19import Control.Monad
20import Crypto.Error.Types (CryptoFailable (..),
21 throwCryptoError)
22import Crypto.PubKey.Curve25519
20import qualified Data.Aeson as JSON 23import qualified Data.Aeson as JSON
21 ;import Data.Aeson (FromJSON, ToJSON, (.=)) 24 ;import Data.Aeson (FromJSON, ToJSON, (.=))
22import Data.Bits
23import Data.Bits.ByteString () 25import Data.Bits.ByteString ()
24import Data.ByteArray as BA (ByteArrayAccess, Bytes) 26import qualified Data.ByteArray as BA
25import qualified Data.ByteArray as BA 27 ;import Data.ByteArray as BA (ByteArrayAccess)
26import qualified Data.ByteString as B 28import qualified Data.ByteString as B
27 ;import Data.ByteString (ByteString) 29 ;import Data.ByteString (ByteString)
28import qualified Data.ByteString.Base16 as Base16 30import qualified Data.ByteString.Base16 as Base16
@@ -33,18 +35,12 @@ import Data.Hashable
33import Data.IP 35import Data.IP
34import Data.Serialize as S 36import Data.Serialize as S
35import Data.Word 37import Data.Word
38import Foreign.Storable
39import GHC.TypeLits
36import Network.Address hiding (nodePort) 40import Network.Address hiding (nodePort)
37import Network.Socket 41import System.IO.Unsafe (unsafeDupablePerformIO)
38import qualified Text.ParserCombinators.ReadP as RP 42import qualified Text.ParserCombinators.ReadP as RP
39import Text.Read 43import Text.Read
40import GHC.TypeLits
41import Crypto.PubKey.Curve25519
42import Crypto.Error.Types (CryptoFailable(..))
43
44data Address
45 = DHTNode NodeInfo -- A direct DHT exchange.
46 | OnionFromOwner NodeInfo (ForwardPath 3) -- Your own created onion path.
47 | OnionToOwner NodeInfo (ReturnPath 3) -- An onion path end point.
48 44
49-- | perform io for hashes that do allocation and ffi. 45-- | perform io for hashes that do allocation and ffi.
50-- unsafeDupablePerformIO is used when possible as the 46-- unsafeDupablePerformIO is used when possible as the
@@ -363,14 +359,6 @@ zeroID = PubKey $ B.replicate 32 0
363 359
364-} 360-}
365 361
366newtype ReturnPath (n::Nat) = ReturnPath ByteString
367 deriving (Eq, Ord,Data)
368
369instance KnownNat n => Serialize (ReturnPath n) where
370 -- Size: 59 = 1(family) + 16(ip) + 2(port) +16(mac) + 24(nonce)
371 get = ReturnPath <$> getBytes ( 59 * (fromIntegral $ natVal $ Proxy @n) )
372 put (ReturnPath bs) = putByteString bs
373
374newtype ForwardPath (n::Nat) = ForwardPath ByteString 362newtype ForwardPath (n::Nat) = ForwardPath ByteString
375 deriving (Eq, Ord,Data) 363 deriving (Eq, Ord,Data)
376 364
diff --git a/ToxCrypto.hs b/ToxCrypto.hs
index cae7e251..6f0fcf1a 100644
--- a/ToxCrypto.hs
+++ b/ToxCrypto.hs
@@ -7,6 +7,8 @@ module ToxCrypto
7 , publicKey 7 , publicKey
8 , SecretKey 8 , SecretKey
9 , Encrypted 9 , Encrypted
10 , Encrypted8
11 , Assym(..)
10 , Plain 12 , Plain
11 , computeSharedSecret 13 , computeSharedSecret
12 , encrypt 14 , encrypt
@@ -47,6 +49,10 @@ import qualified Data.ByteString.Internal
47newtype Encrypted a = Encrypted ByteString 49newtype Encrypted a = Encrypted ByteString
48 deriving (Eq,Ord,Data) 50 deriving (Eq,Ord,Data)
49 51
52newtype Encrypted8 a = E8 (Encrypted (a,Nonce8))
53 deriving Serialize
54
55
50newtype Auth = Auth Poly1305.Auth deriving (Eq, ByteArrayAccess) 56newtype Auth = Auth Poly1305.Auth deriving (Eq, ByteArrayAccess)
51instance Ord Auth where 57instance Ord Auth where
52 compare (Auth a) (Auth b) = comparing (BA.convert :: Poly1305.Auth -> Bytes) a b 58 compare (Auth a) (Auth b) = comparing (BA.convert :: Poly1305.Auth -> Bytes) a b
@@ -210,3 +216,13 @@ zeros32 = Nonce32 $ BA.replicate 32 0
210 216
211zeros24 :: ByteString 217zeros24 :: ByteString
212zeros24 = BA.take 24 zs where Nonce32 zs = zeros32 218zeros24 = BA.take 24 zs where Nonce32 zs = zeros32
219
220-- | `32` | sender's DHT public key |
221-- | `24` | nonce |
222-- | `?` | encrypted message |
223data Assym a = Assym
224 { senderKey :: PublicKey
225 , assymNonce :: Nonce24
226 , assymData :: a
227 }
228
diff --git a/ToxTransport.hs b/ToxTransport.hs
index 694d9d79..3e442d49 100644
--- a/ToxTransport.hs
+++ b/ToxTransport.hs
@@ -15,16 +15,6 @@ module ToxTransport
15 15
16 , UDPTransport 16 , UDPTransport
17 17
18 -- DHTTransport
19 , DHTMessage(..)
20 , Ping
21 , Pong
22 , GetNodes
23 , SendNodes
24 , CookieRequest
25 , Cookie
26 , DHTRequest
27
28 -- OnionTransport 18 -- OnionTransport
29 , OnionToOwner(..) 19 , OnionToOwner(..)
30 , OnionMessage(..) 20 , OnionMessage(..)
@@ -48,9 +38,8 @@ module ToxTransport
48 ) where 38 ) where
49 39
50import Network.QueryResponse 40import Network.QueryResponse
51import ToxAddress as Tox hiding (OnionToOwner, ReturnPath)
52import ToxCrypto 41import ToxCrypto
53import ToxPacket 42import DHTTransport
54 43
55import Control.Applicative 44import Control.Applicative
56import Control.Arrow 45import Control.Arrow
@@ -98,76 +87,11 @@ toxTransport crypto closeLookup udp = do
98type HandleHi a = Maybe (Either String (DHTMessage Encrypted8, NodeInfo)) -> IO a 87type HandleHi a = Maybe (Either String (DHTMessage Encrypted8, NodeInfo)) -> IO a
99type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a 88type HandleLo a = Maybe (Either String (ByteString, SockAddr)) -> IO a
100 89
101data DHTMessage (f :: * -> *)
102 = DHTPing (Assym (f Ping))
103 | DHTPong (Assym (f Pong))
104 | DHTGetNodes (Assym (f GetNodes))
105 | DHTSendNodes (Assym (f SendNodes))
106 | DHTCookieRequest (Assym (f CookieRequest))
107 | DHTCookie Nonce24 (f Cookie)
108 | DHTDHTRequest PublicKey (Assym (f DHTRequest))
109
110instance Sized GetNodes where
111 size = ConstSize 32 -- TODO This right?
112
113instance Sized SendNodes where
114 size = VarSize $ \(SendNodes ns) -> _nodeFormatSize * length ns
115
116instance Sized Ping where size = ConstSize 1
117instance Sized Pong where size = ConstSize 1
118
119newtype Encrypted8 a = E8 (Encrypted (a,Nonce8))
120 deriving Serialize
121
122-- instance (Sized a, Sized b) => Sized (a,b) where size = _todo 90-- instance (Sized a, Sized b) => Sized (a,b) where size = _todo
123 91
124getDHT :: Sized a => Get (Assym (Encrypted8 a))
125getDHT = _todo
126
127getOnionAssym :: Get (Assym (Encrypted DataToRoute)) 92getOnionAssym :: Get (Assym (Encrypted DataToRoute))
128getOnionAssym = _todo 93getOnionAssym = _todo
129 94
130getCookie :: Get (Nonce24, Encrypted8 Cookie)
131getCookie = get
132
133getDHTReqest :: Get (PublicKey, Assym (Encrypted8 DHTRequest))
134getDHTReqest = _todo
135
136fanGet :: ByteString -> Get x -> (x -> a) -> (x -> b) -> Either String (a,b)
137fanGet bs getIt f nid = fmap (f &&& nid) $ runGet getIt bs
138
139-- Throws an error if called with a non-internet socket.
140direct :: Sized a => ByteString
141 -> SockAddr
142 -> (Assym (Encrypted8 a)
143 -> DHTMessage Encrypted8)
144 -> Either String (DHTMessage Encrypted8, NodeInfo)
145direct bs saddr f = fanGet bs getDHT f (asymNodeInfo saddr)
146
147-- Throws an error if called with a non-internet socket.
148asymNodeInfo saddr asym = either (error . mappend "asymNodeInfo: ") id $ nodeInfo (NodeId $ senderKey asym) saddr
149
150-- Throws an error if called with a non-internet socket.
151noReplyAddr saddr = either (error . mappend "noReplyAddr: ") id $ nodeInfo zeroID saddr
152
153parseDHTAddr :: (ByteString, SockAddr) -> Either (DHTMessage Encrypted8,NodeInfo) (ByteString,SockAddr)
154parseDHTAddr (msg,saddr)
155 | Just (typ,bs) <- B.uncons msg
156 , let right = Right (msg,saddr)
157 left = either (const right) Left
158 = case typ of
159 0x00 -> left $ direct bs saddr DHTPing
160 0x01 -> left $ direct bs saddr DHTPong
161 0x02 -> left $ direct bs saddr DHTGetNodes
162 0x04 -> left $ direct bs saddr DHTSendNodes
163 0x18 -> left $ direct bs saddr DHTCookieRequest
164 0x19 -> left $ fanGet bs getCookie (uncurry DHTCookie) (const $ noReplyAddr saddr)
165 0x20 -> left $ fanGet bs getDHTReqest (uncurry DHTDHTRequest) (asymNodeInfo saddr . snd)
166 _ -> right
167
168encodeDHTAddr :: (DHTMessage Encrypted8,NodeInfo) -> (ByteString, SockAddr)
169encodeDHTAddr = _todo
170
171 95
172data OnionMessage (f :: * -> *) 96data OnionMessage (f :: * -> *)
173 = OnionAnnounce (Assym (f (AnnounceRequest,Nonce8))) 97 = OnionAnnounce (Assym (f (AnnounceRequest,Nonce8)))
@@ -396,6 +320,12 @@ data ReturnPath (n :: Nat) where
396 NoReturnPath :: ReturnPath 0 320 NoReturnPath :: ReturnPath 0
397 ReturnPath :: Nonce24 -> Encrypted (Addressed (ReturnPath n)) -> ReturnPath (n + 1) 321 ReturnPath :: Nonce24 -> Encrypted (Addressed (ReturnPath n)) -> ReturnPath (n + 1)
398 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
399data Forwarding (n :: Nat) msg where 329data Forwarding (n :: Nat) msg where
400 NotForwarded :: msg -> Forwarding 0 msg 330 NotForwarded :: msg -> Forwarding 0 msg
401 Forwarding :: Assym (Encrypted (Addressed (Forwarding n msg))) -> Forwarding (n + 1) msg 331 Forwarding :: Assym (Encrypted (Addressed (Forwarding n msg))) -> Forwarding (n + 1) msg