summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--evrpc.c17
-rw-r--r--evrpc.h42
-rw-r--r--test/regress_rpc.c20
3 files changed, 59 insertions, 20 deletions
diff --git a/evrpc.c b/evrpc.c
index e221150b..256f016d 100644
--- a/evrpc.c
+++ b/evrpc.c
@@ -382,6 +382,7 @@ evrpc_schedule_request(struct evhttp_connection *connection,
{
struct evhttp_request *req = NULL;
struct evrpc_pool *pool = ctx->pool;
+ struct evrpc_status status;
char *uri = NULL;
int res = 0;
@@ -418,7 +419,9 @@ evrpc_schedule_request(struct evhttp_connection *connection,
return (0);
error:
- (*ctx->cb)(ctx->request, ctx->reply, ctx->cb_arg);
+ memset(&status, 0, sizeof(status));
+ status.error = EVRPC_STATUS_ERR_UNSTARTED;
+ (*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg);
evrpc_request_wrapper_free(ctx);
return (-1);
}
@@ -450,20 +453,28 @@ evrpc_reply_done(struct evhttp_request *req, void *arg)
{
struct evrpc_request_wrapper *ctx = arg;
struct evrpc_pool *pool = ctx->pool;
+ struct evrpc_status status;
int res = -1;
/* cancel any timeout we might have scheduled */
event_del(&ctx->ev_timeout);
+ memset(&status, 0, sizeof(status));
/* we need to get the reply now */
- if (req != NULL)
+ if (req != NULL) {
res = ctx->reply_unmarshal(ctx->reply, req->input_buffer);
+ if (res == -1) {
+ status.error = EVRPC_STATUS_ERR_BADPAYLOAD;
+ }
+ } else {
+ status.error = EVRPC_STATUS_ERR_TIMEOUT;
+ }
if (res == -1) {
/* clear everything that we might have written previously */
ctx->reply_clear(ctx->reply);
}
- (*ctx->cb)(ctx->request, ctx->reply, ctx->cb_arg);
+ (*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg);
evrpc_request_wrapper_free(ctx);
diff --git a/evrpc.h b/evrpc.h
index 2cb97457..18855b2a 100644
--- a/evrpc.h
+++ b/evrpc.h
@@ -104,6 +104,7 @@ struct evrpc {
#define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname
struct evhttp_request;
+struct evrpc_status;
/* We alias the RPC specific structs to this voided one */
struct evrpc_req_generic {
@@ -117,7 +118,7 @@ struct evrpc_req_generic {
* the static structure for this rpc; that can be used to
* automatically unmarshal and marshal the http buffers.
*/
- struct evrpc* rpc;
+ struct evrpc *rpc;
/*
* the http request structure on which we need to answer.
@@ -132,41 +133,43 @@ struct evrpc_req_generic {
/*
* You need to use EVRPC_HEADER to create structures and function prototypes
- * needed by the server and client implmentation.
+ * needed by the server and client implementation.
*/
#define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \
EVRPC_STRUCT(rpcname) { \
struct reqstruct* request; \
struct rplystruct* reply; \
struct evrpc* rpc; \
- void (*done)(struct evrpc* rpc, void *request, void *reply); \
+ void (*done)(struct evrpc_status *, \
+ struct evrpc* rpc, void *request, void *reply); \
}; \
int evrpc_send_request_##rpcname(struct evrpc_pool *, \
struct reqstruct *, struct rplystruct *, \
- void (*)(struct reqstruct *, struct rplystruct *, void *cbarg), \
+ void (*)(struct evrpc_status *, \
+ struct reqstruct *, struct rplystruct *, void *cbarg), \
void *);
#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \
int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \
struct reqstruct *request, struct rplystruct *reply, \
- void (*cb)(struct reqstruct *, struct rplystruct *, void *cbarg), \
+ void (*cb)(struct evrpc_status *, \
+ struct reqstruct *, struct rplystruct *, void *cbarg), \
void *cbarg) { \
+ struct evrpc_status status; \
struct evrpc_request_wrapper *ctx; \
ctx = (struct evrpc_request_wrapper *) \
malloc(sizeof(struct evrpc_request_wrapper)); \
- if (ctx == NULL) { \
- (*(cb))(request, reply, cbarg); \
- return (-1); \
- } \
+ if (ctx == NULL) \
+ goto error; \
ctx->pool = pool; \
ctx->evcon = NULL; \
ctx->name = strdup(#rpcname); \
if (ctx->name == NULL) { \
free(ctx); \
- (*(cb))(request, reply, cbarg); \
- return (-1); \
+ goto error; \
} \
- ctx->cb = (void (*)(void *, void *, void *))cb; \
+ ctx->cb = (void (*)(struct evrpc_status *, \
+ void *, void *, void *))cb; \
ctx->cb_arg = cbarg; \
ctx->request = (void *)request; \
ctx->reply = (void *)reply; \
@@ -174,6 +177,11 @@ int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \
ctx->reply_clear = (void (*)(void *))rplystruct##_clear; \
ctx->reply_unmarshal = (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal; \
return (evrpc_make_request(ctx)); \
+error: \
+ memset(&status, 0, sizeof(status)); \
+ status.error = EVRPC_STATUS_ERR_UNSTARTED; \
+ (*(cb))(&status, request, reply, cbarg); \
+ return (-1); \
}
@@ -238,6 +246,14 @@ int evrpc_unregister_rpc(struct evrpc_base *, const char *name);
struct evrpc_pool;
struct evhttp_connection;
+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
+ int error;
+};
+
struct evrpc_request_wrapper {
TAILQ_ENTRY(evrpc_request_wrapper) next;
@@ -254,7 +270,7 @@ struct evrpc_request_wrapper {
char *name;
/* callback */
- void (*cb)(void *request, void *reply, void *arg);
+ void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg);
void *cb_arg;
void *request;
diff --git a/test/regress_rpc.c b/test/regress_rpc.c
index b90f8654..56462763 100644
--- a/test/regress_rpc.c
+++ b/test/regress_rpc.c
@@ -317,11 +317,15 @@ rpc_pool_with_connection(short port)
}
static void
-GotKillCb(struct msg *msg, struct kill *kill, void *arg)
+GotKillCb(struct evrpc_status *status,
+ struct msg *msg, struct kill *kill, void *arg)
{
char *weapon;
char *action;
+ if (status->error != EVRPC_STATUS_ERR_NONE)
+ goto done;
+
if (EVTAG_GET(kill, weapon, &weapon) == -1) {
fprintf(stderr, "get weapon\n");
goto done;
@@ -344,11 +348,15 @@ done:
}
static void
-GotKillCbTwo(struct msg *msg, struct kill *kill, void *arg)
+GotKillCbTwo(struct evrpc_status *status,
+ struct msg *msg, struct kill *kill, void *arg)
{
char *weapon;
char *action;
+ if (status->error != EVRPC_STATUS_ERR_NONE)
+ goto done;
+
if (EVTAG_GET(kill, weapon, &weapon) == -1) {
fprintf(stderr, "get weapon\n");
goto done;
@@ -481,8 +489,12 @@ rpc_basic_queued_client(void)
}
static void
-GotErrorCb(struct msg *msg, struct kill *kill, void *arg)
+GotErrorCb(struct evrpc_status *status,
+ struct msg *msg, struct kill *kill, void *arg)
{
+ if (status->error != EVRPC_STATUS_ERR_TIMEOUT)
+ goto done;
+
/* should never be complete but just to check */
if (kill_complete(kill) == 0)
goto done;
@@ -519,7 +531,7 @@ rpc_client_timeout(void)
kill = kill_new();
- EVRPC_MAKE_REQUEST(NeverReply, pool, msg, kill, GotErrorCb, NULL);
+ EVRPC_MAKE_REQUEST(NeverReply, pool, msg, kill, GotErrorCb, NULL);
test_ok = 0;