rb_connect: use SO_ERROR

This commit is contained in:
Simon Arlott 2017-08-23 22:15:05 +01:00
parent 9caecc9348
commit 589dbf4d0f
No known key found for this signature in database
GPG key ID: C8975F2043CA5D24

View file

@ -68,7 +68,7 @@ static int number_fd = 0;
int rb_maxconnections = 0; int rb_maxconnections = 0;
static PF rb_connect_timeout; static PF rb_connect_timeout;
static PF rb_connect_tryconnect; static PF rb_connect_outcome;
static void mangle_mapped_sockaddr(struct sockaddr *in); static void mangle_mapped_sockaddr(struct sockaddr *in);
#ifndef HAVE_SOCKETPAIR #ifndef HAVE_SOCKETPAIR
@ -434,7 +434,9 @@ void
rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest, rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest,
struct sockaddr *clocal, CNCB * callback, void *data, int timeout) struct sockaddr *clocal, CNCB * callback, void *data, int timeout)
{ {
if(F == NULL) int retval;
if (F == NULL)
return; return;
lrb_assert(callback); lrb_assert(callback);
@ -462,9 +464,32 @@ rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest,
/* We have a valid IP, so we just call tryconnect */ /* We have a valid IP, so we just call tryconnect */
/* Make sure we actually set the timeout here .. */ /* Make sure we actually set the timeout here .. */
rb_settimeout(F, timeout, rb_connect_timeout, NULL); rb_settimeout(F, timeout, rb_connect_timeout, NULL);
rb_connect_tryconnect(F, NULL);
}
retval = connect(F->fd,
(struct sockaddr *)&F->connect->hostaddr,
GET_SS_LEN(&F->connect->hostaddr));
/* Error? */
if (retval < 0) {
/*
* If we get EISCONN, then we've already connect()ed the socket,
* which is a good thing.
* -- adrian
*/
rb_get_errno();
if (errno == EISCONN) {
rb_connect_callback(F, RB_OK);
} else if (rb_ignore_errno(errno)) {
/* Ignore error? Reschedule */
rb_setselect(F, RB_SELECT_CONNECT, rb_connect_outcome, NULL);
} else {
/* Error? Fail with RB_ERR_CONNECT */
rb_connect_callback(F, RB_ERR_CONNECT);
}
return;
}
/* If we get here, we've succeeded, so call with RB_OK */
rb_connect_callback(F, RB_OK);
}
/* /*
* rb_connect_callback() - call the callback, and continue with life * rb_connect_callback() - call the callback, and continue with life
@ -505,45 +530,28 @@ rb_connect_timeout(rb_fde_t *F, void *notused)
rb_connect_callback(F, RB_ERR_TIMEOUT); rb_connect_callback(F, RB_ERR_TIMEOUT);
} }
/* static void rb_connect_tryconnect(rb_platform_fd_t fd, void *notused)
* Input: The fd, the handler data(unused).
* Output: None.
* Side-effects: Try and connect with pending connect data for the FD. If
* we succeed or get a fatal error, call the callback.
* Otherwise, it is still blocking or something, so register
* to select for a write event on this FD.
*/
static void static void
rb_connect_tryconnect(rb_fde_t *F, void *notused) rb_connect_outcome(rb_fde_t *F, void *notused)
{ {
int retval; int retval;
int err = 0;
socklen_t len = sizeof(err);
if(F == NULL || F->connect == NULL || F->connect->callback == NULL) if(F == NULL || F->connect == NULL || F->connect->callback == NULL)
return; return;
/* Try the connect() */ retval = getsockopt(F->fd, SOL_SOCKET, SO_ERROR, &err, &len);
retval = connect(F->fd, if (retval < 0) {
(struct sockaddr *)&F->connect->hostaddr,
GET_SS_LEN(&F->connect->hostaddr));
/* Error? */
if(retval < 0)
{
/*
* If we get EISCONN, then we've already connect()ed the socket,
* which is a good thing.
* -- adrian
*/
rb_get_errno(); rb_get_errno();
if(errno == EISCONN) } else if (err != 0) {
rb_connect_callback(F, RB_OK); errno = err;
else if(rb_ignore_errno(errno)) retval = -1;
/* Ignore error? Reschedule */ }
rb_setselect(F, RB_SELECT_CONNECT, rb_connect_tryconnect, NULL); if (retval < 0) {
else /* Error? Fail with RB_ERR_CONNECT */
/* Error? Fail with RB_ERR_CONNECT */ rb_connect_callback(F, RB_ERR_CONNECT);
rb_connect_callback(F, RB_ERR_CONNECT);
return; return;
} }
/* If we get here, we've suceeded, so call with RB_OK */ /* If we get here, we've succeeded, so call with RB_OK */
rb_connect_callback(F, RB_OK); rb_connect_callback(F, RB_OK);
} }