Пример #1
0
static gboolean
on_timer_source_ready (GObject *stream, GoaAlarm *self)
{
  gint64 number_of_fires;
  gssize bytes_read;
  gboolean run_again = FALSE;

  g_return_val_if_fail (GOA_IS_ALARM (self), FALSE);
  g_return_val_if_fail (self->priv->type == GOA_ALARM_TYPE_TIMER, FALSE);

  g_rec_mutex_lock (&self->priv->lock);
  if (g_cancellable_is_cancelled (self->priv->cancellable))
    goto out;

  bytes_read =
    g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (stream),
                                              &number_of_fires, sizeof (gint64),
                                              NULL, NULL);

  if (bytes_read == sizeof (gint64))
    {
      if (number_of_fires < 0 || number_of_fires > 1)
        {
          goa_warning ("GoaAlarm: expected timerfd to report firing once,"
                       "but it reported firing %ld times\n", (long) number_of_fires);
        }
    }

  fire_or_rearm_alarm (self);
  run_again = TRUE;
out:
  g_rec_mutex_unlock (&self->priv->lock);
  return run_again;
}
static gboolean do_console_raw_local_read(GObject *stream,
                                          gpointer opaque)
{
    GUnixInputStream *localStdin = G_UNIX_INPUT_STREAM(stream);
    GVirSandboxConsoleRaw *console = GVIR_SANDBOX_CONSOLE_RAW(opaque);
    GVirSandboxConsoleRawPrivate *priv = console->priv;
    GError *err = NULL;

    gssize ret = g_pollable_input_stream_read_nonblocking
        (G_POLLABLE_INPUT_STREAM(localStdin),
         priv->localToConsole + priv->localToConsoleOffset,
         priv->localToConsoleLength - priv->localToConsoleOffset,
         NULL, &err);
    if (ret < 0) {
        g_debug("Error from local read %s", err ? err->message : "");
        do_console_raw_close(console, err);
        g_error_free(err);
        goto cleanup;
    }

    if (ret == 0)
        priv->localEOF = TRUE;
    else if (priv->localToConsole[priv->localToConsoleOffset] ==
             CONTROL(gvir_sandbox_console_get_escape(GVIR_SANDBOX_CONSOLE(console)))) {
        do_console_raw_close(console, err);
        goto cleanup;
    }

    priv->localToConsoleOffset += ret;

    priv->localStdinSource = NULL;
    do_console_raw_update_events(console);
 cleanup:
    return FALSE;
}
static gboolean
on_read_bytes (GPollableInputStream * stream, Client * client)
{
  gssize r;
  gchar data[4096];
  GError *err = NULL;

  do {
    r = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM
        (client->istream), data, sizeof (data), NULL, &err);
    if (r > 0)
      g_byte_array_append (client->current_message, (guint8 *) data, r);
  } while (r > 0);

  if (r == 0) {
    remove_client (client);
    return FALSE;
  } else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
    guint8 *tmp = client->current_message->data;

    g_clear_error (&err);

    while (client->current_message->len > 3) {
      if (tmp[0] == 0x0d && tmp[1] == 0x0a && tmp[2] == 0x0d && tmp[3] == 0x0a) {
        guint len;

        g_byte_array_append (client->current_message, (const guint8 *) "\0", 1);
        len = tmp - client->current_message->data + 5;
        client_message (client, (gchar *) client->current_message->data, len);
        g_byte_array_remove_range (client->current_message, 0, len);
        tmp = client->current_message->data;
      } else {
        tmp++;
      }
    }

    if (client->current_message->len >= 1024 * 1024) {
      g_print ("No complete request after 1MB of data\n");
      remove_client (client);
      return FALSE;
    }

    return TRUE;
  } else {
    g_print ("Read error %s\n", err->message);
    g_clear_error (&err);
    remove_client (client);
    return FALSE;
  }

  return FALSE;
}
Пример #4
0
static gboolean
on_request_input (GObject *pollable_input,
                  gpointer user_data)
{
  GPollableInputStream *input = (GPollableInputStream *)pollable_input;
  CockpitRequest *request = user_data;
  GError *error = NULL;
  gsize length;
  gssize count;

  length = request->buffer->len;
  g_byte_array_set_size (request->buffer, length + 4096);

  count = g_pollable_input_stream_read_nonblocking (input, request->buffer->data + length,
                                                    4096, NULL, &error);
  if (count < 0)
    {
      g_byte_array_set_size (request->buffer, length);

      /* Just wait and try again */
      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
        {
          g_error_free (error);
          return TRUE;
        }

      if (!should_suppress_request_error (error))
        g_warning ("couldn't read from connection: %s", error->message);

      cockpit_request_finish (request);
      g_error_free (error);
      return FALSE;
    }

  g_byte_array_set_size (request->buffer, length + count);

  if (count == 0)
    {
      if (request->eof_okay)
        close_io_stream (request->io);
      else
        g_debug ("caller closed connection early");
      cockpit_request_finish (request);
      return FALSE;
    }

  /* Once we receive data EOF is unexpected (until possible next request) */
  request->eof_okay = FALSE;

  return parse_and_process_request (request);
}
Пример #5
0
static gboolean
on_timer_source_ready (GObject *stream, GoaAlarm *self)
{
  gint64 number_of_fires;
  gssize bytes_read;
  gboolean run_again = FALSE;
  GError *error = NULL;

  g_return_val_if_fail (GOA_IS_ALARM (self), FALSE);

  g_rec_mutex_lock (&self->priv->lock);

  if (self->priv->type != GOA_ALARM_TYPE_TIMER)
    {
      g_warning ("GoaAlarm: timer source ready callback called "
                 "when timer source isn't supposed to be used. "
                 "Current timer type is %u", self->priv->type);
      goto out;
    }

  bytes_read =
    g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (stream),
                                              &number_of_fires, sizeof (gint64),
                                              NULL, &error);

  if (bytes_read < 0)
    {
      g_warning ("GoaAlarm: failed to read from timer fd: %s\n",
                 error->message);
      g_error_free (error);
      goto out;
    }

  if (bytes_read == sizeof (gint64))
    {
      if (number_of_fires < 0 || number_of_fires > 1)
        {
          g_warning ("GoaAlarm: expected timerfd to report firing once,"
                     "but it reported firing %ld times\n", (long) number_of_fires);
        }
    }

  fire_or_rearm_alarm (self);
  run_again = TRUE;
out:
  g_rec_mutex_unlock (&self->priv->lock);
  return run_again;
}
Пример #6
0
static gboolean
stdin_func (
    GPollableInputStream *g_stdin,
    GMainLoop *loop)
{
  char buf[2];

  if (g_pollable_input_stream_read_nonblocking (g_stdin, buf, 1, NULL, NULL)
      != -1)
    {
      g_main_loop_quit (loop);
      return FALSE;
    }

  return TRUE;
}
Пример #7
0
gboolean GamepadDevice::readCallback(GObject* pollableStream, gpointer data)
{
    GamepadDevice* gamepadDevice = reinterpret_cast<GamepadDevice*>(data);

    GError* error = 0;
    struct js_event event;

    g_pollable_input_stream_read_nonblocking(G_POLLABLE_INPUT_STREAM(pollableStream),
                                             &event, sizeof(event), 0, &error);

    if (error) {
        gboolean ret = g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
        g_error_free(error);
        return ret;
    }

    gamepadDevice->updateForEvent(event);

    return TRUE;
}
Пример #8
0
/**
 * g_pollable_stream_read:
 * @stream: a #GInputStream
 * @buffer: a buffer to read data into
 * @count: the number of bytes to read
 * @blocking: whether to do blocking I/O
 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
 * @error: location to store the error occurring, or %NULL to ignore
 *
 * Tries to read from @stream, as with g_input_stream_read() (if
 * @blocking is %TRUE) or g_pollable_input_stream_read_nonblocking()
 * (if @blocking is %FALSE). This can be used to more easily share
 * code between blocking and non-blocking implementations of a method.
 *
 * If @blocking is %FALSE, then @stream must be a
 * #GPollableInputStream for which g_pollable_input_stream_can_poll()
 * returns %TRUE, or else the behavior is undefined. If @blocking is
 * %TRUE, then @stream does not need to be a #GPollableInputStream.
 *
 * Returns: the number of bytes read, or -1 on error.
 *
 * Since: 2.34
 */
gssize
g_pollable_stream_read (GInputStream   *stream,
			void           *buffer,
			gsize           count,
			gboolean        blocking,
			GCancellable   *cancellable,
			GError        **error)
{
  if (blocking)
    {
      return g_input_stream_read (stream,
				  buffer, count,
				  cancellable, error);
    }
  else
    {
      return g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (stream),
						       buffer, count,
						       cancellable, error);
    }
}
Пример #9
0
static gboolean
sysroot_stdout_ready_cb (GPollableInputStream *pollable_stream,
                         StdoutClosure *closure)
{
  glnx_unref_object RpmostreedSysroot *sysroot = NULL;
  glnx_unref_object RpmostreedTransaction *transaction = NULL;
  GMemoryInputStream *memory_stream;
  GBufferedInputStream *buffered_stream;
  char buffer[1024];
  gconstpointer stream_buffer;
  gsize stream_buffer_size;
  gsize total_bytes_read = 0;
  gboolean have_line = FALSE;
  GError *local_error = NULL;

  sysroot = g_weak_ref_get (&closure->sysroot);
  if (sysroot != NULL)
    transaction = rpmostreed_transaction_monitor_ref_active_transaction (sysroot->transaction_monitor);

  /* XXX Would very much like g_buffered_input_stream_fill_nonblocking().
   *     Much of this function is a clumsy and inefficient attempt to
   *     achieve the same thing.
   *
   *     See: https://bugzilla.gnome.org/726797
   */

  buffered_stream = G_BUFFERED_INPUT_STREAM (closure->data_stream);
  memory_stream = (GMemoryInputStream *) g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (buffered_stream));

  while (local_error == NULL)
    {
      gssize n_read;

      n_read = g_pollable_input_stream_read_nonblocking (pollable_stream,
                                                         buffer,
                                                         sizeof (buffer),
                                                         NULL, &local_error);

      if (n_read > 0)
        {
          /* XXX Gotta use GBytes so the data gets copied. */
          g_autoptr(GBytes) bytes = g_bytes_new (buffer, n_read);
          g_memory_input_stream_add_bytes (memory_stream, bytes);
          total_bytes_read += n_read;
        }
    }

  if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
    goto out;

  g_clear_error (&local_error);

read_another_line:

  /* Fill the buffered stream with the data we just put in the
   * memory stream, then peek at the buffer to see if it's safe
   * to call g_data_input_stream_read_line() without blocking.
   *
   * XXX Oye, there's gotta be an easier way to do this...
   */

  /* This should never fail since it's just reading from memory. */
  g_buffered_input_stream_fill (buffered_stream, total_bytes_read, NULL, NULL);

  stream_buffer = g_buffered_input_stream_peek_buffer (buffered_stream, &stream_buffer_size);
  have_line = (memchr (stream_buffer, '\n', stream_buffer_size) != NULL);

  if (have_line)
    {
      g_autofree char *line = NULL;
      gsize length;

      line = g_data_input_stream_read_line (closure->data_stream,
                                            &length, NULL, &local_error);

      if (local_error != NULL)
        goto out;

      /* If there's an active transaction, forward the line to the
       * transaction's owner through the "Message" signal.  Otherwise
       * dump it to the non-redirected standard output stream. */
      if (transaction != NULL)
        {
          rpmostree_transaction_emit_message (RPMOSTREE_TRANSACTION (transaction), line);
        }
      else
        {
          /* This is essentially puts(), don't care about errors. */
          g_output_stream_write_all (closure->real_stdout,
                                     line, length, NULL, NULL, NULL);
          g_output_stream_write_all (closure->real_stdout,
                                     "\n", 1, NULL, NULL, NULL);
        }

      goto read_another_line;
    }

out:
  if (local_error != NULL)
    {
      g_warning ("Failed to read stdout pipe: %s", local_error->message);
      g_clear_error (&local_error);
    }

  return G_SOURCE_CONTINUE;
}
Пример #10
0
static void
test_zero_length_reads_writes (NiceAddress *addr)
{
  NiceAgent *agent;
  guint stream_id;
  GIOStream *io_stream;
  GInputStream *input_stream;
  GOutputStream *output_stream;
  GPollableInputStream *pollable_input_stream;
  GPollableOutputStream *pollable_output_stream;
  GError *error = NULL;
  guint8 buf[1];  /* should never be accessed */

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

  input_stream = g_io_stream_get_input_stream (G_IO_STREAM (io_stream));
  output_stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream));
  pollable_input_stream = G_POLLABLE_INPUT_STREAM (input_stream);
  pollable_output_stream = G_POLLABLE_OUTPUT_STREAM (output_stream);

  /* Check zero-length reads and writes complete immediately without error. */
  g_assert (g_input_stream_read (input_stream, buf, 0, NULL, &error) == 0);
  g_assert_no_error (error);

  g_assert (g_output_stream_write (output_stream, buf, 0, NULL, &error) == 0);
  g_assert_no_error (error);

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

  g_assert (
      g_pollable_output_stream_write_nonblocking (pollable_output_stream,
          buf, 0, NULL, &error) == 0);
  g_assert_no_error (error);

  /* Remove the component and check that zero-length reads and writes still
   * result in a 0 response, rather than any error. */
  nice_agent_remove_stream (agent, stream_id);
  g_assert (g_io_stream_is_closed (G_IO_STREAM (io_stream)));

  g_assert (g_input_stream_read (input_stream, buf, 0, NULL, &error) == 0);
  g_assert_no_error (error);

  g_assert (g_output_stream_write (output_stream, buf, 0, NULL, &error) == 0);
  g_assert_no_error (error);

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

  g_assert (
      g_pollable_output_stream_write_nonblocking (pollable_output_stream,
          buf, 0, NULL, &error) == 0);
  g_assert_no_error (error);

  g_object_unref (io_stream);
  g_object_unref (agent);
}
Пример #11
0
static void
test_pollable_cancellation (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;
  GCancellable *cancellable;

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

  /* Grab the input and output streams. */
  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);

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

  /* Check the non-blocking read() and write() return immediately if called with
   * a cancelled cancellable. */
  cancellable = g_cancellable_new ();
  g_cancellable_cancel (cancellable);

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

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

  g_object_unref (cancellable);

  /* Check the GSources invoke a callback when run with the cancellable
   * cancelled. */
  cancellable = g_cancellable_new ();
  stream_source =
      g_pollable_input_stream_create_source (pollable_input_stream,
          cancellable);

  check_pollable_source_cancellation (stream_source, cancellable);

  g_source_unref (stream_source);
  g_object_unref (cancellable);

  /* And for the output stream. */
  cancellable = g_cancellable_new ();
  stream_source =
      g_pollable_output_stream_create_source (pollable_output_stream,
          cancellable);

  check_pollable_source_cancellation (stream_source, cancellable);

  g_object_unref (io_stream);
  g_source_unref (stream_source);
  g_object_unref (cancellable);
  g_object_unref (agent);
}
Пример #12
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);
}
Пример #13
0
static gboolean
dispatch_input (GPollableInputStream *is,
                gpointer user_data)
{
  CockpitStream *self = (CockpitStream *)user_data;
  GError *error = NULL;
  gboolean read = FALSE;
  gssize ret = 0;
  gsize len;
  gboolean eof;

  for (;;)
    {
      g_return_val_if_fail (self->priv->in_source, FALSE);
      len = self->priv->in_buffer->len;

      g_byte_array_set_size (self->priv->in_buffer, len + 1024);
      ret = g_pollable_input_stream_read_nonblocking (is, self->priv->in_buffer->data + len,
                                                      1024, NULL, &error);

      if (ret < 0)
        {
          g_byte_array_set_size (self->priv->in_buffer, len);
          if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
            {
              g_error_free (error);
              break;
            }
          else
            {
              set_problem_from_error (self, "couldn't read", error);
              g_error_free (error);
              close_immediately (self, NULL);
              return FALSE;
            }
        }

      g_byte_array_set_size (self->priv->in_buffer, len + ret);

      if (ret == 0)
        {
          g_debug ("%s: end of input", self->priv->name);
          stop_input (self);
          break;
        }
      else if (ret > 0)
        {
          g_debug ("%s: read %d bytes", self->priv->name, (int)ret);
          self->priv->received = TRUE;
          read = TRUE;
        }
    }

  g_object_ref (self);

  eof = (self->priv->in_source == NULL);
  if (eof || read)
    g_signal_emit (self, cockpit_stream_sig_read, 0, self->priv->in_buffer, eof);

  if (eof)
    close_maybe (self);

  g_object_unref (self);
  return TRUE;
}