Skip to content

Commit

Permalink
When a bufferevent_connect() call fails, give the client an error cal…
Browse files Browse the repository at this point in the history
…lback.

Patch from Christopher Davis.

svn:r1444
  • Loading branch information
nmathewson committed Oct 14, 2009
1 parent fc83ca3 commit 25af695
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
3 changes: 2 additions & 1 deletion ChangeLog
Expand Up @@ -6,7 +6,7 @@ Changes in 2.0.3-alpha:
o Try to compile better with MSVC: patches from Brodie Thiesfield
o New evconnlistener_get_fd function to expose a listener's associated socket.
o Expose an ev_socklen_t type for consistent use across platforms.
o Make bufferevenr_socket_connect() work when the original fd was -1.
o Make bufferevent_socket_connect() work when the original fd was -1.
o Fix a bug in bufferevent_socket_connect() when the connection succeeds too quickly.
o Export an evutil_sockaddr_cmp() to compare to sockaddr objects for equality.
o Add a bufferevent_get_enabled() to tell what a bufferevent has been configured to do.
Expand All @@ -26,6 +26,7 @@ Changes in 2.0.3-alpha:
o New event_base_got_exit() and event_base_got_break() functions to tell whether an event loop exited because of an event_base_loopexit() or an event_base_loopbreak(). Patch from Ka-Hing Cheung.
o When adding or deleting an event from a non-main thread, only wake up the main thread when its behavior actually needs to change.
o Fix some bugs when using the old evdns interfaces to initialize the evdns module.
o Detect errors during bufferevent_connect(). Patch from Christopher Davis.


Changes in 2.0.2-alpha:
Expand Down
18 changes: 15 additions & 3 deletions bufferevent_sock.c
Expand Up @@ -192,12 +192,24 @@ bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
goto error;
}
if (bufev_p->connecting) {
int c = evutil_socket_finished_connecting(fd);

if (c == 0)
goto done;

bufev_p->connecting = 0;
connected = 1;
_bufferevent_run_eventcb(bufev, BEV_EVENT_CONNECTED);
if (!(bufev->enabled & EV_WRITE)) {
if (c < 0) {
event_del(&bufev->ev_write);
event_del(&bufev->ev_read);
_bufferevent_run_eventcb(bufev, BEV_EVENT_ERROR);
goto done;
} else {
connected = 1;
_bufferevent_run_eventcb(bufev, BEV_EVENT_CONNECTED);
if (!(bufev->enabled & EV_WRITE)) {
event_del(&bufev->ev_write);
goto done;
}
}
}

Expand Down
23 changes: 23 additions & 0 deletions evutil.c
Expand Up @@ -297,6 +297,29 @@ evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen)
return -1;
}

/* Check whether a socket on which we called connect() is done
connecting. Return 1 for connected, 0 for not yet, -1 for error. In the
error case, set the current socket errno to the error that happened during
the connect operation. */
int
evutil_socket_finished_connecting(evutil_socket_t fd)
{
int e;
ev_socklen_t elen = sizeof(e);

if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&e, &elen) < 0)
return -1;

if (e) {
if (EVUTIL_ERR_CONNECT_RETRIABLE(e))
return 0;
EVUTIL_SET_SOCKET_ERROR(e);
return -1;
}

return 1;
}

#ifdef WIN32
#define E(code, s) { code, (s " [" #code " ]") }
static struct { int code; const char *msg; } windows_socket_errors[] = {
Expand Down
2 changes: 2 additions & 0 deletions util-internal.h
Expand Up @@ -130,6 +130,8 @@ extern const char EVUTIL_TOLOWER_TABLE[];

int evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen);

int evutil_socket_finished_connecting(evutil_socket_t fd);

#ifdef __cplusplus
}
#endif
Expand Down

0 comments on commit 25af695

Please sign in to comment.