mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-12 22:10:12 -04:00
Report DNS error when lookup fails during bufferevent_socket_connect_hostname.
This commit is contained in:
parent
25c442e582
commit
0ef407065e
@ -165,6 +165,9 @@ struct bufferevent_private {
|
||||
* an events callback is pending. */
|
||||
int errno_pending;
|
||||
|
||||
/** The DNS error code for bufferevent_socket_connect_hostname */
|
||||
int dns_error;
|
||||
|
||||
/** Used to implement deferred callbacks */
|
||||
struct deferred_cb deferred;
|
||||
|
||||
|
@ -431,6 +431,8 @@ bufferevent_connect_getaddrinfo_cb(int result, struct evutil_addrinfo *ai,
|
||||
void *arg)
|
||||
{
|
||||
struct bufferevent *bev = arg;
|
||||
struct bufferevent_private *bev_p =
|
||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||
int r;
|
||||
BEV_LOCK(bev);
|
||||
|
||||
@ -438,7 +440,7 @@ bufferevent_connect_getaddrinfo_cb(int result, struct evutil_addrinfo *ai,
|
||||
bufferevent_unsuspend_read(bev, BEV_SUSPEND_LOOKUP);
|
||||
|
||||
if (result != 0) {
|
||||
/* XXX Communicate the error somehow. */
|
||||
bev_p->dns_error = result;
|
||||
_bufferevent_run_eventcb(bev, BEV_EVENT_ERROR);
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
if (ai)
|
||||
@ -459,12 +461,18 @@ bufferevent_socket_connect_hostname(struct bufferevent *bev,
|
||||
char portbuf[10];
|
||||
struct evutil_addrinfo hint;
|
||||
int err;
|
||||
struct bufferevent_private *bev_p =
|
||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||
|
||||
if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC)
|
||||
return -1;
|
||||
if (port < 1 || port > 65535)
|
||||
return -1;
|
||||
|
||||
BEV_LOCK(bev);
|
||||
bev_p->dns_error = 0;
|
||||
BEV_UNLOCK(bev);
|
||||
|
||||
evutil_snprintf(portbuf, sizeof(portbuf), "%d", port);
|
||||
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
@ -488,6 +496,20 @@ bufferevent_socket_connect_hostname(struct bufferevent *bev,
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_socket_get_dns_error(struct bufferevent *bev)
|
||||
{
|
||||
int rv;
|
||||
struct bufferevent_private *bev_p =
|
||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||
|
||||
BEV_LOCK(bev);
|
||||
rv = bev_p->dns_error;
|
||||
BEV_LOCK(bev);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new buffered event object.
|
||||
*
|
||||
|
@ -185,6 +185,16 @@ struct evdns_base;
|
||||
int bufferevent_socket_connect_hostname(struct bufferevent *b,
|
||||
struct evdns_base *, int, const char *, int);
|
||||
|
||||
/**
|
||||
Return the error code for the last failed DNS lookup attempt made by
|
||||
bufferevent_socket_connect_hostname().
|
||||
|
||||
@param bev The bufferevent object.
|
||||
@return DNS error code.
|
||||
@see evutil_gai_strerror()
|
||||
*/
|
||||
int bufferevent_socket_get_dns_error(struct bufferevent *bev);
|
||||
|
||||
/**
|
||||
Assign a bufferevent to a specific event_base.
|
||||
|
||||
|
@ -969,26 +969,37 @@ nil_accept_cb(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *s,
|
||||
/* don't do anything with the socket; let it close when we exit() */
|
||||
}
|
||||
|
||||
struct be_conn_hostname_result {
|
||||
int dnserr;
|
||||
int what;
|
||||
};
|
||||
|
||||
/* Bufferevent event callback for the connect_hostname test: remembers what
|
||||
* event we got. */
|
||||
static void
|
||||
be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
{
|
||||
int *got = ctx;
|
||||
if (!*got) {
|
||||
struct be_conn_hostname_result *got = ctx;
|
||||
if (!got->what) {
|
||||
TT_BLATHER(("Got a bufferevent event %d", what));
|
||||
*got = what;
|
||||
got->what = what;
|
||||
|
||||
if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) {
|
||||
int r;
|
||||
++total_connected_or_failed;
|
||||
TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed));
|
||||
if ((r = bufferevent_socket_get_dns_error(bev))) {
|
||||
got->dnserr = r;
|
||||
TT_BLATHER(("DNS error %d: %s", r,
|
||||
evutil_gai_strerror(r)));
|
||||
}
|
||||
if (total_connected_or_failed >= 5)
|
||||
event_base_loopexit(be_connect_hostname_base,
|
||||
NULL);
|
||||
}
|
||||
} else {
|
||||
TT_FAIL(("Two events on one bufferevent. %d,%d",
|
||||
(int)*got, (int)what));
|
||||
got->what, (int)what));
|
||||
}
|
||||
}
|
||||
|
||||
@ -998,8 +1009,8 @@ test_bufferevent_connect_hostname(void *arg)
|
||||
struct basic_test_data *data = arg;
|
||||
struct evconnlistener *listener = NULL;
|
||||
struct bufferevent *be1=NULL, *be2=NULL, *be3=NULL, *be4=NULL, *be5=NULL;
|
||||
int be1_outcome=0, be2_outcome=0, be3_outcome=0, be4_outcome=0,
|
||||
be5_outcome=0;
|
||||
struct be_conn_hostname_result be1_outcome={0,0}, be2_outcome={0,0},
|
||||
be3_outcome={0,0}, be4_outcome={0,0}, be5_outcome={0,0};
|
||||
struct evdns_base *dns=NULL;
|
||||
struct evdns_server_port *port=NULL;
|
||||
evutil_socket_t server_fd=-1;
|
||||
@ -1072,11 +1083,16 @@ test_bufferevent_connect_hostname(void *arg)
|
||||
|
||||
event_base_dispatch(data->base);
|
||||
|
||||
tt_int_op(be1_outcome, ==, BEV_EVENT_ERROR);
|
||||
tt_int_op(be2_outcome, ==, BEV_EVENT_CONNECTED);
|
||||
tt_int_op(be3_outcome, ==, BEV_EVENT_CONNECTED);
|
||||
tt_int_op(be4_outcome, ==, BEV_EVENT_CONNECTED);
|
||||
tt_int_op(be5_outcome, ==, BEV_EVENT_ERROR);
|
||||
tt_int_op(be1_outcome.what, ==, BEV_EVENT_ERROR);
|
||||
tt_int_op(be1_outcome.dnserr, ==, EVUTIL_EAI_NONAME);
|
||||
tt_int_op(be2_outcome.what, ==, BEV_EVENT_CONNECTED);
|
||||
tt_int_op(be2_outcome.dnserr, ==, 0);
|
||||
tt_int_op(be3_outcome.what, ==, BEV_EVENT_CONNECTED);
|
||||
tt_int_op(be3_outcome.dnserr, ==, 0);
|
||||
tt_int_op(be4_outcome.what, ==, BEV_EVENT_CONNECTED);
|
||||
tt_int_op(be4_outcome.dnserr, ==, 0);
|
||||
tt_int_op(be5_outcome.what, ==, BEV_EVENT_ERROR);
|
||||
tt_int_op(be5_outcome.dnserr, ==, EVUTIL_EAI_NONAME);
|
||||
|
||||
tt_int_op(n_accept, ==, 3);
|
||||
tt_int_op(n_dns, ==, 2);
|
||||
|
Loading…
x
Reference in New Issue
Block a user