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