rb_connect: use SO_ERROR
This commit is contained in:
parent
9caecc9348
commit
589dbf4d0f
1 changed files with 42 additions and 34 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue