]> granicus.if.org Git - libevent/commitdiff
support removing of http callbacks and removing of registered RPCs
authorNiels Provos <provos@gmail.com>
Wed, 23 May 2007 05:20:59 +0000 (05:20 +0000)
committerNiels Provos <provos@gmail.com>
Wed, 23 May 2007 05:20:59 +0000 (05:20 +0000)
svn:r355

buffer.c
evhttp.h
evrpc.c
evrpc.h
http.c
test/regress_rpc.c

index 53c0bf8cb2f604ce9aa39887a61d2be2ea5b1887..6b558a833bd09fb956ad6d5cda4f627207c4980a 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -44,6 +44,7 @@
 #include <sys/ioctl.h>
 #endif
 
+#include <assert.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -134,9 +135,13 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
        int sz;
        va_list aq;
 
+       /* make sure that at least some space is available */
+       evbuffer_expand(buf, 64);
        for (;;) {
+               size_t used = buf->misalign + buf->off;
                buffer = (char *)buf->buffer + buf->off;
-               space = buf->totallen - buf->misalign - buf->off;
+               assert(buf->totallen >= used);
+               space = buf->totallen - used;
 
 #ifndef va_copy
 #define        va_copy(dst, src)       memcpy(&(dst), &(src), sizeof(va_list))
@@ -152,7 +157,7 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
 
                va_end(aq);
 
-               if (sz == -1)
+               if (sz < 0)
                        return (-1);
                if (sz < space) {
                        buf->off += sz;
index 3477b763945d40773e16e296720259647a100f1d..16744163dbb17d58f77500fc42b7a6b52ed5dd5c 100644 (file)
--- a/evhttp.h
+++ b/evhttp.h
@@ -75,6 +75,9 @@ void evhttp_free(struct evhttp* http);
 void evhttp_set_cb(struct evhttp *, const char *,
     void (*)(struct evhttp_request *, void *), void *);
 
+/* Removes the callback for a specified URI */
+int evhttp_del_cb(struct evhttp *, const char *);
+
 /* Set a callback for all requests that are not caught by specific callbacks */
 void evhttp_set_gencb(struct evhttp *,
     void (*)(struct evhttp_request *, void *), void *);
diff --git a/evrpc.c b/evrpc.c
index d575cd14adad88a621a78481f3a21a031a11a899..0d3e014dad5d3c57a296d8f796297859ab427b30 100644 (file)
--- a/evrpc.c
+++ b/evrpc.c
@@ -133,6 +133,35 @@ evrpc_register_rpc(struct evrpc_base *base, struct evrpc *rpc,
        return (0);
 }
 
+int
+evrpc_unregister_rpc(struct evrpc_base *base, const char *name)
+{
+       char *registered_uri = NULL;
+       struct evrpc *rpc;
+
+       /* find the right rpc; linear search might be slow */
+       TAILQ_FOREACH(rpc, &base->registered_rpcs, next) {
+               if (strcmp(rpc->uri, name) == 0)
+                       break;
+       }
+       if (rpc == NULL) {
+               /* We did not find an RPC with this name */
+               return (-1);
+       }
+       TAILQ_REMOVE(&base->registered_rpcs, rpc, next);
+       
+       free((char *)rpc->uri);
+       free(rpc);
+
+        registered_uri = evrpc_construct_uri(name);
+
+       /* remove the http server callback */
+       assert(evhttp_del_cb(base->http_server, registered_uri) == 0);
+
+       free(registered_uri);
+       return (0);
+}
+
 static void
 evrpc_request_cb(struct evhttp_request *req, void *arg)
 {
diff --git a/evrpc.h b/evrpc.h
index fc452623608bd646505f3c1854ca6aef7cf84186..5ec5ff84c57057745d741d071aeec59192d29cb7 100644 (file)
--- a/evrpc.h
+++ b/evrpc.h
@@ -223,6 +223,11 @@ struct evrpc_base *evrpc_init(struct evhttp *server);
 int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
     void (*)(struct evrpc_req_generic*, void *), void *);
 
+/* Takes the named RPCs and tried to unregister it */
+#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc(base, #name)
+
+int evrpc_unregister_rpc(struct evrpc_base *, const char *name);
+
 /*
  * Client-side RPC support
  */
diff --git a/http.c b/http.c
index 20ab464169b37bf19eb930c2a01b398ab3d08123..e69c33a5ff1294a97c5782b14c8786b9ddab1bc8 100644 (file)
--- a/http.c
+++ b/http.c
@@ -1976,6 +1976,25 @@ evhttp_set_cb(struct evhttp *http, const char *uri,
        TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
 }
 
+int
+evhttp_del_cb(struct evhttp *http, const char *uri)
+{
+       struct evhttp_cb *http_cb;
+
+       TAILQ_FOREACH(http_cb, &http->callbacks, next) {
+               if (strcmp(http_cb->what, uri) == 0)
+                       break;
+       }
+       if (http_cb == NULL)
+               return (-1);
+
+       TAILQ_REMOVE(&http->callbacks, http_cb, next);
+       free(http_cb->what);
+       free(http_cb);
+
+       return (0);
+}
+
 void
 evhttp_set_gencb(struct evhttp *http,
     void (*cb)(struct evhttp_request *, void *), void *cbarg)
index dcae9c9e092d6eae5f74d2a0b35a758c76c1d1c2..7a346ac4c9f971c67f4123e7d361c5e858c1d7cc 100644 (file)
@@ -128,6 +128,13 @@ rpc_setup(struct evhttp **phttp, short *pport, struct evrpc_base **pbase)
        *pbase = base;
 }
 
+static void
+rpc_teardown(struct evrpc_base *base)
+{
+       assert(EVRPC_UNREGISTER(base, Message) == 0);
+       assert(EVRPC_UNREGISTER(base, NeverReply) == 0);
+}
+
 static void
 rpc_postrequest_failure(struct evhttp_request *req, void *arg)
 {
@@ -189,6 +196,8 @@ rpc_basic_test(void)
        test_ok = 0;
 
        event_dispatch();
+
+       rpc_teardown(base);
        
        if (test_ok != 1) {
                fprintf(stdout, "FAILED\n");
@@ -276,6 +285,8 @@ rpc_basic_message(void)
 
        event_dispatch();
        
+       rpc_teardown(base);
+       
        if (test_ok != 1) {
                fprintf(stdout, "FAILED\n");
                exit(1);
@@ -399,6 +410,8 @@ rpc_basic_client(void)
 
        event_dispatch();
        
+       rpc_teardown(base);
+       
        if (test_ok != 2) {
                fprintf(stdout, "FAILED (2)\n");
                exit(1);
@@ -448,6 +461,8 @@ rpc_basic_queued_client(void)
 
        event_dispatch();
        
+       rpc_teardown(base);
+       
        if (test_ok != 2) {
                fprintf(stdout, "FAILED (1)\n");
                exit(1);
@@ -508,6 +523,8 @@ rpc_client_timeout(void)
 
        event_dispatch();
        
+       rpc_teardown(base);
+       
        if (test_ok != 2) {
                fprintf(stdout, "FAILED (1)\n");
                exit(1);