Exemplo n.º 1
0
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;
}