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