Ejemplo n.º 1
0
bool HTTP_Stream::open(const HTTP_Stream_Position& position)
{
    bool success = false;
    CFStreamClientContext CTX = { 0, this, NULL, NULL, NULL };
    
    /* Already opened a read stream, return */
    if (m_readStream) {
        goto out;
    }
    
    /* Reset state */
    m_position = position;
    
    m_readPending = false;
    m_httpHeadersParsed = false;
    m_contentType = "";
    
    m_icyStream = false;
    m_icyHeaderCR = false;
    m_icyHeadersRead = false;
    m_icyHeadersParsed = false;
    
    m_icyHeaderLines.clear();
    m_icyMetaDataInterval = 0;
    m_dataByteReadCount = 0;
    m_metaDataBytesRemaining = 0;
    
    if (!m_url) {
        goto out;
    }
	
    /* Failed to create a stream */
    if (!(m_readStream = createReadStream(m_url))) {
        goto out;
    }
    
    if (!CFReadStreamSetClient(m_readStream, kCFStreamEventHasBytesAvailable |
	                                         kCFStreamEventEndEncountered |
	                                         kCFStreamEventErrorOccurred, readCallBack, &CTX)) {
        CFRelease(m_readStream), m_readStream = 0;
        goto out;
    }
    
    setScheduledInRunLoop(true);
    
    if (!CFReadStreamOpen(m_readStream)) {
        /* Open failed: clean */
        CFReadStreamSetClient(m_readStream, 0, NULL, NULL);
        setScheduledInRunLoop(false);
        if (m_readStream) {
            CFRelease(m_readStream), m_readStream = 0;
        }
        goto out;
    }
    
    success = true;

out:
    return success;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
void SocketStreamHandle::scheduleStreams()
{
    ASSERT(m_readStream);
    ASSERT(m_writeStream);

    CFStreamClientContext clientContext = { 0, this, 0, 0, copyCFStreamDescription };
    // FIXME: Pass specific events we're interested in instead of -1.
    CFReadStreamSetClient(m_readStream.get(), static_cast<CFOptionFlags>(-1), readStreamCallback, &clientContext);
    CFWriteStreamSetClient(m_writeStream.get(), static_cast<CFOptionFlags>(-1), writeStreamCallback, &clientContext);

#if PLATFORM(WIN)
    CFReadStreamScheduleWithRunLoop(m_readStream.get(), loaderRunLoop(), kCFRunLoopDefaultMode);
    CFWriteStreamScheduleWithRunLoop(m_writeStream.get(), loaderRunLoop(), kCFRunLoopDefaultMode);
#else
    CFReadStreamScheduleWithRunLoop(m_readStream.get(), CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
    CFWriteStreamScheduleWithRunLoop(m_writeStream.get(), CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
#endif

    CFReadStreamOpen(m_readStream.get());
    CFWriteStreamOpen(m_writeStream.get());

#ifndef BUILDING_ON_TIGER
    if (m_pacRunLoopSource)
        removePACRunLoopSource();
#endif

    m_connectingSubstate = WaitingForConnect;
}
Ejemplo n.º 4
0
/* MyStreamInfoDestroy destroys a MyStreamInfo 'object', cleaning up any resources that it owns. */                                       
static void
MyStreamInfoDestroy(MyStreamInfo * info)
{
    assert(info != NULL);
    
    if (info->readStream) {
        CFReadStreamUnscheduleFromRunLoop(info->readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
        (void) CFReadStreamSetClient(info->readStream, kCFStreamEventNone, NULL, NULL);
        
        /* CFReadStreamClose terminates the stream. */
        CFReadStreamClose(info->readStream);
        CFRelease(info->readStream);
    }

    if (info->writeStream) {
        CFWriteStreamUnscheduleFromRunLoop(info->writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
        (void) CFWriteStreamSetClient(info->writeStream, kCFStreamEventNone, NULL, NULL);
        
        /* CFWriteStreamClose terminates the stream. */
        CFWriteStreamClose(info->writeStream);
        CFRelease(info->writeStream);
    }

    if (info->proxyDict) {
        CFRelease(info->proxyDict);             // see discussion of <rdar://problem/3745574> below
    }
    
    free(info);
}
Ejemplo n.º 5
0
static void advanceCurrentStream(FormStreamFields *form)
{
    closeCurrentStream(form);

    if (form->remainingElements.isEmpty())
        return;

    // Create the new stream.
    FormDataElement& nextInput = form->remainingElements.last();
    if (nextInput.m_type == FormDataElement::data) {
        size_t size = nextInput.m_data.size();
        char* data = nextInput.m_data.releaseBuffer();
        form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull);
        form->currentData = data;
    } else {
        CFStringRef filename = nextInput.m_filename.createCFString();
#if PLATFORM(WIN)
        CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLWindowsPathStyle, FALSE);
#else
        CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLPOSIXPathStyle, FALSE);
#endif
        CFRelease(filename);
        form->currentStream = CFReadStreamCreateWithFile(0, fileURL);
        CFRelease(fileURL);
    }
    form->remainingElements.removeLast();

    // Set up the callback.
    CFStreamClientContext context = { 0, form, NULL, NULL, NULL };
    CFReadStreamSetClient(form->currentStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
        formEventCallback, &context);

    // Schedule with the current set of run loops.
    CFSetApplyFunction(form->scheduledRunLoopPairs, scheduleWithPair, form->currentStream);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
static void asynchttp_complete(asynchttp_t *http) {
    secdebug("http", "http: %p", http);
    /* Shutdown streams and timer, we're about to invoke our client callback. */
    if (http->stream) {
        CFReadStreamSetClient(http->stream, kCFStreamEventNone, NULL, NULL);
        CFReadStreamSetDispatchQueue(http->stream, NULL);
        CFReadStreamClose(http->stream);
        CFReleaseNull(http->stream);
    }
    if (http->timer) {
        dispatch_source_cancel(http->timer);
        dispatch_release_null(http->timer);
    }

    if (http->completed) {
        /* This should probably move to our clients. */
        CFTimeInterval maxAge = NULL_TIME;
        if (http->response) {
            CFStringRef cacheControl = CFHTTPMessageCopyHeaderFieldValue(
                http->response, CFSTR("cache-control"));
            if (cacheControl) {
                CFStringRef maxAgeValue = copyParseMaxAge(cacheControl);
                CFRelease(cacheControl);
                if (maxAgeValue) {
                    secdebug("http", "http header max-age: %@", maxAgeValue);
                    maxAge = CFStringGetDoubleValue(maxAgeValue);
                    CFRelease(maxAgeValue);
                }
            }
        }
        http->completed(http, maxAge);
    }
}
Ejemplo n.º 8
0
/* extern */ void
_CFTypeInvalidate(CFTypeRef obj) {

	CFTypeID t = CFGetTypeID(obj);

	/* Invalidate according to type of object. */
	if (t == CFRunLoopSourceGetTypeID()) {
		CFRunLoopSourceInvalidate((CFRunLoopSourceRef)obj);
	}

	else if (t == CFMachPortGetTypeID()) {
		CFMachPortInvalidate((CFMachPortRef)obj);
	}

	else if (t == CFSocketGetTypeID()) {
		CFSocketInvalidate((CFSocketRef)obj);
	}

	/* For scheduled types of objects, it is invalidated by setting the client to NULL. */
	else if (t == CFReadStreamGetTypeID()) {
		CFReadStreamSetClient((CFReadStreamRef)obj, kCFStreamEventNone, NULL, NULL);
	}

	else if (t == CFWriteStreamGetTypeID()) {
		CFWriteStreamSetClient((CFWriteStreamRef)obj, kCFStreamEventNone, NULL, NULL);
	}

	else if (t == CFHostGetTypeID()) {
		CFHostSetClient((CFHostRef)obj, NULL, NULL);
	}

	else if (t == SCNetworkReachabilityGetTypeID()) {
		SCNetworkReachabilitySetCallback((SCNetworkReachabilityRef)obj, NULL, NULL);
	}

	else if (t == CFRunLoopTimerGetTypeID()) {
		CFRunLoopTimerInvalidate((CFRunLoopTimerRef)obj);
	}

	else if (t == CFNetServiceGetTypeID()) {
		CFNetServiceSetClient((CFNetServiceRef)obj, NULL, NULL);
	}

	else if (t == CFNetServiceBrowserGetTypeID()) {
		CFNetServiceBrowserInvalidate((CFNetServiceBrowserRef)obj);
	}

	else if (t == CFNetServiceMonitorGetTypeID()) {
		CFNetServiceMonitorInvalidate((CFNetServiceMonitorRef)obj);
	}

	else if (t == SCNetworkReachabilityGetTypeID()) {
		SCNetworkConnectionStop((SCNetworkConnectionRef)obj, FALSE);
	}
}
Ejemplo n.º 9
0
static void closeCurrentStream(FormStreamFields* form)
{
    if (form->currentStream) {
        CFReadStreamClose(form->currentStream);
        CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, 0, 0);
        CFRelease(form->currentStream);
        form->currentStream = 0;
        form->currentStreamRangeLength = BlobDataItem::toEndOfFile;
    }

    form->currentData = nullptr;
}
Ejemplo n.º 10
0
void HTTP_Stream::close()
{
    /* The stream has been already closed */
    if (!m_readStream) {
        return;
    }
    
    CFReadStreamSetClient(m_readStream, 0, NULL, NULL);
    setScheduledInRunLoop(false);
    CFReadStreamClose(m_readStream);
    CFRelease(m_readStream), m_readStream = 0;
}
Ejemplo n.º 11
0
// Return false if we cannot advance the stream. Currently the only possible failure is that the underlying file has been removed or changed since File.slice.
static bool advanceCurrentStream(FormStreamFields* form)
{
    closeCurrentStream(form);

    if (form->remainingElements.isEmpty())
        return true;

    // Create the new stream.
    FormDataElement& nextInput = form->remainingElements.last();

    if (nextInput.m_type == FormDataElement::data) {
        size_t size = nextInput.m_data.size();
        MallocPtr<char> data = nextInput.m_data.releaseBuffer();
        form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data.get()), size, kCFAllocatorNull);
        form->currentData = std::move(data);
    } else {
#if ENABLE(BLOB)
        // Check if the file has been changed or not if required.
        if (isValidFileTime(nextInput.m_expectedFileModificationTime)) {
            time_t fileModificationTime;
            if (!getFileModificationTime(nextInput.m_filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(nextInput.m_expectedFileModificationTime))
                return false;
        }
#endif
        const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename;
        form->currentStream = CFReadStreamCreateWithFile(0, pathAsURL(path).get());
        if (!form->currentStream) {
            // The file must have been removed or become unreadable.
            return false;
        }
#if ENABLE(BLOB)
        if (nextInput.m_fileStart > 0) {
            RetainPtr<CFNumberRef> position = adoptCF(CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart));
            CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position.get());
        }
        form->currentStreamRangeLength = nextInput.m_fileLength;
#endif
    }
    form->remainingElements.removeLast();

    // Set up the callback.
    CFStreamClientContext context = { 0, form, 0, 0, 0 };
    CFReadStreamSetClient(form->currentStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
        formEventCallback, &context);

    // Schedule with the current set of run loops.
    SchedulePairHashSet::iterator end = form->scheduledRunLoopPairs.end();
    for (SchedulePairHashSet::iterator it = form->scheduledRunLoopPairs.begin(); it != end; ++it)
        CFReadStreamScheduleWithRunLoop(form->currentStream, (*it)->runLoop(), (*it)->mode());

    return true;
}
Ejemplo n.º 12
0
static void closeCurrentStream(FormStreamFields *form)
{
    if (form->currentStream) {
        CFReadStreamClose(form->currentStream);
        CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, NULL, NULL);
        CFRelease(form->currentStream);
        form->currentStream = NULL;
    }
    if (form->currentData) {
        fastFree(form->currentData);
        form->currentData = 0;
    }
}
static void closeCurrentStream(FormStreamFields* form)
{
    ASSERT(form->streamIsBeingOpenedOrClosedLock.isHeld());

    if (form->currentStream) {
        CFReadStreamClose(form->currentStream);
        CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, 0, 0);
        CFRelease(form->currentStream);
        form->currentStream = 0;
        form->currentStreamRangeLength = BlobDataItem::toEndOfFile;
    }

    form->currentData = nullptr;
}
Ejemplo n.º 14
0
/* MySimpleDirectoryListing implements the directory list command.  It sets up a MyStreamInfo 
'object' with the read stream being an FTP stream of the directory to list and with no 
write stream.  It then returns, and the real work happens asynchronously in the runloop.  
The function returns true if the stream setup succeeded, and false if it failed. */
static Boolean
MySimpleDirectoryListing(CFStringRef urlString, CFStringRef username, CFStringRef password)
{
    CFReadStreamRef        readStream;
    CFStreamClientContext  context = { 0, NULL, NULL, NULL, NULL };
    CFURLRef               downloadURL;
    Boolean                success = true;
    MyStreamInfo           *streamInfo;

    assert(urlString != NULL);

    downloadURL = CFURLCreateWithString(kCFAllocatorDefault, urlString, NULL);
    assert(downloadURL != NULL);

    /* Create an FTP read stream for downloading operation from an FTP URL. */
    readStream = CFReadStreamCreateWithFTPURL(kCFAllocatorDefault, downloadURL);
    assert(readStream != NULL);
    CFRelease(downloadURL);
        
    /* Initialize our MyStreamInfo structure, which we use to store some information about the stream. */
    MyStreamInfoCreate(&streamInfo, readStream, NULL);
    context.info = (void *)streamInfo;

    /* CFReadStreamSetClient registers a callback to hear about interesting events that occur on a stream. */
    success = CFReadStreamSetClient(readStream, kNetworkEvents, MyDirectoryListingCallBack, &context);
    if (success) {

        /* Schedule a run loop on which the client can be notified about stream events.  The client
        callback will be triggered via the run loop.  It's the caller's responsibility to ensure that
        the run loop is running. */
        CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
        
        MyCFStreamSetUsernamePassword(readStream, username, password);
        MyCFStreamSetFTPProxy(readStream, &streamInfo->proxyDict);
    
        /* CFReadStreamOpen will return success/failure.  Opening a stream causes it to reserve all the
        system resources it requires.  If the stream can open non-blocking, this will always return TRUE;
        listen to the run loop source to find out when the open completes and whether it was successful. */
        success = CFReadStreamOpen(readStream);
        if (success == false) {
            fprintf(stderr, "CFReadStreamOpen failed\n");
            MyStreamInfoDestroy(streamInfo);
        }
    } else {
        fprintf(stderr, "CFReadStreamSetClient failed\n");
        MyStreamInfoDestroy(streamInfo);
    }

    return success;
}
Ejemplo n.º 15
0
static void cfstream_data_close(struct mailstream_cfstream_data * cfstream_data)
{
  if (cfstream_data->writeStream != NULL) {
    CFWriteStreamSetClient(cfstream_data->writeStream, kCFStreamEventNone, NULL, NULL);
    CFWriteStreamClose(cfstream_data->writeStream);
    CFRelease(cfstream_data->writeStream);
    cfstream_data->writeStream = NULL;
  }
  if (cfstream_data->readStream != NULL) {
    CFReadStreamSetClient(cfstream_data->readStream, kCFStreamEventNone, NULL, NULL);
    CFReadStreamClose(cfstream_data->readStream);
    CFRelease(cfstream_data->readStream);
    cfstream_data->readStream = NULL;
  }
}
Ejemplo n.º 16
0
static void IPStreamCallback(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo)
{
	CFMutableDataRef responseData = (CFMutableDataRef)clientCallBackInfo;

	if(eventType & kCFStreamEventHasBytesAvailable)
	{
		UInt8 buffer[1024];
		CFIndex read;

		do {
			read = CFReadStreamRead(stream, buffer, sizeof(buffer));
			if(read > 0)
				CFDataAppendBytes(responseData, buffer, read);

		} while(read > 0);
	}

	if(eventType & (kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred))
	{
		if((eventType & kCFStreamEventEndEncountered) && publicIPState == IPStateFetching)
		{
			if(publicIPData)
				CFRelease(publicIPData);

			publicIPData = CFDataCreateCopy(kCFAllocatorDefault, responseData);
			publicIPState = IPStateFetched;
		}

		if(eventType & kCFStreamEventErrorOccurred)
		{
			if(publicIPData)
				CFRelease(publicIPData);

			publicIPData = NULL;
			publicIPState = IPStateInvalid;
		}

		CFReadStreamClose(stream);
		CFReadStreamSetClient(stream, 0, NULL, NULL);
		CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
		CFRelease(stream);

		CFRelease(responseData);
	}
}
Ejemplo n.º 17
0
    bool TCPStream_CFNetwork::connect() {
        state = Stream::State::Opening;

        CFStringRef host_cfstring = CFStringCreateWithCString(kCFAllocatorDefault,
                                                              remoteHostName.c_str(),
                                                              kCFStringEncodingUTF8);

        CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
                                           host_cfstring,
                                           remotePortNumber,
                                           &inputStream,
                                           &outputStream);
        CFRelease(host_cfstring);

        CFStreamClientContext inputStreamContext;
        memset(&inputStreamContext, 0, sizeof(inputStreamContext));
        inputStreamContext.info = reinterpret_cast<void *>(this);

        CFReadStreamSetClient(inputStream,
                              kCFStreamEventHasBytesAvailable |
                              kCFStreamEventEndEncountered |
                              kCFStreamEventErrorOccurred,
                              inputStreamCallback,
                              &inputStreamContext);

        CFReadStreamScheduleWithRunLoop(inputStream, CFRunLoopGetMain(), kCFRunLoopDefaultMode);

        if (CFReadStreamOpen(inputStream) && CFWriteStreamOpen(outputStream)) {
            state = Stream::State::Open;
            return true;
        } else {
            CFRelease(outputStream);
            CFRelease(inputStream);
            outputStream = nullptr;
            inputStream = nullptr;

            state = Stream::State::NotOpen;
            return false;
        }
    }
Ejemplo n.º 18
0
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);
  }
}
Ejemplo n.º 19
0
/* extern */ void
HttpContextClose(HttpContextRef context) {

	CFRunLoopRef runLoop = CFRunLoopGetCurrent();

	// Check if the read stream exists.
	if (context->_inStream) {
		
		// Unschedule, close, and release it.
		CFReadStreamSetClient(context->_inStream, 0, NULL, NULL);
		CFReadStreamUnscheduleFromRunLoop(context->_inStream, runLoop, kCFRunLoopCommonModes);
		CFReadStreamClose(context->_inStream);
		CFRelease(context->_inStream);
		
		// Remove the reference.
		context->_inStream = NULL;
	}

	// Check if the write stream exists.
	if (context->_outStream) {
		
		// Unschedule, close, and release it.
		CFWriteStreamSetClient(context->_outStream, 0, NULL, NULL);
		CFWriteStreamUnscheduleFromRunLoop(context->_outStream, runLoop, kCFRunLoopCommonModes);
		CFWriteStreamClose(context->_outStream);
		CFRelease(context->_outStream);
		
		// Remove the reference.
		context->_outStream = NULL;
	}

    // Get rid of the timer, if it still exists
    if (context->_timer != NULL) {

        CFRunLoopTimerInvalidate(context->_timer);
        CFRelease(context->_timer);
        context->_timer = NULL;
    }
}
Ejemplo n.º 20
0
mailstream_low * mailstream_low_cfstream_open_voip_timeout(const char * hostname, int16_t port,
  int voip_enabled, time_t timeout)
{
#if HAVE_CFNETWORK
  mailstream_low * s;
  struct mailstream_cfstream_data * cfstream_data;
  CFReadStreamRef readStream;
  CFWriteStreamRef writeStream;
  CFStringRef hostString;
  CFOptionFlags readFlags;
  CFOptionFlags writeFlags;
  int r;
  
  hostString = CFStringCreateWithCString(NULL, hostname, kCFStringEncodingUTF8);
  CFStreamCreatePairWithSocketToHost(NULL, hostString, port, &readStream, &writeStream);
  CFRelease(hostString);

#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR  
  if (voip_enabled) {
    CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
    CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  }
#endif
  
  cfstream_data = cfstream_data_new(readStream, writeStream);
  s = mailstream_low_new(cfstream_data, mailstream_cfstream_driver);
	mailstream_low_set_timeout(s, timeout);  

  //fprintf(stderr, "open %s %i -> %p\n", hostname, port, s);
  
  /* setup streams */
  cfstream_data->streamContext.info = s;
  
  readFlags = kCFStreamEventOpenCompleted |
  kCFStreamEventHasBytesAvailable |
  kCFStreamEventErrorOccurred |
  kCFStreamEventEndEncountered;
  
  writeFlags = kCFStreamEventOpenCompleted |
  kCFStreamEventCanAcceptBytes |
  kCFStreamEventErrorOccurred |
  kCFStreamEventEndEncountered;
  
  CFReadStreamSetClient(cfstream_data->readStream, readFlags, readStreamCallback, &cfstream_data->streamContext);
  CFWriteStreamSetClient(cfstream_data->writeStream, writeFlags, writeStreamCallback, &cfstream_data->streamContext);
  
  CFRelease(readStream);
  CFRelease(writeStream);
  readStream = NULL;
  writeStream = NULL;
  
  /* setup cancel */
  cfstream_data->cancelContext.info = s;
  cfstream_data->cancelContext.perform = cancelPerform;
  cfstream_data->cancelSource = CFRunLoopSourceCreate(NULL, 0, &cfstream_data->cancelContext);
  
  r = low_open(s);
  if (r < 0) {
    mailstream_low_cfstream_close(s);
    return NULL;
  }
  
  return s;
#else
  return NULL;
#endif
}
Ejemplo n.º 21
0
/* MySimpleDownload implements the download command.  It sets up a MyStreamInfo 'object' 
with the read stream being an FTP stream of the file to download and the write stream being 
a file stream of the destination file.  It then returns, and the real work happens 
asynchronously in the runloop.  The function returns true if the stream setup succeeded, 
and false if it failed. */
static Boolean
MySimpleDownload(CFStringRef urlString, CFURLRef destinationFolder, CFStringRef username, CFStringRef password)
{
    CFReadStreamRef        readStream;
    CFWriteStreamRef       writeStream;
    CFStreamClientContext  context = { 0, NULL, NULL, NULL, NULL };
    CFURLRef               downloadPath, downloadURL;
    CFStringRef            fileName;
    Boolean                dirPath, success = true;
    MyStreamInfo           *streamInfo;

    assert(urlString != NULL);
    assert(destinationFolder != NULL);
    assert( (username != NULL) || (password == NULL) );

    /* Returns true if the CFURL path represents a directory. */
    dirPath = CFURLHasDirectoryPath(destinationFolder);
    if (!dirPath) {
        fprintf(stderr, "Download destination must be a directory.\n");
        return false;
    }
    
    /* Create a CFURL from the urlString. */
    downloadURL = CFURLCreateWithString(kCFAllocatorDefault, urlString, NULL);
    assert(downloadURL != NULL);

    /* Copy the end of the file path and use it as the file name. */
    fileName = CFURLCopyLastPathComponent(downloadURL);
    assert(fileName != NULL);

    /* Create the downloadPath by taking the destination folder and appending the file name. */
    downloadPath = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, destinationFolder, fileName, false);
    assert(downloadPath != NULL);
    CFRelease(fileName);

    /* Create a CFWriteStream for the file being downloaded. */
    writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, downloadPath);
    assert(writeStream != NULL);
    CFRelease(downloadPath);
    
    /* CFReadStreamCreateWithFTPURL creates an FTP read stream for downloading from an FTP URL. */
    readStream = CFReadStreamCreateWithFTPURL(kCFAllocatorDefault, downloadURL);
    assert(readStream != NULL);
    CFRelease(downloadURL);
    
    /* Initialize our MyStreamInfo structure, which we use to store some information about the stream. */
    MyStreamInfoCreate(&streamInfo, readStream, writeStream);
    context.info = (void *)streamInfo;

    /* CFWriteStreamOpen will return success/failure.  Opening a stream causes it to reserve all the
    system resources it requires.  If the stream can open non-blocking, this will always return TRUE;
    listen to the run loop source to find out when the open completes and whether it was successful. */
    success = CFWriteStreamOpen(writeStream);
    if (success) {
    
        /* CFReadStreamSetClient registers a callback to hear about interesting events that occur on a stream. */
        success = CFReadStreamSetClient(readStream, kNetworkEvents, MyDownloadCallBack, &context);
        if (success) {

            /* Schedule a run loop on which the client can be notified about stream events.  The client
            callback will be triggered via the run loop.  It's the caller's responsibility to ensure that
            the run loop is running. */
            CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
            
            MyCFStreamSetUsernamePassword(readStream, username, password);
            MyCFStreamSetFTPProxy(readStream, &streamInfo->proxyDict);
            
            /* Setting the kCFStreamPropertyFTPFetchResourceInfo property will instruct the FTP stream
            to fetch the file size before downloading the file.  Note that fetching the file size adds
            some time to the length of the download.  Fetching the file size allows you to potentially
            provide a progress dialog during the download operation. You will retrieve the actual file
            size after your CFReadStream Callback gets called with a kCFStreamEventOpenCompleted event. */
            CFReadStreamSetProperty(readStream, kCFStreamPropertyFTPFetchResourceInfo, kCFBooleanTrue);
            
            /* CFReadStreamOpen will return success/failure.  Opening a stream causes it to reserve all the
            system resources it requires.  If the stream can open non-blocking, this will always return TRUE;
            listen to the run loop source to find out when the open completes and whether it was successful. */
            success = CFReadStreamOpen(readStream);
            if (success == false) {
                fprintf(stderr, "CFReadStreamOpen failed\n");
                MyStreamInfoDestroy(streamInfo);
            }
        } else {
            fprintf(stderr, "CFReadStreamSetClient failed\n");
            MyStreamInfoDestroy(streamInfo);
        }
    } else {
        fprintf(stderr, "CFWriteStreamOpen failed\n");
        MyStreamInfoDestroy(streamInfo);
    }

    return success;
}
Ejemplo n.º 22
0
/* extern */ Boolean
HttpContextOpen(HttpContextRef context) {

	do {
		Boolean didSet;
		CFRunLoopRef runLoop = CFRunLoopGetCurrent();
		
		CFStreamClientContext streamCtxt = {0, context, (void*(*)(void*))&HttpContextRetain, (void(*)(void*))&HttpContextRelease, NULL};
		CFRunLoopTimerContext timerCtxt = {0, context, (const void*(*)(const void*))&HttpContextRetain, (void(*)(const void*))&HttpContextRelease, NULL};
		
		// Set the client on the read stream.
		didSet = CFReadStreamSetClient(context->_inStream,
									   kReadEvents,
									   (CFReadStreamClientCallBack)&_ReadStreamCallBack,
									   &streamCtxt);
									   
		// Fail if unable to set the client.
		if (!didSet)
			break;
		
		// Set the client on the write stream.
		didSet = CFWriteStreamSetClient(context->_outStream,
										kWriteEvents,
										(CFWriteStreamClientCallBack)&_WriteStreamCallBack,
										&streamCtxt);
		
		// Fail if unable to set the client.
		if (!didSet)
			break;
			
		// Schedule the streams on the current run loop and default mode.
		CFReadStreamScheduleWithRunLoop(context->_inStream, runLoop, kCFRunLoopCommonModes);
		CFWriteStreamScheduleWithRunLoop(context->_outStream, runLoop, kCFRunLoopCommonModes);
		
		// Open the stream for reading.
		if (!CFReadStreamOpen(context->_inStream))
			break;
			
		// Open the stream for writing.
		if (!CFWriteStreamOpen(context->_outStream))
			break;
		
		// Create the timeout timer
		context->_timer = CFRunLoopTimerCreate(CFGetAllocator(context->_inStream),
											   CFAbsoluteTimeGetCurrent() + kTimeOutInSeconds,
											   0,		// interval
											   0,		// flags
											   0,		// order
											   (CFRunLoopTimerCallBack)_TimerCallBack,
											   &timerCtxt);
		
		// Fail if unable to create the timer.
		if (context->_timer == NULL)
			break;
			
        CFRunLoopAddTimer(runLoop, context->_timer, kCFRunLoopCommonModes);
            
		return TRUE;
		
	} while (0);
	
	// Something failed, so clean up.
	HttpContextClose(context);
	
	return FALSE;
}
int tnet_transport_wrap(tnet_transport_t *transport, int index) {
    transport_context_t *context = transport->context;
    transport_socket_t *sock = context->sockets[index];
    
    // If the socket is already wrapped in a CFSocket then return.
    if (sock->cf_socket || sock->cf_read_stream) {
        return 1;
    }
    
    // Put a reference to the transport context 
    const CFSocketContext socket_context = { 0, transport, NULL, NULL, NULL };
    
    if (TNET_SOCKET_TYPE_IS_DGRAM(sock->type)) {
        
        // Create a CFSocket from the native socket and register for Read events
        sock->cf_socket = CFSocketCreateWithNative(kCFAllocatorDefault, 
                                                   sock->fd,
                                                   kCFSocketReadCallBack, 
                                                   &__CFSocketCallBack, 
                                                   &socket_context);
        
        // Don't close the socket if the CFSocket is invalidated
        CFOptionFlags flags = CFSocketGetSocketFlags(sock->cf_socket);
        flags = flags & ~kCFSocketCloseOnInvalidate;
        CFSocketSetSocketFlags(sock->cf_socket, flags);
		
        
        // Create a new RunLoopSource and register it with the main thread RunLoop
        sock->cf_run_loop_source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, sock->cf_socket, 0);
        CFRunLoopAddSource(context->cf_run_loop, sock->cf_run_loop_source, kCFRunLoopDefaultMode);
        CFRelease(sock->cf_run_loop_source);
        
    } else if (TNET_SOCKET_TYPE_IS_STREAM(sock->type)) {
        
        // Create a pair of streams (read/write) from the socket
        CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock->fd, &sock->cf_read_stream, &sock->cf_write_stream);
        
        // Don't close underlying socket
        CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse);
        CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse);
        
        if (TNET_SOCKET_TYPE_IS_SECURE(sock->type)) {
            CFMutableDictionaryRef settings = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
            CFDictionaryAddValue(settings, kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue);
            CFDictionaryAddValue(settings, kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue);
            CFDictionaryAddValue(settings, kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse);
            CFDictionaryAddValue(settings, kCFStreamSSLPeerName, kCFNull);
            
            // Set the SSL settings
            CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL);
            CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamPropertySSLSettings, settings);
            CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL);
            CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamPropertySSLSettings, settings);
            
            CFRelease(settings);
        }
        
#if __IPHONE_4_0
        // Mark the stream for VoIP usage
        CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
        CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
#endif
        
        // Setup a context for the streams
        CFStreamClientContext streamContext = { 0, transport, NULL, NULL, NULL };
        
        // Set the client callback for the stream
        CFReadStreamSetClient(sock->cf_read_stream, 
                              kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
                              &__CFReadStreamClientCallBack, 
                              &streamContext);
        CFWriteStreamSetClient(sock->cf_write_stream, 
                               kCFStreamEventOpenCompleted | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, 
                               &__CFWriteStreamClientCallBack, 
                               &streamContext);
        
        // Enroll streams in the run-loop
        CFReadStreamScheduleWithRunLoop(sock->cf_read_stream, context->cf_run_loop, kCFRunLoopDefaultMode);
        CFWriteStreamScheduleWithRunLoop(sock->cf_write_stream, context->cf_run_loop, kCFRunLoopDefaultMode);
        
        // Release references
        CFRelease(sock->cf_read_stream);
        CFRelease(sock->cf_write_stream);
        
        CFReadStreamOpen(sock->cf_read_stream);
        CFWriteStreamOpen(sock->cf_write_stream);
    }
    
    return 0;
}