xref: /freebsd/contrib/libevent/include/event2/rpc.h (revision c8e7f78a3d28ff6e6223ed136ada8e1e2f34965e)
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
35 extern "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 
149 struct evbuffer;
150 struct event_base;
151 struct evrpc_req_generic;
152 struct evrpc_request_wrapper;
153 struct 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 
161 struct evhttp_request;
162 struct evrpc_status;
163 struct 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) \
177 EVRPC_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 };								     \
185 EVENT2_EXPORT_SYMBOL \
186 int 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 
192 struct evrpc_pool;
193 
194 /** use EVRPC_GENERATE instead */
195 EVENT2_EXPORT_SYMBOL
196 struct 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 */
266 EVENT2_EXPORT_SYMBOL
267 void evrpc_request_done(struct evrpc_req_generic *req);
268 
269 /** accessors for request and reply */
270 EVENT2_EXPORT_SYMBOL
271 void *evrpc_get_request(struct evrpc_req_generic *req);
272 EVENT2_EXPORT_SYMBOL
273 void *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 
289 struct evrpc_base;
290 struct 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  */
300 EVENT2_EXPORT_SYMBOL
301 struct 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  */
311 EVENT2_EXPORT_SYMBOL
312 void 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 */
348 EVENT2_EXPORT_SYMBOL
349 int 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 
362 EVENT2_EXPORT_SYMBOL
363 int evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
364 
365 /*
366  * Client-side RPC support
367  */
368 
369 struct evhttp_connection;
370 struct 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 */
401 EVENT2_EXPORT_SYMBOL
402 int 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  */
415 EVENT2_EXPORT_SYMBOL
416 struct 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  */
422 EVENT2_EXPORT_SYMBOL
423 void 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  */
433 EVENT2_EXPORT_SYMBOL
434 void 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  */
445 EVENT2_EXPORT_SYMBOL
446 void 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  */
464 EVENT2_EXPORT_SYMBOL
465 void 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 
472 enum 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 
490 enum 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  */
512 EVENT2_EXPORT_SYMBOL
513 void *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  */
526 EVENT2_EXPORT_SYMBOL
527 int 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  */
536 EVENT2_EXPORT_SYMBOL
537 int 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  */
550 EVENT2_EXPORT_SYMBOL
551 void 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  */
564 EVENT2_EXPORT_SYMBOL
565 int 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  */
575 EVENT2_EXPORT_SYMBOL
576 struct 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  */
585 EVENT2_EXPORT_SYMBOL
586 int 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  */
602 EVENT2_EXPORT_SYMBOL
603 int 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 */
612 EVENT2_EXPORT_SYMBOL
613 struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx);
614 EVENT2_EXPORT_SYMBOL
615 void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx,
616     struct evrpc_pool *pool);
617 EVENT2_EXPORT_SYMBOL
618 void 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