bool HTTPInputSource::Open(CFErrorRef *error) { if(IsOpen()) { LOGGER_WARNING("org.sbooth.AudioEngine.InputSource.HTTP", "Open() called on an InputSource that is already open"); return true; } // Set up the HTTP request mRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), mURL, kCFHTTPVersion1_1); if(NULL == mRequest) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } CFHTTPMessageSetHeaderFieldValue(mRequest, CFSTR("User-Agent"), CFSTR("SFBAudioEngine")); // Seek support if(0 < mDesiredOffset) { CFStringRef byteRange = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("bytes=%ld-"), mDesiredOffset); CFHTTPMessageSetHeaderFieldValue(mRequest, CFSTR("Range"), byteRange); CFRelease(byteRange), byteRange = NULL; } mReadStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, mRequest, NULL); if(NULL == mReadStream) { CFRelease(mRequest), mRequest = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } // Start the HTTP connection CFStreamClientContext myContext = { 0, this, NULL, NULL, NULL }; CFOptionFlags clientFlags = kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered; if(!CFReadStreamSetClient(mReadStream, clientFlags, myCFReadStreamClientCallBack, &myContext)) { CFRelease(mRequest), mRequest = NULL; CFRelease(mReadStream), mReadStream = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } CFReadStreamScheduleWithRunLoop(mReadStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); if(!CFReadStreamOpen(mReadStream)) { CFRelease(mRequest), mRequest = NULL; CFRelease(mReadStream), mReadStream = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } while(NULL == mResponseHeaders) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); mIsOpen = true; return true; }
CFReadStreamRef HTTP_Stream::createReadStream(CFURLRef url) { CFReadStreamRef readStream = 0; CFHTTPMessageRef request = 0; CFDictionaryRef proxySettings = 0; Stream_Configuration *config = Stream_Configuration::configuration(); if (!(request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, httpRequestMethod, url, kCFHTTPVersion1_1))) { goto out; } if (config->userAgent) { CFHTTPMessageSetHeaderFieldValue(request, httpUserAgentHeader, config->userAgent); } CFHTTPMessageSetHeaderFieldValue(request, icyMetaDataHeader, icyMetaDataValue); if (m_position.start > 0 && m_position.end > m_position.start) { CFStringRef rangeHeaderValue = CFStringCreateWithFormat(NULL, NULL, CFSTR("bytes=%llu-%llu"), m_position.start, m_position.end); CFHTTPMessageSetHeaderFieldValue(request, httpRangeHeader, rangeHeaderValue); CFRelease(rangeHeaderValue); } if (!(readStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, request, 0))) { goto out; } proxySettings = CFNetworkCopySystemProxySettings(); if (proxySettings) { CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPProxy, proxySettings); CFRelease(proxySettings); } out: if (request) { CFRelease(request); } return readStream; }
static void send_upload_request( SG_context* pCtx, CFHTTPMessageRef myRequest, CFReadStreamRef upload, CFReadStreamRef* pp ) { CFReadStreamRef myReadStream = NULL; myReadStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, myRequest, upload); if (!CFReadStreamOpen(myReadStream)) { CFStreamError myErr = CFReadStreamGetError(myReadStream); if (myErr.domain == kCFStreamErrorDomainPOSIX) { // Interpret myErr.error as a UNIX errno. SG_ERR_THROW( SG_ERR_ERRNO(myErr.error) ); } else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) { // Interpret myErr.error as a MacOS error code. // TODO SG_ERR_THROW( SG_ERR_MAC((OSStatus) myErr.error) ); SG_ERR_THROW( SG_ERR_UNSPECIFIED ); } } *pp = myReadStream; myReadStream = NULL; fail: if (myReadStream) { CFReadStreamClose(myReadStream); CFRelease(myReadStream); myReadStream = NULL; } }