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)
#define EVTAG_HAS(msg, member) \
((msg)->member##_set == 1)
+#ifndef _EVENT2_RPC_COMPAT_H_
+
/**
Assigns a value to the member in the message.
#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.
*/
*/
#define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length)
+
+
struct evbuffer;
struct event_base;
struct evrpc_req_generic;
* @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
} 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;
* @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 *);
*/
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
*
#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
*
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,
--- /dev/null
+/*
+ * Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
+ * 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_ */