12b15cb3dSCy Schubert /* 22b15cb3dSCy Schubert * Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu> 32b15cb3dSCy Schubert * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 42b15cb3dSCy Schubert * 52b15cb3dSCy Schubert * Redistribution and use in source and binary forms, with or without 62b15cb3dSCy Schubert * modification, are permitted provided that the following conditions 72b15cb3dSCy Schubert * are met: 82b15cb3dSCy Schubert * 1. Redistributions of source code must retain the above copyright 92b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer. 102b15cb3dSCy Schubert * 2. Redistributions in binary form must reproduce the above copyright 112b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer in the 122b15cb3dSCy Schubert * documentation and/or other materials provided with the distribution. 132b15cb3dSCy Schubert * 3. The name of the author may not be used to endorse or promote products 142b15cb3dSCy Schubert * derived from this software without specific prior written permission. 152b15cb3dSCy Schubert * 162b15cb3dSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 172b15cb3dSCy Schubert * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 182b15cb3dSCy Schubert * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 192b15cb3dSCy Schubert * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 202b15cb3dSCy Schubert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 212b15cb3dSCy Schubert * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 222b15cb3dSCy Schubert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 232b15cb3dSCy Schubert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 242b15cb3dSCy Schubert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 252b15cb3dSCy Schubert * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 262b15cb3dSCy Schubert */ 272b15cb3dSCy Schubert #ifndef EVENT2_RPC_H_INCLUDED_ 282b15cb3dSCy Schubert #define EVENT2_RPC_H_INCLUDED_ 292b15cb3dSCy Schubert 30*a466cc55SCy Schubert /* For int types. */ 31*a466cc55SCy Schubert #include <event2/util.h> 32*a466cc55SCy Schubert #include <event2/visibility.h> 33*a466cc55SCy Schubert 342b15cb3dSCy Schubert #ifdef __cplusplus 352b15cb3dSCy Schubert extern "C" { 362b15cb3dSCy Schubert #endif 372b15cb3dSCy Schubert 382b15cb3dSCy Schubert /** @file rpc.h 392b15cb3dSCy Schubert * 402b15cb3dSCy Schubert * This header files provides basic support for an RPC server and client. 412b15cb3dSCy Schubert * 422b15cb3dSCy Schubert * To support RPCs in a server, every supported RPC command needs to be 432b15cb3dSCy Schubert * defined and registered. 442b15cb3dSCy Schubert * 452b15cb3dSCy Schubert * EVRPC_HEADER(SendCommand, Request, Reply); 462b15cb3dSCy Schubert * 472b15cb3dSCy Schubert * SendCommand is the name of the RPC command. 482b15cb3dSCy Schubert * Request is the name of a structure generated by event_rpcgen.py. 492b15cb3dSCy Schubert * It contains all parameters relating to the SendCommand RPC. The 502b15cb3dSCy Schubert * server needs to fill in the Reply structure. 512b15cb3dSCy Schubert * Reply is the name of a structure generated by event_rpcgen.py. It 522b15cb3dSCy Schubert * contains the answer to the RPC. 532b15cb3dSCy Schubert * 542b15cb3dSCy Schubert * To register an RPC with an HTTP server, you need to first create an RPC 552b15cb3dSCy Schubert * base with: 562b15cb3dSCy Schubert * 572b15cb3dSCy Schubert * struct evrpc_base *base = evrpc_init(http); 582b15cb3dSCy Schubert * 592b15cb3dSCy Schubert * A specific RPC can then be registered with 602b15cb3dSCy Schubert * 612b15cb3dSCy Schubert * EVRPC_REGISTER(base, SendCommand, Request, Reply, FunctionCB, arg); 622b15cb3dSCy Schubert * 632b15cb3dSCy Schubert * when the server receives an appropriately formatted RPC, the user callback 642b15cb3dSCy Schubert * is invoked. The callback needs to fill in the reply structure. 652b15cb3dSCy Schubert * 662b15cb3dSCy Schubert * void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg); 672b15cb3dSCy Schubert * 682b15cb3dSCy Schubert * To send the reply, call EVRPC_REQUEST_DONE(rpc); 692b15cb3dSCy Schubert * 702b15cb3dSCy Schubert * See the regression test for an example. 712b15cb3dSCy Schubert */ 722b15cb3dSCy Schubert 732b15cb3dSCy Schubert /** 742b15cb3dSCy Schubert Determines if the member has been set in the message 752b15cb3dSCy Schubert 762b15cb3dSCy Schubert @param msg the message to inspect 772b15cb3dSCy Schubert @param member the member variable to test for presences 782b15cb3dSCy Schubert @return 1 if it's present or 0 otherwise. 792b15cb3dSCy Schubert */ 802b15cb3dSCy Schubert #define EVTAG_HAS(msg, member) \ 812b15cb3dSCy Schubert ((msg)->member##_set == 1) 822b15cb3dSCy Schubert 832b15cb3dSCy Schubert #ifndef EVENT2_RPC_COMPAT_H_INCLUDED_ 842b15cb3dSCy Schubert 852b15cb3dSCy Schubert /** 862b15cb3dSCy Schubert Assigns a value to the member in the message. 872b15cb3dSCy Schubert 882b15cb3dSCy Schubert @param msg the message to which to assign a value 892b15cb3dSCy Schubert @param member the name of the member variable 902b15cb3dSCy Schubert @param value the value to assign 912b15cb3dSCy Schubert */ 922b15cb3dSCy Schubert #define EVTAG_ASSIGN(msg, member, value) \ 932b15cb3dSCy Schubert (*(msg)->base->member##_assign)((msg), (value)) 942b15cb3dSCy Schubert /** 952b15cb3dSCy Schubert Assigns a value to the member in the message. 962b15cb3dSCy Schubert 972b15cb3dSCy Schubert @param msg the message to which to assign a value 982b15cb3dSCy Schubert @param member the name of the member variable 992b15cb3dSCy Schubert @param value the value to assign 1002b15cb3dSCy Schubert @param len the length of the value 1012b15cb3dSCy Schubert */ 1022b15cb3dSCy Schubert #define EVTAG_ASSIGN_WITH_LEN(msg, member, value, len) \ 1032b15cb3dSCy Schubert (*(msg)->base->member##_assign)((msg), (value), (len)) 1042b15cb3dSCy Schubert /** 1052b15cb3dSCy Schubert Returns the value for a member. 1062b15cb3dSCy Schubert 1072b15cb3dSCy Schubert @param msg the message from which to get the value 1082b15cb3dSCy Schubert @param member the name of the member variable 1092b15cb3dSCy Schubert @param pvalue a pointer to the variable to hold the value 1102b15cb3dSCy Schubert @return 0 on success, -1 otherwise. 1112b15cb3dSCy Schubert */ 1122b15cb3dSCy Schubert #define EVTAG_GET(msg, member, pvalue) \ 1132b15cb3dSCy Schubert (*(msg)->base->member##_get)((msg), (pvalue)) 1142b15cb3dSCy Schubert /** 1152b15cb3dSCy Schubert Returns the value for a member. 1162b15cb3dSCy Schubert 1172b15cb3dSCy Schubert @param msg the message from which to get the value 1182b15cb3dSCy Schubert @param member the name of the member variable 1192b15cb3dSCy Schubert @param pvalue a pointer to the variable to hold the value 1202b15cb3dSCy Schubert @param plen a pointer to the length of the value 1212b15cb3dSCy Schubert @return 0 on success, -1 otherwise. 1222b15cb3dSCy Schubert */ 1232b15cb3dSCy Schubert #define EVTAG_GET_WITH_LEN(msg, member, pvalue, plen) \ 1242b15cb3dSCy Schubert (*(msg)->base->member##_get)((msg), (pvalue), (plen)) 1252b15cb3dSCy Schubert 1262b15cb3dSCy Schubert #endif /* EVENT2_RPC_COMPAT_H_INCLUDED_ */ 1272b15cb3dSCy Schubert 1282b15cb3dSCy Schubert /** 1292b15cb3dSCy Schubert Adds a value to an array. 1302b15cb3dSCy Schubert */ 1312b15cb3dSCy Schubert #define EVTAG_ARRAY_ADD_VALUE(msg, member, value) \ 1322b15cb3dSCy Schubert (*(msg)->base->member##_add)((msg), (value)) 1332b15cb3dSCy Schubert /** 1342b15cb3dSCy Schubert Allocates a new entry in the array and returns it. 1352b15cb3dSCy Schubert */ 1362b15cb3dSCy Schubert #define EVTAG_ARRAY_ADD(msg, member) \ 1372b15cb3dSCy Schubert (*(msg)->base->member##_add)(msg) 1382b15cb3dSCy Schubert /** 1392b15cb3dSCy Schubert Gets a variable at the specified offset from the array. 1402b15cb3dSCy Schubert */ 1412b15cb3dSCy Schubert #define EVTAG_ARRAY_GET(msg, member, offset, pvalue) \ 1422b15cb3dSCy Schubert (*(msg)->base->member##_get)((msg), (offset), (pvalue)) 1432b15cb3dSCy Schubert /** 1442b15cb3dSCy Schubert Returns the number of entries in the array. 1452b15cb3dSCy Schubert */ 1462b15cb3dSCy Schubert #define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length) 1472b15cb3dSCy Schubert 1482b15cb3dSCy Schubert 1492b15cb3dSCy Schubert struct evbuffer; 1502b15cb3dSCy Schubert struct event_base; 1512b15cb3dSCy Schubert struct evrpc_req_generic; 1522b15cb3dSCy Schubert struct evrpc_request_wrapper; 1532b15cb3dSCy Schubert struct evrpc; 1542b15cb3dSCy Schubert 1552b15cb3dSCy Schubert /** The type of a specific RPC Message 1562b15cb3dSCy Schubert * 1572b15cb3dSCy Schubert * @param rpcname the name of the RPC message 1582b15cb3dSCy Schubert */ 1592b15cb3dSCy Schubert #define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname 1602b15cb3dSCy Schubert 1612b15cb3dSCy Schubert struct evhttp_request; 1622b15cb3dSCy Schubert struct evrpc_status; 1632b15cb3dSCy Schubert struct evrpc_hook_meta; 1642b15cb3dSCy Schubert 1652b15cb3dSCy Schubert /** Creates the definitions and prototypes for an RPC 1662b15cb3dSCy Schubert * 1672b15cb3dSCy Schubert * You need to use EVRPC_HEADER to create structures and function prototypes 1682b15cb3dSCy Schubert * needed by the server and client implementation. The structures have to be 1692b15cb3dSCy Schubert * defined in an .rpc file and converted to source code via event_rpcgen.py 1702b15cb3dSCy Schubert * 1712b15cb3dSCy Schubert * @param rpcname the name of the RPC 1722b15cb3dSCy Schubert * @param reqstruct the name of the RPC request structure 1732b15cb3dSCy Schubert * @param replystruct the name of the RPC reply structure 1742b15cb3dSCy Schubert * @see EVRPC_GENERATE() 1752b15cb3dSCy Schubert */ 1762b15cb3dSCy Schubert #define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \ 1772b15cb3dSCy Schubert EVRPC_STRUCT(rpcname) { \ 1782b15cb3dSCy Schubert struct evrpc_hook_meta *hook_meta; \ 1792b15cb3dSCy Schubert struct reqstruct* request; \ 1802b15cb3dSCy Schubert struct rplystruct* reply; \ 1812b15cb3dSCy Schubert struct evrpc* rpc; \ 1822b15cb3dSCy Schubert struct evhttp_request* http_req; \ 1832b15cb3dSCy Schubert struct evbuffer* rpc_data; \ 1842b15cb3dSCy Schubert }; \ 185*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL \ 1862b15cb3dSCy Schubert int evrpc_send_request_##rpcname(struct evrpc_pool *, \ 1872b15cb3dSCy Schubert struct reqstruct *, struct rplystruct *, \ 1882b15cb3dSCy Schubert void (*)(struct evrpc_status *, \ 1892b15cb3dSCy Schubert struct reqstruct *, struct rplystruct *, void *cbarg), \ 1902b15cb3dSCy Schubert void *); 1912b15cb3dSCy Schubert 1922b15cb3dSCy Schubert struct evrpc_pool; 1932b15cb3dSCy Schubert 1942b15cb3dSCy Schubert /** use EVRPC_GENERATE instead */ 195*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1962b15cb3dSCy Schubert struct evrpc_request_wrapper *evrpc_make_request_ctx( 1972b15cb3dSCy Schubert struct evrpc_pool *pool, void *request, void *reply, 1982b15cb3dSCy Schubert const char *rpcname, 1992b15cb3dSCy Schubert void (*req_marshal)(struct evbuffer*, void *), 2002b15cb3dSCy Schubert void (*rpl_clear)(void *), 2012b15cb3dSCy Schubert int (*rpl_unmarshal)(void *, struct evbuffer *), 2022b15cb3dSCy Schubert void (*cb)(struct evrpc_status *, void *, void *, void *), 2032b15cb3dSCy Schubert void *cbarg); 2042b15cb3dSCy Schubert 2052b15cb3dSCy Schubert /** Creates a context structure that contains rpc specific information. 2062b15cb3dSCy Schubert * 2072b15cb3dSCy Schubert * EVRPC_MAKE_CTX is used to populate a RPC specific context that 2082b15cb3dSCy Schubert * contains information about marshaling the RPC data types. 2092b15cb3dSCy Schubert * 2102b15cb3dSCy Schubert * @param rpcname the name of the RPC 2112b15cb3dSCy Schubert * @param reqstruct the name of the RPC request structure 2122b15cb3dSCy Schubert * @param replystruct the name of the RPC reply structure 2132b15cb3dSCy Schubert * @param pool the evrpc_pool over which to make the request 2142b15cb3dSCy Schubert * @param request a pointer to the RPC request structure object 2152b15cb3dSCy Schubert * @param reply a pointer to the RPC reply structure object 2162b15cb3dSCy Schubert * @param cb the callback function to call when the RPC has completed 2172b15cb3dSCy Schubert * @param cbarg the argument to supply to the callback 2182b15cb3dSCy Schubert */ 2192b15cb3dSCy Schubert #define EVRPC_MAKE_CTX(rpcname, reqstruct, rplystruct, \ 2202b15cb3dSCy Schubert pool, request, reply, cb, cbarg) \ 2212b15cb3dSCy Schubert evrpc_make_request_ctx(pool, request, reply, \ 2222b15cb3dSCy Schubert #rpcname, \ 2232b15cb3dSCy Schubert (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ 2242b15cb3dSCy Schubert (void (*)(void *))rplystruct##_clear, \ 2252b15cb3dSCy Schubert (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \ 2262b15cb3dSCy Schubert (void (*)(struct evrpc_status *, void *, void *, void *))cb, \ 2272b15cb3dSCy Schubert cbarg) 2282b15cb3dSCy Schubert 2292b15cb3dSCy Schubert /** Generates the code for receiving and sending an RPC message 2302b15cb3dSCy Schubert * 2312b15cb3dSCy Schubert * EVRPC_GENERATE is used to create the code corresponding to sending 2322b15cb3dSCy Schubert * and receiving a particular RPC message 2332b15cb3dSCy Schubert * 2342b15cb3dSCy Schubert * @param rpcname the name of the RPC 2352b15cb3dSCy Schubert * @param reqstruct the name of the RPC request structure 2362b15cb3dSCy Schubert * @param replystruct the name of the RPC reply structure 2372b15cb3dSCy Schubert * @see EVRPC_HEADER() 2382b15cb3dSCy Schubert */ 2392b15cb3dSCy Schubert #define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \ 2402b15cb3dSCy Schubert int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \ 2412b15cb3dSCy Schubert struct reqstruct *request, struct rplystruct *reply, \ 2422b15cb3dSCy Schubert void (*cb)(struct evrpc_status *, \ 2432b15cb3dSCy Schubert struct reqstruct *, struct rplystruct *, void *cbarg), \ 2442b15cb3dSCy Schubert void *cbarg) { \ 2452b15cb3dSCy Schubert return evrpc_send_request_generic(pool, request, reply, \ 2462b15cb3dSCy Schubert (void (*)(struct evrpc_status *, void *, void *, void *))cb, \ 2472b15cb3dSCy Schubert cbarg, \ 2482b15cb3dSCy Schubert #rpcname, \ 2492b15cb3dSCy Schubert (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ 2502b15cb3dSCy Schubert (void (*)(void *))rplystruct##_clear, \ 2512b15cb3dSCy Schubert (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal); \ 2522b15cb3dSCy Schubert } 2532b15cb3dSCy Schubert 2542b15cb3dSCy Schubert /** Provides access to the HTTP request object underlying an RPC 2552b15cb3dSCy Schubert * 2562b15cb3dSCy Schubert * Access to the underlying http object; can be used to look at headers or 2572b15cb3dSCy Schubert * for getting the remote ip address 2582b15cb3dSCy Schubert * 2592b15cb3dSCy Schubert * @param rpc_req the rpc request structure provided to the server callback 2602b15cb3dSCy Schubert * @return an struct evhttp_request object that can be inspected for 2612b15cb3dSCy Schubert * HTTP headers or sender information. 2622b15cb3dSCy Schubert */ 2632b15cb3dSCy Schubert #define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req 2642b15cb3dSCy Schubert 2652b15cb3dSCy Schubert /** completes the server response to an rpc request */ 266*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 2672b15cb3dSCy Schubert void evrpc_request_done(struct evrpc_req_generic *req); 2682b15cb3dSCy Schubert 2692b15cb3dSCy Schubert /** accessors for request and reply */ 270*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 2712b15cb3dSCy Schubert void *evrpc_get_request(struct evrpc_req_generic *req); 272*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 2732b15cb3dSCy Schubert void *evrpc_get_reply(struct evrpc_req_generic *req); 2742b15cb3dSCy Schubert 2752b15cb3dSCy Schubert /** Creates the reply to an RPC request 2762b15cb3dSCy Schubert * 2772b15cb3dSCy Schubert * EVRPC_REQUEST_DONE is used to answer a request; the reply is expected 2782b15cb3dSCy Schubert * to have been filled in. The request and reply pointers become invalid 2792b15cb3dSCy Schubert * after this call has finished. 2802b15cb3dSCy Schubert * 2812b15cb3dSCy Schubert * @param rpc_req the rpc request structure provided to the server callback 2822b15cb3dSCy Schubert */ 2832b15cb3dSCy Schubert #define EVRPC_REQUEST_DONE(rpc_req) do { \ 2842b15cb3dSCy Schubert struct evrpc_req_generic *req_ = (struct evrpc_req_generic *)(rpc_req); \ 2852b15cb3dSCy Schubert evrpc_request_done(req_); \ 2862b15cb3dSCy Schubert } while (0) 2872b15cb3dSCy Schubert 2882b15cb3dSCy Schubert 2892b15cb3dSCy Schubert struct evrpc_base; 2902b15cb3dSCy Schubert struct evhttp; 2912b15cb3dSCy Schubert 2922b15cb3dSCy Schubert /* functions to start up the rpc system */ 2932b15cb3dSCy Schubert 2942b15cb3dSCy Schubert /** Creates a new rpc base from which RPC requests can be received 2952b15cb3dSCy Schubert * 2962b15cb3dSCy Schubert * @param server a pointer to an existing HTTP server 297*a466cc55SCy Schubert * @return a newly allocated evrpc_base struct or NULL if an error occurred 2982b15cb3dSCy Schubert * @see evrpc_free() 2992b15cb3dSCy Schubert */ 300*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 3012b15cb3dSCy Schubert struct evrpc_base *evrpc_init(struct evhttp *server); 3022b15cb3dSCy Schubert 3032b15cb3dSCy Schubert /** 3042b15cb3dSCy Schubert * Frees the evrpc base 3052b15cb3dSCy Schubert * 3062b15cb3dSCy Schubert * For now, you are responsible for making sure that no rpcs are ongoing. 3072b15cb3dSCy Schubert * 3082b15cb3dSCy Schubert * @param base the evrpc_base object to be freed 3092b15cb3dSCy Schubert * @see evrpc_init 3102b15cb3dSCy Schubert */ 311*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 3122b15cb3dSCy Schubert void evrpc_free(struct evrpc_base *base); 3132b15cb3dSCy Schubert 3142b15cb3dSCy Schubert /** register RPCs with the HTTP Server 3152b15cb3dSCy Schubert * 3162b15cb3dSCy Schubert * registers a new RPC with the HTTP server, each RPC needs to have 3172b15cb3dSCy Schubert * a unique name under which it can be identified. 3182b15cb3dSCy Schubert * 3192b15cb3dSCy Schubert * @param base the evrpc_base structure in which the RPC should be 3202b15cb3dSCy Schubert * registered. 3212b15cb3dSCy Schubert * @param name the name of the RPC 3222b15cb3dSCy Schubert * @param request the name of the RPC request structure 3232b15cb3dSCy Schubert * @param reply the name of the RPC reply structure 3242b15cb3dSCy Schubert * @param callback the callback that should be invoked when the RPC 3252b15cb3dSCy Schubert * is received. The callback has the following prototype 3262b15cb3dSCy Schubert * void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg) 3272b15cb3dSCy Schubert * @param cbarg an additional parameter that can be passed to the callback. 3282b15cb3dSCy Schubert * The parameter can be used to carry around state. 3292b15cb3dSCy Schubert */ 3302b15cb3dSCy Schubert #define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \ 3312b15cb3dSCy Schubert evrpc_register_generic(base, #name, \ 3322b15cb3dSCy Schubert (void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \ 333*a466cc55SCy Schubert (void *(*)(void *))request##_new_with_arg, NULL, \ 3342b15cb3dSCy Schubert (void (*)(void *))request##_free, \ 3352b15cb3dSCy Schubert (int (*)(void *, struct evbuffer *))request##_unmarshal, \ 336*a466cc55SCy Schubert (void *(*)(void *))reply##_new_with_arg, NULL, \ 3372b15cb3dSCy Schubert (void (*)(void *))reply##_free, \ 3382b15cb3dSCy Schubert (int (*)(void *))reply##_complete, \ 3392b15cb3dSCy Schubert (void (*)(struct evbuffer *, void *))reply##_marshal) 3402b15cb3dSCy Schubert 3412b15cb3dSCy Schubert /** 3422b15cb3dSCy Schubert Low level function for registering an RPC with a server. 3432b15cb3dSCy Schubert 3442b15cb3dSCy Schubert Use EVRPC_REGISTER() instead. 3452b15cb3dSCy Schubert 3462b15cb3dSCy Schubert @see EVRPC_REGISTER() 3472b15cb3dSCy Schubert */ 348*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 3492b15cb3dSCy Schubert int evrpc_register_rpc(struct evrpc_base *, struct evrpc *, 3502b15cb3dSCy Schubert void (*)(struct evrpc_req_generic*, void *), void *); 3512b15cb3dSCy Schubert 3522b15cb3dSCy Schubert /** 3532b15cb3dSCy Schubert * Unregisters an already registered RPC 3542b15cb3dSCy Schubert * 3552b15cb3dSCy Schubert * @param base the evrpc_base object from which to unregister an RPC 3562b15cb3dSCy Schubert * @param name the name of the rpc to unregister 3572b15cb3dSCy Schubert * @return -1 on error or 0 when successful. 3582b15cb3dSCy Schubert * @see EVRPC_REGISTER() 3592b15cb3dSCy Schubert */ 3602b15cb3dSCy Schubert #define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc((base), #name) 3612b15cb3dSCy Schubert 362*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 3632b15cb3dSCy Schubert int evrpc_unregister_rpc(struct evrpc_base *base, const char *name); 3642b15cb3dSCy Schubert 3652b15cb3dSCy Schubert /* 3662b15cb3dSCy Schubert * Client-side RPC support 3672b15cb3dSCy Schubert */ 3682b15cb3dSCy Schubert 3692b15cb3dSCy Schubert struct evhttp_connection; 3702b15cb3dSCy Schubert struct evrpc_status; 3712b15cb3dSCy Schubert 3722b15cb3dSCy Schubert /** launches an RPC and sends it to the server 3732b15cb3dSCy Schubert * 3742b15cb3dSCy Schubert * EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server. 3752b15cb3dSCy Schubert * 3762b15cb3dSCy Schubert * @param name the name of the RPC 3772b15cb3dSCy Schubert * @param pool the evrpc_pool that contains the connection objects over which 3782b15cb3dSCy Schubert * the request should be sent. 3792b15cb3dSCy Schubert * @param request a pointer to the RPC request structure - it contains the 3802b15cb3dSCy Schubert * data to be sent to the server. 3812b15cb3dSCy Schubert * @param reply a pointer to the RPC reply structure. It is going to be filled 3822b15cb3dSCy Schubert * if the request was answered successfully 3832b15cb3dSCy Schubert * @param cb the callback to invoke when the RPC request has been answered 3842b15cb3dSCy Schubert * @param cbarg an additional argument to be passed to the client 3852b15cb3dSCy Schubert * @return 0 on success, -1 on failure 3862b15cb3dSCy Schubert */ 3872b15cb3dSCy Schubert #define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg) \ 3882b15cb3dSCy Schubert evrpc_send_request_##name((pool), (request), (reply), (cb), (cbarg)) 3892b15cb3dSCy Schubert 3902b15cb3dSCy Schubert /** 3912b15cb3dSCy Schubert Makes an RPC request based on the provided context. 3922b15cb3dSCy Schubert 3932b15cb3dSCy Schubert This is a low-level function and should not be used directly 3942b15cb3dSCy Schubert unless a custom context object is provided. Use EVRPC_MAKE_REQUEST() 3952b15cb3dSCy Schubert instead. 3962b15cb3dSCy Schubert 3972b15cb3dSCy Schubert @param ctx a context from EVRPC_MAKE_CTX() 3982b15cb3dSCy Schubert @returns 0 on success, -1 otherwise. 3992b15cb3dSCy Schubert @see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX() 4002b15cb3dSCy Schubert */ 401*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 4022b15cb3dSCy Schubert int evrpc_make_request(struct evrpc_request_wrapper *ctx); 4032b15cb3dSCy Schubert 4042b15cb3dSCy Schubert /** creates an rpc connection pool 4052b15cb3dSCy Schubert * 4062b15cb3dSCy Schubert * a pool has a number of connections associated with it. 4072b15cb3dSCy Schubert * rpc requests are always made via a pool. 4082b15cb3dSCy Schubert * 4092b15cb3dSCy Schubert * @param base a pointer to an struct event_based object; can be left NULL 4102b15cb3dSCy Schubert * in singled-threaded applications 411*a466cc55SCy Schubert * @return a newly allocated struct evrpc_pool object or NULL if an error 412*a466cc55SCy Schubert * occurred 4132b15cb3dSCy Schubert * @see evrpc_pool_free() 4142b15cb3dSCy Schubert */ 415*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 4162b15cb3dSCy Schubert struct evrpc_pool *evrpc_pool_new(struct event_base *base); 4172b15cb3dSCy Schubert /** frees an rpc connection pool 4182b15cb3dSCy Schubert * 4192b15cb3dSCy Schubert * @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new() 4202b15cb3dSCy Schubert * @see evrpc_pool_new() 4212b15cb3dSCy Schubert */ 422*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 4232b15cb3dSCy Schubert void evrpc_pool_free(struct evrpc_pool *pool); 4242b15cb3dSCy Schubert 4252b15cb3dSCy Schubert /** 4262b15cb3dSCy Schubert * Adds a connection over which rpc can be dispatched to the pool. 4272b15cb3dSCy Schubert * 4282b15cb3dSCy Schubert * The connection object must have been newly created. 4292b15cb3dSCy Schubert * 4302b15cb3dSCy Schubert * @param pool the pool to which to add the connection 4312b15cb3dSCy Schubert * @param evcon the connection to add to the pool. 4322b15cb3dSCy Schubert */ 433*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 4342b15cb3dSCy Schubert void evrpc_pool_add_connection(struct evrpc_pool *pool, 4352b15cb3dSCy Schubert struct evhttp_connection *evcon); 4362b15cb3dSCy Schubert 4372b15cb3dSCy Schubert /** 4382b15cb3dSCy Schubert * Removes a connection from the pool. 4392b15cb3dSCy Schubert * 4402b15cb3dSCy Schubert * The connection object must have been newly created. 4412b15cb3dSCy Schubert * 4422b15cb3dSCy Schubert * @param pool the pool from which to remove the connection 4432b15cb3dSCy Schubert * @param evcon the connection to remove from the pool. 4442b15cb3dSCy Schubert */ 445*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 4462b15cb3dSCy Schubert void evrpc_pool_remove_connection(struct evrpc_pool *pool, 4472b15cb3dSCy Schubert struct evhttp_connection *evcon); 4482b15cb3dSCy Schubert 4492b15cb3dSCy Schubert /** 4502b15cb3dSCy Schubert * Sets the timeout in secs after which a request has to complete. The 4512b15cb3dSCy Schubert * RPC is completely aborted if it does not complete by then. Setting 4522b15cb3dSCy Schubert * the timeout to 0 means that it never timeouts and can be used to 4532b15cb3dSCy Schubert * implement callback type RPCs. 4542b15cb3dSCy Schubert * 4552b15cb3dSCy Schubert * Any connection already in the pool will be updated with the new 4562b15cb3dSCy Schubert * timeout. Connections added to the pool after set_timeout has be 4572b15cb3dSCy Schubert * called receive the pool timeout only if no timeout has been set 4582b15cb3dSCy Schubert * for the connection itself. 4592b15cb3dSCy Schubert * 4602b15cb3dSCy Schubert * @param pool a pointer to a struct evrpc_pool object 4612b15cb3dSCy Schubert * @param timeout_in_secs the number of seconds after which a request should 4622b15cb3dSCy Schubert * timeout and a failure be returned to the callback. 4632b15cb3dSCy Schubert */ 464*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 4652b15cb3dSCy Schubert void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs); 4662b15cb3dSCy Schubert 4672b15cb3dSCy Schubert /** 4682b15cb3dSCy Schubert * Hooks for changing the input and output of RPCs; this can be used to 4692b15cb3dSCy Schubert * implement compression, authentication, encryption, ... 4702b15cb3dSCy Schubert */ 4712b15cb3dSCy Schubert 4722b15cb3dSCy Schubert enum EVRPC_HOOK_TYPE { 4732b15cb3dSCy Schubert EVRPC_INPUT, /**< apply the function to an input hook */ 4742b15cb3dSCy Schubert EVRPC_OUTPUT /**< apply the function to an output hook */ 4752b15cb3dSCy Schubert }; 4762b15cb3dSCy Schubert 4772b15cb3dSCy Schubert #ifndef _WIN32 4782b15cb3dSCy Schubert /** Deprecated alias for EVRPC_INPUT. Not available on windows, where it 4792b15cb3dSCy Schubert * conflicts with platform headers. */ 4802b15cb3dSCy Schubert #define INPUT EVRPC_INPUT 4812b15cb3dSCy Schubert /** Deprecated alias for EVRPC_OUTPUT. Not available on windows, where it 4822b15cb3dSCy Schubert * conflicts with platform headers. */ 4832b15cb3dSCy Schubert #define OUTPUT EVRPC_OUTPUT 4842b15cb3dSCy Schubert #endif 4852b15cb3dSCy Schubert 4862b15cb3dSCy Schubert /** 4872b15cb3dSCy Schubert * Return value from hook processing functions 4882b15cb3dSCy Schubert */ 4892b15cb3dSCy Schubert 4902b15cb3dSCy Schubert enum EVRPC_HOOK_RESULT { 4912b15cb3dSCy Schubert EVRPC_TERMINATE = -1, /**< indicates the rpc should be terminated */ 4922b15cb3dSCy Schubert EVRPC_CONTINUE = 0, /**< continue processing the rpc */ 4932b15cb3dSCy Schubert EVRPC_PAUSE = 1 /**< pause processing request until resumed */ 4942b15cb3dSCy Schubert }; 4952b15cb3dSCy Schubert 4962b15cb3dSCy Schubert /** adds a processing hook to either an rpc base or rpc pool 4972b15cb3dSCy Schubert * 4982b15cb3dSCy Schubert * If a hook returns TERMINATE, the processing is aborted. On CONTINUE, 4992b15cb3dSCy Schubert * the request is immediately processed after the hook returns. If the 5002b15cb3dSCy Schubert * hook returns PAUSE, request processing stops until evrpc_resume_request() 5012b15cb3dSCy Schubert * has been called. 5022b15cb3dSCy Schubert * 5032b15cb3dSCy Schubert * The add functions return handles that can be used for removing hooks. 5042b15cb3dSCy Schubert * 5052b15cb3dSCy Schubert * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool 5062b15cb3dSCy Schubert * @param hook_type either INPUT or OUTPUT 5072b15cb3dSCy Schubert * @param cb the callback to call when the hook is activated 5082b15cb3dSCy Schubert * @param cb_arg an additional argument for the callback 5092b15cb3dSCy Schubert * @return a handle to the hook so it can be removed later 5102b15cb3dSCy Schubert * @see evrpc_remove_hook() 5112b15cb3dSCy Schubert */ 512*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 5132b15cb3dSCy Schubert void *evrpc_add_hook(void *vbase, 5142b15cb3dSCy Schubert enum EVRPC_HOOK_TYPE hook_type, 5152b15cb3dSCy Schubert int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *), 5162b15cb3dSCy Schubert void *cb_arg); 5172b15cb3dSCy Schubert 5182b15cb3dSCy Schubert /** removes a previously added hook 5192b15cb3dSCy Schubert * 5202b15cb3dSCy Schubert * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool 5212b15cb3dSCy Schubert * @param hook_type either INPUT or OUTPUT 5222b15cb3dSCy Schubert * @param handle a handle returned by evrpc_add_hook() 5232b15cb3dSCy Schubert * @return 1 on success or 0 on failure 5242b15cb3dSCy Schubert * @see evrpc_add_hook() 5252b15cb3dSCy Schubert */ 526*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 5272b15cb3dSCy Schubert int evrpc_remove_hook(void *vbase, 5282b15cb3dSCy Schubert enum EVRPC_HOOK_TYPE hook_type, 5292b15cb3dSCy Schubert void *handle); 5302b15cb3dSCy Schubert 5312b15cb3dSCy Schubert /** resume a paused request 5322b15cb3dSCy Schubert * 5332b15cb3dSCy Schubert * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool 5342b15cb3dSCy Schubert * @param ctx the context pointer provided to the original hook call 5352b15cb3dSCy Schubert */ 536*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 537*a466cc55SCy Schubert int evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res); 5382b15cb3dSCy Schubert 5392b15cb3dSCy Schubert /** adds meta data to request 5402b15cb3dSCy Schubert * 5412b15cb3dSCy Schubert * evrpc_hook_add_meta() allows hooks to add meta data to a request. for 5422b15cb3dSCy Schubert * a client request, the meta data can be inserted by an outgoing request hook 5432b15cb3dSCy Schubert * and retrieved by the incoming request hook. 5442b15cb3dSCy Schubert * 5452b15cb3dSCy Schubert * @param ctx the context provided to the hook call 5462b15cb3dSCy Schubert * @param key a NUL-terminated c-string 5472b15cb3dSCy Schubert * @param data the data to be associated with the key 5482b15cb3dSCy Schubert * @param data_size the size of the data 5492b15cb3dSCy Schubert */ 550*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 5512b15cb3dSCy Schubert void evrpc_hook_add_meta(void *ctx, const char *key, 5522b15cb3dSCy Schubert const void *data, size_t data_size); 5532b15cb3dSCy Schubert 5542b15cb3dSCy Schubert /** retrieves meta data previously associated 5552b15cb3dSCy Schubert * 5562b15cb3dSCy Schubert * evrpc_hook_find_meta() can be used to retrieve meta data associated to a 5572b15cb3dSCy Schubert * request by a previous hook. 5582b15cb3dSCy Schubert * @param ctx the context provided to the hook call 5592b15cb3dSCy Schubert * @param key a NUL-terminated c-string 5602b15cb3dSCy Schubert * @param data pointer to a data pointer that will contain the retrieved data 5612b15cb3dSCy Schubert * @param data_size pointer to the size of the data 5622b15cb3dSCy Schubert * @return 0 on success or -1 on failure 5632b15cb3dSCy Schubert */ 564*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 5652b15cb3dSCy Schubert int evrpc_hook_find_meta(void *ctx, const char *key, 5662b15cb3dSCy Schubert void **data, size_t *data_size); 5672b15cb3dSCy Schubert 5682b15cb3dSCy Schubert /** 5692b15cb3dSCy Schubert * returns the connection object associated with the request 5702b15cb3dSCy Schubert * 5712b15cb3dSCy Schubert * @param ctx the context provided to the hook call 572*a466cc55SCy Schubert * @return a pointer to the evhttp_connection object or NULL if an error 573*a466cc55SCy Schubert * occurred 5742b15cb3dSCy Schubert */ 575*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 5762b15cb3dSCy Schubert struct evhttp_connection *evrpc_hook_get_connection(void *ctx); 5772b15cb3dSCy Schubert 5782b15cb3dSCy Schubert /** 5792b15cb3dSCy Schubert Function for sending a generic RPC request. 5802b15cb3dSCy Schubert 5812b15cb3dSCy Schubert Do not call this function directly, use EVRPC_MAKE_REQUEST() instead. 5822b15cb3dSCy Schubert 5832b15cb3dSCy Schubert @see EVRPC_MAKE_REQUEST() 5842b15cb3dSCy Schubert */ 585*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 5862b15cb3dSCy Schubert int evrpc_send_request_generic(struct evrpc_pool *pool, 5872b15cb3dSCy Schubert void *request, void *reply, 5882b15cb3dSCy Schubert void (*cb)(struct evrpc_status *, void *, void *, void *), 5892b15cb3dSCy Schubert void *cb_arg, 5902b15cb3dSCy Schubert const char *rpcname, 5912b15cb3dSCy Schubert void (*req_marshal)(struct evbuffer *, void *), 5922b15cb3dSCy Schubert void (*rpl_clear)(void *), 5932b15cb3dSCy Schubert int (*rpl_unmarshal)(void *, struct evbuffer *)); 5942b15cb3dSCy Schubert 5952b15cb3dSCy Schubert /** 5962b15cb3dSCy Schubert Function for registering a generic RPC with the RPC base. 5972b15cb3dSCy Schubert 5982b15cb3dSCy Schubert Do not call this function directly, use EVRPC_REGISTER() instead. 5992b15cb3dSCy Schubert 6002b15cb3dSCy Schubert @see EVRPC_REGISTER() 6012b15cb3dSCy Schubert */ 602*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 603*a466cc55SCy Schubert int evrpc_register_generic(struct evrpc_base *base, const char *name, 6042b15cb3dSCy Schubert void (*callback)(struct evrpc_req_generic *, void *), void *cbarg, 6052b15cb3dSCy Schubert void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *), 6062b15cb3dSCy Schubert int (*req_unmarshal)(void *, struct evbuffer *), 6072b15cb3dSCy Schubert void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *), 6082b15cb3dSCy Schubert int (*rpl_complete)(void *), 6092b15cb3dSCy Schubert void (*rpl_marshal)(struct evbuffer *, void *)); 6102b15cb3dSCy Schubert 6112b15cb3dSCy Schubert /** accessors for obscure and undocumented functionality */ 612*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 6132b15cb3dSCy Schubert struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx); 614*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 6152b15cb3dSCy Schubert void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx, 6162b15cb3dSCy Schubert struct evrpc_pool *pool); 617*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 6182b15cb3dSCy Schubert void evrpc_request_set_cb(struct evrpc_request_wrapper *ctx, 6192b15cb3dSCy Schubert void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg), 6202b15cb3dSCy Schubert void *cb_arg); 6212b15cb3dSCy Schubert 6222b15cb3dSCy Schubert #ifdef __cplusplus 6232b15cb3dSCy Schubert } 6242b15cb3dSCy Schubert #endif 6252b15cb3dSCy Schubert 6262b15cb3dSCy Schubert #endif /* EVENT2_RPC_H_INCLUDED_ */ 627