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: { CFStreamError error = CFReadStreamGetError(m_readStream.get()); m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error. break; } case kCFStreamEventEndEncountered: platformClose(); break; } }
static void handle_server_response(CFReadStreamRef stream, CFStreamEventType type, void *info) { asynchttp_t *http = (asynchttp_t *)info; if (!http->stream) { secerror("Avoiding crash due to CFReadStream invoking us after we called CFReadStreamSetDispatchQueue(stream, NULL) on a different block on our serial queue"); return; } switch (type) { case kCFStreamEventHasBytesAvailable: { UInt8 buffer[POST_BUFSIZE]; CFIndex length; do { #if 1 length = CFReadStreamRead(stream, buffer, sizeof(buffer)); #else const UInt8 *buffer = CFReadStreamGetBuffer(stream, -1, &length); #endif secdebug("http", "stream: %@ kCFStreamEventHasBytesAvailable read: %lu bytes", stream, length); if (length < 0) { /* Negative length == error */ asynchttp_complete(http); break; } else if (length > 0) { //CFHTTPMessageAppendBytes(http->response, buffer, length); CFDataAppendBytes(http->data, buffer, length); } else { /* Read 0 bytes, are we are done or do we wait for kCFStreamEventEndEncountered? */ asynchttp_complete(http); break; } } while (CFReadStreamHasBytesAvailable(stream)); break; } case kCFStreamEventErrorOccurred: { CFStreamError error = CFReadStreamGetError(stream); secdebug("http", "stream: %@ kCFStreamEventErrorOccurred domain: %ld error: %ld", stream, error.domain, (long) error.error); if (error.domain == kCFStreamErrorDomainPOSIX) { ocspdErrorLog("CFReadStream posix: %s", strerror(error.error)); } else if (error.domain == kCFStreamErrorDomainMacOSStatus) { ocspdErrorLog("CFReadStream osstatus: %"PRIstatus, error.error); } else { ocspdErrorLog("CFReadStream domain: %ld error: %"PRIstatus, error.domain, error.error); } asynchttp_complete(http); break; } case kCFStreamEventEndEncountered: { http->response = (CFHTTPMessageRef)CFReadStreamCopyProperty( stream, kCFStreamPropertyHTTPResponseHeader); secdebug("http", "stream: %@ kCFStreamEventEndEncountered hdr: %@", stream, http->response); CFHTTPMessageSetBody(http->response, http->data); asynchttp_complete(http); break; } default: ocspdErrorLog("handle_server_response unexpected event type: %lu", type); 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; } }