|
From: Nick M. <ni...@us...> - 2010-02-28 17:27:05
|
Author: Niels Provos <pr...@fr...>
Date: Sat, 27 Feb 2010 18:59:06 -0800
Subject: deal with connect() failing immediately
Commit: 7bc48bfd3ac61aa4ff118cacb44145c6ecda366e
---
bufferevent-internal.h | 3 +++
bufferevent_sock.c | 16 +++++++++++++++-
evutil.c | 4 +++-
util-internal.h | 11 +++++++++--
4 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/bufferevent-internal.h b/bufferevent-internal.h
index 81cadf1..eac3183 100644
--- a/bufferevent-internal.h
+++ b/bufferevent-internal.h
@@ -137,6 +137,9 @@ struct bufferevent_private {
unsigned writecb_pending : 1;
/** Flag: set if we are currently busy connecting. */
unsigned connecting : 1;
+ /** Flag: set if a connect failed prematurely; this is a hack for
+ * getting around the bufferevent abstraction. */
+ unsigned connection_refused : 1;
/** Set to the events pending if we have deferred callbacks and
* an events callback is pending. */
short eventcb_pending;
diff --git a/bufferevent_sock.c b/bufferevent_sock.c
index 2225a2a..22e7603 100644
--- a/bufferevent_sock.c
+++ b/bufferevent_sock.c
@@ -213,6 +213,12 @@ bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
}
if (bufev_p->connecting) {
int c = evutil_socket_finished_connecting(fd);
+ /* we need to fake the error if the connection was refused
+ * immediately - usually connection to localhost on BSD */
+ if (bufev_p->connection_refused) {
+ bufev_p->connection_refused = 0;
+ c = -1;
+ }
if (c == 0)
goto done;
@@ -395,11 +401,19 @@ bufferevent_socket_connect(struct bufferevent *bev,
result = 0;
goto done;
}
- } else {
+ } if (r == 1) {
/* The connect succeeded already. How very BSD of it. */
result = 0;
bufev_p->connecting = 1;
event_active(&bev->ev_write, EV_WRITE, 1);
+ } else {
+ /* The connect failed already. How very BSD of it. */
+ if (! be_socket_enable(bev, EV_WRITE)) {
+ bufev_p->connection_refused = 1;
+ bufev_p->connecting = 1;
+ result = 0;
+ goto done;
+ }
}
goto done;
diff --git a/evutil.c b/evutil.c
index a4dc2ef..7df0214 100644
--- a/evutil.c
+++ b/evutil.c
@@ -355,7 +355,7 @@ evutil_socket_geterror(evutil_socket_t sock)
}
#endif
-/* 1 for connected, 0 for not yet, -1 for error. */
+/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */
int
evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen)
{
@@ -374,6 +374,8 @@ evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen)
int e = evutil_socket_geterror(*fd_ptr);
if (EVUTIL_ERR_CONNECT_RETRIABLE(e))
return 0;
+ if (EVUTIL_ERR_CONNECT_REFUSED(e))
+ return 2;
goto err;
} else {
return 1;
diff --git a/util-internal.h b/util-internal.h
index 726b693..6fa4bd6 100644
--- a/util-internal.h
+++ b/util-internal.h
@@ -66,13 +66,17 @@ extern "C" {
/* True iff e is an error that means a read/write operation can be retried. */
#define EVUTIL_ERR_RW_RETRIABLE(e) \
((e) == EINTR || (e) == EAGAIN)
-/* True iff e is an error that means an accept can be retried. */
+/* True iff e is an error that means an connect can be retried. */
#define EVUTIL_ERR_CONNECT_RETRIABLE(e) \
((e) == EINTR || (e) == EINPROGRESS)
-/* True iff e is an error that means a connect can be retried. */
+/* True iff e is an error that means a accept can be retried. */
#define EVUTIL_ERR_ACCEPT_RETRIABLE(e) \
((e) == EINTR || (e) == EAGAIN || (e) == ECONNABORTED)
+/* True iff e is an error that means the connection was refused */
+#define EVUTIL_ERR_CONNECT_REFUSED(e) \
+ ((e) == ECONNREFUSED)
+
#else
#define EVUTIL_ERR_RW_RETRIABLE(e) \
@@ -88,6 +92,9 @@ extern "C" {
#define EVUTIL_ERR_ACCEPT_RETRIABLE(e) \
EVUTIL_ERR_RW_RETRIABLE(e)
+#define EVUTIL_ERR_CONNECT_REFUSED(e) \
+ ((e) == WSAECONNREFUSED)
+
#endif
#ifdef _EVENT_socklen_t
--
1.6.3
|