summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-07-13 16:53:05 -0400
committerjoe <joe@jerkface.net>2017-07-13 16:53:05 -0400
commit36562749e2204da4500742c7f62676c19f0ce999 (patch)
tree1233136f067bf40cdefb23901680b12d36fc357e
parent0ba49d7ba71f634cc7692124874a72dfad14d425 (diff)
TOX rewrite: Response nonces are now distinct from query nonces.
-rw-r--r--Tox.hs22
-rw-r--r--src/Network/QueryResponse.hs76
2 files changed, 54 insertions, 44 deletions
diff --git a/Tox.hs b/Tox.hs
index e1a1bf8a..77cd0ae0 100644
--- a/Tox.hs
+++ b/Tox.hs
@@ -240,16 +240,16 @@ encodePacket :: SecretKey -> SecretsCache -> Message ByteString -> NodeInfo -> (
240encodePacket sk cache msg ni = ( S.runPut . putMessage $ encryptMessage sk cache (nodeId ni) msg 240encodePacket sk cache msg ni = ( S.runPut . putMessage $ encryptMessage sk cache (nodeId ni) msg
241 , nodeAddr ni ) 241 , nodeAddr ni )
242 242
243newClient :: SockAddr -> IO (Client String Method TransactionId NodeInfo (Message ByteString) ()) 243newClient :: SockAddr -> IO (Client String Method TransactionId NodeInfo (Message ByteString))
244newClient addr = do 244newClient addr = do
245 udp <- udpTransport addr 245 udp <- udpTransport addr
246 secret <- generateSecretKey 246 secret <- generateSecretKey
247 let pubkey = key2id $ toPublic secret 247 let pubkey = key2id $ toPublic secret
248 cache <- newEmptyCache 248 cache <- newEmptyCache
249 drg <- getSystemDRG 249 drg <- getSystemDRG
250 let me = NodeInfo pubkey (fromMaybe (toEnum 0) $ fromSockAddr addr) 250 self <- atomically $ newTVar
251 (fromMaybe 0 $ sockAddrPort addr) 251 $ NodeInfo pubkey (fromMaybe (toEnum 0) $ fromSockAddr addr)
252 tox <- atomically $ newTVar (me,()) 252 (fromMaybe 0 $ sockAddrPort addr)
253 let net = layerTransport (parsePacket secret cache) 253 let net = layerTransport (parsePacket secret cache)
254 (encodePacket secret cache) 254 (encodePacket secret cache)
255 udp 255 udp
@@ -258,12 +258,18 @@ newClient addr = do
258 , lookupHandler = handlers 258 , lookupHandler = handlers
259 , tableMethods = tbl 259 , tableMethods = tbl
260 } 260 }
261 genNonce24 var (TransactionId nonce8 _) = atomically $ do
262 (g,pending) <- readTVar var
263 let (bs, g') = randomBytesGenerate 24 g
264 writeTVar var (g',pending)
265 return $ TransactionId nonce8 (Nonce24 bs)
261 client tbl var = Client 266 client tbl var = Client
262 { clientNet = net 267 { clientNet = net
263 , clientDispatcher = dispatch tbl 268 , clientDispatcher = dispatch tbl
264 , clientErrorReporter = ignoreErrors -- TODO 269 , clientErrorReporter = ignoreErrors -- TODO
265 , clientPending = var 270 , clientPending = var
266 , clientContext = atomically (readTVar tox) 271 , clientAddress = atomically (readTVar self)
272 , clientResponseId = genNonce24 var
267 } 273 }
268 if fitsInInt (Proxy :: Proxy Word64) 274 if fitsInInt (Proxy :: Proxy Word64)
269 then do 275 then do
@@ -300,7 +306,7 @@ classify (Message { msgType = typ
300 PongType -> IsResponse 306 PongType -> IsResponse
301 SendNodesType -> IsResponse 307 SendNodesType -> IsResponse
302 308
303encodePayload typ _ (TransactionId (Nonce8 tid) nonce) self dest b 309encodePayload typ (TransactionId (Nonce8 tid) nonce) self dest b
304 = Message { msgType = typ 310 = Message { msgType = typ
305 , msgOrigin = nodeId self 311 , msgOrigin = nodeId self
306 , msgNonce = nonce 312 , msgNonce = nonce
@@ -312,8 +318,8 @@ decodePayload msg = S.decode $ dropEnd8 $ msgPayload msg
312 318
313handler typ f = Just $ MethodHandler decodePayload (encodePayload typ) f 319handler typ f = Just $ MethodHandler decodePayload (encodePayload typ) f
314 320
315handlers :: Method -> Maybe (MethodHandler String TransactionId NodeInfo (Message ByteString) ()) 321handlers :: Method -> Maybe (MethodHandler String TransactionId NodeInfo (Message ByteString))
316handlers PingType = error "handler PingType pingH" 322handlers PingType = handler PingType pingH
317handlers GetNodesType = error "find_node" 323handlers GetNodesType = error "find_node"
318handlers _ = Nothing 324handlers _ = Nothing
319 325
diff --git a/src/Network/QueryResponse.hs b/src/Network/QueryResponse.hs
index 221c2284..9262132f 100644
--- a/src/Network/QueryResponse.hs
+++ b/src/Network/QueryResponse.hs
@@ -45,7 +45,7 @@ import System.Timeout
45-- > r <- sendQuery client method q 45-- > r <- sendQuery client method q
46-- > -- Quit client. 46-- > -- Quit client.
47-- > quitServer 47-- > quitServer
48forkListener :: Client err meth tid addr x ctx -> IO (IO ()) 48forkListener :: Client err meth tid addr x -> IO (IO ())
49forkListener client = do 49forkListener client = do
50 thread_id <- forkIO $ do 50 thread_id <- forkIO $ do
51 myThreadId >>= flip labelThread "listener" 51 myThreadId >>= flip labelThread "listener"
@@ -58,21 +58,21 @@ forkListener client = do
58-- out if 'forkListener' was never invoked to spawn a thread receive and 58-- out if 'forkListener' was never invoked to spawn a thread receive and
59-- dispatch the response. 59-- dispatch the response.
60sendQuery :: 60sendQuery ::
61 forall err a b tbl x ctx meth tid addr. 61 forall err a b tbl x meth tid addr.
62 Client err meth tid addr x ctx -- ^ A query/response implementation. 62 Client err meth tid addr x -- ^ A query/response implementation.
63 -> MethodSerializer addr x ctx meth a b -- ^ Information for marshalling the query. 63 -> MethodSerializer addr x meth a b -- ^ Information for marshalling the query.
64 -> a -- ^ The outbound query. 64 -> a -- ^ The outbound query.
65 -> addr -- ^ Destination address of query. 65 -> addr -- ^ Destination address of query.
66 -> IO (Maybe b) -- ^ The response, or 'Nothing' if it timed out. 66 -> IO (Maybe b) -- ^ The response, or 'Nothing' if it timed out.
67sendQuery (Client net d err pending whoami) meth q addr = do 67sendQuery (Client net d err pending whoami _) meth q addr = do
68 mvar <- newEmptyMVar 68 mvar <- newEmptyMVar
69 tid <- atomically $ do 69 tid <- atomically $ do
70 tbl <- readTVar pending 70 tbl <- readTVar pending
71 let (tid, tbl') = dispatchRegister (tableMethods d) mvar tbl 71 let (tid, tbl') = dispatchRegister (tableMethods d) mvar tbl
72 writeTVar pending tbl' 72 writeTVar pending tbl'
73 return tid 73 return tid
74 (self,ctx) <- whoami 74 self <- whoami
75 sendMessage net addr (wrapQuery meth ctx self addr q) 75 sendMessage net addr (wrapQuery meth self addr q)
76 mres <- timeout (methodTimeout meth) $ takeMVar mvar 76 mres <- timeout (methodTimeout meth) $ takeMVar mvar
77 case mres of 77 case mres of
78 Just x -> return $ Just $ unwrapResponse meth x 78 Just x -> return $ Just $ unwrapResponse meth x
@@ -84,21 +84,25 @@ sendQuery (Client net d err pending whoami) meth q addr = do
84-- * Implementing a query\/response 'Client'. 84-- * Implementing a query\/response 'Client'.
85 85
86-- | All inputs required to implement a query\/response client. 86-- | All inputs required to implement a query\/response client.
87data Client err meth tid addr x ctx = forall tbl. Client 87data Client err meth tid addr x = forall tbl. Client
88 { -- | The 'Transport' used to dispatch and receive packets. 88 { -- | The 'Transport' used to dispatch and receive packets.
89 clientNet :: Transport err addr x 89 clientNet :: Transport err addr x
90 -- | Methods for handling inbound packets. 90 -- | Methods for handling inbound packets.
91 , clientDispatcher :: DispatchMethods tbl err meth tid addr x ctx 91 , clientDispatcher :: DispatchMethods tbl err meth tid addr x
92 -- | Methods for reporting various conditions. 92 -- | Methods for reporting various conditions.
93 , clientErrorReporter :: ErrorReporter addr x meth tid err 93 , clientErrorReporter :: ErrorReporter addr x meth tid err
94 -- | State necessary for routing inbound responses and assigning unique 94 -- | State necessary for routing inbound responses and assigning unique
95 -- /tid/ values for outgoing queries. 95 -- /tid/ values for outgoing queries.
96 , clientPending :: TVar tbl 96 , clientPending :: TVar tbl
97 -- | An action yielding this client\'s own address along with some 97 -- | An action yielding this client\'s own address. It is invoked once
98 -- context neccessary for serializing outgoing packets. It is invoked 98 -- on each outbound and inbound packet. It is valid for this to always
99 -- once on each outbound and inbound packet. It is valid for this to 99 -- return the same value.
100 -- always return the same value. 100 , clientAddress :: IO addr
101 , clientContext :: IO (addr,ctx) 101 -- | Transform a query /tid/ value to an appropriate response /tid/
102 -- value. Normally, this would be the identity transformation, but if
103 -- /tid/ includes a unique cryptographic nonce, then it should be
104 -- generated here.
105 , clientResponseId :: tid -> IO tid
102 } 106 }
103 107
104-- | An incomming message can be classified into three cases. 108-- | An incomming message can be classified into three cases.
@@ -108,13 +112,13 @@ data MessageClass err meth tid
108 | IsResponse tid -- ^ A response to a outgoing query we associated with a /tid/ value. 112 | IsResponse tid -- ^ A response to a outgoing query we associated with a /tid/ value.
109 | IsUnknown err -- ^ None of the above. 113 | IsUnknown err -- ^ None of the above.
110 114
111-- | Handler for an inbound query of type _x_ from an address of type _addr_. 115-- | Handler for an inbound query of type /x/ from an address of type _addr_.
112data MethodHandler err tid addr x ctx = forall a b. MethodHandler 116data MethodHandler err tid addr x = forall a b. MethodHandler
113 { -- | Parse the query into a more specific type for this method. 117 { -- | Parse the query into a more specific type for this method.
114 methodParse :: x -> Either err a 118 methodParse :: x -> Either err a
115 -- | Serialize the response for transmission, given a context /ctx/ and the origin 119 -- | Serialize the response for transmission, given a context /ctx/ and the origin
116 -- and destination addresses. 120 -- and destination addresses.
117 , methodSerialize :: ctx -> tid -> addr -> addr -> b -> x 121 , methodSerialize :: tid -> addr -> addr -> b -> x
118 -- | Fully typed action to perform upon the query. The remote origin 122 -- | Fully typed action to perform upon the query. The remote origin
119 -- address of the query is provided to the handler. 123 -- address of the query is provided to the handler.
120 , methodAction :: addr -> a -> IO b 124 , methodAction :: addr -> a -> IO b
@@ -123,20 +127,19 @@ data MethodHandler err tid addr x ctx = forall a b. MethodHandler
123-- | Attempt to invoke a 'MethodHandler' upon a given inbound query. If the 127-- | Attempt to invoke a 'MethodHandler' upon a given inbound query. If the
124-- parse is successful, the returned IO action will construct our reply. 128-- parse is successful, the returned IO action will construct our reply.
125-- Otherwise, a parse err is returned. 129-- Otherwise, a parse err is returned.
126dispatchQuery :: MethodHandler err tid addr x ctx -- ^ Handler to invoke. 130dispatchQuery :: MethodHandler err tid addr x -- ^ Handler to invoke.
127 -> ctx -- ^ Arbitrary context used during serialization. 131 -> tid -- ^ The transaction id for this query\/response session.
128 -> tid -- ^ The transaction id for this query\/response session. 132 -> addr -- ^ Our own address, to which the query was sent.
129 -> addr -- ^ Our own address, to which the query was sent. 133 -> x -- ^ The query packet.
130 -> x -- ^ The query packet. 134 -> addr -- ^ The origin address of the query.
131 -> addr -- ^ The origin address of the query.
132 -> Either err (IO x) 135 -> Either err (IO x)
133dispatchQuery (MethodHandler unwrapQ wrapR f) ctx tid self x addr = 136dispatchQuery (MethodHandler unwrapQ wrapR f) tid self x addr =
134 fmap (\a -> wrapR ctx tid self addr <$> f addr a) $ unwrapQ x 137 fmap (\a -> wrapR tid self addr <$> f addr a) $ unwrapQ x
135 138
136-- | These four parameters are required to implement an ougoing query. A 139-- | These four parameters are required to implement an ougoing query. A
137-- peer-to-peer algorithm will define a 'MethodSerializer' for every 'MethodHandler' that 140-- peer-to-peer algorithm will define a 'MethodSerializer' for every 'MethodHandler' that
138-- might be returned by 'lookupHandler'. 141-- might be returned by 'lookupHandler'.
139data MethodSerializer addr x ctx meth a b = MethodSerializer 142data MethodSerializer addr x meth a b = MethodSerializer
140 { -- | Seconds to wait for a response. 143 { -- | Seconds to wait for a response.
141 methodTimeout :: Int 144 methodTimeout :: Int
142 -- | A method identifier used for error reporting. This needn't be the 145 -- | A method identifier used for error reporting. This needn't be the
@@ -146,7 +149,7 @@ data MethodSerializer addr x ctx meth a b = MethodSerializer
146 -- The /addr/ arguments are, respectively, our own origin address and the 149 -- The /addr/ arguments are, respectively, our own origin address and the
147 -- destination of the request. The /ctx/ argument is useful for attaching 150 -- destination of the request. The /ctx/ argument is useful for attaching
148 -- auxillary notations on all outgoing packets. 151 -- auxillary notations on all outgoing packets.
149 , wrapQuery :: ctx -> addr -> addr -> a -> x 152 , wrapQuery :: addr -> addr -> a -> x
150 -- | Parse an inbound packet /x/ into a response /b/ for this query. 153 -- | Parse an inbound packet /x/ into a response /b/ for this query.
151 , unwrapResponse :: x -> b 154 , unwrapResponse :: x -> b
152 } 155 }
@@ -274,11 +277,11 @@ transactionMethods (TableMethods insert delete lookup) generate = TransactionMet
274 } 277 }
275 278
276-- | A set of methods neccessary for dispatching incomming packets. 279-- | A set of methods neccessary for dispatching incomming packets.
277data DispatchMethods tbl err meth tid addr x ctx = DispatchMethods 280data DispatchMethods tbl err meth tid addr x = DispatchMethods
278 { -- | Clasify an inbound packet as a query or response. 281 { -- | Clasify an inbound packet as a query or response.
279 classifyInbound :: x -> MessageClass err meth tid 282 classifyInbound :: x -> MessageClass err meth tid
280 -- | Lookup the handler for a inbound query. 283 -- | Lookup the handler for a inbound query.
281 , lookupHandler :: meth -> Maybe (MethodHandler err tid addr x ctx) 284 , lookupHandler :: meth -> Maybe (MethodHandler err tid addr x)
282 -- | Methods for handling incomming responses. 285 -- | Methods for handling incomming responses.
283 , tableMethods :: TransactionMethods tbl tid x 286 , tableMethods :: TransactionMethods tbl tid x
284 } 287 }
@@ -326,10 +329,10 @@ contramapE f (ErrorReporter pe mh unk tim)
326-- 'fix' in a forked thread that loops until 'awaitMessage' returns 'Nothing' 329-- 'fix' in a forked thread that loops until 'awaitMessage' returns 'Nothing'
327-- or throws an exception. 330-- or throws an exception.
328handleMessage :: 331handleMessage ::
329 Client err meth tid addr x ctx 332 Client err meth tid addr x
330 -> IO () 333 -> IO ()
331 -> IO () 334 -> IO ()
332handleMessage (Client net d err pending whoami) again = do 335handleMessage (Client net d err pending whoami responseID) again = do
333 awaitMessage net >>= \case 336 awaitMessage net >>= \case
334 Just (Left e) -> do reportParseError err e 337 Just (Left e) -> do reportParseError err e
335 again 338 again
@@ -338,10 +341,11 @@ handleMessage (Client net d err pending whoami) again = do
338 IsQuery meth tid -> case lookupHandler d meth of 341 IsQuery meth tid -> case lookupHandler d meth of
339 Nothing -> reportMissingHandler err meth addr plain 342 Nothing -> reportMissingHandler err meth addr plain
340 Just m -> do 343 Just m -> do
341 (self,ctx) <- whoami 344 self <- whoami
345 tid' <- responseID tid
342 either (reportParseError err) 346 either (reportParseError err)
343 (>>= sendMessage net addr) 347 (>>= sendMessage net addr)
344 (dispatchQuery m ctx tid self plain addr) 348 (dispatchQuery m tid' self plain addr)
345 IsResponse tid -> do 349 IsResponse tid -> do
346 action <- atomically $ do 350 action <- atomically $ do
347 ts0 <- readTVar pending 351 ts0 <- readTVar pending