int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) { int status; rb_blocking_function_t *func = connect_blocking; struct connect_arg arg; arg.fd = fd; arg.sockaddr = sockaddr; arg.len = len; #if defined(SOCKS) && !defined(SOCKS5) if (socks) func = socks_connect_blocking; #endif status = (int)BLOCKING_REGION_FD(func, &arg); if (status < 0) { switch (errno) { case EINTR: #ifdef ERESTART case ERESTART: #endif case EAGAIN: #ifdef EINPROGRESS case EINPROGRESS: #endif return wait_connectable(fd); } } return status; }
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) { int status; rb_blocking_function_t *func = connect_blocking; struct connect_arg arg; #if WAIT_IN_PROGRESS > 0 int wait_in_progress = -1; int sockerr; socklen_t sockerrlen; #endif arg.fd = fd; arg.sockaddr = sockaddr; arg.len = len; #if defined(SOCKS) && !defined(SOCKS5) if (socks) func = socks_connect_blocking; #endif for (;;) { status = (int)BLOCKING_REGION_FD(func, &arg); if (status < 0) { switch (errno) { case EINTR: #if defined(ERESTART) case ERESTART: #endif continue; case EAGAIN: #ifdef EINPROGRESS case EINPROGRESS: #endif #if WAIT_IN_PROGRESS > 0 sockerrlen = (socklen_t)sizeof(sockerr); status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen); if (status) break; if (sockerr) { status = -1; errno = sockerr; break; } #endif #ifdef EALREADY case EALREADY: #endif #if WAIT_IN_PROGRESS > 0 wait_in_progress = WAIT_IN_PROGRESS; #endif status = wait_connectable(fd); if (status) { break; } errno = 0; continue; #if WAIT_IN_PROGRESS > 0 case EINVAL: if (wait_in_progress-- > 0) { /* * connect() after EINPROGRESS returns EINVAL on * some platforms, need to check true error * status. */ sockerrlen = (socklen_t)sizeof(sockerr); status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen); if (!status && !sockerr) { struct timeval tv = {0, 100000}; rb_thread_wait_for(tv); continue; } status = -1; errno = sockerr; } break; #endif #ifdef EISCONN case EISCONN: status = 0; errno = 0; break; #endif default: break; } } return status; } }