]> granicus.if.org Git - libevent/commitdiff
change the signature of the client rpc callback to pass in an rpc status; the status
authorNiels Provos <provos@gmail.com>
Tue, 29 May 2007 05:38:58 +0000 (05:38 +0000)
committerNiels Provos <provos@gmail.com>
Tue, 29 May 2007 05:38:58 +0000 (05:38 +0000)
allows us to determine if an error happened.

svn:r363

evrpc.c
evrpc.h
test/regress_rpc.c

diff --git a/evrpc.c b/evrpc.c
index e221150bc593f30b41a4fca3c4c51fae17680807..256f016d3fe1f9a4d13c954146c3224000a1a27f 100644 (file)
--- 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 2cb9745705910d1e7d9557e9649ca274b21bf61e..18855b2a27b27bb33d7e6461d413754abcadb6d9 100644 (file)
--- 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 evrpcrpc;
+       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;
index b90f865478bb5800af600abff647722713cb6f2a..5646276364204a0ce519c50944799a9010f8a1c4 100644 (file)
@@ -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;