From: Niels Provos Date: Tue, 29 May 2007 05:38:58 +0000 (+0000) Subject: change the signature of the client rpc callback to pass in an rpc status; the status X-Git-Tag: release-2.0.1-alpha~618 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3794534feb99f94e052359c7cce61462ed909383;p=libevent change the signature of the client rpc callback to pass in an rpc status; the status allows us to determine if an error happened. svn:r363 --- 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;