mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 04:50:37 -04:00
deal with connect() failing immediately
This commit is contained in:
parent
98edb891f8
commit
7bc48bfd3a
@ -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;
|
||||
|
@ -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;
|
||||
|
4
evutil.c
4
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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user