1/*	$NetBSD: rpc.h,v 1.6 2021/04/10 19:18:45 rillig Exp $	*/
2
3/*
4 * Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
5 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29#ifndef EVENT2_RPC_H_INCLUDED_
30#define EVENT2_RPC_H_INCLUDED_
31
32/* For int types. */
33#include <event2/util.h>
34#include <event2/visibility.h>
35
36#ifdef __cplusplus
37extern "C" {
38#endif
39
40/** @file rpc.h
41 *
42 * This header files provides basic support for an RPC server and client.
43 *
44 * To support RPCs in a server, every supported RPC command needs to be
45 * defined and registered.
46 *
47 * EVRPC_HEADER(SendCommand, Request, Reply);
48 *
49 *  SendCommand is the name of the RPC command.
50 *  Request is the name of a structure generated by event_rpcgen.py.
51 *    It contains all parameters relating to the SendCommand RPC.  The
52 *    server needs to fill in the Reply structure.
53 *  Reply is the name of a structure generated by event_rpcgen.py.  It
54 *    contains the answer to the RPC.
55 *
56 * To register an RPC with an HTTP server, you need to first create an RPC
57 * base with:
58 *
59 *   struct evrpc_base *base = evrpc_init(http);
60 *
61 * A specific RPC can then be registered with
62 *
63 * EVRPC_REGISTER(base, SendCommand, Request, Reply,  FunctionCB, arg);
64 *
65 * when the server receives an appropriately formatted RPC, the user callback
66 * is invoked.   The callback needs to fill in the reply structure.
67 *
68 * void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg);
69 *
70 * To send the reply, call EVRPC_REQUEST_DONE(rpc);
71 *
72 * See the regression test for an example.
73 */
74
75/**
76   Determines if the member has been set in the message
77
78   @param msg the message to inspect
79   @param member the member variable to test for presences
80   @return 1 if it's present or 0 otherwise.
81*/
82#define EVTAG_HAS(msg, member) \
83	((msg)->member##_set == 1)
84
85#ifndef EVENT2_RPC_COMPAT_H_INCLUDED_
86
87/**
88   Assigns a value to the member in the message.
89
90   @param msg the message to which to assign a value
91   @param member the name of the member variable
92   @param value the value to assign
93*/
94#define EVTAG_ASSIGN(msg, member, value) \
95	(*(msg)->base->member##_assign)((msg), (value))
96/**
97   Assigns a value to the member in the message.
98
99   @param msg the message to which to assign a value
100   @param member the name of the member variable
101   @param value the value to assign
102   @param len the length of the value
103*/
104#define EVTAG_ASSIGN_WITH_LEN(msg, member, value, len)	\
105	(*(msg)->base->member##_assign)((msg), (value), (len))
106/**
107   Returns the value for a member.
108
109   @param msg the message from which to get the value
110   @param member the name of the member variable
111   @param pvalue a pointer to the variable to hold the value
112   @return 0 on success, -1 otherwise.
113*/
114#define EVTAG_GET(msg, member, pvalue) \
115	(*(msg)->base->member##_get)((msg), (pvalue))
116/**
117   Returns the value for a member.
118
119   @param msg the message from which to get the value
120   @param member the name of the member variable
121   @param pvalue a pointer to the variable to hold the value
122   @param plen a pointer to the length of the value
123   @return 0 on success, -1 otherwise.
124*/
125#define EVTAG_GET_WITH_LEN(msg, member, pvalue, plen)	\
126	(*(msg)->base->member##_get)((msg), (pvalue), (plen))
127
128#endif  /* EVENT2_RPC_COMPAT_H_INCLUDED_ */
129
130/**
131   Adds a value to an array.
132*/
133#define EVTAG_ARRAY_ADD_VALUE(msg, member, value) \
134	(*(msg)->base->member##_add)((msg), (value))
135/**
136   Allocates a new entry in the array and returns it.
137*/
138#define EVTAG_ARRAY_ADD(msg, member) \
139	(*(msg)->base->member##_add)(msg)
140/**
141   Gets a variable at the specified offset from the array.
142*/
143#define EVTAG_ARRAY_GET(msg, member, offset, pvalue)	\
144	(*(msg)->base->member##_get)((msg), (offset), (pvalue))
145/**
146   Returns the number of entries in the array.
147*/
148#define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length)
149
150
151struct evbuffer;
152struct event_base;
153struct evrpc_req_generic;
154struct evrpc_request_wrapper;
155struct evrpc;
156
157/** The type of a specific RPC Message
158 *
159 * @param rpcname the name of the RPC message
160 */
161#define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname
162
163struct evhttp_request;
164struct evrpc_status;
165struct evrpc_hook_meta;
166
167/** Creates the definitions and prototypes for an RPC
168 *
169 * You need to use EVRPC_HEADER to create structures and function prototypes
170 * needed by the server and client implementation.  The structures have to be
171 * defined in an .rpc file and converted to source code via event_rpcgen.py
172 *
173 * @param rpcname the name of the RPC
174 * @param reqstruct the name of the RPC request structure
175 * @param replystruct the name of the RPC reply structure
176 * @see EVRPC_GENERATE()
177 */
178#define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \
179EVRPC_STRUCT(rpcname) {	\
180	struct evrpc_hook_meta *hook_meta; \
181	struct reqstruct* request; \
182	struct rplystruct* reply; \
183	struct evrpc* rpc; \
184	struct evhttp_request* http_req; \
185	struct evbuffer* rpc_data; \
186};								     \
187EVENT2_EXPORT_SYMBOL \
188int evrpc_send_request_##rpcname(struct evrpc_pool *, \
189    struct reqstruct *, struct rplystruct *, \
190    void (*)(struct evrpc_status *, \
191	struct reqstruct *, struct rplystruct *, void *cbarg),	\
192    void *);
193
194struct evrpc_pool;
195
196/** use EVRPC_GENERATE instead */
197EVENT2_EXPORT_SYMBOL
198struct evrpc_request_wrapper *evrpc_make_request_ctx(
199	struct evrpc_pool *pool, void *request, void *reply,
200	const char *rpcname,
201	void (*req_marshal)(struct evbuffer*, void *),
202	void (*rpl_clear)(void *),
203	int (*rpl_unmarshal)(void *, struct evbuffer *),
204	void (*cb)(struct evrpc_status *, void *, void *, void *),
205	void *cbarg);
206
207/** Creates a context structure that contains rpc specific information.
208 *
209 * EVRPC_MAKE_CTX is used to populate a RPC specific context that
210 * contains information about marshaling the RPC data types.
211 *
212 * @param rpcname the name of the RPC
213 * @param reqstruct the name of the RPC request structure
214 * @param replystruct the name of the RPC reply structure
215 * @param pool the evrpc_pool over which to make the request
216 * @param request a pointer to the RPC request structure object
217 * @param reply a pointer to the RPC reply structure object
218 * @param cb the callback function to call when the RPC has completed
219 * @param cbarg the argument to supply to the callback
220 */
221#define EVRPC_MAKE_CTX(rpcname, reqstruct, rplystruct, \
222    pool, request, reply, cb, cbarg)					\
223	evrpc_make_request_ctx(pool, request, reply,			\
224	    #rpcname,							\
225	    (void (*)(struct evbuffer *, void *))reqstruct##_marshal,	\
226	    (void (*)(void *))rplystruct##_clear,			\
227	    (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \
228	    (void (*)(struct evrpc_status *, void *, void *, void *))cb, \
229	    cbarg)
230
231/** Generates the code for receiving and sending an RPC message
232 *
233 * EVRPC_GENERATE is used to create the code corresponding to sending
234 * and receiving a particular RPC message
235 *
236 * @param rpcname the name of the RPC
237 * @param reqstruct the name of the RPC request structure
238 * @param replystruct the name of the RPC reply structure
239 * @see EVRPC_HEADER()
240 */
241#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct)			\
242	int evrpc_send_request_##rpcname(struct evrpc_pool *pool,	\
243	    struct reqstruct *request, struct rplystruct *reply,	\
244	    void (*cb)(struct evrpc_status *,				\
245		struct reqstruct *, struct rplystruct *, void *cbarg),	\
246	    void *cbarg) {						\
247	return evrpc_send_request_generic(pool, request, reply,	\
248	    (void (*)(struct evrpc_status *, void *, void *, void *))cb, \
249	    cbarg,							\
250	    #rpcname,							\
251	    (void (*)(struct evbuffer *, void *))reqstruct##_marshal,	\
252	    (void (*)(void *))rplystruct##_clear,			\
253	    (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal); \
254}
255
256/** Provides access to the HTTP request object underlying an RPC
257 *
258 * Access to the underlying http object; can be used to look at headers or
259 * for getting the remote ip address
260 *
261 * @param rpc_req the rpc request structure provided to the server callback
262 * @return an struct evhttp_request object that can be inspected for
263 * HTTP headers or sender information.
264 */
265#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req
266
267/** completes the server response to an rpc request */
268EVENT2_EXPORT_SYMBOL
269void evrpc_request_done(struct evrpc_req_generic *req);
270
271/** accessors for request and reply */
272EVENT2_EXPORT_SYMBOL
273void *evrpc_get_request(struct evrpc_req_generic *req);
274EVENT2_EXPORT_SYMBOL
275void *evrpc_get_reply(struct evrpc_req_generic *req);
276
277/** Creates the reply to an RPC request
278 *
279 * EVRPC_REQUEST_DONE is used to answer a request; the reply is expected
280 * to have been filled in.  The request and reply pointers become invalid
281 * after this call has finished.
282 *
283 * @param rpc_req the rpc request structure provided to the server callback
284 */
285#define EVRPC_REQUEST_DONE(rpc_req) do { \
286  struct evrpc_req_generic *req_ = (struct evrpc_req_generic *)(rpc_req); \
287  evrpc_request_done(req_);					\
288} while (0)
289
290
291struct evrpc_base;
292struct evhttp;
293
294/* functions to start up the rpc system */
295
296/** Creates a new rpc base from which RPC requests can be received
297 *
298 * @param server a pointer to an existing HTTP server
299 * @return a newly allocated evrpc_base struct or NULL if an error occurred
300 * @see evrpc_free()
301 */
302EVENT2_EXPORT_SYMBOL
303struct evrpc_base *evrpc_init(struct evhttp *server);
304
305/**
306 * Frees the evrpc base
307 *
308 * For now, you are responsible for making sure that no rpcs are ongoing.
309 *
310 * @param base the evrpc_base object to be freed
311 * @see evrpc_init
312 */
313EVENT2_EXPORT_SYMBOL
314void evrpc_free(struct evrpc_base *base);
315
316/** register RPCs with the HTTP Server
317 *
318 * registers a new RPC with the HTTP server, each RPC needs to have
319 * a unique name under which it can be identified.
320 *
321 * @param base the evrpc_base structure in which the RPC should be
322 *   registered.
323 * @param name the name of the RPC
324 * @param request the name of the RPC request structure
325 * @param reply the name of the RPC reply structure
326 * @param callback the callback that should be invoked when the RPC
327 * is received.  The callback has the following prototype
328 *   void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg)
329 * @param cbarg an additional parameter that can be passed to the callback.
330 *   The parameter can be used to carry around state.
331 */
332#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg)	\
333	evrpc_register_generic(base, #name,				\
334	    (void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \
335	    (void *(*)(void *))request##_new_with_arg, NULL,		\
336	    (void (*)(void *))request##_free,				\
337	    (int (*)(void *, struct evbuffer *))request##_unmarshal,	\
338	    (void *(*)(void *))reply##_new_with_arg, NULL,		\
339	    (void (*)(void *))reply##_free, \
340	    (int (*)(void *))reply##_complete, \
341	    (void (*)(struct evbuffer *, void *))reply##_marshal)
342
343/**
344   Low level function for registering an RPC with a server.
345
346   Use EVRPC_REGISTER() instead.
347
348   @see EVRPC_REGISTER()
349*/
350EVENT2_EXPORT_SYMBOL
351int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
352    void (*)(struct evrpc_req_generic*, void *), void *);
353
354/**
355 * Unregisters an already registered RPC
356 *
357 * @param base the evrpc_base object from which to unregister an RPC
358 * @param name the name of the rpc to unregister
359 * @return -1 on error or 0 when successful.
360 * @see EVRPC_REGISTER()
361 */
362#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc((base), #name)
363
364EVENT2_EXPORT_SYMBOL
365int evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
366
367/*
368 * Client-side RPC support
369 */
370
371struct evhttp_connection;
372struct evrpc_status;
373
374/** launches an RPC and sends it to the server
375 *
376 * EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server.
377 *
378 * @param name the name of the RPC
379 * @param pool the evrpc_pool that contains the connection objects over which
380 *   the request should be sent.
381 * @param request a pointer to the RPC request structure - it contains the
382 *   data to be sent to the server.
383 * @param reply a pointer to the RPC reply structure.  It is going to be filled
384 *   if the request was answered successfully
385 * @param cb the callback to invoke when the RPC request has been answered
386 * @param cbarg an additional argument to be passed to the client
387 * @return 0 on success, -1 on failure
388 */
389#define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg)	\
390	evrpc_send_request_##name((pool), (request), (reply), (cb), (cbarg))
391
392/**
393   Makes an RPC request based on the provided context.
394
395   This is a low-level function and should not be used directly
396   unless a custom context object is provided.  Use EVRPC_MAKE_REQUEST()
397   instead.
398
399   @param ctx a context from EVRPC_MAKE_CTX()
400   @returns 0 on success, -1 otherwise.
401   @see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX()
402*/
403EVENT2_EXPORT_SYMBOL
404int evrpc_make_request(struct evrpc_request_wrapper *ctx);
405
406/** creates an rpc connection pool
407 *
408 * a pool has a number of connections associated with it.
409 * rpc requests are always made via a pool.
410 *
411 * @param base a pointer to an struct event_based object; can be left NULL
412 *   in singled-threaded applications
413 * @return a newly allocated struct evrpc_pool object or NULL if an error
414 *   occurred
415 * @see evrpc_pool_free()
416 */
417EVENT2_EXPORT_SYMBOL
418struct evrpc_pool *evrpc_pool_new(struct event_base *base);
419/** frees an rpc connection pool
420 *
421 * @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new()
422 * @see evrpc_pool_new()
423 */
424EVENT2_EXPORT_SYMBOL
425void evrpc_pool_free(struct evrpc_pool *pool);
426
427/**
428 * Adds a connection over which rpc can be dispatched to the pool.
429 *
430 * The connection object must have been newly created.
431 *
432 * @param pool the pool to which to add the connection
433 * @param evcon the connection to add to the pool.
434 */
435EVENT2_EXPORT_SYMBOL
436void evrpc_pool_add_connection(struct evrpc_pool *pool,
437    struct evhttp_connection *evcon);
438
439/**
440 * Removes a connection from the pool.
441 *
442 * The connection object must have been newly created.
443 *
444 * @param pool the pool from which to remove the connection
445 * @param evcon the connection to remove from the pool.
446 */
447EVENT2_EXPORT_SYMBOL
448void evrpc_pool_remove_connection(struct evrpc_pool *pool,
449    struct evhttp_connection *evcon);
450
451/**
452 * Sets the timeout in secs after which a request has to complete.  The
453 * RPC is completely aborted if it does not complete by then.  Setting
454 * the timeout to 0 means that it never timeouts and can be used to
455 * implement callback type RPCs.
456 *
457 * Any connection already in the pool will be updated with the new
458 * timeout.  Connections added to the pool after set_timeout has be
459 * called receive the pool timeout only if no timeout has been set
460 * for the connection itself.
461 *
462 * @param pool a pointer to a struct evrpc_pool object
463 * @param timeout_in_secs the number of seconds after which a request should
464 *   timeout and a failure be returned to the callback.
465 */
466EVENT2_EXPORT_SYMBOL
467void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs);
468
469/**
470 * Hooks for changing the input and output of RPCs; this can be used to
471 * implement compression, authentication, encryption, ...
472 */
473
474enum EVRPC_HOOK_TYPE {
475	EVRPC_INPUT,		/**< apply the function to an input hook */
476	EVRPC_OUTPUT		/**< apply the function to an output hook */
477};
478
479#ifndef _WIN32
480/** Deprecated alias for EVRPC_INPUT.  Not available on windows, where it
481 * conflicts with platform headers. */
482#define INPUT EVRPC_INPUT
483/** Deprecated alias for EVRPC_OUTPUT.  Not available on windows, where it
484 * conflicts with platform headers. */
485#define OUTPUT EVRPC_OUTPUT
486#endif
487
488/**
489 * Return value from hook processing functions
490 */
491
492enum EVRPC_HOOK_RESULT {
493	EVRPC_TERMINATE = -1,	/**< indicates the rpc should be terminated */
494	EVRPC_CONTINUE = 0,	/**< continue processing the rpc */
495	EVRPC_PAUSE = 1		/**< pause processing request until resumed */
496};
497
498/** adds a processing hook to either an rpc base or rpc pool
499 *
500 * If a hook returns TERMINATE, the processing is aborted. On CONTINUE,
501 * the request is immediately processed after the hook returns.  If the
502 * hook returns PAUSE, request processing stops until evrpc_resume_request()
503 * has been called.
504 *
505 * The add functions return handles that can be used for removing hooks.
506 *
507 * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
508 * @param hook_type either INPUT or OUTPUT
509 * @param cb the callback to call when the hook is activated
510 * @param cb_arg an additional argument for the callback
511 * @return a handle to the hook so it can be removed later
512 * @see evrpc_remove_hook()
513 */
514EVENT2_EXPORT_SYMBOL
515void *evrpc_add_hook(void *vbase,
516    enum EVRPC_HOOK_TYPE hook_type,
517    int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *),
518    void *cb_arg);
519
520/** removes a previously added hook
521 *
522 * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
523 * @param hook_type either INPUT or OUTPUT
524 * @param handle a handle returned by evrpc_add_hook()
525 * @return 1 on success or 0 on failure
526 * @see evrpc_add_hook()
527 */
528EVENT2_EXPORT_SYMBOL
529int evrpc_remove_hook(void *vbase,
530    enum EVRPC_HOOK_TYPE hook_type,
531    void *handle);
532
533/** resume a paused request
534 *
535 * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
536 * @param ctx the context pointer provided to the original hook call
537 */
538EVENT2_EXPORT_SYMBOL
539int evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
540
541/** adds meta data to request
542 *
543 * evrpc_hook_add_meta() allows hooks to add meta data to a request. for
544 * a client request, the meta data can be inserted by an outgoing request hook
545 * and retrieved by the incoming request hook.
546 *
547 * @param ctx the context provided to the hook call
548 * @param key a NUL-terminated c-string
549 * @param data the data to be associated with the key
550 * @param data_size the size of the data
551 */
552EVENT2_EXPORT_SYMBOL
553void evrpc_hook_add_meta(void *ctx, const char *key,
554    const void *data, size_t data_size);
555
556/** retrieves meta data previously associated
557 *
558 * evrpc_hook_find_meta() can be used to retrieve meta data associated to a
559 * request by a previous hook.
560 * @param ctx the context provided to the hook call
561 * @param key a NUL-terminated c-string
562 * @param data pointer to a data pointer that will contain the retrieved data
563 * @param data_size pointer to the size of the data
564 * @return 0 on success or -1 on failure
565 */
566EVENT2_EXPORT_SYMBOL
567int evrpc_hook_find_meta(void *ctx, const char *key,
568    void **data, size_t *data_size);
569
570/**
571 * returns the connection object associated with the request
572 *
573 * @param ctx the context provided to the hook call
574 * @return a pointer to the evhttp_connection object or NULL if an error
575 *   occurred
576 */
577EVENT2_EXPORT_SYMBOL
578struct evhttp_connection *evrpc_hook_get_connection(void *ctx);
579
580/**
581   Function for sending a generic RPC request.
582
583   Do not call this function directly, use EVRPC_MAKE_REQUEST() instead.
584
585   @see EVRPC_MAKE_REQUEST()
586 */
587EVENT2_EXPORT_SYMBOL
588int evrpc_send_request_generic(struct evrpc_pool *pool,
589    void *request, void *reply,
590    void (*cb)(struct evrpc_status *, void *, void *, void *),
591    void *cb_arg,
592    const char *rpcname,
593    void (*req_marshal)(struct evbuffer *, void *),
594    void (*rpl_clear)(void *),
595    int (*rpl_unmarshal)(void *, struct evbuffer *));
596
597/**
598   Function for registering a generic RPC with the RPC base.
599
600   Do not call this function directly, use EVRPC_REGISTER() instead.
601
602   @see EVRPC_REGISTER()
603 */
604EVENT2_EXPORT_SYMBOL
605int evrpc_register_generic(struct evrpc_base *base, const char *name,
606    void (*callback)(struct evrpc_req_generic *, void *), void *cbarg,
607    void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *),
608    int (*req_unmarshal)(void *, struct evbuffer *),
609    void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *),
610    int (*rpl_complete)(void *),
611    void (*rpl_marshal)(struct evbuffer *, void *));
612
613/** accessors for obscure and undocumented functionality */
614EVENT2_EXPORT_SYMBOL
615struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx);
616EVENT2_EXPORT_SYMBOL
617void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx,
618    struct evrpc_pool *pool);
619EVENT2_EXPORT_SYMBOL
620void evrpc_request_set_cb(struct evrpc_request_wrapper *ctx,
621    void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg),
622    void *cb_arg);
623
624#ifdef __cplusplus
625}
626#endif
627
628#endif /* EVENT2_RPC_H_INCLUDED_ */
629