NS_IMETHODIMP
nsDNSRecord::GetAddresses(nsTArray<NetAddr> & aAddressArray)
{
    if (mDone) {
        return NS_ERROR_NOT_AVAILABLE;
    }

    mHostRecord->addr_info_lock.Lock();
    if (mHostRecord->addr_info) {
        for (NetAddrElement *iter = mHostRecord->addr_info->mAddresses.getFirst();
             iter; iter = iter->getNext()) {
            if (mHostRecord->Blacklisted(&iter->mAddress)) {
                continue;
            }
            NetAddr *addr = aAddressArray.AppendElement(NetAddr());
            memcpy(addr, &iter->mAddress, sizeof(NetAddr));
            if (addr->raw.family == AF_INET) {
                addr->inet.port = 0;
            } else if (addr->raw.family == AF_INET6) {
                addr->inet6.port = 0;
            }
        }
        mHostRecord->addr_info_lock.Unlock();
    } else {
        mHostRecord->addr_info_lock.Unlock();

        if (!mHostRecord->addr) {
            return NS_ERROR_NOT_AVAILABLE;
        }
        NetAddr *addr = aAddressArray.AppendElement(NetAddr());
        memcpy(addr, mHostRecord->addr, sizeof(NetAddr));
        if (addr->raw.family == AF_INET) {
            addr->inet.port = 0;
        } else if (addr->raw.family == AF_INET6) {
            addr->inet6.port = 0;
        }
    }
    return NS_OK;
}
示例#2
0
NS_IMETHODIMP
nsDNSRecord::GetNextAddr(PRUint16 port, PRNetAddr *addr)
{
    // not a programming error to poke the DNS record when it has no more
    // entries.  just fail without any debug warnings.  this enables consumers
    // to enumerate the DNS record without calling HasMore.
    if (mDone)
        return NS_ERROR_NOT_AVAILABLE;

    mHostRecord->addr_info_lock.Lock();
    bool startedFresh = !mIter;

    if (mHostRecord->addr_info) {
        if (!mIter)
            mIterGenCnt = mHostRecord->addr_info_gencnt;
        else if (mIterGenCnt != mHostRecord->addr_info_gencnt) {
            // mHostRecord->addr_info has changed, so mIter is invalid.
            // Restart the iteration.  Alternatively, we could just fail.
            mIter = nsnull;
            mIterGenCnt = mHostRecord->addr_info_gencnt;
            startedFresh = true;
        }

        do {
            mLastIter = mIter;
            mIter = PR_EnumerateAddrInfo(mIter, mHostRecord->addr_info,
                                         port, addr);
        }
        while (mIter && mHostRecord->Blacklisted(addr));

        if (startedFresh && !mIter) {
            // if everything was blacklisted we want to reset the blacklist (and
            // likely relearn it) and return the first address. That is better
            // than nothing
            mHostRecord->ResetBlacklist();
            mLastIter = nsnull;
            mIter = PR_EnumerateAddrInfo(nsnull, mHostRecord->addr_info,
                                         port, addr);
        }
            
        mHostRecord->addr_info_lock.Unlock();
        if (!mIter) {
            mDone = true;
            return NS_ERROR_NOT_AVAILABLE;
        }
    }
    else {
        mHostRecord->addr_info_lock.Unlock();
        if (!mHostRecord->addr) {
            // Both mHostRecord->addr_info and mHostRecord->addr are null.
            // This can happen if mHostRecord->addr_info expired and the
            // attempt to reresolve it failed.
            return NS_ERROR_NOT_AVAILABLE;
        }
        memcpy(addr, mHostRecord->addr, sizeof(PRNetAddr));
        // set given port
        port = PR_htons(port);
        if (addr->raw.family == PR_AF_INET)
            addr->inet.port = port;
        else
            addr->ipv6.port = port;
        mDone = true; // no iterations
    }
        
    return NS_OK; 
}
示例#3
0
NS_IMETHODIMP
nsDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
{
    if (mDone) {
        return NS_ERROR_NOT_AVAILABLE;
    }

    mHostRecord->addr_info_lock.Lock();
    if (mHostRecord->addr_info) {
        if (mIterGenCnt != mHostRecord->addr_info_gencnt) {
            // mHostRecord->addr_info has changed, restart the iteration.
            mIter = nullptr;
            mIterGenCnt = mHostRecord->addr_info_gencnt;
        }

        bool startedFresh = !mIter;

        do {
            if (!mIter) {
                mIter = mHostRecord->addr_info->mAddresses.getFirst();
            } else {
                mIter = mIter->getNext();
            }
        }
        while (mIter && mHostRecord->Blacklisted(&mIter->mAddress));

        if (!mIter && startedFresh) {
            // If everything was blacklisted we want to reset the blacklist (and
            // likely relearn it) and return the first address. That is better
            // than nothing.
            mHostRecord->ResetBlacklist();
            mIter = mHostRecord->addr_info->mAddresses.getFirst();
        }

        if (mIter) {
            memcpy(addr, &mIter->mAddress, sizeof(NetAddr));
        }

        mHostRecord->addr_info_lock.Unlock();

        if (!mIter) {
            mDone = true;
            return NS_ERROR_NOT_AVAILABLE;
        }
    }
    else {
        mHostRecord->addr_info_lock.Unlock();

        if (!mHostRecord->addr) {
            // Both mHostRecord->addr_info and mHostRecord->addr are null.
            // This can happen if mHostRecord->addr_info expired and the
            // attempt to reresolve it failed.
            return NS_ERROR_NOT_AVAILABLE;
        }
        memcpy(addr, mHostRecord->addr, sizeof(NetAddr));
        mDone = true;
    }

    // set given port
    port = htons(port);
    if (addr->raw.family == AF_INET) {
        addr->inet.port = port;
    }
    else if (addr->raw.family == AF_INET6) {
        addr->inet6.port = port;
    }

    return NS_OK;
}