int CwxSockConnector::connect (CwxSockStream& stream, CwxAddr const& remoteAddr, CwxAddr const& localAddr, CwxTimeouter* timeout, int protocol, bool reuse_addr, CWX_NET_SOCKET_ATTR_FUNC fn, void* fnArg) { if ((stream.getHandle() == CWX_INVALID_HANDLE) && (stream.open(remoteAddr.getType(), SOCK_STREAM, protocol, reuse_addr) == -1)) { return -1; } if (localAddr != CwxAddr::sap_any) { sockaddr *laddr = reinterpret_cast<sockaddr *> (localAddr.getAddr()); int size = localAddr.getSize (); if (::bind (stream.getHandle (), laddr, size) == -1) { CwxErrGuard guard; stream.close (); return -1; } } // Enable non-blocking, if required. if ((timeout != 0) && (stream.setNonblock(true) == -1)) { CwxErrGuard guard; stream.close (); return -1; } if (fn) { if (0 != fn(stream.getHandle(), fnArg)) { CwxErrGuard guard; stream.close(); return -1; } } int result = ::connect (stream.getHandle (), reinterpret_cast<sockaddr *> (remoteAddr.getAddr ()), remoteAddr.getSize ()); if (result == -1 && timeout != 0) { // Check whether the connection is in progress. if (errno == EINPROGRESS || errno == EWOULDBLOCK) { // This expression checks if we were polling. if (*timeout->getTimeout() == CwxTimeValue::ZERO) { errno = EWOULDBLOCK; } // Wait synchronously using timeout. else if (this->complete (stream, 0, timeout) == -1) { } else { return 0; } } } // EISCONN is treated specially since this routine may be used to // check if we are already connected. if (result != -1 || errno == EISCONN) { // Start out with non-blocking disabled on the new_stream. result = stream.setNonblock(false); if (result == -1) { CwxErrGuard guard; stream.close (); } } else if (!(errno == EWOULDBLOCK || errno == ETIMEDOUT)) { CwxErrGuard guard; stream.close (); } return result; }