summaryrefslogtreecommitdiff
path: root/src/Network/QueryResponse.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-07-12 23:29:56 -0400
committerjoe <joe@jerkface.net>2017-07-12 23:29:56 -0400
commit908ca2d33232362655eda8147f460a1a5cd61a9e (patch)
treee63f729de6efd53b004746efef1d7e81ff7a5756 /src/Network/QueryResponse.hs
parent58db745cc60428ee7a959599b2e83ff7504d5b57 (diff)
WIP: Mainline DHT rewrite.
Diffstat (limited to 'src/Network/QueryResponse.hs')
-rw-r--r--src/Network/QueryResponse.hs73
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
42forkListener :: Client err tbl meth tid addr x -> IO (IO ()) 42forkListener :: Client err tbl meth tid addr x ctx -> IO (IO ())
43forkListener client = do 43forkListener 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.
54sendQuery :: 54sendQuery ::
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.
61sendQuery (Client net d err pending whoami) meth q addr = do 61sendQuery (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.
81data Client err tbl meth tid addr x = Client 81data 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_.
104data MethodHandler err addr x = forall a b. MethodHandler 105data 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.
118dispatchQuery :: MethodHandler err addr x -- ^ Handler to invoke. 119dispatchQuery :: 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)
123dispatchQuery (MethodHandler unwrapQ wrapR f) self x addr = 125dispatchQuery (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'.
129data Method addr x meth a b = Method 131data 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.
230data DispatchMethods tbl err meth tid addr x = DispatchMethods 233data 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.
266handleMessage :: 269handleMessage ::
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 ()
270handleMessage (Client net d err pending whoami) again = do 273handleMessage (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