diff --git a/http-internal.h b/http-internal.h index 05e286ca..e5c1972e 100644 --- a/http-internal.h +++ b/http-internal.h @@ -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 58fef169..d5c51f46 100644 --- 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) diff --git a/include/event2/http.h b/include/event2/http.h index e69ebf9e..936c5163 100644 --- a/include/event2/http.h +++ b/include/event2/http.h @@ -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