summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Network/QueryResponse.hs76
1 files changed, 40 insertions, 36 deletions
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