示例#1
0
int mailstream_wait_idle(mailstream * s, int max_idle_delay)
{
  int fd;
  int idle_fd;
  int cancel_fd;
  int maxfd;
  fd_set readfds;
  struct timeval delay;
  int r;
  
  if (s->low->driver == mailstream_cfstream_driver) {
    return mailstream_cfstream_wait_idle(s, max_idle_delay);
  }
  
  fd = mailstream_low_get_fd(mailstream_get_low(s));
  idle_fd = mailstream_cancel_get_fd(s->idle);
  cancel_fd = mailstream_cancel_get_fd(mailstream_low_get_cancel(mailstream_get_low(s)));
  
  FD_ZERO(&readfds);
  FD_SET(fd, &readfds);
  FD_SET(idle_fd, &readfds);
  FD_SET(cancel_fd, &readfds);
  maxfd = fd;
  if (idle_fd > maxfd) {
    maxfd = idle_fd;
  }
  if (cancel_fd > maxfd) {
    maxfd = cancel_fd;
  }
  delay.tv_sec = max_idle_delay;
  delay.tv_usec = 0;
  
  r = select(maxfd + 1, &readfds, NULL, NULL, &delay);
  if (r == 0) {
    // timeout
    return MAILSTREAM_IDLE_TIMEOUT;
  }
  else if (r == -1) {
    // do nothing
    return MAILSTREAM_IDLE_ERROR;
  }
  else {
    if (FD_ISSET(fd, &readfds)) {
      // has something on socket
      return MAILSTREAM_IDLE_HASDATA;
    }
    if (FD_ISSET(idle_fd, &readfds)) {
      // idle interrupted
      mailstream_cancel_ack(s->idle);
      return MAILSTREAM_IDLE_INTERRUPTED;
    }
    if (FD_ISSET(cancel_fd, &readfds)) {
      // idle cancelled
      mailstream_cancel_ack(mailstream_low_get_cancel(mailstream_get_low(s)));
      return MAILSTREAM_IDLE_CANCELLED;
    }
    return MAILSTREAM_IDLE_ERROR;
  }
}
示例#2
0
static int wait_read(mailstream_low * s)
{
  fd_set fds_read;
  struct timeval timeout;
  int fd;
  struct mailstream_ssl_data * ssl_data;
  int max_fd;
  int r;
  int cancelled;
  int got_data;
#ifdef WIN32
  HANDLE event;
#endif
  
  ssl_data = (struct mailstream_ssl_data *) s->data;
  timeout = mailstream_network_delay;
  
#ifdef USE_GNUTLS
  if (gnutls_record_check_pending(ssl_data->session) != 0)
    return 0;
#endif

  FD_ZERO(&fds_read);
  fd = mailstream_cancel_get_fd(ssl_data->cancel);
  FD_SET(fd, &fds_read);
#ifdef WIN32
  event = CreateEvent(NULL, TRUE, FALSE, NULL);
  WSAEventSelect(ssl_data->fd, event, FD_READ | FD_CLOSE);
  FD_SET(event, &fds_read);
  r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
  if (WAIT_TIMEOUT == r)
    return -1;
  
  cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd);
  got_data = (fds_read.fd_array[r - WAIT_OBJECT_0] == event);
#else
  FD_SET(ssl_data->fd, &fds_read);
  max_fd = ssl_data->fd;
  if (fd > max_fd)
    max_fd = fd;
  r = select(max_fd + 1, &fds_read, NULL, NULL, &timeout);
  if (r <= 0)
    return -1;
  
  cancelled = (FD_ISSET(fd, &fds_read));
  got_data = FD_ISSET(ssl_data->fd, &fds_read);
#endif
  if (cancelled) {
    /* cancelled */
    mailstream_cancel_ack(ssl_data->cancel);
    return -1;
  }
  
  return 0;
}
示例#3
0
/*
 mostly copied from mailstream_ssl.c
 removed their windows support - we only need iOS
*/
static int wait_write_compress(mailstream_low * s)
{
  fd_set fds_read;
  fd_set fds_write;
  struct timeval timeout;
  int r;
  int fd;
  int max_fd;
  int cancelled;
  int write_enabled;
    
  // use the session timeout if set
  if (s->timeout) {
    timeout.tv_sec = s->timeout;
    timeout.tv_usec = 0;
  } else {
    timeout = mailstream_network_delay;
  }
    
  FD_ZERO(&fds_read);
  struct mailstream_cancel * cancel = mailstream_low_compress_get_cancel(s);
  fd = mailstream_cancel_get_fd(cancel);
  FD_SET(fd, &fds_read);
  FD_ZERO(&fds_write);
  FD_SET(mailstream_low_compress_get_fd(s), &fds_write);
    
  max_fd = mailstream_low_compress_get_fd(s);
  if (fd > max_fd)
    max_fd = fd;
    
  r = select(max_fd + 1, &fds_read, &fds_write, NULL, &timeout);
  if (r <= 0)
    return -1;
    
  cancelled = FD_ISSET(fd, &fds_read);
  write_enabled = FD_ISSET(mailstream_low_compress_get_fd(s), &fds_write);
    
  if (cancelled) {
    /* cancelled */
    mailstream_cancel_ack(cancel);
    return -1;
  }
    
  if (!write_enabled)
    return 0;
    
  return 1;
}
示例#4
0
static int wait_write(mailstream_low * s)
{
  fd_set fds_read;
  fd_set fds_write;
  struct timeval timeout;
  int r;
  int fd;
  struct mailstream_ssl_data * ssl_data;
  int max_fd;
  int cancelled;
  int write_enabled;
#ifdef WIN32
  HANDLE event;
#endif
  
  ssl_data = (struct mailstream_ssl_data *) s->data;
  if (mailstream_cancel_cancelled(ssl_data->cancel))
    return -1;
 
  if (s->timeout == 0) {
    timeout = mailstream_network_delay;
  }
  else {
		timeout.tv_sec = s->timeout;
    timeout.tv_usec = 0;
  }
  
  FD_ZERO(&fds_read);
  fd = mailstream_cancel_get_fd(ssl_data->cancel);
  FD_SET(fd, &fds_read);
  FD_ZERO(&fds_write);
#ifdef WIN32
  event = CreateEvent(NULL, TRUE, FALSE, NULL);
  WSAEventSelect(ssl_data->fd, event, FD_WRITE | FD_CLOSE);
  FD_SET(event, &fds_read);
  r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
  if (r < 0) {
		WSAEventSelect(ssl_data->fd, event, 0);
		CloseHandle(event);
    return -1;
	}
  
  cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd) /* SEB 20070709 */;
  write_enabled = (fds_read.fd_array[r - WAIT_OBJECT_0] == event);
	WSAEventSelect(ssl_data->fd, event, 0);
	CloseHandle(event);
#else
  FD_SET(ssl_data->fd, &fds_write);
  
  max_fd = ssl_data->fd;
  if (fd > max_fd)
    max_fd = fd;
  
  r = select(max_fd + 1, &fds_read, &fds_write, NULL, &timeout);
  if (r <= 0)
    return -1;
  
  cancelled = FD_ISSET(fd, &fds_read);
  write_enabled = FD_ISSET(ssl_data->fd, &fds_write);
#endif
  
  if (cancelled) {
    /* cancelled */
    mailstream_cancel_ack(ssl_data->cancel);
    return -1;
  }
  
  if (!write_enabled)
    return 0;
  
  return 1;
}
示例#5
0
static int wait_write(mailstream_low * s)
{
  struct timeval timeout;
  int r;
  int cancellation_fd;
  struct mailstream_ssl_data * ssl_data;
  int cancelled;
  int write_enabled;
#if defined(WIN32)
  fd_set fds_read;
  fd_set fds_write;
  HANDLE event;
#elif USE_POLL
  struct pollfd pfd[2];
#else
  fd_set fds_read;
  fd_set fds_write;
  int max_fd;
#endif
  
  ssl_data = (struct mailstream_ssl_data *) s->data;
  if (mailstream_cancel_cancelled(ssl_data->cancel))
    return -1;
 
  if (s->timeout == 0) {
    timeout = mailstream_network_delay;
  }
  else {
		timeout.tv_sec = s->timeout;
    timeout.tv_usec = 0;
  }
  
  cancellation_fd = mailstream_cancel_get_fd(ssl_data->cancel);
#if defined(WIN32)
  FD_ZERO(&fds_read);
  FD_ZERO(&fds_write);
  FD_SET(cancellation_fd, &fds_read);
  event = CreateEvent(NULL, TRUE, FALSE, NULL);
  WSAEventSelect(ssl_data->fd, event, FD_WRITE | FD_CLOSE);
  FD_SET(event, &fds_read);
  r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
  if (r < 0) {
		WSAEventSelect(ssl_data->fd, event, 0);
		CloseHandle(event);
    return -1;
	}
  
  cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == cancellation_fd) /* SEB 20070709 */;
  write_enabled = (fds_read.fd_array[r - WAIT_OBJECT_0] == event);
	WSAEventSelect(ssl_data->fd, event, 0);
	CloseHandle(event);
#elif USE_POLL
  pfd[0].fd = ssl_data->fd;
  pfd[0].events = POLLOUT;
  pfd[0].revents = 0;

  pfd[1].fd = cancellation_fd;
  pfd[1].events = POLLIN;
  pfd[1].revents = 0;

  r = poll(&pfd[0], 2, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
  if (r <= 0)
    return -1;
 
  cancelled = pfd[1].revents & POLLIN;
  write_enabled = pfd[0].revents & POLLOUT;
#else
  FD_ZERO(&fds_read);
  FD_ZERO(&fds_write);
  FD_SET(cancellation_fd, &fds_read);
  FD_SET(ssl_data->fd, &fds_write);
  
  max_fd = cancellation_fd > ssl_data->fd ? cancellation_fd : ssl_data->fd;
  r = select(max_fd + 1, &fds_read, &fds_write, NULL, &timeout);
  if (r <= 0)
    return -1;

  cancelled = FD_ISSET(cancellation_fd, &fds_read);
  write_enabled = FD_ISSET(ssl_data->fd, &fds_write);
#endif
  
  if (cancelled) {
    /* cancelled */
    mailstream_cancel_ack(ssl_data->cancel);
    return -1;
  }
  
  if (!write_enabled)
    return 0;
  
  return 1;
}
示例#6
0
static int wait_read(mailstream_low * s)
{
  struct timeval timeout;
  int cancellation_fd;
  struct mailstream_ssl_data * ssl_data;
  int r;
  int cancelled;
#if defined(WIN32)
  fd_set fds_read;
  HANDLE event;
#elif USE_POLL
  struct pollfd pfd[2];
#else
  fd_set fds_read;
  int max_fd;
#endif

  ssl_data = (struct mailstream_ssl_data *) s->data;
  if (s->timeout == 0) {
    timeout = mailstream_network_delay;
  }
  else {
		timeout.tv_sec = s->timeout;
    timeout.tv_usec = 0;
  }
  
#ifdef USE_GNUTLS
  if (gnutls_record_check_pending(ssl_data->session) != 0)
    return 0;
#endif

  cancellation_fd = mailstream_cancel_get_fd(ssl_data->cancel);
#if defined(WIN32)
  FD_ZERO(&fds_read);
  FD_SET(cancellation_fd, &fds_read);
  event = CreateEvent(NULL, TRUE, FALSE, NULL);
  WSAEventSelect(ssl_data->fd, event, FD_READ | FD_CLOSE);
  FD_SET(event, &fds_read);
  r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
  if (WAIT_TIMEOUT == r) {
    WSAEventSelect(ssl_data->fd, event, 0);
    CloseHandle(event);
    return -1;
  }
  
  cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == cancellation_fd);
  WSAEventSelect(ssl_data->fd, event, 0);
  CloseHandle(event);
#elif USE_POLL
  pfd[0].fd = ssl_data->fd;
  pfd[0].events = POLLIN;
  pfd[0].revents = 0;

  pfd[1].fd = cancellation_fd;
  pfd[1].events = POLLIN;
  pfd[1].revents = 0;

  r = poll(&pfd[0], 2, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
  if (r <= 0)
    return -1;
  
  cancelled = pfd[1].revents & POLLIN;
#else
  FD_ZERO(&fds_read);
  FD_SET(cancellation_fd, &fds_read);
  FD_SET(ssl_data->fd, &fds_read);
  max_fd = cancellation_fd > ssl_data->fd ? cancellation_fd : ssl_data->fd;
  r = select(max_fd + 1, &fds_read, NULL, NULL, &timeout);
  if (r <= 0)
      return -1;
  cancelled = FD_ISSET(cancellation_fd, &fds_read);
#endif
  if (cancelled) {
    /* cancelled */
    mailstream_cancel_ack(ssl_data->cancel);
    return -1;
  }
  
  return 0;
}
示例#7
0
int mailstream_low_wait_idle(mailstream_low * low, struct mailstream_cancel * idle,
                             int max_idle_delay)
{
  int fd;
  int idle_fd;
  int cancel_fd;
  int maxfd;
  fd_set readfds;
  struct timeval delay;
  int r;
  
  if (low->driver == mailstream_cfstream_driver) {
    return mailstream_low_cfstream_wait_idle(low, max_idle_delay);
  }
  else if (low->driver == mailstream_compress_driver) {
    return mailstream_low_compress_wait_idle(low, idle, max_idle_delay);
  }
  
  if (idle == NULL) {
		return MAILSTREAM_IDLE_ERROR;
	}
  if (mailstream_low_get_cancel(low) == NULL) {
		return MAILSTREAM_IDLE_ERROR;
	}
  fd = mailstream_low_get_fd(low);
  idle_fd = mailstream_cancel_get_fd(idle);
  cancel_fd = mailstream_cancel_get_fd(mailstream_low_get_cancel(low));
  
  FD_ZERO(&readfds);
#ifdef WIN32
  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
  WSAEventSelect(fd, event, FD_READ | FD_CLOSE);
  FD_SET(event, &readfds);
  FD_SET(idle_fd, &readfds);
  FD_SET(cancel_fd, &readfds);
  r = WaitForMultipleObjects(readfds.fd_count, readfds.fd_array, FALSE, max_idle_delay * 1000);
  WSAEventSelect(fd, event, 0);
  CloseHandle(event);
  if (r == WAIT_TIMEOUT) {
	  return MAILSTREAM_IDLE_TIMEOUT;
  }
  else if (r == WAIT_OBJECT_0){
	  return MAILSTREAM_IDLE_HASDATA;
  }
  else if (r == WAIT_OBJECT_0 + 1){
	  return MAILSTREAM_IDLE_INTERRUPTED;
  }
  else if (r == WAIT_OBJECT_0 + 2){
	  return MAILSTREAM_IDLE_CANCELLED;
  }
  DWORD i = GetLastError();
  return MAILSTREAM_IDLE_ERROR;
#else
  FD_SET(fd, &readfds);
  FD_SET(idle_fd, &readfds);
  FD_SET(cancel_fd, &readfds);
  maxfd = fd;
  if (idle_fd > maxfd) {
    maxfd = idle_fd;
  }
  if (cancel_fd > maxfd) {
    maxfd = cancel_fd;
  }
  delay.tv_sec = max_idle_delay;
  delay.tv_usec = 0;
  
  r = select(maxfd + 1, &readfds, NULL, NULL, &delay);
  if (r == 0) {
    // timeout
    return MAILSTREAM_IDLE_TIMEOUT;
  }
  else if (r == -1) {
    // do nothing
    return MAILSTREAM_IDLE_ERROR;
  }
  else {
    if (FD_ISSET(fd, &readfds)) {
      // has something on socket
      return MAILSTREAM_IDLE_HASDATA;
    }
    if (FD_ISSET(idle_fd, &readfds)) {
      // idle interrupted
      mailstream_cancel_ack(idle);
      return MAILSTREAM_IDLE_INTERRUPTED;
    }
    if (FD_ISSET(cancel_fd, &readfds)) {
      // idle cancelled
      mailstream_cancel_ack(mailstream_low_get_cancel(low));
      return MAILSTREAM_IDLE_CANCELLED;
    }
    return MAILSTREAM_IDLE_ERROR;
  }
#endif
}
示例#8
0
static ssize_t mailstream_low_socket_read(mailstream_low * s,
					  void * buf, size_t count)
{
  struct mailstream_socket_data * socket_data;
  
  socket_data = (struct mailstream_socket_data *) s->data;

  if (mailstream_cancel_cancelled(socket_data->cancel))
    return -1;
  
  /* timeout */
  {
    fd_set fds_read;
    struct timeval timeout;
    int r;
    int fd;
    int cancelled;
    int got_data;
#ifdef WIN32
    HANDLE event;
#else
    int max_fd;
#endif
    
    if (s->timeout == 0) {
      timeout = mailstream_network_delay;
    }
    else {
			timeout.tv_sec = s->timeout;
      timeout.tv_usec = 0;
    }
    
    FD_ZERO(&fds_read);
    fd = mailstream_cancel_get_fd(socket_data->cancel);
    FD_SET(fd, &fds_read);
    
#ifdef WIN32
    event = CreateEvent(NULL, TRUE, FALSE, NULL);
    WSAEventSelect(socket_data->fd, event, FD_READ | FD_CLOSE);
    FD_SET(event, &fds_read);
    r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
    if (WAIT_TIMEOUT == r) {
			WSAEventSelect(socket_data->fd, event, 0);
			CloseHandle(event);
      return -1;
		}
    
    cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd);
    got_data = (fds_read.fd_array[r - WAIT_OBJECT_0] == event);
		WSAEventSelect(socket_data->fd, event, 0);
		CloseHandle(event);
#else
    FD_SET(socket_data->fd, &fds_read);
    max_fd = socket_data->fd;
    if (fd > max_fd)
      max_fd = fd;
    r = select(max_fd + 1, &fds_read, NULL,/* &fds_excp*/ NULL, &timeout);
    if (r <= 0)
      return -1;
    
    cancelled = FD_ISSET(fd, &fds_read);
    got_data = FD_ISSET(socket_data->fd, &fds_read);
#endif
    
    if (cancelled) {
      /* cancelled */
      mailstream_cancel_ack(socket_data->cancel);
      return -1;
    }
    
    if (!got_data)
      return 0;
  }
  
  if (socket_data->use_read) {
    return read(socket_data->fd, buf, count);
  }
  else {
    return recv(socket_data->fd, buf, count, 0);
  }
}