From a146af1db892bf2e85cd80599ab992b8a79420ea Mon Sep 17 00:00:00 2001 From: Niels Provos Date: Sat, 25 Apr 2009 00:15:55 +0000 Subject: [PATCH] move more code directly into evrpc.c; provide backwards compatible vararg macros svn:r1244 --- Doxyfile | 1 + evrpc.c | 70 +++++++++++++++++ evrpc.h | 1 + include/Makefile.am | 2 +- include/event2/rpc.h | 147 ++++++++++++++++++++---------------- include/event2/rpc_compat.h | 61 +++++++++++++++ include/event2/rpc_struct.h | 21 +++++- 7 files changed, 236 insertions(+), 67 deletions(-) create mode 100644 include/event2/rpc_compat.h diff --git a/Doxyfile b/Doxyfile index 62b83efa..3fc853e5 100644 --- a/Doxyfile +++ b/Doxyfile @@ -64,6 +64,7 @@ INPUT = event.h evdns.h evhttp.h evrpc.h \ include/event2/bufferevent_compat.h \ include/event2/util.h \ include/event2/rpc.h include/event2/rpc_struct.h \ + include/event2/rpc_compat.h \ include/event2/dns.h include/event2/dns_struct.h \ include/event2/dns_compat.h \ include/event2/http.h include/event2/http_struct.h \ diff --git a/evrpc.c b/evrpc.c index c1d7ebf9..1de50ca6 100644 --- a/evrpc.c +++ b/evrpc.c @@ -1042,6 +1042,76 @@ evrpc_hook_get_connection(void *ctx) return (req->hook_meta != NULL ? req->hook_meta->evcon : NULL); } +int +evrpc_send_request_generic(struct evrpc_pool *pool, + void *request, void *reply, + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cb_arg, + const char *rpcname, + void (*req_marshal)(struct evbuffer *, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *)) +{ + struct evrpc_status status; + struct evrpc_request_wrapper *ctx; + ctx = evrpc_make_request_ctx(pool, request, reply, + rpcname, req_marshal, rpl_clear, rpl_unmarshal, cb, cb_arg); + if (ctx == NULL) + goto error; + return (evrpc_make_request(ctx)); +error: + memset(&status, 0, sizeof(status)); + status.error = EVRPC_STATUS_ERR_UNSTARTED; + (*(cb))(&status, request, reply, cb_arg); + return (-1); +} + +/** Takes a request object and fills it in with the right magic */ +static struct evrpc * +evrpc_register_object(const char *name, + void *(*req_new)(void), void (*req_free)(void *), + int (*req_unmarshal)(void *, struct evbuffer *), + void *(*rpl_new)(void), void (*rpl_free)(void *), + int (*rpl_complete)(void *), + void (*rpl_marshal)(struct evbuffer *, void *)) +{ + struct evrpc* rpc = (struct evrpc *)mm_calloc(1, sizeof(struct evrpc)); + if (rpc == NULL) + return (NULL); + rpc->uri = mm_strdup(name); + if (rpc->uri == NULL) { + mm_free(rpc); + return (NULL); + } + rpc->request_new = req_new; + rpc->request_free = req_free; + rpc->request_unmarshal = req_unmarshal; + rpc->reply_new = rpl_new; + rpc->reply_free = rpl_free; + rpc->reply_complete = rpl_complete; + rpc->reply_marshal = rpl_marshal; + return (rpc); +} + +int +evrpc_register_generic(struct evrpc_base *base, const char *name, + void (*callback)(struct evrpc_req_generic *, void *), void *cbarg, + void *(*req_new)(void), void (*req_free)(void *), + int (*req_unmarshal)(void *, struct evbuffer *), + void *(*rpl_new)(void), void (*rpl_free)(void *), + int (*rpl_complete)(void *), + void (*rpl_marshal)(struct evbuffer *, void *)) +{ + struct evrpc* rpc = + evrpc_register_object(name, req_new, req_free, req_unmarshal, + rpl_new, rpl_free, rpl_complete, rpl_marshal); + if (rpc == NULL) + return (-1); + evrpc_register_rpc(base, rpc, + (void (*)(struct evrpc_req_generic*, void *))callback, cbarg); + return (0); +} + /** accessors for obscure and undocumented functionality */ struct evrpc_pool * evrpc_request_get_pool(struct evrpc_request_wrapper *ctx) diff --git a/evrpc.h b/evrpc.h index 0e88806a..a7e27a90 100644 --- a/evrpc.h +++ b/evrpc.h @@ -30,5 +30,6 @@ #include #include #include +#include #endif /* _EVRPC_H_ */ diff --git a/include/Makefile.am b/include/Makefile.am index 4be3a730..6a80feb6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -15,5 +15,5 @@ nobase_include_HEADERS = \ event2/bufferevent_struct.h event2/event.h event2/event_compat.h \ event2/event_struct.h event2/tag.h event2/util.h \ event2/http.h event2/http_struct.h event2/http_compat.h \ - event2/rpc.h event2/rpc_struct.h \ + event2/rpc.h event2/rpc_struct.h event2/rpc_compat.h \ event2/dns.h event2/dns_struct.h event2/dns_compat.h diff --git a/include/event2/rpc.h b/include/event2/rpc.h index 3d70f08f..dfa7966b 100644 --- a/include/event2/rpc.h +++ b/include/event2/rpc.h @@ -76,6 +76,8 @@ extern "C" { #define EVTAG_HAS(msg, member) \ ((msg)->member##_set == 1) +#ifndef _EVENT2_RPC_COMPAT_H_ + /** Assigns a value to the member in the message. @@ -117,6 +119,8 @@ extern "C" { #define EVTAG_GET_WITH_LEN(msg, member, pvalue, plen) \ (*(msg)->base->member##_get)(msg, pvalue, plen) +#endif /* _EVENT2_RPC_COMPAT_H_ */ + /** Adds a value to an array. */ @@ -137,6 +141,8 @@ extern "C" { */ #define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length) + + struct evbuffer; struct event_base; struct evrpc_req_generic; @@ -225,31 +231,21 @@ struct evrpc_request_wrapper *evrpc_make_request_ctx( * @param replystruct the name of the RPC reply structure * @see EVRPC_HEADER() */ -#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \ -int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \ - struct reqstruct *request, struct rplystruct *reply, \ - void (*cb)(struct evrpc_status *, \ - struct reqstruct *, struct rplystruct *, void *cbarg), \ - void *cbarg) { \ - struct evrpc_status status; \ - struct evrpc_request_wrapper *ctx; \ - ctx = evrpc_make_request_ctx(pool, request, reply, \ - #rpcname, \ - (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ - (void (*)(void *))rplystruct##_clear, \ - (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \ +#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \ + int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \ + struct reqstruct *request, struct rplystruct *reply, \ + void (*cb)(struct evrpc_status *, \ + struct reqstruct *, struct rplystruct *, void *cbarg), \ + void *cbarg) { \ + return evrpc_send_request_generic(pool, request, reply, \ (void (*)(struct evrpc_status *, void *, void *, void *))cb, \ - cbarg); \ - if (ctx == NULL) \ - goto error; \ - return (evrpc_make_request(ctx)); \ -error: \ - memset(&status, 0, sizeof(status)); \ - status.error = EVRPC_STATUS_ERR_UNSTARTED; \ - (*(cb))(&status, request, reply, cbarg); \ - return (-1); \ + cbarg, \ + #rpcname, \ + (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ + (void (*)(void *))rplystruct##_clear, \ + (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal); \ } - + /** Provides access to the HTTP request object underlying an RPC * * Access to the underlying http object; can be used to look at headers or @@ -278,23 +274,6 @@ void evrpc_request_done(struct evrpc_req_generic *req); } while (0) -/* Takes a request object and fills it in with the right magic */ -#define EVRPC_REGISTER_OBJECT(rpc, name, request, reply) \ - do { \ - (rpc)->uri = strdup(#name); \ - if ((rpc)->uri == NULL) { \ - fprintf(stderr, "failed to register object\n"); \ - exit(1); \ - } \ - (rpc)->request_new = (void *(*)(void))request##_new; \ - (rpc)->request_free = (void (*)(void *))request##_free; \ - (rpc)->request_unmarshal = (int (*)(void *, struct evbuffer *))request##_unmarshal; \ - (rpc)->reply_new = (void *(*)(void))reply##_new; \ - (rpc)->reply_free = (void (*)(void *))reply##_free; \ - (rpc)->reply_complete = (int (*)(void *))reply##_complete; \ - (rpc)->reply_marshal = (void (*)(struct evbuffer*, void *))reply##_marshal; \ - } while (0) - struct evrpc_base; struct evhttp; @@ -334,14 +313,24 @@ void evrpc_free(struct evrpc_base *base); * @param cbarg an additional parameter that can be passed to the callback. * The parameter can be used to carry around state. */ -#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \ - do { \ - struct evrpc* rpc = (struct evrpc *)calloc(1, sizeof(struct evrpc)); \ - EVRPC_REGISTER_OBJECT(rpc, name, request, reply); \ - evrpc_register_rpc(base, rpc, \ - (void (*)(struct evrpc_req_generic*, void *))callback, cbarg); \ - } while (0) +#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \ + evrpc_register_generic(base, #name, \ + (void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \ + (void *(*)(void))request##_new, \ + (void (*)(void *))request##_free, \ + (int (*)(void *, struct evbuffer *))request##_unmarshal, \ + (void *(*)(void))reply##_new, \ + (void (*)(void *))reply##_free, \ + (int (*)(void *))reply##_complete, \ + (void (*)(struct evbuffer *, void *))reply##_marshal) + +/** + Low level function for registering an RPC with a server. + + Use EVRPC_REGISTER() instead. + @see EVRPC_REGISTER() +*/ int evrpc_register_rpc(struct evrpc_base *, struct evrpc *, void (*)(struct evrpc_req_generic*, void *), void *); @@ -362,21 +351,7 @@ int evrpc_unregister_rpc(struct evrpc_base *base, const char *name); */ struct evhttp_connection; - -/** - * provides information about the completed RPC request. - */ -struct evrpc_status { -#define EVRPC_STATUS_ERR_NONE 0 -#define EVRPC_STATUS_ERR_TIMEOUT 1 -#define EVRPC_STATUS_ERR_BADPAYLOAD 2 -#define EVRPC_STATUS_ERR_UNSTARTED 3 -#define EVRPC_STATUS_ERR_HOOKABORTED 4 - int error; - - /* for looking at headers or other information */ - struct evhttp_request *http_req; -}; +struct evrpc_status; /** launches an RPC and sends it to the server * @@ -396,7 +371,18 @@ struct evrpc_status { #define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg) \ evrpc_send_request_##name(pool, request, reply, cb, cbarg) -int evrpc_make_request(struct evrpc_request_wrapper *); +/** + Makes an RPC request based on the provided context. + + This is a low-level function and should not be used directly + unless a custom context object is provided. Use EVRPC_MAKE_REQUEST() + instead. + + @param ctx a context from EVRPC_MAKE_CTX() + @returns 0 on success, -1 otherwise. + @see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX() +*/ +int evrpc_make_request(struct evrpc_request_wrapper *ctx); /** creates an rpc connection pool * @@ -552,13 +538,46 @@ void evrpc_hook_add_meta(void *ctx, const char *key, int evrpc_hook_find_meta(void *ctx, const char *key, void **data, size_t *data_size); -/** returns the connection object associated with the request +/** + * returns the connection object associated with the request * * @param ctx the context provided to the hook call * @return a pointer to the evhttp_connection object */ struct evhttp_connection *evrpc_hook_get_connection(void *ctx); +/** + Function for sending a generic RPC request. + + Do not call this function directly, use EVRPC_MAKE_REQUEST() instead. + + @see EVRPC_MAKE_REQUEST() + */ +int evrpc_send_request_generic(struct evrpc_pool *pool, + void *request, void *reply, + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cb_arg, + const char *rpcname, + void (*req_marshal)(struct evbuffer *, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *)); + +/** + Function for registering a generic RPC with the RPC base. + + Do not call this function directly, use EVRPC_REGISTER() instead. + + @see EVRPC_REGISTER() + */ +int +evrpc_register_generic(struct evrpc_base *base, const char *name, + void (*callback)(struct evrpc_req_generic *, void *), void *cbarg, + void *(*req_new)(void), void (*req_free)(void *), + int (*req_unmarshal)(void *, struct evbuffer *), + void *(*rpl_new)(void), void (*rpl_free)(void *), + int (*rpl_complete)(void *), + void (*rpl_marshal)(struct evbuffer *, void *)); + /** accessors for obscure and undocumented functionality */ struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx); void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx, diff --git a/include/event2/rpc_compat.h b/include/event2/rpc_compat.h new file mode 100644 index 00000000..5711efa7 --- /dev/null +++ b/include/event2/rpc_compat.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2009 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _EVENT2_RPC_COMPAT_H_ +#define _EVENT2_RPC_COMPAT_H_ + +/** @file rpc_compat.h + + Deprecated versions of the functions in rpc.h: provided only for + backwards compatibility. + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** backwards compatible accessors that work only with gcc */ +#ifdef __GNUC__ + +#undef EVTAG_ASSIGN +#undef EVTAG_GET +#undef EVTAG_ADD + +#define EVTAG_ASSIGN(msg, member, args...) \ + (*(msg)->base->member##_assign)(msg, ## args) +#define EVTAG_GET(msg, member, args...) \ + (*(msg)->base->member##_get)(msg, ## args) +#define EVTAG_ADD(msg, member, args...) \ + (*(msg)->base->member##_add)(msg, ## args) +#endif +#define EVTAG_LEN(msg, member) ((msg)->member##_length) + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_EVENT_COMPAT_H_ */ diff --git a/include/event2/rpc_struct.h b/include/event2/rpc_struct.h index d7d3f46f..51d0e765 100644 --- a/include/event2/rpc_struct.h +++ b/include/event2/rpc_struct.h @@ -32,10 +32,27 @@ extern "C" { #endif /** @file rpc_struct.h - * - * This header files provides basic support for an RPC server and client. + + Structures used by rpc.h. Using these structures directly may harm + forward compatibility: be careful! + */ +/** + * provides information about the completed RPC request. + */ +struct evrpc_status { +#define EVRPC_STATUS_ERR_NONE 0 +#define EVRPC_STATUS_ERR_TIMEOUT 1 +#define EVRPC_STATUS_ERR_BADPAYLOAD 2 +#define EVRPC_STATUS_ERR_UNSTARTED 3 +#define EVRPC_STATUS_ERR_HOOKABORTED 4 + int error; + + /* for looking at headers or other information */ + struct evhttp_request *http_req; +}; + /* the structure below needs to be synchronized with evrpc_req_generic */ /* Encapsulates a request */ -- 2.40.0