]> granicus.if.org Git - libevent/commitdiff
Add evhttp callback for bufferevent creation; this lets evhttp support SSL.
authorNick Mathewson <nickm@torproject.org>
Mon, 12 Sep 2011 14:46:17 +0000 (10:46 -0400)
committerNick Mathewson <nickm@torproject.org>
Mon, 12 Sep 2011 14:48:35 +0000 (10:48 -0400)
Based on a patch uploaded anonymously to sourceforge; cleaned up
by Graham Leggett to work with current libevents.

http-internal.h
http.c
include/event2/http.h

index 05e286cab5655ba1a12beaf2d4329c0104f43186..e5c1972e67c6b100920ef8285c58195c94fe30b6 100644 (file)
@@ -165,6 +165,8 @@ struct evhttp {
           don't match. */
        void (*gencb)(struct evhttp_request *req, void *);
        void *gencbarg;
+       struct bufferevent* (*bevcb)(struct event_base *, void *);
+       void *bevcbarg;
 
        struct event_base *base;
 };
diff --git a/http.c b/http.c
index 58fef1695a258badec647ea607ec94ddcf6d12cc..d5c51f4662ac9369f1ceed5ff800aa76e1747d47 100644 (file)
--- a/http.c
+++ b/http.c
@@ -1375,6 +1375,7 @@ evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
                evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
        } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
                evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
+       } else if (what == BEV_EVENT_CONNECTED) {
        } else {
                evhttp_connection_fail(evcon, EVCON_HTTP_BUFFER_ERROR);
        }
@@ -2153,7 +2154,7 @@ evhttp_connection_new(const char *address, unsigned short port)
 }
 
 struct evhttp_connection *
-evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
+evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
     const char *address, unsigned short port)
 {
        struct evhttp_connection *evcon = NULL;
@@ -2179,12 +2180,18 @@ evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
                goto error;
        }
 
-       if ((evcon->bufev = bufferevent_new(-1,
-                   evhttp_read_cb,
-                   evhttp_write_cb,
-                   evhttp_error_cb, evcon)) == NULL) {
-               event_warn("%s: bufferevent_new failed", __func__);
-               goto error;
+       if (bev == NULL) {
+               if ((evcon->bufev = bufferevent_new(-1,
+                                       evhttp_read_cb,
+                                       evhttp_write_cb,
+                                       evhttp_error_cb, evcon)) == NULL) {
+                       event_warn("%s: bufferevent_new failed", __func__);
+                       goto error;
+               }
+       }
+       else {
+               bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
+               evcon->bufev = bev;
        }
 
        evcon->state = EVCON_DISCONNECTED;
@@ -2209,6 +2216,18 @@ evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
        return (NULL);
 }
 
+struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
+{
+       return evcon->bufev;
+}
+
+struct evhttp_connection *
+evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
+    const char *address, unsigned short port)
+{
+       return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
+}
+
 void
 evhttp_connection_set_base(struct evhttp_connection *evcon,
     struct event_base *base)
@@ -3562,6 +3581,14 @@ evhttp_set_gencb(struct evhttp *http,
        http->gencbarg = cbarg;
 }
 
+void
+evhttp_set_bevcb(struct evhttp *http,
+    struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
+{
+       http->bevcb = cb;
+       http->bevcbarg = cbarg;
+}
+
 /*
  * Request related functions
  */
@@ -3786,6 +3813,7 @@ evhttp_get_request_connection(
 {
        struct evhttp_connection *evcon;
        char *hostname = NULL, *portname = NULL;
+       struct bufferevent* bev = NULL;
 
        name_from_addr(sa, salen, &hostname, &portname);
        if (hostname == NULL || portname == NULL) {
@@ -3798,8 +3826,11 @@ evhttp_get_request_connection(
                        __func__, hostname, portname, fd));
 
        /* we need a connection object to put the http request on */
-       evcon = evhttp_connection_base_new(
-               http->base, NULL, hostname, atoi(portname));
+       if (http->bevcb != NULL) {
+               bev = (*http->bevcb)(http->base, http->bevcbarg);
+       }
+       evcon = evhttp_connection_base_bufferevent_new(
+               http->base, NULL, bev, hostname, atoi(portname));
        mm_free(hostname);
        mm_free(portname);
        if (evcon == NULL)
index e69ebf9eced0a3feeb09b56702fead80bde7e722..936c5163efd67fb2d4b821a220620338ab8226a2 100644 (file)
@@ -37,6 +37,7 @@ extern "C" {
 /* In case we haven't included the right headers yet. */
 struct evbuffer;
 struct event_base;
+struct bufferevent;
 
 /** @file event2/http.h
  *
@@ -69,6 +70,7 @@ struct evhttp_request;
 struct evkeyvalq;
 struct evhttp_bound_socket;
 struct evconnlistener;
+struct evdns_base;
 
 /**
  * Create a new HTTP server.
@@ -233,6 +235,23 @@ int evhttp_del_cb(struct evhttp *, const char *);
 void evhttp_set_gencb(struct evhttp *http,
     void (*cb)(struct evhttp_request *, void *), void *arg);
 
+/**
+   Set a callback used to create new bufferevents for connections
+   to a given evhttp object.
+
+   You can use this to override the default bufferevent type -- for example,
+   to make this evhttp object use SSL bufferevents rather than unencrypted
+   ones.
+
+   New bufferevents must be allocated with no fd set on them.
+
+   @param http the evhttp server object for which to set the callback
+   @param cb the callback to invoke for incoming connections
+   @param arg an context argument for the callback
+ */
+void evhttp_set_bevcb(struct evhttp *http,
+    struct bufferevent *(*cb)(struct event_base *, void *), void *arg);
+
 /**
    Adds a virtual host to the http server.
 
@@ -397,6 +416,29 @@ enum evhttp_cmd_type {
 /** a request object can represent either a request or a reply */
 enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE };
 
+/**
+ * Create and return a connection object that can be used to for making HTTP
+ * requests.  The connection object tries to resolve address and establish the
+ * connection when it is given an http request object.
+ *
+ * @param base the event_base to use for handling the connection
+ * @param dnsbase the dns_base to use for resolving host names; if not
+ *     specified host name resolution will block.
+ * @param bev a bufferevent to use for connecting to the server; if NULL, a
+ *     socket-based bufferevent will be created.  This buffrevent will be freed
+ *     when the connection closes.  It must have no fd set on it.
+ * @param address the address to which to connect
+ * @param port the port to connect to
+ * @return an evhttp_connection object that can be used for making requests
+ */
+struct evhttp_connection *evhttp_connection_base_bufferevent_new(
+       struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev, const char *address, unsigned short port);
+
+/**
+ * Return the bufferevent that an evhttp_connection is using.
+ */
+struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon);
+
 /**
  * Creates a new request object that needs to be filled in with the request
  * parameters.  The callback is executed when the request completed or an
@@ -418,12 +460,10 @@ void evhttp_request_set_chunked_cb(struct evhttp_request *,
 /** Frees the request object and removes associated events. */
 void evhttp_request_free(struct evhttp_request *req);
 
-struct evdns_base;
-
 /**
- * A connection object that can be used to for making HTTP requests.  The
- * connection object tries to resolve address and establish the connection
- * when it is given an http request object.
+ * Create and return a connection object that can be used to for making HTTP
+ * requests.  The connection object tries to resolve address and establish the
+ * connection when it is given an http request object.
  *
  * @param base the event_base to use for handling the connection
  * @param dnsbase the dns_base to use for resolving host names; if not