Add evhttp callback for bufferevent creation; this lets evhttp support SSL.

Based on a patch uploaded anonymously to sourceforge; cleaned up
by Graham Leggett to work with current libevents.
This commit is contained in:
Nick Mathewson 2011-09-12 10:46:17 -04:00
parent caf133f901
commit 8d3a8500f4
3 changed files with 87 additions and 14 deletions

View 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;
};

49
http.c
View File

@ -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)

View 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