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