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