summaryrefslogtreecommitdiff
path: root/DHTTransport.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-09-03 17:00:13 -0400
committerjoe <joe@jerkface.net>2017-09-03 17:00:13 -0400
commit287379163d93d58142972f5f94c2beb8e872f7d4 (patch)
treed36d782a92ef499af073785321f81cc1ae11fd39 /DHTTransport.hs
parent6e82103d0e7f87127bb5b3f1f395e1d5b7adb1e0 (diff)
Implemented more stubs for DHT transport.
Diffstat (limited to 'DHTTransport.hs')
-rw-r--r--DHTTransport.hs131
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
30import Control.Arrow 30import Control.Arrow
31import Control.Monad 31import Control.Monad
32import Data.Bool
32import qualified Data.ByteString as B 33import qualified Data.ByteString as B
33 ;import Data.ByteString (ByteString) 34 ;import Data.ByteString (ByteString)
34import Data.Tuple 35import Data.Tuple
35import Data.Serialize as S (Get, Serialize, get, put, runGet) 36import Data.Serialize as S
36import Data.Word 37import Data.Word
37import Network.Socket 38import 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
52mapMessage :: forall f b. (forall a. Nonce24 -> f a -> b) -> DHTMessage f -> b 53mapMessage :: forall f b. (forall a. Nonce24 -> f a -> b) -> DHTMessage f -> b
53mapMessage f msg = f _todo _todo 54mapMessage f (DHTPing a) = f (assymNonce a) (assymData a)
55mapMessage f (DHTPong a) = f (assymNonce a) (assymData a)
56mapMessage f (DHTGetNodes a) = f (assymNonce a) (assymData a)
57mapMessage f (DHTSendNodes a) = f (assymNonce a) (assymData a)
58mapMessage f (DHTCookieRequest a) = f (assymNonce a) (assymData a)
59mapMessage f (DHTDHTRequest _ a) = f (assymNonce a) (assymData a)
60mapMessage f (DHTCookie nonce fcookie) = f nonce fcookie
54 61
55instance Sized GetNodes where
56 size = ConstSize 32 -- TODO This right?
57
58instance Sized SendNodes where
59 size = VarSize $ \(SendNodes ns) -> _nodeFormatSize * length ns
60 62
61instance Sized Ping where size = ConstSize 1 63instance Sized Ping where size = ConstSize 1
62instance Sized Pong where size = ConstSize 1 64instance Sized Pong where size = ConstSize 1
@@ -77,27 +79,48 @@ parseDHTAddr (msg,saddr)
77 _ -> right 79 _ -> right
78 80
79encodeDHTAddr :: (DHTMessage Encrypted8,NodeInfo) -> (ByteString, SockAddr) 81encodeDHTAddr :: (DHTMessage Encrypted8,NodeInfo) -> (ByteString, SockAddr)
80encodeDHTAddr = _todo 82encodeDHTAddr (msg,ni) = (runPut $ putMessage msg, nodeAddr ni)
83
84dhtMessageType :: DHTMessage Encrypted8 -> ( Word8, Put )
85dhtMessageType (DHTPing a) = (0x00, putAssym a)
86dhtMessageType (DHTPong a) = (0x01, putAssym a)
87dhtMessageType (DHTGetNodes a) = (0x02, putAssym a)
88dhtMessageType (DHTSendNodes a) = (0x04, putAssym a)
89dhtMessageType (DHTCookieRequest a) = (0x18, putAssym a)
90dhtMessageType (DHTCookie n x) = (0x19, put n >> put x)
91dhtMessageType (DHTDHTRequest k a) = (0x20, putPublicKey k >> putAssym a)
92
93putMessage :: DHTMessage Encrypted8 -> Put
94putMessage msg = case dhtMessageType msg of (typ,p) -> put typ >> p
81 95
82getCookie :: Get (Nonce24, Encrypted8 Cookie) 96getCookie :: Get (Nonce24, Encrypted8 Cookie)
83getCookie = get 97getCookie = get
84 98
85getDHTReqest :: Get (PublicKey, Assym (Encrypted8 DHTRequest)) 99getDHTReqest :: Get (PublicKey, Assym (Encrypted8 DHTRequest))
86getDHTReqest = _todo 100getDHTReqest = (,) <$> 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
88getDHT :: Sized a => Get (Assym (Encrypted8 a)) 111getDHT :: Sized a => Get (Assym (Encrypted8 a))
89getDHT = _todo 112getDHT = 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.
93direct :: Sized a => ByteString 116direct :: 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)
98direct bs saddr f = fanGet bs getDHT f (asymNodeInfo saddr) 120direct 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.
123asymNodeInfo :: SockAddr -> Assym a -> NodeInfo
101asymNodeInfo saddr asym = either (error . mappend "asymNodeInfo: ") id $ nodeInfo (NodeId $ senderKey asym) saddr 124asymNodeInfo 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)
105fanGet bs getIt f nid = fmap (f &&& nid) $ runGet getIt bs 128fanGet 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.
131noReplyAddr :: SockAddr -> NodeInfo
108noReplyAddr saddr = either (error . mappend "noReplyAddr: ") id $ nodeInfo zeroID saddr 132noReplyAddr 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
119data DHTRequestPacket = DHTRequestPacket
120 { requestTarget :: PublicKey
121 , request :: Assym (Encrypted DHTRequest)
122 }
123
124instance Serialize DHTRequestPacket where
125 get = _todo
126 put = _todo
127
128
129data DHTRequest 135data 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
154instance 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
134instance Serialize DHTRequest where 162instance 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
187instance 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
150newtype GetNodes = GetNodes NodeId 194newtype GetNodes = GetNodes NodeId
151 deriving (Eq,Ord,Show,Read,S.Serialize) 195 deriving (Eq,Ord,Show,Read,S.Serialize)
152 196
197instance Sized GetNodes where
198 size = ConstSize 32 -- TODO This right?
199
153newtype SendNodes = SendNodes [NodeInfo] 200newtype SendNodes = SendNodes [NodeInfo]
154 deriving (Eq,Ord,Show,Read) 201 deriving (Eq,Ord,Show,Read)
155 202
203instance 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
156instance S.Serialize SendNodes where 208instance 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)
189instance Sized Cookie where size = ConstSize 112 -- 24 byte nonce + 88 byte cookie data 241instance Sized Cookie where size = ConstSize 112 -- 24 byte nonce + 88 byte cookie data
190 242
191instance Serialize Cookie where 243instance 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
195data CookieData = CookieData -- 16 (mac) 247data 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
253instance Sized CookieData where
254 size = ConstSize 72
255
201instance Sized CookieRequest where 256instance 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
204instance Serialize CookieRequest where 259instance 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
208forwardDHTRequests :: TransportCrypto -> (PublicKey -> IO (Maybe NodeInfo)) -> DHTTransport -> DHTTransport 263forwardDHTRequests :: TransportCrypto -> (PublicKey -> IO (Maybe NodeInfo)) -> DHTTransport -> DHTTransport
209forwardDHTRequests crypto closeLookup dht = dht { awaitMessage = await' } 264forwardDHTRequests 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
229encryptMessage crypto n (Left plain) = _todo 284encryptMessage crypto n (Left plain) = _todo -- need cached public key.
230 285
231decrypt :: TransportCrypto -> DHTMessage Encrypted8 -> NodeInfo -> Either String (DHTMessage ((,) Nonce8), NodeInfo) 286decrypt :: TransportCrypto -> DHTMessage Encrypted8 -> NodeInfo -> Either String (DHTMessage ((,) Nonce8), NodeInfo)
232decrypt crypto msg ni = (, ni) <$> (sequenceMessage $ transcode (decryptMessage crypto) msg) 287decrypt 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)
244decryptMessage crypto n (Left (E8 e)) = _todo 299decryptMessage crypto n (Left (E8 e)) = _todo -- need cached public key
245 300
246sequenceMessage :: Applicative m => DHTMessage (m ∘ f) -> m (DHTMessage f) 301sequenceMessage :: Applicative m => DHTMessage (m ∘ f) -> m (DHTMessage f)
247sequenceMessage (DHTPing asym) = fmap DHTPing $ sequenceA $ fmap uncomposed asym 302sequenceMessage (DHTPing asym) = fmap DHTPing $ sequenceA $ fmap uncomposed asym