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; }
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); }
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; }
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; }
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; }
/** * 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); } }
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; }
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); }
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); }
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); }
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; }