diff options
author | joe <joe@jerkface.net> | 2017-09-03 17:00:13 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-09-03 17:00:13 -0400 |
commit | 287379163d93d58142972f5f94c2beb8e872f7d4 (patch) | |
tree | d36d782a92ef499af073785321f81cc1ae11fd39 /DHTTransport.hs | |
parent | 6e82103d0e7f87127bb5b3f1f395e1d5b7adb1e0 (diff) |
Implemented more stubs for DHT transport.
Diffstat (limited to 'DHTTransport.hs')
-rw-r--r-- | DHTTransport.hs | 131 |
1 files changed, 93 insertions, 38 deletions
diff --git a/DHTTransport.hs b/DHTTransport.hs index 690ee346..778390cf 100644 --- a/DHTTransport.hs +++ b/DHTTransport.hs | |||
@@ -29,10 +29,11 @@ import Network.QueryResponse | |||
29 | 29 | ||
30 | import Control.Arrow | 30 | import Control.Arrow |
31 | import Control.Monad | 31 | import Control.Monad |
32 | import Data.Bool | ||
32 | import qualified Data.ByteString as B | 33 | import qualified Data.ByteString as B |
33 | ;import Data.ByteString (ByteString) | 34 | ;import Data.ByteString (ByteString) |
34 | import Data.Tuple | 35 | import Data.Tuple |
35 | import Data.Serialize as S (Get, Serialize, get, put, runGet) | 36 | import Data.Serialize as S |
36 | import Data.Word | 37 | import Data.Word |
37 | import Network.Socket | 38 | import Network.Socket |
38 | 39 | ||
@@ -50,13 +51,14 @@ data DHTMessage (f :: * -> *) | |||
50 | | DHTDHTRequest PublicKey (Assym (f DHTRequest)) | 51 | | DHTDHTRequest PublicKey (Assym (f DHTRequest)) |
51 | 52 | ||
52 | mapMessage :: forall f b. (forall a. Nonce24 -> f a -> b) -> DHTMessage f -> b | 53 | mapMessage :: forall f b. (forall a. Nonce24 -> f a -> b) -> DHTMessage f -> b |
53 | mapMessage f msg = f _todo _todo | 54 | mapMessage f (DHTPing a) = f (assymNonce a) (assymData a) |
55 | mapMessage f (DHTPong a) = f (assymNonce a) (assymData a) | ||
56 | mapMessage f (DHTGetNodes a) = f (assymNonce a) (assymData a) | ||
57 | mapMessage f (DHTSendNodes a) = f (assymNonce a) (assymData a) | ||
58 | mapMessage f (DHTCookieRequest a) = f (assymNonce a) (assymData a) | ||
59 | mapMessage f (DHTDHTRequest _ a) = f (assymNonce a) (assymData a) | ||
60 | mapMessage f (DHTCookie nonce fcookie) = f nonce fcookie | ||
54 | 61 | ||
55 | instance Sized GetNodes where | ||
56 | size = ConstSize 32 -- TODO This right? | ||
57 | |||
58 | instance Sized SendNodes where | ||
59 | size = VarSize $ \(SendNodes ns) -> _nodeFormatSize * length ns | ||
60 | 62 | ||
61 | instance Sized Ping where size = ConstSize 1 | 63 | instance Sized Ping where size = ConstSize 1 |
62 | instance Sized Pong where size = ConstSize 1 | 64 | instance Sized Pong where size = ConstSize 1 |
@@ -77,27 +79,48 @@ parseDHTAddr (msg,saddr) | |||
77 | _ -> right | 79 | _ -> right |
78 | 80 | ||
79 | encodeDHTAddr :: (DHTMessage Encrypted8,NodeInfo) -> (ByteString, SockAddr) | 81 | encodeDHTAddr :: (DHTMessage Encrypted8,NodeInfo) -> (ByteString, SockAddr) |
80 | encodeDHTAddr = _todo | 82 | encodeDHTAddr (msg,ni) = (runPut $ putMessage msg, nodeAddr ni) |
83 | |||
84 | dhtMessageType :: DHTMessage Encrypted8 -> ( Word8, Put ) | ||
85 | dhtMessageType (DHTPing a) = (0x00, putAssym a) | ||
86 | dhtMessageType (DHTPong a) = (0x01, putAssym a) | ||
87 | dhtMessageType (DHTGetNodes a) = (0x02, putAssym a) | ||
88 | dhtMessageType (DHTSendNodes a) = (0x04, putAssym a) | ||
89 | dhtMessageType (DHTCookieRequest a) = (0x18, putAssym a) | ||
90 | dhtMessageType (DHTCookie n x) = (0x19, put n >> put x) | ||
91 | dhtMessageType (DHTDHTRequest k a) = (0x20, putPublicKey k >> putAssym a) | ||
92 | |||
93 | putMessage :: DHTMessage Encrypted8 -> Put | ||
94 | putMessage msg = case dhtMessageType msg of (typ,p) -> put typ >> p | ||
81 | 95 | ||
82 | getCookie :: Get (Nonce24, Encrypted8 Cookie) | 96 | getCookie :: Get (Nonce24, Encrypted8 Cookie) |
83 | getCookie = get | 97 | getCookie = get |
84 | 98 | ||
85 | getDHTReqest :: Get (PublicKey, Assym (Encrypted8 DHTRequest)) | 99 | getDHTReqest :: Get (PublicKey, Assym (Encrypted8 DHTRequest)) |
86 | getDHTReqest = _todo | 100 | getDHTReqest = (,) <$> getPublicKey <*> getAssym |
101 | |||
102 | -- ## DHT Request packets | ||
103 | -- | ||
104 | -- | Length | Contents | | ||
105 | -- |:-------|:--------------------------| | ||
106 | -- | `1` | `uint8_t` (0x20) | | ||
107 | -- | `32` | receiver's DHT public key | | ||
108 | -- ... ... | ||
109 | |||
87 | 110 | ||
88 | getDHT :: Sized a => Get (Assym (Encrypted8 a)) | 111 | getDHT :: Sized a => Get (Assym (Encrypted8 a)) |
89 | getDHT = _todo | 112 | getDHT = getAssym |
90 | 113 | ||
91 | 114 | ||
92 | -- Throws an error if called with a non-internet socket. | 115 | -- Throws an error if called with a non-internet socket. |
93 | direct :: Sized a => ByteString | 116 | direct :: Sized a => ByteString |
94 | -> SockAddr | 117 | -> SockAddr |
95 | -> (Assym (Encrypted8 a) | 118 | -> (Assym (Encrypted8 a) -> DHTMessage Encrypted8) |
96 | -> DHTMessage Encrypted8) | ||
97 | -> Either String (DHTMessage Encrypted8, NodeInfo) | 119 | -> Either String (DHTMessage Encrypted8, NodeInfo) |
98 | direct bs saddr f = fanGet bs getDHT f (asymNodeInfo saddr) | 120 | direct bs saddr f = fanGet bs getDHT f (asymNodeInfo saddr) |
99 | 121 | ||
100 | -- Throws an error if called with a non-internet socket. | 122 | -- Throws an error if called with a non-internet socket. |
123 | asymNodeInfo :: SockAddr -> Assym a -> NodeInfo | ||
101 | asymNodeInfo saddr asym = either (error . mappend "asymNodeInfo: ") id $ nodeInfo (NodeId $ senderKey asym) saddr | 124 | asymNodeInfo saddr asym = either (error . mappend "asymNodeInfo: ") id $ nodeInfo (NodeId $ senderKey asym) saddr |
102 | 125 | ||
103 | 126 | ||
@@ -105,35 +128,49 @@ fanGet :: ByteString -> Get x -> (x -> a) -> (x -> b) -> Either String (a,b) | |||
105 | fanGet bs getIt f nid = fmap (f &&& nid) $ runGet getIt bs | 128 | fanGet bs getIt f nid = fmap (f &&& nid) $ runGet getIt bs |
106 | 129 | ||
107 | -- Throws an error if called with a non-internet socket. | 130 | -- Throws an error if called with a non-internet socket. |
131 | noReplyAddr :: SockAddr -> NodeInfo | ||
108 | noReplyAddr saddr = either (error . mappend "noReplyAddr: ") id $ nodeInfo zeroID saddr | 132 | noReplyAddr saddr = either (error . mappend "noReplyAddr: ") id $ nodeInfo zeroID saddr |
109 | 133 | ||
110 | 134 | ||
111 | -- ## DHT Request packets | ||
112 | -- | ||
113 | -- | Length | Contents | | ||
114 | -- |:-------|:--------------------------| | ||
115 | -- | `1` | `uint8_t` (0x20) | | ||
116 | -- | `32` | receiver's DHT public key | | ||
117 | -- ... ... | ||
118 | |||
119 | data DHTRequestPacket = DHTRequestPacket | ||
120 | { requestTarget :: PublicKey | ||
121 | , request :: Assym (Encrypted DHTRequest) | ||
122 | } | ||
123 | |||
124 | instance Serialize DHTRequestPacket where | ||
125 | get = _todo | ||
126 | put = _todo | ||
127 | |||
128 | |||
129 | data DHTRequest | 135 | data DHTRequest |
136 | -- #### NAT ping request | ||
137 | -- | ||
138 | -- Length Contents | ||
139 | -- :------- :------------------------- | ||
140 | -- `1` `uint8_t` (0xfe) | ||
141 | -- `1` `uint8_t` (0x00) | ||
142 | -- `8` `uint64_t` random number | ||
130 | = NATPing Nonce8 | 143 | = NATPing Nonce8 |
144 | -- #### NAT ping response | ||
145 | -- | ||
146 | -- Length Contents | ||
147 | -- :------- :----------------------------------------------------------------- | ||
148 | -- `1` `uint8_t` (0xfe) | ||
149 | -- `1` `uint8_t` (0x01) | ||
150 | -- `8` `uint64_t` random number (the same that was received in request) | ||
131 | | NATPong Nonce8 | 151 | | NATPong Nonce8 |
132 | | DHTPK DHTPublicKey | 152 | | DHTPK DHTPublicKey |
133 | 153 | ||
154 | instance Sized DHTRequest where | ||
155 | size = VarSize $ \case | ||
156 | NATPing _ -> 10 | ||
157 | NATPong _ -> 10 | ||
158 | DHTPK dhtpk -> 41 + case size of | ||
159 | ConstSize nodes -> nodes | ||
160 | VarSize sznodes -> sznodes (dhtpkNodes dhtpk) | ||
161 | |||
134 | instance Serialize DHTRequest where | 162 | instance Serialize DHTRequest where |
135 | get = return _todo | 163 | get = do |
136 | put _ = return () -- todo | 164 | tag <- get |
165 | case tag :: Word8 of | ||
166 | 0xfe -> do | ||
167 | direction <- get | ||
168 | bool NATPong NATPing (direction==(0::Word8)) <$> get | ||
169 | 0x9c -> DHTPK <$> get | ||
170 | _ -> fail ("unrecognized DHT request: "++show tag) | ||
171 | put (NATPing n) = put (0xfe00 :: Word16) >> put n | ||
172 | put (NATPong n) = put (0xfe01 :: Word16) >> put n | ||
173 | put (DHTPK pk) = put (0x9c :: Word8) >> put pk | ||
137 | 174 | ||
138 | -- | Length | Contents | | 175 | -- | Length | Contents | |
139 | -- |:------------|:------------------------------------| | 176 | -- |:------------|:------------------------------------| |
@@ -147,12 +184,27 @@ data DHTPublicKey = DHTPublicKey | |||
147 | , dhtpkNodes :: SendNodes | 184 | , dhtpkNodes :: SendNodes |
148 | } | 185 | } |
149 | 186 | ||
187 | instance Serialize DHTPublicKey where | ||
188 | get = DHTPublicKey <$> get <*> getPublicKey <*> get | ||
189 | put (DHTPublicKey nonce key nodes) = do | ||
190 | put nonce | ||
191 | putPublicKey key | ||
192 | put nodes | ||
193 | |||
150 | newtype GetNodes = GetNodes NodeId | 194 | newtype GetNodes = GetNodes NodeId |
151 | deriving (Eq,Ord,Show,Read,S.Serialize) | 195 | deriving (Eq,Ord,Show,Read,S.Serialize) |
152 | 196 | ||
197 | instance Sized GetNodes where | ||
198 | size = ConstSize 32 -- TODO This right? | ||
199 | |||
153 | newtype SendNodes = SendNodes [NodeInfo] | 200 | newtype SendNodes = SendNodes [NodeInfo] |
154 | deriving (Eq,Ord,Show,Read) | 201 | deriving (Eq,Ord,Show,Read) |
155 | 202 | ||
203 | instance Sized SendNodes where | ||
204 | size = VarSize $ \(SendNodes ns) -> case size of | ||
205 | ConstSize nodeFormatSize -> nodeFormatSize * length ns | ||
206 | VarSize nsize -> sum $ map nsize ns | ||
207 | |||
156 | instance S.Serialize SendNodes where | 208 | instance S.Serialize SendNodes where |
157 | get = do | 209 | get = do |
158 | cnt <- S.get :: S.Get Word8 | 210 | cnt <- S.get :: S.Get Word8 |
@@ -189,8 +241,8 @@ data Cookie = Cookie Nonce24 (Encrypted CookieData) | |||
189 | instance Sized Cookie where size = ConstSize 112 -- 24 byte nonce + 88 byte cookie data | 241 | instance Sized Cookie where size = ConstSize 112 -- 24 byte nonce + 88 byte cookie data |
190 | 242 | ||
191 | instance Serialize Cookie where | 243 | instance Serialize Cookie where |
192 | get = return $ Cookie _todo _todo | 244 | get = Cookie <$> get <*> get |
193 | put _ = return () -- todo | 245 | put (Cookie nonce dta) = put nonce >> put dta |
194 | 246 | ||
195 | data CookieData = CookieData -- 16 (mac) | 247 | data CookieData = CookieData -- 16 (mac) |
196 | { cookieTime :: Word64 -- 8 | 248 | { cookieTime :: Word64 -- 8 |
@@ -198,12 +250,15 @@ data CookieData = CookieData -- 16 (mac) | |||
198 | , dhtKey :: PublicKey -- + 32 | 250 | , dhtKey :: PublicKey -- + 32 |
199 | } -- = 88 bytes when encrypted. | 251 | } -- = 88 bytes when encrypted. |
200 | 252 | ||
253 | instance Sized CookieData where | ||
254 | size = ConstSize 72 | ||
255 | |||
201 | instance Sized CookieRequest where | 256 | instance Sized CookieRequest where |
202 | size = ConstSize 64 -- 32 byte key + 32 byte padding | 257 | size = ConstSize 64 -- 32 byte key + 32 byte padding |
203 | 258 | ||
204 | instance Serialize CookieRequest where | 259 | instance Serialize CookieRequest where |
205 | get = CookieRequest <$> return _todo | 260 | get = CookieRequest <$> getPublicKey <* {- padding -} getPublicKey |
206 | put (CookieRequest _) = return () -- todo | 261 | put (CookieRequest k) = putPublicKey k >> {- padding -} putPublicKey k |
207 | 262 | ||
208 | forwardDHTRequests :: TransportCrypto -> (PublicKey -> IO (Maybe NodeInfo)) -> DHTTransport -> DHTTransport | 263 | forwardDHTRequests :: TransportCrypto -> (PublicKey -> IO (Maybe NodeInfo)) -> DHTTransport -> DHTTransport |
209 | forwardDHTRequests crypto closeLookup dht = dht { awaitMessage = await' } | 264 | forwardDHTRequests crypto closeLookup dht = dht { awaitMessage = await' } |
@@ -226,7 +281,7 @@ encryptMessage crypto n (Right assym) = E8 $ ToxCrypto.encrypt secret plain | |||
226 | where | 281 | where |
227 | secret = computeSharedSecret (transportSecret crypto) (senderKey assym) n | 282 | secret = computeSharedSecret (transportSecret crypto) (senderKey assym) n |
228 | plain = encodePlain $ swap $ assymData assym | 283 | plain = encodePlain $ swap $ assymData assym |
229 | encryptMessage crypto n (Left plain) = _todo | 284 | encryptMessage crypto n (Left plain) = _todo -- need cached public key. |
230 | 285 | ||
231 | decrypt :: TransportCrypto -> DHTMessage Encrypted8 -> NodeInfo -> Either String (DHTMessage ((,) Nonce8), NodeInfo) | 286 | decrypt :: TransportCrypto -> DHTMessage Encrypted8 -> NodeInfo -> Either String (DHTMessage ((,) Nonce8), NodeInfo) |
232 | decrypt crypto msg ni = (, ni) <$> (sequenceMessage $ transcode (decryptMessage crypto) msg) | 287 | decrypt crypto msg ni = (, ni) <$> (sequenceMessage $ transcode (decryptMessage crypto) msg) |
@@ -241,7 +296,7 @@ decryptMessage crypto n (Right assymE) = plain8 $ ToxCrypto.decrypt secret e | |||
241 | secret = computeSharedSecret (transportSecret crypto) (senderKey assymE) n | 296 | secret = computeSharedSecret (transportSecret crypto) (senderKey assymE) n |
242 | E8 e = assymData assymE | 297 | E8 e = assymData assymE |
243 | plain8 = Composed . fmap swap . (>>= decodePlain) | 298 | plain8 = Composed . fmap swap . (>>= decodePlain) |
244 | decryptMessage crypto n (Left (E8 e)) = _todo | 299 | decryptMessage crypto n (Left (E8 e)) = _todo -- need cached public key |
245 | 300 | ||
246 | sequenceMessage :: Applicative m => DHTMessage (m ∘ f) -> m (DHTMessage f) | 301 | sequenceMessage :: Applicative m => DHTMessage (m ∘ f) -> m (DHTMessage f) |
247 | sequenceMessage (DHTPing asym) = fmap DHTPing $ sequenceA $ fmap uncomposed asym | 302 | sequenceMessage (DHTPing asym) = fmap DHTPing $ sequenceA $ fmap uncomposed asym |