Example #1
0
static ssize_t mailstream_low_ssl_read(mailstream_low * s,
				       void * buf, size_t count)
{
  struct mailstream_ssl_data * ssl_data;
  int r;

  ssl_data = (struct mailstream_ssl_data *) s->data;
  
  if (mailstream_cancel_cancelled(ssl_data->cancel))
    return -1;
  
  while (1) {
    int ssl_r;
    
    r = SSL_read(ssl_data->ssl_conn, buf, count);
    if (r > 0)
      return r;
    
    ssl_r = SSL_get_error(ssl_data->ssl_conn, r);
    switch (ssl_r) {
    case SSL_ERROR_NONE:
      return r;
      
    case SSL_ERROR_ZERO_RETURN:
      return r;
      
    case SSL_ERROR_WANT_READ:
      r = wait_read(s);
      if (r < 0)
        return r;
      break;
      
    default:
      return -1;
    }
  }
}
Example #2
0
static ssize_t mailstream_low_ssl_read(mailstream_low * s,
				       void * buf, size_t count)
{
  struct mailstream_ssl_data * ssl_data;
  int r;

  ssl_data = (struct mailstream_ssl_data *) s->data;
  if (mailstream_cancel_cancelled(ssl_data->cancel))
    return -1;
  
  while (1) {
    r = gnutls_record_recv(ssl_data->session, buf, count);
    if (r > 0)
      return r;
    
    switch (r) {
    case 0: /* closed connection */
      return -1;
    
    case GNUTLS_E_REHANDSHAKE:
      do {
         r = gnutls_handshake(ssl_data->session); 
      } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED);
      break; /* re-receive */
    case GNUTLS_E_AGAIN:
    case GNUTLS_E_INTERRUPTED:
      r = wait_read(s);
      if (r < 0)
        return r;
      break;
      
    default:
      return -1;
    }
  }
}
Example #3
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;
}
Example #4
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;
}
Example #5
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);
  }
}