SOCKET TickDbImpl::createConnection()

in src/dxapi/native/tickdb/http/tickdb_http.cpp [248:340]


SOCKET TickDbImpl::createConnection(enum TCP::NoDelayMode noDelayMode, bool nothrowOnWrongAddr) const
{
    int result;
    int socketOptionsFlag;

    const char *errMsg = NULL;
    bool noThrow = false;

    struct sockaddr_in local_addr; // , remote_addr;
    struct addrinfo *addr = NULL, *current_addr, hints;
    SOCKET s0 = INVALID_SOCKET;

    ::memset(&local_addr, 0, sizeof(local_addr));

    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    local_addr.sin_port = 0;

    s0 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (!isValidSocket(s0)) {
        SOCKCHECK(-1, "socket() call failed!", false);
    }

    // Enable SO_REUSEADDR
    socketOptionsFlag = 1;
    result = setsockopt(s0, SOL_SOCKET, SO_REUSEADDR, (char *)&socketOptionsFlag, sizeof(socketOptionsFlag));
    SOCKCHECK(result, "setsockopt(SO_REUSEADDR =1) failed!", false);

    result = ::bind(s0, (struct sockaddr *)&local_addr, sizeof(local_addr));
    SOCKCHECK(result, "bind() failed!", false);

    ::memset(&hints, 0, sizeof(hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    result = getaddrinfo(uri.host.c_str(), uri.portString.c_str(), &hints, &addr);
    SOCKCHECK(result, "getaddrinfo() failed!", nothrowOnWrongAddr);
    
    current_addr = addr;
    for (current_addr = addr; current_addr != NULL; current_addr = current_addr->ai_next) {
        // Connect to server.
        result = connect(s0, current_addr->ai_addr, (int)current_addr->ai_addrlen);
        if (SOCKET_ERROR == result) {
            continue;
        }

        break;
    }

    SOCKCHECK(result, "connect() failed!", false);
    freeaddrinfo(addr);
    addr = NULL;

    // Set no-delay mode
    //if (noDelayMode) {
    //    DBGLOG("..setting TCP_NODELAY to 1");
    //}
    socketOptionsFlag = noDelayMode != 0;
    result = setsockopt(s0, IPPROTO_TCP, TCP_NODELAY, (char *)&socketOptionsFlag, sizeof(socketOptionsFlag));

    SOCKCHECK(result, "setsockopt(TCP_NODELAY) failed!", false); // Not a critical error, maybe shouldn't throw

    return s0;

error:

    string out, socketMsg;
    int errorCode;
    socketMsg = last_socket_error(&errorCode, "");
    if (NULL != addr) {
        freeaddrinfo(addr);
        addr = NULL;
    }
       //.append(" / ").append(socketErrMsg))
       ;

    if (isValidSocket(s0)) {
        closesocket(s0);
        s0 = INVALID_SOCKET;
    }

    DBGLOGERR(&out, LOGHDR ": %s (%s) %s", ID, errMsg, uri.full.c_str(), socketMsg.c_str());
    if (!noThrow) {
        throw DxApiImpl::IOStreamException(errorCode, out);
    }
    else {
        return INVALID_SOCKET;
    }
}