Exemplo n.º 1
0
void SocketStreamHandle::writeStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventCanAcceptBytes: {
        // Possibly, a spurious event from CONNECT handshake.
        if (!CFWriteStreamCanAcceptBytes(m_writeStream.get()))
            return;

        if (m_connectingSubstate == WaitingForCredentials)
            break;

        if (m_connectingSubstate == WaitingForConnect) {
            m_connectingSubstate = Connected;
            m_state = Open;

            RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference.
            m_client->didOpen(this);
            break;
        }

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        sendPendingData();
        break;
    }
    case kCFStreamEventErrorOccurred: {
#ifndef BUILDING_ON_TIGER
        RetainPtr<CFErrorRef> error(AdoptCF, CFWriteStreamCopyError(m_writeStream.get()));
        reportErrorToClient(error.get());
#else
        CFStreamError error = CFWriteStreamGetError(m_writeStream.get());
        m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error.
#endif
        break;
    }
    case kCFStreamEventEndEncountered:
        // FIXME: Currently, we handle closing in read callback, but these can come independently (e.g. a server can stop listening, but keep sending data).
        break;
    }
}
void SocketStreamHandle::writeStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventCanAcceptBytes: {
        // Possibly, a spurious event from CONNECT handshake.
        if (!CFWriteStreamCanAcceptBytes(m_writeStream.get()))
            return;

        if (m_connectingSubstate == WaitingForCredentials)
            break;

        if (m_connectingSubstate == WaitingForConnect) {
            m_connectingSubstate = Connected;
            m_state = Open;
            m_client->didOpenSocketStream(this);
            break;
        }

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        sendPendingData();
        break;
    }
    case kCFStreamEventErrorOccurred: {
        RetainPtr<CFErrorRef> error(AdoptCF, CFWriteStreamCopyError(m_writeStream.get()));
        reportErrorToClient(error.get());
        break;
    }
    case kCFStreamEventEndEncountered:
        // FIXME: Currently, we handle closing in read callback, but these can come independently (e.g. a server can stop listening, but keep sending data).
        break;
    }
}
Exemplo n.º 3
0
void SocketStreamHandle::readStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable: {
        if (m_connectingSubstate == WaitingForConnect) {
            if (m_connectionType == CONNECTProxy) {
                RetainPtr<CFHTTPMessageRef> proxyResponse(AdoptCF, wkCopyCONNECTProxyResponse(m_readStream.get(), m_httpsURL.get()));
                if (proxyResponse && (407 == CFHTTPMessageGetResponseStatusCode(proxyResponse.get()))) {
                    addCONNECTCredentials(proxyResponse.get());
                    return;
                }
            }
        } else if (m_connectingSubstate == WaitingForCredentials)
            break;

        if (m_connectingSubstate == WaitingForConnect) {
            m_connectingSubstate = Connected;
            m_state = Open;

            RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference.
            m_client->didOpen(this);
            if (m_state == Closed)
                break;
            // Fall through.
        } else if (m_state == Closed)
            break;

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        CFIndex length;
        UInt8 localBuffer[1024]; // Used if CFReadStreamGetBuffer couldn't return anything.
        const UInt8* ptr = CFReadStreamGetBuffer(m_readStream.get(), 0, &length);
        if (!ptr) {
            length = CFReadStreamRead(m_readStream.get(), localBuffer, sizeof(localBuffer));
            ptr = localBuffer;
        }

        m_client->didReceiveData(this, reinterpret_cast<const char*>(ptr), length);

        break;
    }
    case kCFStreamEventCanAcceptBytes:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventErrorOccurred: {
#ifndef BUILDING_ON_TIGER
        RetainPtr<CFErrorRef> error(AdoptCF, CFReadStreamCopyError(m_readStream.get()));
        reportErrorToClient(error.get());
#else
        CFStreamError error = CFReadStreamGetError(m_readStream.get());
        m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error.
#endif
        break;
    }
    case kCFStreamEventEndEncountered:
        platformClose();
        break;
    }
}
void SocketStreamHandle::readStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable: {
        if (m_connectingSubstate == WaitingForConnect) {
            if (m_connectionType == CONNECTProxy) {
                RetainPtr<CFHTTPMessageRef> proxyResponse(AdoptCF, wkCopyCONNECTProxyResponse(m_readStream.get(), m_httpsURL.get()));
                if (proxyResponse) {
                    CFIndex proxyResponseCode = CFHTTPMessageGetResponseStatusCode(proxyResponse.get());
                    switch (proxyResponseCode) {
                    case 200:
                        // Successful connection.
                        break;
                    case 407:
                        addCONNECTCredentials(proxyResponse.get());
                        return;
                    default:
                        m_client->didFailSocketStream(this, SocketStreamError(static_cast<int>(proxyResponseCode), m_url.string(), "Proxy connection could not be established"));
                        platformClose();
                        return;
                    }
                }
            }
        } else if (m_connectingSubstate == WaitingForCredentials)
            break;

        if (m_connectingSubstate == WaitingForConnect) {
            m_connectingSubstate = Connected;
            m_state = Open;
            m_client->didOpenSocketStream(this);
            if (m_state == Closed)
                break;
            // Fall through.
        } else if (m_state == Closed)
            break;

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        CFIndex length;
        UInt8 localBuffer[1024]; // Used if CFReadStreamGetBuffer couldn't return anything.
        const UInt8* ptr = CFReadStreamGetBuffer(m_readStream.get(), 0, &length);
        if (!ptr) {
            length = CFReadStreamRead(m_readStream.get(), localBuffer, sizeof(localBuffer));
            ptr = localBuffer;
        }

        m_client->didReceiveSocketStreamData(this, reinterpret_cast<const char*>(ptr), length);

        break;
    }
    case kCFStreamEventCanAcceptBytes:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventErrorOccurred: {
        RetainPtr<CFErrorRef> error(AdoptCF, CFReadStreamCopyError(m_readStream.get()));
        reportErrorToClient(error.get());
        break;
    }
    case kCFStreamEventEndEncountered:
        platformClose();
        break;
    }
}