diff options
Diffstat (limited to 'src/Network/QueryResponse.hs')
-rw-r--r-- | src/Network/QueryResponse.hs | 73 |
1 files changed, 38 insertions, 35 deletions
diff --git a/src/Network/QueryResponse.hs b/src/Network/QueryResponse.hs index 5b8bcda4..58db3a71 100644 --- a/src/Network/QueryResponse.hs +++ b/src/Network/QueryResponse.hs | |||
@@ -39,9 +39,9 @@ import Data.Maybe | |||
39 | -- > r <- sendQuery client method q | 39 | -- > r <- sendQuery client method q |
40 | -- > -- Quit client. | 40 | -- > -- Quit client. |
41 | -- > quitServer | 41 | -- > quitServer |
42 | forkListener :: Client err tbl meth tid addr x -> IO (IO ()) | 42 | forkListener :: Client err tbl meth tid addr x ctx -> IO (IO ()) |
43 | forkListener client = do | 43 | forkListener client = do |
44 | thread_id <- fork $ do | 44 | thread_id <- forkIO $ do |
45 | myThreadId >>= flip labelThread "listener" | 45 | myThreadId >>= flip labelThread "listener" |
46 | fix $ handleMessage client | 46 | fix $ handleMessage client |
47 | return $ do | 47 | return $ do |
@@ -52,12 +52,12 @@ forkListener client = do | |||
52 | -- out if 'forkListener' was never invoked to spawn a thread receive and | 52 | -- out if 'forkListener' was never invoked to spawn a thread receive and |
53 | -- dispatch the response. | 53 | -- dispatch the response. |
54 | sendQuery :: | 54 | sendQuery :: |
55 | forall err a b tbl x meth tid addr. | 55 | forall err a b tbl x ctx meth tid addr. |
56 | Client err tbl meth tid addr x -- ^ A query/response implementation. | 56 | Client err tbl meth tid addr x ctx -- ^ A query/response implementation. |
57 | -> Method addr x meth a b -- ^ Information for marshalling the query. | 57 | -> MethodSerializer addr x ctx meth a b -- ^ Information for marshalling the query. |
58 | -> a -- ^ The outbound query. | 58 | -> a -- ^ The outbound query. |
59 | -> addr -- ^ Destination address of query. | 59 | -> addr -- ^ Destination address of query. |
60 | -> IO (Maybe b) -- ^ The response, or 'Nothing' if it timed out. | 60 | -> IO (Maybe b) -- ^ The response, or 'Nothing' if it timed out. |
61 | sendQuery (Client net d err pending whoami) meth q addr = do | 61 | sendQuery (Client net d err pending whoami) meth q addr = do |
62 | mvar <- newEmptyMVar | 62 | mvar <- newEmptyMVar |
63 | tid <- atomically $ do | 63 | tid <- atomically $ do |
@@ -65,8 +65,8 @@ sendQuery (Client net d err pending whoami) meth q addr = do | |||
65 | let (tid, tbl') = dispatchRegister (tableMethods d) mvar tbl | 65 | let (tid, tbl') = dispatchRegister (tableMethods d) mvar tbl |
66 | writeTVar pending tbl' | 66 | writeTVar pending tbl' |
67 | return tid | 67 | return tid |
68 | self <- whoami | 68 | (self,ctx) <- whoami |
69 | sendMessage net addr (wrapQuery meth self addr q) | 69 | sendMessage net addr (wrapQuery meth ctx self addr q) |
70 | mres <- timeout (methodTimeout meth) $ takeMVar mvar | 70 | mres <- timeout (methodTimeout meth) $ takeMVar mvar |
71 | case mres of | 71 | case mres of |
72 | Just x -> return $ Just $ unwrapResponse meth x | 72 | Just x -> return $ Just $ unwrapResponse meth x |
@@ -78,20 +78,21 @@ sendQuery (Client net d err pending whoami) meth q addr = do | |||
78 | -- * Implementing a query\/response 'Client'. | 78 | -- * Implementing a query\/response 'Client'. |
79 | 79 | ||
80 | -- | All inputs required to implement a query\/response client. | 80 | -- | All inputs required to implement a query\/response client. |
81 | data Client err tbl meth tid addr x = Client | 81 | data Client err tbl meth tid addr x ctx = Client |
82 | { -- | The 'Transport' used to dispatch and receive packets. | 82 | { -- | The 'Transport' used to dispatch and receive packets. |
83 | clientNet :: Transport err addr x | 83 | clientNet :: Transport err addr x |
84 | -- | Methods for handling inbound packets. | 84 | -- | Methods for handling inbound packets. |
85 | , clientDispatcher :: DispatchMethods tbl err meth tid addr x | 85 | , clientDispatcher :: DispatchMethods tbl err meth tid addr x ctx |
86 | -- | Methods for reporting various conditions. | 86 | -- | Methods for reporting various conditions. |
87 | , clientErrorReporter :: ErrorReporter addr x meth tid err | 87 | , clientErrorReporter :: ErrorReporter addr x meth tid err |
88 | -- | State necessary for routing inbound responses and assigning unique | 88 | -- | State necessary for routing inbound responses and assigning unique |
89 | -- /tid/ values for outgoing queries. | 89 | -- /tid/ values for outgoing queries. |
90 | , clientPending :: TVar tbl | 90 | , clientPending :: TVar tbl |
91 | -- | An action yielding this client\'s own address. It is invoked once on | 91 | -- | An action yielding this client\'s own address along with some |
92 | -- each outbound and inbound packet. It is valid for this to always | 92 | -- context neccessary for serializing outgoing packets. It is invoked |
93 | -- return the same value. | 93 | -- once on each outbound and inbound packet. It is valid for this to |
94 | , clientMyAddress :: IO addr | 94 | -- always return the same value. |
95 | , clientContext :: IO (addr,ctx) | ||
95 | } | 96 | } |
96 | 97 | ||
97 | -- | An incomming message can be classified into three cases. | 98 | -- | An incomming message can be classified into three cases. |
@@ -101,12 +102,12 @@ data MessageClass err meth tid | |||
101 | | IsUnknown err -- ^ None of the above. | 102 | | IsUnknown err -- ^ None of the above. |
102 | 103 | ||
103 | -- | Handler for an inbound query of type _x_ from an address of type _addr_. | 104 | -- | Handler for an inbound query of type _x_ from an address of type _addr_. |
104 | data MethodHandler err addr x = forall a b. MethodHandler | 105 | data MethodHandler err addr x ctx = forall a b. MethodHandler |
105 | { -- | Parse the query into a more specific type for this method. | 106 | { -- | Parse the query into a more specific type for this method. |
106 | methodParse :: x -> Either err a | 107 | methodParse :: x -> Either err a |
107 | -- | Serialize the response type for transmission. Origin and destination | 108 | -- | Serialize the response for transmission, given a context /ctx/ and the origin |
108 | -- addresses for the packet are supplied in case they are required. | 109 | -- and destination addresses. |
109 | , methodSerialize :: addr -> addr -> b -> x | 110 | , methodSerialize :: ctx -> addr -> addr -> b -> x |
110 | -- | Fully typed action to perform upon the query. The remote origin | 111 | -- | Fully typed action to perform upon the query. The remote origin |
111 | -- address of the query is provided to the handler. | 112 | -- address of the query is provided to the handler. |
112 | , methodAction :: addr -> a -> IO b | 113 | , methodAction :: addr -> a -> IO b |
@@ -115,18 +116,19 @@ data MethodHandler err addr x = forall a b. MethodHandler | |||
115 | -- | Attempt to invoke a 'MethodHandler' upon a given inbound query. If the | 116 | -- | Attempt to invoke a 'MethodHandler' upon a given inbound query. If the |
116 | -- parse is successful, the returned IO action will construct our reply. | 117 | -- parse is successful, the returned IO action will construct our reply. |
117 | -- Otherwise, a parse err is returned. | 118 | -- Otherwise, a parse err is returned. |
118 | dispatchQuery :: MethodHandler err addr x -- ^ Handler to invoke. | 119 | dispatchQuery :: MethodHandler err addr x ctx -- ^ Handler to invoke. |
119 | -> addr -- ^ Our own address, to which the query was sent. | 120 | -> ctx -- ^ Arbitrary context used during serialization. |
120 | -> x -- ^ The query packet. | 121 | -> addr -- ^ Our own address, to which the query was sent. |
121 | -> addr -- ^ The origin address of the query. | 122 | -> x -- ^ The query packet. |
123 | -> addr -- ^ The origin address of the query. | ||
122 | -> Either err (IO x) | 124 | -> Either err (IO x) |
123 | dispatchQuery (MethodHandler unwrapQ wrapR f) self x addr = | 125 | dispatchQuery (MethodHandler unwrapQ wrapR f) ctx self x addr = |
124 | fmap (\a -> wrapR self addr <$> f addr a) $ unwrapQ x | 126 | fmap (\a -> wrapR ctx self addr <$> f addr a) $ unwrapQ x |
125 | 127 | ||
126 | -- | These four parameters are required to implement an ougoing query. A | 128 | -- | These four parameters are required to implement an ougoing query. A |
127 | -- peer-to-peer algorithm will define a 'Method' for every 'MethodHandler' that | 129 | -- peer-to-peer algorithm will define a 'MethodSerializer' for every 'MethodHandler' that |
128 | -- might be returned by 'lookupHandler'. | 130 | -- might be returned by 'lookupHandler'. |
129 | data Method addr x meth a b = Method | 131 | data MethodSerializer addr x ctx meth a b = MethodSerializer |
130 | { -- | Seconds to wait for a response. | 132 | { -- | Seconds to wait for a response. |
131 | methodTimeout :: Int | 133 | methodTimeout :: Int |
132 | -- | A method identifier used for error reporting. This needn't be the | 134 | -- | A method identifier used for error reporting. This needn't be the |
@@ -134,8 +136,9 @@ data Method addr x meth a b = Method | |||
134 | , method :: meth | 136 | , method :: meth |
135 | -- | Serialize the outgoing query /a/ into a transmitable packet /x/. | 137 | -- | Serialize the outgoing query /a/ into a transmitable packet /x/. |
136 | -- The /addr/ arguments are, respectively, our own origin address and the | 138 | -- The /addr/ arguments are, respectively, our own origin address and the |
137 | -- destination of the request. | 139 | -- destination of the request. The /ctx/ argument is useful for attaching |
138 | , wrapQuery :: addr -> addr -> a -> x | 140 | -- auxillary notations on all outgoing packets. |
141 | , wrapQuery :: ctx -> addr -> addr -> a -> x | ||
139 | -- | Parse an inbound packet /x/ into a response /b/ for this query. | 142 | -- | Parse an inbound packet /x/ into a response /b/ for this query. |
140 | , unwrapResponse :: x -> b | 143 | , unwrapResponse :: x -> b |
141 | } | 144 | } |
@@ -227,11 +230,11 @@ transactionTableMethods insert delete lookup generate = TableMethods | |||
227 | } | 230 | } |
228 | 231 | ||
229 | -- | A set of methods neccessary for dispatching incomming packets. | 232 | -- | A set of methods neccessary for dispatching incomming packets. |
230 | data DispatchMethods tbl err meth tid addr x = DispatchMethods | 233 | data DispatchMethods tbl err meth tid addr x ctx = DispatchMethods |
231 | { -- | Clasify an inbound packet as a query or response. | 234 | { -- | Clasify an inbound packet as a query or response. |
232 | classifyInbound :: x -> MessageClass err meth tid | 235 | classifyInbound :: x -> MessageClass err meth tid |
233 | -- | Lookup the handler for a inbound query. | 236 | -- | Lookup the handler for a inbound query. |
234 | , lookupHandler :: meth -> Maybe (MethodHandler err addr x) | 237 | , lookupHandler :: meth -> Maybe (MethodHandler err addr x ctx) |
235 | -- | Methods for handling incomming responses. | 238 | -- | Methods for handling incomming responses. |
236 | , tableMethods :: TableMethods tbl tid x | 239 | , tableMethods :: TableMethods tbl tid x |
237 | } | 240 | } |
@@ -264,7 +267,7 @@ data ErrorReporter addr x meth tid err = ErrorReporter | |||
264 | -- 'fix' in a forked thread that loops until 'awaitMessage' returns 'Nothing' | 267 | -- 'fix' in a forked thread that loops until 'awaitMessage' returns 'Nothing' |
265 | -- or throws an exception. | 268 | -- or throws an exception. |
266 | handleMessage :: | 269 | handleMessage :: |
267 | Client err tbl meth tid addr x | 270 | Client err tbl meth tid addr x ctx |
268 | -> IO () | 271 | -> IO () |
269 | -> IO () | 272 | -> IO () |
270 | handleMessage (Client net d err pending whoami) again = do | 273 | handleMessage (Client net d err pending whoami) again = do |
@@ -276,10 +279,10 @@ handleMessage (Client net d err pending whoami) again = do | |||
276 | IsQuery meth -> case lookupHandler d meth of | 279 | IsQuery meth -> case lookupHandler d meth of |
277 | Nothing -> reportMissingHandler err meth addr plain | 280 | Nothing -> reportMissingHandler err meth addr plain |
278 | Just m -> do | 281 | Just m -> do |
279 | self <- whoami | 282 | (self,ctx) <- whoami |
280 | either (reportParseError err) | 283 | either (reportParseError err) |
281 | (>>= sendMessage net addr) | 284 | (>>= sendMessage net addr) |
282 | (dispatchQuery m self plain addr) | 285 | (dispatchQuery m ctx self plain addr) |
283 | IsResponse tid -> do | 286 | IsResponse tid -> do |
284 | action <- atomically $ do | 287 | action <- atomically $ do |
285 | ts0 <- readTVar pending | 288 | ts0 <- readTVar pending |