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;
}
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;
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;
}
#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)
{
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;
/* 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) \
#define EVUTIL_ERR_ACCEPT_RETRIABLE(e) \
EVUTIL_ERR_RW_RETRIABLE(e)
+#define EVUTIL_ERR_CONNECT_REFUSED(e) \
+ ((e) == WSAECONNREFUSED)
+
#endif
#ifdef _EVENT_socklen_t