Esempio n. 1
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;
}
Esempio n. 2
0
CURLcode SSLImpl::connect(int sockfd, int nonblocking, int *done, int ssl_verify_peer, void *storage, char* host_name)
{
    ssl_data_t *data = (ssl_data_t*)storage;
    
    CFStreamCreatePairWithSocket(kCFAllocatorDefault, sockfd, &data->readStream, &data->writeStream);
    // Indicate that the connection needs to be done in secure manner
    CFReadStreamSetProperty(data->readStream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelSSLv3);
    CFWriteStreamSetProperty(data->writeStream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelSSLv3);
    
    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (!dict) {
        RAWLOG_ERROR("Can not allocate CFMutableDictionaryRef");
        return CURLE_SSL_CONNECT_ERROR;
    }
    
    CFDictionarySetValue(dict, kCFStreamSSLValidatesCertificateChain, ssl_verify_peer ? kCFBooleanTrue : kCFBooleanFalse);
    CFReadStreamSetProperty(data->readStream, kCFStreamPropertySSLSettings, dict);
    CFWriteStreamSetProperty(data->writeStream, kCFStreamPropertySSLSettings, dict);
    CFRelease(dict);
    
    if (!CFReadStreamOpen(data->readStream) || !CFWriteStreamOpen(data->writeStream)) {
        RAWLOG_ERROR("SSL connection error");
        return CURLE_SSL_CONNECT_ERROR;
    }
    CFReadStreamScheduleWithRunLoop(    data->readStream,
                                        CFRunLoopGetCurrent(),
                                        kCFRunLoopCommonModes);
    CFWriteStreamScheduleWithRunLoop(    data->writeStream,
                                    CFRunLoopGetCurrent(),
                                    kCFRunLoopCommonModes);
    *done = 1;
    return CURLE_OK;
}
Esempio n. 3
0
void SSLImpl::shutdown(void *storage)
{
    ssl_data_t *data = (ssl_data_t*)storage;
    if (!data)
        return;
    CFReadStreamScheduleWithRunLoop(    data->readStream,
                                    CFRunLoopGetCurrent(),
                                    kCFRunLoopCommonModes);
    CFWriteStreamScheduleWithRunLoop(    data->writeStream,
                                     CFRunLoopGetCurrent(),
                                     kCFRunLoopCommonModes);
    if (data->readStream) {
        CFReadStreamRef readStream = (CFReadStreamRef)data->readStream;
        CFReadStreamClose(readStream);
        data->readStream = NULL;
    }
    if (data->writeStream) {
        CFWriteStreamRef writeStream = (CFWriteStreamRef)data->writeStream;
        CFWriteStreamClose(writeStream);
        data->writeStream = NULL;
    }
}
Esempio n. 4
0
extern MyInfoRef StartWWAN(ConnectClientCallBack clientCB, void *refCon)
{
	char						host[] = kTestHost;
	int							portNum = kTestPort;
	CFDataRef					addressData;
	MyStreamInfoPtr				myInfoPtr;
	CFStreamClientContext		ctxt = {0, NULL, NULL, NULL, NULL};
	Boolean						errorOccurred = FALSE;
	
	myInfoPtr = malloc(sizeof(MyStreamInfo));
	if (!myInfoPtr)
	{
		return NULL;
	}
	
	// init the allocated memory
	memset(myInfoPtr, 0, sizeof(MyStreamInfo));
	myInfoPtr->clientCB = clientCB;
	myInfoPtr->refCon = refCon;
	ctxt.info = myInfoPtr;
	
	// Check for a dotted-quad address, if so skip any host lookups
	in_addr_t addr = inet_addr(host);
	if (addr != INADDR_NONE) {
		// Create the streams from numberical host
		struct sockaddr_in sin;
		memset(&sin, 0, sizeof(sin));
		
		sin.sin_len= sizeof(sin);
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr = addr;
		sin.sin_port = htons(portNum);
		
		addressData = CFDataCreate(NULL, (UInt8 *)&sin, sizeof(sin));
		CFSocketSignature sig = { AF_INET, SOCK_STREAM, IPPROTO_TCP, addressData };
		
		// Create the streams.
		CFStreamCreatePairWithPeerSocketSignature(kCFAllocatorDefault, &sig, &(myInfoPtr->rStreamRef), &(myInfoPtr->wStreamRef));
		CFRelease(addressData);
	} else {
		// Create the streams from ascii host name
		CFStringRef hostStr = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, host, kCFStringEncodingUTF8, kCFAllocatorNull);
		CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, hostStr, portNum, &(myInfoPtr->rStreamRef), &(myInfoPtr->wStreamRef));
        //hostStr = NULL;
        if(hostStr)
        {
            CFRelease(hostStr);
        }
	}
	
	myInfoPtr->isConnected = FALSE;
	myInfoPtr->isStreamInitd = TRUE;
	myInfoPtr->isClientSet = FALSE;
	
	// Inform the streams to kill the socket when it is done with it.
	// This effects the write stream too since the pair shares the
	// one socket.
	CFWriteStreamSetProperty(myInfoPtr->wStreamRef, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
	
	// set up the client
	if (!CFWriteStreamSetClient(myInfoPtr->wStreamRef, kCFStreamEventOpenCompleted | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
								MyCFWriteStreamClientCallBack, &ctxt))
	{
		printf("CFWriteStreamSetClient failed\n");
		errorOccurred = TRUE;
	}
	else
		myInfoPtr->isClientSet = TRUE;
	
	if (!errorOccurred)
	{
		// schedule the stream
		CFWriteStreamScheduleWithRunLoop(myInfoPtr->wStreamRef, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
		
		// Try to open the stream.
		if (!CFWriteStreamOpen(myInfoPtr->wStreamRef))
		{
			printf("CFWriteStreamOpen failed\n");
			errorOccurred = TRUE;
		}
	}
	
	if (!errorOccurred)
	{
		// everything worked so far, so run the runloop - when the callback gets called, it will stop the run loop
		printf("CFWriteStreamOpen returned with no error - calling CFRunLoopRun\n");
		CFRunLoopRun();
		if (myInfoPtr->errorOccurred)
			errorOccurred = TRUE;
		printf("after CFRunLoopRun - returning\n");
	}
	
	if (errorOccurred)
	{
		myInfoPtr->isConnected = FALSE;
		CleanupAfterWAAN(myInfoPtr);
		CloseStreams(myInfoPtr);
		
		if (myInfoPtr->isStreamInitd)
		{
            if(myInfoPtr->rStreamRef)
                CFRelease(myInfoPtr->rStreamRef);
            if(myInfoPtr->wStreamRef)
                CFRelease(myInfoPtr->wStreamRef);
			myInfoPtr->isStreamInitd = FALSE;
		}
		free(myInfoPtr);
		return NULL;
	}
    
	return (MyInfoRef)myInfoPtr;
}
static int wait_runloop(mailstream_low * s, int wait_state)
{
  struct mailstream_cfstream_data * cfstream_data;
  int read_scheduled;
  int write_scheduled;
  int error;
  
  setup_runloop(s);
  
  cfstream_data = (struct mailstream_cfstream_data *) s->data;
  cfstream_data->state = wait_state;
  
  read_scheduled = 0;
  write_scheduled = 0;
  error = WAIT_RUNLOOP_EXIT_NO_ERROR;
  
  switch (wait_state) {
    case STATE_WAIT_OPEN:
      //fprintf(stderr, "wait open\n");
      CFReadStreamScheduleWithRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
      CFWriteStreamScheduleWithRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
      read_scheduled = 1;
      write_scheduled = 1;
      break;
    case STATE_WAIT_READ:
      //fprintf(stderr, "wait read\n");
      CFReadStreamScheduleWithRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
      read_scheduled = 1;
      break;
    case STATE_WAIT_WRITE:
      //fprintf(stderr, "wait write\n");
      CFWriteStreamScheduleWithRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
      write_scheduled = 1;
      break;
    case STATE_WAIT_IDLE:
      //fprintf(stderr, "wait idle\n");
      CFReadStreamScheduleWithRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
      read_scheduled = 1;
      break;
    case STATE_WAIT_SSL:
      //fprintf(stderr, "wait ssl\n");
      CFReadStreamScheduleWithRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
      CFWriteStreamScheduleWithRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
      read_scheduled = 1;
      write_scheduled = 1;
      break;
  }
  
  if (read_scheduled) {
    if (CFReadStreamHasBytesAvailable(cfstream_data->readStream)) {
      readStreamCallback(cfstream_data->readStream, kCFStreamEventHasBytesAvailable, s);
    }
  }
  if (write_scheduled) {
    if (CFWriteStreamCanAcceptBytes(cfstream_data->writeStream)) {
      writeStreamCallback(cfstream_data->writeStream, kCFStreamEventCanAcceptBytes, s);
    }
  }
  
  while (1) {
    struct timeval timeout;
    CFTimeInterval delay;
    int r;
    int done;
    
    if (cfstream_data->cancelled) {
      error = WAIT_RUNLOOP_EXIT_CANCELLED;
      break;
    }
    if (cfstream_data->state == STATE_WAIT_IDLE) {
      if (cfstream_data->idleInterrupted) {
        error = WAIT_RUNLOOP_EXIT_INTERRUPTED;
        break;
      }
    }

    done = 0;
    switch (cfstream_data->state) {
      case STATE_OPEN_READ_DONE:
        CFReadStreamUnscheduleFromRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
        read_scheduled = 0;
        break;
      case STATE_OPEN_WRITE_DONE:
        CFWriteStreamUnscheduleFromRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
        write_scheduled = 0;
        break;
      case STATE_OPEN_READ_WRITE_DONE:
        done = 1;
        break;
      case STATE_OPEN_WRITE_READ_DONE:
        done = 1;
        break;
      case STATE_READ_DONE:
        done = 1;
        break;
      case STATE_WRITE_DONE:
        done = 1;
        break;
      case STATE_IDLE_DONE:
        done = 1;
        break;
      case STATE_SSL_READ_DONE:
        done = 1;
        break;
      case STATE_SSL_WRITE_DONE:
        done = 1;
        break;
      case STATE_SSL_READ_WRITE_DONE:
        done = 1;
        break;
      case STATE_SSL_WRITE_READ_DONE:
        done = 1;
        break;
    }
    
    if (done) {
      break;
    }
    
    if (wait_state == STATE_WAIT_IDLE) {
      timeout.tv_sec = cfstream_data->idleMaxDelay;
      timeout.tv_usec = 0;
    }
    else {
	    if (s->timeout == 0) {
				timeout = mailstream_network_delay;
			}
			else {
	      timeout.tv_sec = s->timeout;
	      timeout.tv_usec = 0;
			}
    }
    delay = (CFTimeInterval) timeout.tv_sec + (CFTimeInterval) timeout.tv_usec / (CFTimeInterval) 1e6;
    
    r = CFRunLoopRunInMode(kCFRunLoopDefaultMode, delay, true);
    if (r == kCFRunLoopRunTimedOut) {
      error = WAIT_RUNLOOP_EXIT_TIMEOUT;
      break;
    }
  }
  
  if (read_scheduled) {
    CFReadStreamUnscheduleFromRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
  }
  if (write_scheduled) {
    CFWriteStreamUnscheduleFromRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode);
  }
  
  unsetup_runloop(s);
  
  if (error != WAIT_RUNLOOP_EXIT_NO_ERROR)
    return error;
  
  return WAIT_RUNLOOP_EXIT_NO_ERROR;
}
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;
}
Esempio n. 7
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;
}
Esempio n. 8
0
/* MySimpleUpload implements the upload command.  It sets up a MyStreamInfo 'object' 
with the read stream being a file stream of the file to upload and the write stream being 
an FTP 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
MySimpleUpload(CFStringRef uploadDirectory, CFURLRef fileURL, CFStringRef username, CFStringRef password)
{
    CFWriteStreamRef       writeStream;
    CFReadStreamRef        readStream;
    CFStreamClientContext  context = { 0, NULL, NULL, NULL, NULL };
    CFURLRef               uploadURL, destinationURL;
    CFStringRef            fileName;
    Boolean                success = true;
    MyStreamInfo           *streamInfo;

    assert(uploadDirectory != NULL);
    assert(fileURL != NULL);
    assert( (username != NULL) || (password == NULL) );
    
    /* Create a CFURL from the upload directory string */
    destinationURL = CFURLCreateWithString(kCFAllocatorDefault, uploadDirectory, NULL);
    assert(destinationURL != NULL);

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

    /* Create the destination URL by taking the upload directory and appending the file name. */
    uploadURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, destinationURL, fileName, false);
    assert(uploadURL != NULL);
    CFRelease(destinationURL);
    CFRelease(fileName);
    
    /* Create a CFReadStream from the local file being uploaded. */
    readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL);
    assert(readStream != NULL);
    
    /* Create an FTP write stream for uploading operation to a FTP URL. If the URL specifies a
    directory, the open will be followed by a close event/state and the directory will have been
    created. Intermediary directory structure is not created. */
    writeStream = CFWriteStreamCreateWithFTPURL(kCFAllocatorDefault, uploadURL);
    assert(writeStream != NULL);
    CFRelease(uploadURL);
    
    /* Initialize our MyStreamInfo structure, which we use to store some information about the stream. */
    MyStreamInfoCreate(&streamInfo, readStream, writeStream);
    context.info = (void *)streamInfo;

    /* 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) {
        
        /* CFWriteStreamSetClient registers a callback to hear about interesting events that occur on a stream. */
        success = CFWriteStreamSetClient(writeStream, kNetworkEvents, MyUploadCallBack, &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. */
            CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
            
            MyCFStreamSetUsernamePassword(writeStream, username, password);
            MyCFStreamSetFTPProxy(writeStream, &streamInfo->proxyDict);
            
            /* 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 == false) {
                fprintf(stderr, "CFWriteStreamOpen failed\n");
                MyStreamInfoDestroy(streamInfo);
            }
        } else {
            fprintf(stderr, "CFWriteStreamSetClient failed\n");
            MyStreamInfoDestroy(streamInfo);
        }
    } else {
        fprintf(stderr, "CFReadStreamOpen failed\n");
        MyStreamInfoDestroy(streamInfo);
    }

    return success;
}