Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Report DNS error when lookup fails during bufferevent_socket_connect_…

…hostname.
  • Loading branch information...
commit 0ef407065e5fb98f704b426d1d4fc878a85a391d 1 parent 25c442e
@chris-davis chris-davis authored
View
3  bufferevent-internal.h
@@ -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;
View
24 bufferevent_sock.c
@@ -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.
*
View
10 include/event2/bufferevent.h
@@ -186,6 +186,16 @@ 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.
@param base an event_base returned by event_init()
View
38 test/regress_dns.c
@@ -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);
Please sign in to comment.
Something went wrong with that request. Please try again.