コード例 #1
0
ファイル: gpollableoutputstream.c プロジェクト: patito/glib
static gssize
g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream  *stream,
						    const void             *buffer,
						    gsize                   count,
						    GError                **error)
{
  if (!g_pollable_output_stream_is_writable (stream))
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
                           g_strerror (EAGAIN));
      return -1;
    }

  return G_OUTPUT_STREAM_GET_CLASS (stream)->
    write_fn (G_OUTPUT_STREAM (stream), buffer, count, NULL, error);
}
コード例 #2
0
int SocketStreamHandle::platformSend(const char* data, int length)
{
    if (!g_pollable_output_stream_is_writable(m_outputStream.get())) {
        beginWaitingForSocketWritability();
        return 0;
    }

    GOwnPtr<GError> error;
    gssize written = g_pollable_output_stream_write_nonblocking(m_outputStream.get(), data, length, 0, &error.outPtr());
    if (error && !g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
        m_client->didFail(this, SocketStreamError(error->code)); // FIXME: Provide a sensible error.
        return 0;
    }

    // If we did not send all the bytes we were given, we know that
    // SocketStreamHandleBase will need to send more in the future.
    if (written < length)
        beginWaitingForSocketWritability();

    return written;
}
コード例 #3
0
static gboolean
source_cancelled_cb (GObject *pollable_stream, gpointer user_data)
{
  GMainLoop *main_loop = user_data;

  /* Try and check that the callback was invoked due to cancellation rather than
   * a poll() event on the socket itself. */
  if (G_IS_POLLABLE_INPUT_STREAM (pollable_stream)) {
    g_assert (
        !g_pollable_input_stream_is_readable (
            G_POLLABLE_INPUT_STREAM (pollable_stream)));
  } else {
    g_assert (
        !g_pollable_output_stream_is_writable (
            G_POLLABLE_OUTPUT_STREAM (pollable_stream)));
  }

  g_main_loop_quit (main_loop);

  return FALSE;
}
コード例 #4
0
gboolean
g_tls_connection_base_check (GTlsConnectionBase  *tls,
			     GIOCondition         condition)
{
  /* Racy, but worst case is that we just get WOULD_BLOCK back */
  if (tls->need_finish_handshake)
    return TRUE;

  /* If a handshake or close is in progress, then tls_istream and
   * tls_ostream are blocked, regardless of the base stream status.
   */
  if (tls->handshaking)
    return FALSE;

  if (((condition & G_IO_IN) && tls->read_closing) ||
      ((condition & G_IO_OUT) && tls->write_closing))
    return FALSE;

  if (condition & G_IO_IN)
    return g_pollable_input_stream_is_readable (tls->base_istream);
  else
    return g_pollable_output_stream_is_writable (tls->base_ostream);
}
コード例 #5
0
static void
test_pollable_properties (NiceAddress *addr)
{
  NiceAgent *agent;
  guint stream_id;
  GIOStream *io_stream;
  GInputStream *input_stream;
  GOutputStream *output_stream;
  GPollableInputStream *pollable_input_stream;
  GPollableOutputStream *pollable_output_stream;
  guint8 buf[65536];
  GError *error = NULL;
  GSource *stream_source;

  agent = nice_agent_new_reliable (NULL, NICE_COMPATIBILITY_RFC5245);
  nice_agent_add_local_address (agent, addr);

  /* Add a stream. */
  stream_id = nice_agent_add_stream (agent, 1);

  /* Try building an I/O stream around it. */
  io_stream = nice_agent_get_io_stream (agent, stream_id, 1);
  g_assert (G_IS_IO_STREAM (io_stream));
  g_assert (NICE_IS_IO_STREAM (io_stream));

  /* Check the input stream’s properties. */
  input_stream = g_io_stream_get_input_stream (G_IO_STREAM (io_stream));
  g_assert (G_IS_POLLABLE_INPUT_STREAM (input_stream));
  pollable_input_stream = G_POLLABLE_INPUT_STREAM (input_stream);

  g_assert (g_pollable_input_stream_can_poll (pollable_input_stream));
  g_assert (!g_pollable_input_stream_is_readable (pollable_input_stream));

  g_assert (
      g_pollable_input_stream_read_nonblocking (pollable_input_stream,
          buf, sizeof (buf), NULL, &error) == -1);
  g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
  g_clear_error (&error);

  stream_source =
      g_pollable_input_stream_create_source (pollable_input_stream, NULL);
  g_assert (stream_source != NULL);
  g_source_unref (stream_source);

  /* Check the output stream’s properties. */
  output_stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream));
  g_assert (G_IS_POLLABLE_OUTPUT_STREAM (output_stream));
  pollable_output_stream = G_POLLABLE_OUTPUT_STREAM (output_stream);

  g_assert (g_pollable_output_stream_can_poll (pollable_output_stream));
  g_assert (!g_pollable_output_stream_is_writable (pollable_output_stream));

  g_assert (
      g_pollable_output_stream_write_nonblocking (pollable_output_stream,
          buf, sizeof (buf), NULL, &error) == -1);
  g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
  g_clear_error (&error);

  stream_source =
      g_pollable_output_stream_create_source (pollable_output_stream, NULL);
  g_assert (stream_source != NULL);
  g_source_unref (stream_source);

  /* Remove the component and check that the I/O streams close. */
  nice_agent_remove_stream (agent, stream_id);

  g_assert (!g_pollable_input_stream_is_readable (pollable_input_stream));
  g_assert (!g_pollable_output_stream_is_writable (pollable_output_stream));

  g_assert (
      g_pollable_input_stream_read_nonblocking (pollable_input_stream,
          buf, sizeof (buf), NULL, &error) == 0);
  g_assert_no_error (error);

  g_assert (
      g_pollable_output_stream_write_nonblocking (pollable_output_stream,
          buf, sizeof (buf), NULL, &error) == -1);
  g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
  g_clear_error (&error);

  g_object_unref (io_stream);
  g_object_unref (agent);
}
コード例 #6
0
ファイル: gunixoutputstream.c プロジェクト: GNOME/glib
static GPollableReturn
g_unix_output_stream_pollable_writev_nonblocking (GPollableOutputStream  *stream,
						  const GOutputVector    *vectors,
						  gsize                   n_vectors,
						  gsize                  *bytes_written,
						  GError                **error)
{
  GUnixOutputStream *unix_stream = G_UNIX_OUTPUT_STREAM (stream);
  struct iovec *iov;
  gssize res = -1;

  if (!g_pollable_output_stream_is_writable (stream))
    {
      *bytes_written = 0;
      return G_POLLABLE_RETURN_WOULD_BLOCK;
    }

  /* Clamp to G_MAXINT as writev() takes an integer for the number of vectors.
   * We handle this like a short write in this case
   */
  if (n_vectors > G_MAXINT)
    n_vectors = G_MAXINT;

  if (G_OUTPUT_VECTOR_IS_IOVEC)
    {
      /* ABI is compatible */
      iov = (struct iovec *) vectors;
    }
  else
    {
      gsize i;

      /* ABI is incompatible */
      iov = g_newa (struct iovec, n_vectors);
      for (i = 0; i < n_vectors; i++)
        {
          iov[i].iov_base = (void *)vectors[i].buffer;
          iov[i].iov_len = vectors[i].size;
        }
    }

  while (1)
    {
      int errsv;

      res = writev (unix_stream->priv->fd, iov, n_vectors);
      errsv = errno;
      if (res == -1)
	{
	  if (errsv == EINTR)
	    continue;

	  g_set_error (error, G_IO_ERROR,
		       g_io_error_from_errno (errsv),
		       _("Error writing to file descriptor: %s"),
		       g_strerror (errsv));
	}

      if (bytes_written)
        *bytes_written = res;

      break;
    }

  return res != -1 ? G_POLLABLE_RETURN_OK : G_POLLABLE_RETURN_FAILED;
}