Ejemplo n.º 1
0
void SocketStreamHandle::addCONNECTCredentials(CFHTTPMessageRef proxyResponse)
{
    RetainPtr<CFHTTPAuthenticationRef> authentication(AdoptCF, CFHTTPAuthenticationCreateFromResponse(0, proxyResponse));

    if (!CFHTTPAuthenticationRequiresUserNameAndPassword(authentication.get())) {
        // That's all we can offer...
        m_client->didFail(this, SocketStreamError()); // FIXME: Provide a sensible error.
        return;
    }

    int port = 0;
    CFNumberGetValue(m_proxyPort.get(), kCFNumberIntType, &port);
    RetainPtr<CFStringRef> methodCF(AdoptCF, CFHTTPAuthenticationCopyMethod(authentication.get()));
    RetainPtr<CFStringRef> realmCF(AdoptCF, CFHTTPAuthenticationCopyRealm(authentication.get()));
    ProtectionSpace protectionSpace(String(m_proxyHost.get()), port, ProtectionSpaceProxyHTTPS, String(realmCF.get()), authenticationSchemeFromAuthenticationMethod(methodCF.get()));
    String login;
    String password;
    if (!m_sentStoredCredentials && getStoredCONNECTProxyCredentials(protectionSpace, login, password)) {
        // Try to apply stored credentials, if we haven't tried those already.
        RetainPtr<CFStringRef> loginCF(AdoptCF, login.createCFString());
        RetainPtr<CFStringRef> passwordCF(AdoptCF, password.createCFString());
        // Creating a temporary request to make CFNetwork apply credentials to it. Unfortunately, this cannot work with NTLM authentication.
        RetainPtr<CFHTTPMessageRef> dummyRequest(AdoptCF, CFHTTPMessageCreateRequest(0, CFSTR("GET"), m_httpsURL.get(), kCFHTTPVersion1_1));

        Boolean appliedCredentials = CFHTTPMessageApplyCredentials(dummyRequest.get(), authentication.get(), loginCF.get(), passwordCF.get(), 0);
        ASSERT_UNUSED(appliedCredentials, appliedCredentials);

        RetainPtr<CFStringRef> proxyAuthorizationString(AdoptCF, CFHTTPMessageCopyHeaderFieldValue(dummyRequest.get(), CFSTR("Proxy-Authorization")));

        if (!proxyAuthorizationString) {
            // Fails e.g. for NTLM auth.
            m_client->didFail(this, SocketStreamError()); // FIXME: Provide a sensible error.
            return;
        }

        // Setting the authorization results in a new connection attempt.
        wkSetCONNECTProxyAuthorizationForStream(m_readStream.get(), proxyAuthorizationString.get());
        m_sentStoredCredentials = true;
        return;
    }

    // FIXME: Ask the client if credentials could not be found.

    m_client->didFail(this, SocketStreamError()); // FIXME: Provide a sensible error.
}
Ejemplo n.º 2
0
bool RChannelReaderImpl::FetchNextItemArray(UInt32 maxArraySize,
                                            RChannelItemArrayRef* pItemArray,
                                            DrTimeInterval csTimeOut)
{
    ChannelProcessRequestList requestList;
    ChannelUnitList returnUnitList;
    DryadHandleListEntry* event = NULL;
    bool timedOut = false;
    bool mustBlock = false;
    bool startSupplier = false;

    {
        AutoCriticalSection acs(&m_baseDR);

        if (m_state != RS_Running)
        {
            LogAssert(m_state != RS_Closed);
            /* return an empty array */
            pItemArray->Attach(new RChannelItemArray());
            return true;
        }

        if (!m_unitList.IsEmpty())
        {
            LogAssert(m_startedSupplier == true);
            LogAssert(m_handlerList.IsEmpty());

            RChannelReaderSyncWaiter dummyHandler(NULL,
                                                  INVALID_HANDLE_VALUE,
                                                  NULL);
            dummyHandler.SetMaximumArraySize(maxArraySize);
            RChannelProcessRequest dummyRequest(NULL, &dummyHandler, NULL);
            m_handlerList.InsertAsTail(m_handlerList.CastIn(&dummyRequest));

            TransferWaitingItems("FetchNextItemArray",
                                 &requestList, &returnUnitList);

            RChannelProcessRequest* dummyReturn =
                requestList.CastOut(requestList.RemoveHead());
            LogAssert(dummyReturn == &dummyRequest);

            pItemArray->Set(dummyRequest.GetItemArray());
            LogAssert((*pItemArray)->GetNumberOfItems() > 0);
        }
        else if (m_writerTerminationItem != NULL ||
                 m_readerTerminationItem != NULL)
        {
            /* we have already sent a termination item for processing
               so there aren't going to be any more arriving on the
               queue and we can return an empty list immediately */
            pItemArray->Attach(new RChannelItemArray());
        }
        else if (csTimeOut > DrTimeInterval_Zero)
        {
            if (m_startedSupplier == false)
            {
                /* when we exit the lock, we will start the supplier
                   since this is the first read we have
                   received. After the supplier has been started we'll
                   set m_startedSupplierEvent to prevent a race
                   condition in Interrupt */
                startSupplier = true;
                BOOL bRet = ::ResetEvent(m_startedSupplierEvent);
                LogAssert(bRet != 0);
                m_startedSupplier = true;
            }

            /* we are going to block */
            mustBlock = true;
            event = m_eventCache.GetEvent(true);
        }
        else
        {
            /* there's no item available and a zero timeout --- return
               an empty list immediately */
            pItemArray->Attach(new RChannelItemArray());
            LogAssert(csTimeOut == DrTimeInterval_Zero);
            timedOut = true;
        }

        m_unitLatch.AcceptList(&returnUnitList);
        FOO(&requestList);
        m_sendLatch.AcceptList(&requestList);
    }

    if (startSupplier)
    {
//         DrLogI( "Starting Supplier");
        m_supplier->StartSupplier(m_prefetchCookie);
//         DrLogI( "Started Supplier");
        BOOL bRet = ::SetEvent(m_startedSupplierEvent);
        LogAssert(bRet != 0);
    }

    DispatchRequests("FetchNextItemArray", &requestList, &returnUnitList);

    if (mustBlock == false)
    {
        LogAssert(event == NULL);
    }
    else
    {
        LogAssert(event != NULL);

        *pItemArray = NULL;

        RChannelReaderSyncWaiter* waiter =
            new RChannelReaderSyncWaiter(this, event->GetHandle(), pItemArray);
        this->SupplyHandler(waiter, waiter);

        DWORD timeOut = DrGetTimerMsFromInterval(csTimeOut);
        DWORD dRet = ::WaitForSingleObject(event->GetHandle(), timeOut);

        if (dRet == WAIT_TIMEOUT)
        {
            /* when cancel returns it's guaranteed the handler has
               been called */
            this->Cancel(waiter);
        }
        else
        {
            LogAssert(dRet == WAIT_OBJECT_0);
        }

        LogAssert(*pItemArray != NULL);

        delete waiter;

        {
            AutoCriticalSection acs(&m_baseDR);

            /* save this event in case we need one again in the
               future */
            m_eventCache.ReturnEvent(event);

            /* even if we actually timed out the wait, the handler may
               have supplied an item immediately afterwards or during
               the cancel. We only return a timed out value if there's
               no item ready but we haven't processed a termination
               item, so it's worth waiting for another one. */
            timedOut = ((*pItemArray)->GetNumberOfItems() == 0 &&
                        m_writerTerminationItem == NULL &&
                        m_readerTerminationItem == NULL);
        }
    }

    return (!timedOut);
}