static void FetchIPAddress() { if(publicIPState == IPStateFetching) return; publicIPState = IPStateFetching; const UInt8 bodyBytes[] = {0}; CFDataRef body = CFDataCreate(kCFAllocatorDefault, bodyBytes, 0); CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, CFSTR("http://icanhazip.com"), NULL); CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), url, kCFHTTPVersion1_1); CFHTTPMessageSetBody(request, body); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" // Apple suggests the NSURLSession API instead of CFReadStreamCreateForHTTPRequest, // But obviously that doesn't really work here CFReadStreamRef stream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request); #pragma clang diagnostic pop CFRelease(body); CFRelease(url); CFRelease(request); CFMutableDataRef responseData = CFDataCreateMutable(kCFAllocatorDefault, 17); CFStreamClientContext context = { 0, responseData, NULL, NULL, NULL }; if(!CFReadStreamSetClient(stream, kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred, &IPStreamCallback, &context)) { CFRelease(stream); publicIPState = IPStateInvalid; return; } // Add to the run loop and open the stream CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); if(!CFReadStreamOpen(stream)) { CFReadStreamSetClient(stream, 0, NULL, NULL); CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); CFRelease(stream); publicIPState = IPStateInvalid; return; } // Run the run loop do { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, TRUE); } while(publicIPState == IPStateFetching); }
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 = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request))) { goto out; } CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue); proxySettings = CFNetworkCopySystemProxySettings(); if (proxySettings) { CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPProxy, proxySettings); CFRelease(proxySettings); } out: if (request) { CFRelease(request); } return readStream; }
/* Return true, iff we didn't schedule any work, return false if we did. */ bool asynchttp_request(CFHTTPMessageRef request, asynchttp_t *http) { secdebug("http", "request %@", request); if (request) { http->request = request; CFRetain(request); } /* Create the stream for the request. */ require_quiet(http->stream = CFReadStreamCreateForHTTPRequest( kCFAllocatorDefault, http->request), errOut); /* Set a reasonable timeout */ require_quiet(http->timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, http->queue), errOut); dispatch_source_set_event_handler(http->timer, ^{ asynchttp_timer_proc(http); });
void HTTPLoader::load(CFURLRef url) { CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), url, kCFHTTPVersion1_1); mStream = CFReadStreamCreateForHTTPRequest(NULL, request); CFRelease(request); if (!CFReadStreamOpen(mStream)) { CFRelease(mStream); mStream = 0; } else { CFStreamClientContext context = {0, this, NULL, NULL, NULL}; CFReadStreamSetClient(mStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, readStreamCallback, &context); CFReadStreamScheduleWithRunLoop(mStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); } }
static void send_request( SG_context* pCtx, CFHTTPMessageRef myRequest, CFReadStreamRef* pp ) { CFReadStreamRef myReadStream = NULL; myReadStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, myRequest); 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; } }
nuiHTTPResponse* nuiHTTPRequest::SendRequest() { char* pUrl = mUrl.Export(); CFStringRef originalURLString = CFStringCreateWithCString(kCFAllocatorDefault, pUrl, kCFStringEncodingUTF8); CFStringRef preprocessedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, originalURLString, CFSTR(""), kCFStringEncodingUTF8); CFStringRef urlString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, preprocessedString, NULL, NULL, kCFStringEncodingUTF8); free(pUrl); CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, urlString, NULL); CFRelease(urlString); char* pMeth = mMethod.Export(); CFStringRef method = CFStringCreateWithCString(kCFAllocatorDefault, pMeth, kCFStringEncodingUTF8); free(pMeth); CFHTTPMessageRef req = CFHTTPMessageCreateRequest(kCFAllocatorDefault, method, url, kCFHTTPVersion1_1); CFStringRef userAgentField = CFSTR("User-Agent"); CFStringRef userAgentName = CFSTR("nuiHTTP/2.0"); CFHTTPMessageSetHeaderFieldValue(req, userAgentField, userAgentName); CFRelease(userAgentField); CFRelease(userAgentName); nuiHTTPHeaderMap::const_iterator end = mHeaders.end(); for (nuiHTTPHeaderMap::const_iterator it = mHeaders.begin(); it != end; ++it) { char* pName = it->first.Export(); char* pVal = it->second.Export(); CFStringRef fieldName = CFStringCreateWithCString(kCFAllocatorDefault, pName, kCFStringEncodingUTF8); CFStringRef fieldValue = CFStringCreateWithCString(kCFAllocatorDefault, pVal, kCFStringEncodingUTF8); CFHTTPMessageSetHeaderFieldValue(req, fieldName, fieldValue); CFRelease(fieldName); CFRelease(fieldValue); delete pName; delete pVal; } CFDataRef body = NULL; if (mBody.size()) { body = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8*)&mBody[0], mBody.size(), kCFAllocatorNull); CFHTTPMessageSetBody(req, body); } CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, req); CFReadStreamOpen(readStream); std::vector<char> buf; CFIndex pos = 0; CFIndex size = 0; bool cont = true; do { buf.resize(pos + 1024); size = CFReadStreamRead(readStream, (UInt8*)&buf[pos], 1024); if (size == -1) { return NULL; } else if (size == 0) { if (CFReadStreamGetStatus(readStream) == kCFStreamStatusAtEnd) cont = false; else nglThread::MsSleep(10); } pos += size; } while (cont); CFHTTPMessageRef responseHeader = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader); CFStringRef statusLine = CFHTTPMessageCopyResponseStatusLine(responseHeader); CFIndex strSize = CFStringGetLength(statusLine)+1; char* pStatus = new char[strSize]; CFStringGetCString(statusLine, pStatus, strSize, kCFStringEncodingUTF8); nglString status(pStatus); UInt32 statusCode = CFHTTPMessageGetResponseStatusCode(responseHeader); nuiHTTPResponse* pResponse = new nuiHTTPResponse(statusCode, status); pResponse->SetBody(&buf[0], pos); delete[] pStatus; CFDictionaryRef dict = CFHTTPMessageCopyAllHeaderFields(responseHeader); CFIndex valueCount = CFDictionaryGetCount(dict); const CFStringRef* pNames = new CFStringRef[valueCount]; const CFStringRef* pValues = new CFStringRef[valueCount]; CFDictionaryGetKeysAndValues(dict, (const void**)pNames, (const void**)pValues); for (CFIndex i = 0; i< valueCount; i++) { strSize = CFStringGetLength(pNames[i])+1; char* pName = new char[strSize]; CFStringGetCString(pNames[i], pName, strSize, kCFStringEncodingUTF8); strSize = CFStringGetLength(pValues[i])+1; char* pVal = new char[strSize]; CFStringGetCString(pValues[i], pVal, strSize, kCFStringEncodingUTF8); nglString name(pName); nglString val(pVal); pResponse->AddHeader(name, val); delete[] pName; delete[] pVal; } delete[] pNames; delete[] pValues; CFRelease(responseHeader); CFRelease(url); CFRelease(method); CFRelease(req); CFRelease(readStream); CFRelease(dict); CFRelease(statusLine); if (body) CFRelease(body); return pResponse; }
char* DotMacQuery::ReadStream (CFURLRef url, size_t &responseLength) { SInt32 ito; CFNumberRef cfnTo = NULL; CFDictionaryRef proxyDict = NULL; // make a connection to the provided URL CFHTTPMessageRef httpRequestRef = CFHTTPMessageCreateRequest (kCFAllocatorDefault, CFSTR("GET"), url, kCFHTTPVersion1_1); if (httpRequestRef == NULL) { CSSMError::ThrowCSSMError (CSSMERR_DL_RECORD_NOT_FOUND); } // open the stream CFReadStreamRef httpStreamRef = CFReadStreamCreateForHTTPRequest (kCFAllocatorDefault, httpRequestRef); if (httpStreamRef == NULL) { CSSMError::ThrowCSSMError (CSSMERR_DL_RECORD_NOT_FOUND); } // set a reasonable timeout ito = READ_STREAM_TIMEOUT; cfnTo = CFNumberCreate(NULL, kCFNumberSInt32Type, &ito); if(!CFReadStreamSetProperty(httpStreamRef, _kCFStreamPropertyReadTimeout, cfnTo)) { // oh well - keep going } /* set up possible proxy info */ proxyDict = SCDynamicStoreCopyProxies(NULL); if(proxyDict) { CFReadStreamSetProperty(httpStreamRef, kCFStreamPropertyHTTPProxy, proxyDict); } if (CFReadStreamOpen (httpStreamRef) == false) { CFRelease(httpRequestRef); CFRelease(httpStreamRef); CFRelease(cfnTo); if(proxyDict) { CFRelease(proxyDict); } CSSMError::ThrowCSSMError (CSSMERR_DL_RECORD_NOT_FOUND); } char* response = (char*) malloc (kResponseIncrement); size_t responseBufferLength = kResponseIncrement; responseLength = 0; // read data from the stream CFIndex bytesRead = CFReadStreamRead (httpStreamRef, (UInt8*) response + responseLength, kResponseIncrement); while (bytesRead > 0) { responseLength += bytesRead; responseBufferLength = responseLength + kResponseIncrement; response = (char*) realloc (response, responseBufferLength); bytesRead = CFReadStreamRead (httpStreamRef, (UInt8*) response + responseLength, kResponseIncrement); } CFRelease (httpRequestRef); CFRelease (httpStreamRef); CFRelease(cfnTo); if(proxyDict) { CFRelease(proxyDict); } // check for error if (bytesRead < 0) { CSSMError::ThrowCSSMError (CSSMERR_DL_RECORD_NOT_FOUND); } return response; }