]> granicus.if.org Git - libevent/commitdiff
Report DNS error when lookup fails during bufferevent_socket_connect_hostname.
authorChristopher Davis <chrisd@mangrin.org>
Sat, 24 Apr 2010 07:06:38 +0000 (00:06 -0700)
committerChristopher Davis <chrisd@mangrin.org>
Sat, 24 Apr 2010 07:06:38 +0000 (00:06 -0700)
bufferevent-internal.h
bufferevent_sock.c
include/event2/bufferevent.h
test/regress_dns.c

index 1b56c4322e9dba4304586b9663810d4b794d4fbd..b46de57c811310b49005c27a9d3b5fbf460f8cd3 100644 (file)
@@ -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;
 
index f621e76dacdde4034b12364d41d059783ecd9cf0..28d36421677991dd1d30954cd08fff03249ffeae 100644 (file)
@@ -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.
  *
index b1d7e43a01958e5e0af8b492b68b9c0d6115192d..9040cba9ddcf40a8c6cc0c8b95d70d2c41834842 100644 (file)
@@ -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.
 
index a9310088e4f66d3ebb1d19f8c3d5bd369eba46f4..329dc80f9b93827eb5a21e1a85c55a0582fca57c 100644 (file)
@@ -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);