static int initiate_socket_connection()

in adapters/socketio_berkeley.c [514:637]


static int initiate_socket_connection(SOCKET_IO_INSTANCE* socket_io_instance)
{
    int result;
    int flags;
    struct addrinfo* addr = NULL;
    struct sockaddr_un addrInfoUn;

    if(socket_io_instance->address_type == ADDRESS_TYPE_IP)
    {
        if(!dns_resolver_is_lookup_complete(socket_io_instance->dns_resolver))
        {
            LogError("DNS did not resolve hostname IP address. Hostname:%s", socket_io_instance->hostname);
            result = MU_FAILURE;
        }
        else
        {
            addr = dns_resolver_get_addrInfo(socket_io_instance->dns_resolver);

            if (addr == NULL)
            {
                LogError("DNS resolution failed. Hostname:%s", socket_io_instance->hostname);
                result = MU_FAILURE;
            } 
            else 
            {
                result = 0;
            }
        }
    }
    else
    {
        if (socket_io_instance->hostname != NULL)
        {
            size_t hostname_len = strlen(socket_io_instance->hostname);
            if (hostname_len + 1 > sizeof(addrInfoUn.sun_path))
            {
                LogError("Hostname %s is too long for a unix socket (max len = %lu)", socket_io_instance->hostname, (unsigned long)sizeof(addrInfoUn.sun_path));
                result = MU_FAILURE;
            }
            else
            {
                memset(&addrInfoUn, 0, sizeof(addrInfoUn));
                addrInfoUn.sun_family = AF_UNIX;
                // No need to add NULL terminator due to the above memset
                (void)memcpy(addrInfoUn.sun_path, socket_io_instance->hostname, hostname_len);
                result = 0;
            }
        }
        else
        {
            LogError("Hostname is NULL");
            result = MU_FAILURE;
        }
    }

    if(result == 0)
    {
        if (socket_io_instance->address_type == ADDRESS_TYPE_IP)
        {
            socket_io_instance->socket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
        }
        else
        {
            socket_io_instance->socket = socket(AF_UNIX, SOCK_STREAM, 0);
        }

        if (socket_io_instance->socket < SOCKET_SUCCESS)
        {
            LogError("Failure: socket create failure %d.", socket_io_instance->socket);
            result = MU_FAILURE;
        }
        #ifndef __APPLE__
        else if (socket_io_instance->target_mac_address != NULL &&
                    set_target_network_interface(socket_io_instance->socket, socket_io_instance->target_mac_address) != 0)
        {
            LogError("Failure: failed selecting target network interface (MACADDR=%s).", socket_io_instance->target_mac_address);
            result = MU_FAILURE;
        }
        #endif //__APPLE__
        else if ((-1 == (flags = fcntl(socket_io_instance->socket, F_GETFL, 0))) ||
            (fcntl(socket_io_instance->socket, F_SETFL, flags | O_NONBLOCK) == -1))
        {
            LogError("Failure: fcntl failure.");
            result = MU_FAILURE;
        }
        else
        {
            if (socket_io_instance->address_type == ADDRESS_TYPE_IP)
            {
                result = connect(socket_io_instance->socket, addr->ai_addr, addr->ai_addrlen);
            }
            else
            {
                result = connect(socket_io_instance->socket, (struct sockaddr *)&addrInfoUn, sizeof(addrInfoUn));
            }

            if ((result != 0) && (errno != EINPROGRESS))
            {
                LogError("Failure: connect failure %d.", errno);
                result = MU_FAILURE;
            }
            else  // result == 0 || errno == EINPROGRESS
            {
                // Async connect will return -1.
                result = 0;
                if (socket_io_instance->on_io_open_complete != NULL)
                {
                    socket_io_instance->on_io_open_complete(socket_io_instance->on_io_open_complete_context, IO_OPEN_OK /*: IO_OPEN_ERROR*/);
                }
            }
        }

        if (result != 0)
        {
            if (socket_io_instance->socket >= SOCKET_SUCCESS)
            {
                close(socket_io_instance->socket);
            }
            socket_io_instance->socket = INVALID_SOCKET;
        }
    }

    return result;
}