コード例 #1
0
static ssize_t mailstream_low_cfstream_write(mailstream_low * s,
                                             const void * buf, size_t count)
{
#if HAVE_CFNETWORK
  struct mailstream_cfstream_data * cfstream_data;
  int r;
  
  cfstream_data = (struct mailstream_cfstream_data *) s->data;
  cfstream_data->writeBuffer = buf;
  cfstream_data->writeBufferSize = count;
  
  if (cfstream_data->cancelled)
    return -1;
  
  if (CFWriteStreamCanAcceptBytes(cfstream_data->writeStream)) {
    writeDataToStream(s);
    return cfstream_data->writeResult;
  }
  
  r = wait_runloop(s, STATE_WAIT_WRITE);
  if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) {
    return -1;
  }
  
  return cfstream_data->writeResult;
#else
  return -1;
#endif
}
コード例 #2
0
int SocketStreamHandle::platformSend(const char* data, int length)
{
    if (!CFWriteStreamCanAcceptBytes(m_writeStream.get()))
        return 0;

    return CFWriteStreamWrite(m_writeStream.get(), reinterpret_cast<const UInt8*>(data), length);
}
コード例 #3
0
ファイル: HttpContext.c プロジェクト: DoktahWorm/rhodes
/* static */ void
_HttpContextHandleHasBytesAvailable(HttpContextRef context) {

	UInt8 buffer[2048];
	
	// Try reading the bytes into the buffer.
	CFIndex bytesRead = CFReadStreamRead(context->_inStream, buffer, sizeof(buffer));
	
	// Reset the timeout.
	CFRunLoopTimerSetNextFireDate(context->_timer, CFAbsoluteTimeGetCurrent() + kTimeOutInSeconds);
	
	// If there wasn't an error (-1) and not end (0), process the data.
	if (bytesRead > 0) {
		
		// Add the bytes of data to the receive buffer.
		CFDataAppendBytes(context->_rcvdBytes, buffer, bytesRead);

		// Parse recieved data
        int result = HTTPParseRequest(context);      
        
        if ( result == 1 ) {
            // HTTP message is fully loaded, process it
            HTTPProcessMessage(context);
			
			// Reset the timeout.
			CFRunLoopTimerSetNextFireDate(context->_timer, CFAbsoluteTimeGetCurrent() + kTimeOutInSeconds);
        }
        
        // If the ouput stream can write, try sending the bytes.
		if (result != 0 && CFWriteStreamCanAcceptBytes(context->_outStream))
			_HttpContextHandleCanAcceptBytes(context);
	}
}
コード例 #4
0
void SocketStreamHandle::writeStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventCanAcceptBytes: {
        // Possibly, a spurious event from CONNECT handshake.
        if (!CFWriteStreamCanAcceptBytes(m_writeStream.get()))
            return;

        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);
            break;
        }

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        sendPendingData();
        break;
    }
    case kCFStreamEventErrorOccurred: {
#ifndef BUILDING_ON_TIGER
        RetainPtr<CFErrorRef> error(AdoptCF, CFWriteStreamCopyError(m_writeStream.get()));
        reportErrorToClient(error.get());
#else
        CFStreamError error = CFWriteStreamGetError(m_writeStream.get());
        m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error.
#endif
        break;
    }
    case kCFStreamEventEndEncountered:
        // FIXME: Currently, we handle closing in read callback, but these can come independently (e.g. a server can stop listening, but keep sending data).
        break;
    }
}
コード例 #5
0
ファイル: sslimpl.cpp プロジェクト: nhinze/rhodes
ssize_t SSLImpl::send(const void *mem, size_t len, void *storage)
{
    ssl_data_t *data = (ssl_data_t*)storage;
    
    if (!CFWriteStreamCanAcceptBytes(data->writeStream))
        return 0;
    
    int rc = CFWriteStreamWrite(data->writeStream, (const UInt8 *)mem, len);
    if (rc < 0) {
        CFStreamError err = CFWriteStreamGetError(data->writeStream);
        report_error("SSL send failed", &err);
        return -1;
    }
    
    return rc;
}
コード例 #6
0
    OSStatus TCPStream_CFNetwork::secureTransportWriteCallback (SSLConnectionRef connection,
                                                  const void *data,
                                                  size_t *dataLength)
    {
        auto actualStream = reinterpret_cast<TCPStream_CFNetwork const *>(connection);

        if (!CFWriteStreamCanAcceptBytes(actualStream->outputStream)) {
            *dataLength = 0;
            return errSSLWouldBlock;
        }

        auto bytesWritten = CFWriteStreamWrite(actualStream->outputStream, reinterpret_cast<UInt8 const *>(data), *dataLength);

        if (bytesWritten < *dataLength) {
            *dataLength = bytesWritten;
            return errSSLWouldBlock;
        }

        return noErr;
    }
コード例 #7
0
void SocketStreamHandle::writeStreamCallback(CFStreamEventType type)
{
    switch(type) {
    case kCFStreamEventNone:
        break;
    case kCFStreamEventOpenCompleted:
        break;
    case kCFStreamEventHasBytesAvailable:
        ASSERT_NOT_REACHED();
        break;
    case kCFStreamEventCanAcceptBytes: {
        // Possibly, a spurious event from CONNECT handshake.
        if (!CFWriteStreamCanAcceptBytes(m_writeStream.get()))
            return;

        if (m_connectingSubstate == WaitingForCredentials)
            break;

        if (m_connectingSubstate == WaitingForConnect) {
            m_connectingSubstate = Connected;
            m_state = Open;
            m_client->didOpenSocketStream(this);
            break;
        }

        ASSERT(m_state == Open);
        ASSERT(m_connectingSubstate == Connected);

        sendPendingData();
        break;
    }
    case kCFStreamEventErrorOccurred: {
        RetainPtr<CFErrorRef> error(AdoptCF, CFWriteStreamCopyError(m_writeStream.get()));
        reportErrorToClient(error.get());
        break;
    }
    case kCFStreamEventEndEncountered:
        // FIXME: Currently, we handle closing in read callback, but these can come independently (e.g. a server can stop listening, but keep sending data).
        break;
    }
}
コード例 #8
0
// Internal function, write provided buffer as websocket frame [0x00 buffer 0xff]
//
CFIndex
__WebSocketClientWriteFrame (WebSocketClientRef client, const UInt8 *buffer, CFIndex length) {
    CFIndex result = 0;
    if (client) {
        if (buffer) {
            if (length > 0) {
                if (CFWriteStreamCanAcceptBytes(client->write)) {
                    CFIndex didWrite = CFWriteStreamWrite(client->write, (UInt8[]) { (UInt8) 0x00 }, 1);
                    if (didWrite == 1) {
                        result += didWrite;
                        didWrite = CFWriteStreamWrite(client->write, buffer, length);
                        if (didWrite == length) {
                            result += didWrite;
                            didWrite = CFWriteStreamWrite(client->write, (UInt8[]) { (UInt8) 0xff }, 1);
                            if (didWrite == 1) {
                                result += didWrite;
                            }
                        }
                    }
                }
            }
コード例 #9
0
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;
}