PRBool Resolver :: process(DNSSession* session)
{    
    PR_AtomicIncrement(&curlookups);
    PRBool locstatus = PR_FALSE;

    char host[MAXDNAME];
    resinfo_t resi;
    resinfo_t* rp = &resi;
    struct hostent* hp = NULL;
    PRInt32 rv = 0;
    int querytype = 0;

    if (session)
    {
        session->setStatus(DNS_IN_PROCESS);

        if (FORWARD_LOOKUP == session->getQType ())
        {   
            PR_AtomicIncrement(&namelookups);
    
            memset((char *)rp, 0, sizeof(resi));
            ar_reinfo.re_na_look++;
            strncpy(host, session->getName(), 64);
            host[64] = '\0';
    
            locstatus = PR_TRUE;
            switch(session->getFamily())
            {
                case PR_AF_INET:
                    querytype = T_A;
                    break;
                case PR_AF_INET6:
                    querytype = T_AAAA;
                    break;
                default:
                    locstatus = PR_FALSE;
            }
    
            // Makes and sends the query
            // the session gets automatically added to the hash table
            if (PR_TRUE == locstatus)
            {
                if (do_query_name(rp, host, session, querytype) == -1)
                {
                    PR_SetError(PR_BAD_ADDRESS_ERROR, 0);
                    locstatus = PR_FALSE;
                }
            }
        }

        else

        if (REVERSE_LOOKUP == session->getQType ())
        {
            PR_AtomicIncrement(&addrlookups);

            memset((char *)rp, 0, sizeof(resi));
            ar_reinfo.re_na_look++;
            const PRNetAddr* addrp = session->getIP();

            locstatus = PR_TRUE;
            switch(addrp->raw.family)
            {
                case PR_AF_INET: 
                    rv = do_query_number(rp, (char *) &addrp->inet.ip, session, PR_AF_INET);
                    break;
                case PR_AF_INET6: 
                    rv = do_query_number(rp, (char *) &addrp->ipv6.ip, session, PR_AF_INET6);
                    break;
                default:
                    locstatus = PR_FALSE;
                    PR_SetError(PR_BAD_ADDRESS_ERROR, 0);
                    break;
            }
            if (-1 == rv)
            {
                locstatus = PR_FALSE;
            }
        }
    }

    if (PR_TRUE == locstatus)
    {
        locstatus = PR_FALSE;
        int resend;

        do {
            resend = 0;

            session->wait();
        
            if (DNS_COMPLETED == session->getStatus() )
            {
                // Process answer and return meaningful data to caller.
    
                if (FORWARD_LOOKUP == session->getQType())
                {
                    if ((hp = ar_answer(session, &resend, NULL, 0)) != NULL)
                    {
                        PRInt32 rv = CopyHostent(session->getHentp(), hp,
                                                 session->getBuffer(),
                                                 session->getBufferSize());
                        if (rv != PR_AR_OK)
                            PR_SetError(rv, 0);
                        else
                            locstatus = PR_TRUE;
                    }
                }
                else
                if (REVERSE_LOOKUP == session->getQType())
                {
                    if (hp = ar_answer(session, &resend, NULL, 0))
                    {
                        PRInt32 rv = CopyHostent(session->getHentp(), hp,
                                                 session->getBuffer(),
                                                 session->getBufferSize());
                        if (rv != PR_AR_OK)
                            PR_SetError(rv, 0);
                        else
                            locstatus = PR_TRUE;
                    }
                }
            }
            else
            if (DNS_TIMED_OUT == session->getStatus())
            {
                PR_SetError(PR_IO_TIMEOUT_ERROR, 0);                
            }
            else
            {
                PR_SetError(PR_BAD_ADDRESS_ERROR, 0);
            }
        } while (resend);
    }

    PR_AtomicDecrement(&curlookups);
    return locstatus;
}
// ****************************************************************************
//  Method:  Connect
//
//  Purpose:
//    given a host and a port, connect to it and return the new fd
//
//  Programmer:  Jeremy Meredith
//  Creation:    May 24, 2007
//
// ****************************************************************************
static int
Connect(const char *host, int port)
{
#if defined(_WIN32)
    // Create a copy of the hostent struct in case other WinSock
    // functions want to modify it.
    void *hostInfo = (void *)CopyHostent(gethostbyname(host));
#else
    void *hostInfo = (void *)gethostbyname(host);
#endif

    int                connectedSock;
    struct hostent     *hp;
    struct sockaddr_in server;

    //
    // Set up the structures for opening the sockets.
    //
    hp = (struct hostent *)hostInfo;
    if (hp == NULL)
        return -1;
    memset(&server, 0, sizeof(server));
    memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
    server.sin_family = hp->h_addrtype;
    server.sin_port = htons(port);
    
    // 
    // Create a socket.
    // 
#if defined(_WIN32)
    connectedSock = socket(AF_INET, SOCK_STREAM, 0);
    if (connectedSock == INVALID_SOCKET)
    {
        return -1;
    }

    // Disable the Nagle algorithm 
    int opt = 1;
    setsockopt(connectedSock, IPPROTO_TCP, TCP_NODELAY,
               (const char FAR *)&opt, sizeof(int));

    if (connect(connectedSock, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
        closesocket(connectedSock);
        return -1;
    }
#else
    connectedSock = socket(AF_INET, SOCK_STREAM, 0);
    if (connectedSock < 0)
    {
        return -1;
    }

    // Disable the Nagle algorithm 
    int opt = 1;
    setsockopt(connectedSock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int));
    if (connect(connectedSock, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
        close(connectedSock);
        return -1;
    }
#endif

    return connectedSock;
}