mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-12 05:48:51 -04:00
Allow http connections to use evdns for hostname looksups.
This was as simple as using bufferevent_connect_hostname instead of calling connect() ourself, which already knows how to use an evdns_base if it gets one. Untangling the bind code might be a little trickier.
This commit is contained in:
parent
a334b31c6f
commit
c698b77d19
@ -97,6 +97,7 @@ struct evhttp_connection {
|
||||
void *closecb_arg;
|
||||
|
||||
struct event_base *base;
|
||||
struct evdns_base *dns_base;
|
||||
};
|
||||
|
||||
struct evhttp_cb {
|
||||
|
77
http.c
77
http.c
@ -155,7 +155,6 @@ fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
|
||||
|
||||
extern int debug;
|
||||
|
||||
static int socket_connect(evutil_socket_t kefd, const char *address, unsigned short port);
|
||||
static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
|
||||
static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
|
||||
static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
|
||||
@ -1149,16 +1148,26 @@ evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
|
||||
}
|
||||
|
||||
/*
|
||||
* Call back for asynchronous connection attempt.
|
||||
* Event callback for asynchronous connection attempt.
|
||||
*/
|
||||
|
||||
static void
|
||||
evhttp_connection_cb(struct bufferevent *bufev, void *arg)
|
||||
evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
|
||||
{
|
||||
struct evhttp_connection *evcon = arg;
|
||||
int error;
|
||||
ev_socklen_t errsz = sizeof(error);
|
||||
|
||||
if (!(what & BEV_EVENT_CONNECTED)) {
|
||||
/* some operating systems return ECONNREFUSED immediately
|
||||
* when connecting to a local address. the cleanup is going
|
||||
* to reschedule this function call.
|
||||
*/
|
||||
if (errno == ECONNREFUSED)
|
||||
goto cleanup;
|
||||
evhttp_error_cb(bufev, what, arg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if the connection completed */
|
||||
if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
|
||||
&errsz) == -1) {
|
||||
@ -1784,6 +1793,14 @@ evhttp_connection_base_new(struct event_base *base,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
evhttp_connection_set_evdns_base(struct evhttp_connection *evcon,
|
||||
struct evdns_base *base)
|
||||
{
|
||||
EVUTIL_ASSERT(evcon->dns_base == NULL);
|
||||
evcon->dns_base = base;
|
||||
}
|
||||
|
||||
void
|
||||
evhttp_connection_set_base(struct evhttp_connection *evcon,
|
||||
struct event_base *base)
|
||||
@ -1850,7 +1867,20 @@ evhttp_connection_connect(struct evhttp_connection *evcon)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (socket_connect(evcon->fd, evcon->address, evcon->port) == -1) {
|
||||
/* Set up a callback for successful connection setup */
|
||||
bufferevent_setfd(evcon->bufev, evcon->fd);
|
||||
bufferevent_setcb(evcon->bufev,
|
||||
NULL /* evhttp_read_cb */,
|
||||
NULL /* evhttp_write_cb */,
|
||||
evhttp_connection_cb,
|
||||
evcon);
|
||||
bufferevent_settimeout(evcon->bufev, 0,
|
||||
evcon->timeout != -1 ? evcon->timeout : HTTP_CONNECT_TIMEOUT);
|
||||
/* make sure that we get a write callback */
|
||||
bufferevent_enable(evcon->bufev, EV_WRITE);
|
||||
|
||||
if (bufferevent_socket_connect_hostname(evcon->bufev, evcon->dns_base,
|
||||
AF_UNSPEC, evcon->address, evcon->port) < 0) {
|
||||
event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
|
||||
__func__, evcon->address);
|
||||
/* some operating systems return ECONNREFUSED immediately
|
||||
@ -1861,17 +1891,6 @@ evhttp_connection_connect(struct evhttp_connection *evcon)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set up a callback for successful connection setup */
|
||||
bufferevent_setfd(evcon->bufev, evcon->fd);
|
||||
bufferevent_setcb(evcon->bufev,
|
||||
NULL /* evhttp_read_cb */,
|
||||
evhttp_connection_cb,
|
||||
evhttp_error_cb, evcon);
|
||||
bufferevent_settimeout(evcon->bufev, 0,
|
||||
evcon->timeout != -1 ? evcon->timeout : HTTP_CONNECT_TIMEOUT);
|
||||
/* make sure that we get a write callback */
|
||||
bufferevent_enable(evcon->bufev, EV_WRITE);
|
||||
|
||||
evcon->state = EVCON_CONNECTING;
|
||||
|
||||
return (0);
|
||||
@ -3114,29 +3133,3 @@ bind_socket(const char *address, ev_uint16_t port, int reuse)
|
||||
return (fd);
|
||||
}
|
||||
|
||||
static int
|
||||
socket_connect(evutil_socket_t fd, const char *address, unsigned short port)
|
||||
{
|
||||
struct evutil_addrinfo *ai = make_addrinfo(address, port);
|
||||
int res = -1;
|
||||
|
||||
if (ai == NULL) {
|
||||
event_debug(("%s: make_addrinfo: \"%s:%d\"",
|
||||
__func__, address, port));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) {
|
||||
int err = evutil_socket_geterror(fd);
|
||||
if (! EVUTIL_ERR_CONNECT_RETRIABLE(err))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* everything is fine */
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
evutil_freeaddrinfo(ai);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
@ -355,12 +355,20 @@ void evhttp_request_free(struct evhttp_request *req);
|
||||
|
||||
/**
|
||||
* A connection object that can be used to for making HTTP requests. The
|
||||
* connection object tries to establish the connection when it is given an
|
||||
* http request object.
|
||||
* connection object tries to resolve address and establish the connection
|
||||
* when it is given an http request object.
|
||||
*/
|
||||
struct evhttp_connection *evhttp_connection_base_new(
|
||||
struct event_base *base, const char *address, unsigned short port);
|
||||
|
||||
struct evdns_base;
|
||||
/**
|
||||
* Tell the connection object to use evdns_base when resolving hostnames.
|
||||
* If no base is set, it will block when resolving hostnames.
|
||||
*/
|
||||
void evhttp_connection_set_evdns_base(struct evhttp_connection *evcon,
|
||||
struct evdns_base *base);
|
||||
|
||||
/** Takes ownership of the request object
|
||||
*
|
||||
* Can be used in a request callback to keep onto the request until
|
||||
|
Loading…
x
Reference in New Issue
Block a user