GSource * soup_message_io_get_source (SoupMessage *msg, GCancellable *cancellable, SoupMessageSourceFunc callback, gpointer user_data) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; GSource *base_source, *source; SoupMessageSource *message_source; if (!io) { base_source = g_timeout_source_new (0); } else if (io->paused) { base_source = NULL; } else if (io->async_close_wait) { base_source = g_cancellable_source_new (io->async_close_wait); } else if (SOUP_MESSAGE_IO_STATE_POLLABLE (io->read_state)) { GPollableInputStream *istream; if (io->body_istream) istream = G_POLLABLE_INPUT_STREAM (io->body_istream); else istream = G_POLLABLE_INPUT_STREAM (io->istream); base_source = g_pollable_input_stream_create_source (istream, cancellable); } else if (SOUP_MESSAGE_IO_STATE_POLLABLE (io->write_state)) { GPollableOutputStream *ostream; if (io->body_ostream) ostream = G_POLLABLE_OUTPUT_STREAM (io->body_ostream); else ostream = G_POLLABLE_OUTPUT_STREAM (io->ostream); base_source = g_pollable_output_stream_create_source (ostream, cancellable); } else base_source = g_timeout_source_new (0); source = g_source_new (&message_source_funcs, sizeof (SoupMessageSource)); g_source_set_name (source, "SoupMessageSource"); message_source = (SoupMessageSource *)source; message_source->msg = g_object_ref (msg); message_source->paused = io && io->paused; if (base_source) { g_source_set_dummy_callback (base_source); g_source_add_child_source (source, base_source); g_source_unref (base_source); } g_source_set_callback (source, (GSourceFunc) callback, user_data, NULL); return source; }
static void initialize_io (CockpitStream *self) { GInputStream *is; GOutputStream *os; g_return_if_fail (self->priv->in_source == NULL); is = g_io_stream_get_input_stream (self->priv->io); os = g_io_stream_get_output_stream (self->priv->io); if (!G_IS_POLLABLE_INPUT_STREAM (is) || !g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (is)) || !G_IS_POLLABLE_OUTPUT_STREAM (os) || !g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (os))) { g_warning ("%s: stream is not pollable", self->priv->name); close_immediately (self, "internal-error"); return; } if (self->priv->connecting) { cockpit_connectable_unref (self->priv->connecting); self->priv->connecting = NULL; } self->priv->in_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (is), NULL); g_source_set_name (self->priv->in_source, "stream-input"); g_source_set_callback (self->priv->in_source, (GSourceFunc)dispatch_input, self, NULL); g_source_attach (self->priv->in_source, self->priv->context); if (G_IS_TLS_CONNECTION (self->priv->io)) { self->priv->sig_accept_cert = g_signal_connect (G_TLS_CONNECTION (self->priv->io), "accept-certificate", G_CALLBACK (on_rejected_certificate), self); } else { self->priv->sig_accept_cert = 0; } start_output (self); g_signal_emit (self, cockpit_stream_sig_open, 0); }
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_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 soup_content_sniffer_stream_can_poll (GPollableInputStream *pollable) { GInputStream *base_stream = G_FILTER_INPUT_STREAM (pollable)->base_stream; return G_IS_POLLABLE_INPUT_STREAM (base_stream) && g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (base_stream)); }
static gboolean sysroot_setup_stdout_redirect (RpmostreedSysroot *self, GError **error) { g_autoptr(GInputStream) stream = NULL; g_autoptr(GSource) source = NULL; StdoutClosure *closure; gint pipefd[2]; gboolean ret = FALSE; /* XXX libostree logs messages to systemd's journal and also to stdout. * Redirect our own stdout back to ourselves so we can capture those * messages and pass them on to clients. Admittedly hokey but avoids * hacking libostree directly (for now). */ closure = g_slice_new0 (StdoutClosure); g_weak_ref_set (&closure->sysroot, self); /* Save the real stdout before overwriting its file descriptor. */ closure->real_stdout = g_unix_output_stream_new (dup (STDOUT_FILENO), FALSE); if (pipe (pipefd) < 0) { glnx_set_prefix_error_from_errno (error, "%s", "pipe() failed"); goto out; } if (dup2 (pipefd[1], STDOUT_FILENO) < 0) { glnx_set_prefix_error_from_errno (error, "%s", "dup2() failed"); goto out; } stream = g_memory_input_stream_new (); closure->data_stream = g_data_input_stream_new (stream); g_clear_object (&stream); stream = g_unix_input_stream_new (pipefd[0], FALSE); source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (stream), NULL); /* Transfer ownership of the StdoutClosure. */ g_source_set_callback (source, (GSourceFunc) sysroot_stdout_ready_cb, closure, (GDestroyNotify) stdout_closure_free); closure = NULL; self->stdout_source_id = g_source_attach (source, NULL); ret = TRUE; out: if (closure != NULL) stdout_closure_free (closure); return ret; }
static gboolean schedule_wakeups_with_timerfd (GoaAlarm *self) { #ifdef HAVE_TIMERFD struct itimerspec timer_spec; int fd; int result; GSource *source; static gboolean seen_before = FALSE; if (!seen_before) { g_debug ("GoaAlarm: trying to use kernel timer"); seen_before = TRUE; } fd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC | TFD_NONBLOCK); if (fd < 0) { g_debug ("GoaAlarm: could not create timer fd: %m"); return FALSE; } memset (&timer_spec, 0, sizeof (timer_spec)); timer_spec.it_value.tv_sec = g_date_time_to_unix (self->priv->time) + 1; result = timerfd_settime (fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &timer_spec, NULL); if (result < 0) { g_debug ("GoaAlarm: could not set timer: %m"); return FALSE; } self->priv->type = GOA_ALARM_TYPE_TIMER; self->priv->stream = g_unix_input_stream_new (fd, TRUE); source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (self->priv->stream), NULL); self->priv->scheduled_wakeup_source = source; g_source_set_callback (self->priv->scheduled_wakeup_source, (GSourceFunc) on_timer_source_ready, self, (GDestroyNotify) clear_wakeup_source_pointer); g_source_attach (self->priv->scheduled_wakeup_source, self->priv->context); g_source_unref (source); return TRUE; #endif /*HAVE_TIMERFD */ return FALSE; }
static gboolean soup_content_sniffer_stream_is_readable (GPollableInputStream *stream) { SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (stream); if (sniffer->priv->error || (!sniffer->priv->sniffing && sniffer->priv->buffer)) return TRUE; return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (stream)->base_stream)); }
static void let_me_quit (GMainLoop *loop) { GInputStream *g_stdin = g_unix_input_stream_new (0, FALSE); GSource *source = g_pollable_input_stream_create_source ( G_POLLABLE_INPUT_STREAM (g_stdin), NULL); g_source_set_callback (source, (GSourceFunc) stdin_func, loop, NULL); g_source_attach (source, NULL); g_printf ("Hit Enter to stop logging. (Do not hit Control-C.)\n"); }
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_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 on_new_connection (GSocketService * service, GSocketConnection * connection, GObject * source_object, gpointer user_data) { Client *client = g_slice_new0 (Client); GSocketAddress *addr; GInetAddress *iaddr; gchar *ip; guint16 port; addr = g_socket_connection_get_remote_address (connection, NULL); iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr)); port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); ip = g_inet_address_to_string (iaddr); client->name = g_strdup_printf ("%s:%u", ip, port); g_free (ip); g_object_unref (addr); g_print ("New connection %s\n", client->name); client->connection = (GSocketConnection *) g_object_ref (connection); client->socket = g_socket_connection_get_socket (connection); client->istream = g_io_stream_get_input_stream (G_IO_STREAM (client->connection)); client->ostream = g_io_stream_get_output_stream (G_IO_STREAM (client->connection)); client->current_message = g_byte_array_sized_new (1024); client->tosource = g_timeout_source_new_seconds (5); g_source_set_callback (client->tosource, (GSourceFunc) on_timeout, client, NULL); g_source_attach (client->tosource, NULL); client->isource = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (client->istream), NULL); g_source_set_callback (client->isource, (GSourceFunc) on_read_bytes, client, NULL); g_source_attach (client->isource, NULL); G_LOCK (clients); clients = g_list_prepend (clients, client); G_UNLOCK (clients); return TRUE; }
GamepadDevice::GamepadDevice(int fd, Nix::Gamepad* gamepad) : m_fileDescriptor(fd) , m_nixGamepad(gamepad) , m_inputStream(0) , m_source(0) { char deviceId[Nix::Gamepad::idLengthCap]; if (ioctl(m_fileDescriptor, JSIOCGNAME(sizeof(deviceId)), deviceId) < 0) return; uint8_t numberOfAxes; uint8_t numberOfButtons; if (ioctl(m_fileDescriptor, JSIOCGAXES, &numberOfAxes) < 0 || ioctl(m_fileDescriptor, JSIOCGBUTTONS, &numberOfButtons) < 0) return; memset(m_nixGamepad->id, 0, Nix::Gamepad::idLengthCap); gsize bytesWritten, bytesRead; GError* error = 0; gchar* deviceIdUTF16 = g_convert(deviceId, -1, "UTF-16", "ASCII", &bytesRead, &bytesWritten, &error); if (!error) { memcpy(m_nixGamepad->id, deviceIdUTF16, bytesWritten); g_free(deviceIdUTF16); } else g_error_free(error); m_nixGamepad->connected = false; m_nixGamepad->timestamp = 0; m_nixGamepad->axesLength = std::min<unsigned>(numberOfAxes, Nix::Gamepad::axesLengthCap); m_nixGamepad->buttonsLength = std::min<unsigned>(numberOfButtons, Nix::Gamepad::buttonsLengthCap); unsigned i, total; for (i = 0, total = m_nixGamepad->axesLength; i < total; i++) m_nixGamepad->axes[i] = 0; for (i = 0, total = m_nixGamepad->buttonsLength; i < total; i++) m_nixGamepad->buttons[i] = 0; m_inputStream = g_unix_input_stream_new(m_fileDescriptor, FALSE); m_source = g_pollable_input_stream_create_source(G_POLLABLE_INPUT_STREAM(m_inputStream), 0); g_source_set_callback(m_source, reinterpret_cast<GSourceFunc>(readCallback), this, 0); g_source_attach(m_source, 0); }
static GSource * soup_content_sniffer_stream_create_source (GPollableInputStream *stream, GCancellable *cancellable) { SoupContentSnifferStream *sniffer = SOUP_CONTENT_SNIFFER_STREAM (stream); GSource *base_source, *pollable_source; if (sniffer->priv->error || (!sniffer->priv->sniffing && sniffer->priv->buffer)) base_source = g_timeout_source_new (0); else base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (stream)->base_stream), cancellable); g_source_set_dummy_callback (base_source); pollable_source = g_pollable_source_new (G_OBJECT (stream)); g_source_add_child_source (pollable_source, base_source); g_source_unref (base_source); return pollable_source; }
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 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; }
static GSource * soup_socket_create_watch (SoupSocketPrivate *priv, GIOCondition cond, GPollableSourceFunc callback, gpointer user_data, GCancellable *cancellable) { GSource *watch; GMainContext *async_context; if (cond == G_IO_IN) watch = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (priv->istream), cancellable); else watch = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (priv->ostream), cancellable); g_source_set_callback (watch, (GSourceFunc)callback, user_data, NULL); if (priv->use_thread_context) async_context = g_main_context_get_thread_default (); else async_context = priv->async_context; g_source_attach (watch, async_context); g_source_unref (watch); return watch; }
static void g_tls_connection_base_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GTlsConnectionBase *tls = G_TLS_CONNECTION_BASE (object); GInputStream *istream; GOutputStream *ostream; gboolean system_certdb; GTlsBackend *backend; switch (prop_id) { case PROP_BASE_IO_STREAM: if (tls->base_io_stream) { g_object_unref (tls->base_io_stream); tls->base_istream = NULL; tls->base_ostream = NULL; } tls->base_io_stream = g_value_dup_object (value); if (!tls->base_io_stream) return; istream = g_io_stream_get_input_stream (tls->base_io_stream); ostream = g_io_stream_get_output_stream (tls->base_io_stream); if (G_IS_POLLABLE_INPUT_STREAM (istream) && g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (istream))) { tls->base_istream = G_POLLABLE_INPUT_STREAM (istream); tls->tls_istream = g_tls_input_stream_base_new (tls); } if (G_IS_POLLABLE_OUTPUT_STREAM (ostream) && g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (ostream))) { tls->base_ostream = G_POLLABLE_OUTPUT_STREAM (ostream); tls->tls_ostream = g_tls_output_stream_base_new (tls); } break; case PROP_REQUIRE_CLOSE_NOTIFY: tls->require_close_notify = g_value_get_boolean (value); break; case PROP_REHANDSHAKE_MODE: tls->rehandshake_mode = g_value_get_enum (value); break; case PROP_USE_SYSTEM_CERTDB: system_certdb = g_value_get_boolean (value); if (system_certdb != tls->is_system_certdb) { g_clear_object (&tls->database); if (system_certdb) { backend = g_tls_backend_get_default (); tls->database = g_tls_backend_get_default_database (backend); } tls->is_system_certdb = system_certdb; tls->database_is_unset = FALSE; } break; case PROP_DATABASE: g_clear_object (&tls->database); tls->database = g_value_dup_object (value); tls->is_system_certdb = FALSE; tls->database_is_unset = FALSE; break; case PROP_CERTIFICATE: if (tls->certificate) g_object_unref (tls->certificate); tls->certificate = g_value_dup_object (value); break; case PROP_INTERACTION: g_clear_object (&tls->interaction); tls->interaction = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } }
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 void do_console_raw_update_events(GVirSandboxConsoleRaw *console) { GVirSandboxConsoleRawPrivate *priv = console->priv; if (!priv->attached) /* Closed */ return; if (priv->localStdin) { if ((priv->localToConsoleOffset < priv->localToConsoleLength) && (!priv->localEOF)) { if (priv->localStdinSource == NULL) { priv->localStdinSource = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM(priv->localStdin), NULL); g_source_set_callback(priv->localStdinSource, (GSourceFunc)do_console_raw_local_read, console, NULL); g_source_attach(priv->localStdinSource, g_main_context_default()); } } else { if (priv->localStdinSource) { g_source_destroy(priv->localStdinSource); g_source_unref(priv->localStdinSource); priv->localStdinSource = NULL; } } } /* * With raw consoles we can't distinguish stdout/stderr, so everything * goes to stdout */ if (priv->localStdout) { if (priv->consoleToLocalOffset) { if (priv->localStdoutSource == NULL) { priv->localStdoutSource = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM(priv->localStdout), NULL); g_source_set_callback(priv->localStdoutSource, (GSourceFunc)do_console_raw_local_write, console, NULL); g_source_attach(priv->localStdoutSource, g_main_context_default()); } } else { if (priv->localStdoutSource) { g_source_destroy(priv->localStdoutSource); g_source_unref(priv->localStdoutSource); priv->localStdoutSource = NULL; } } } else { if (priv->consoleToLocalOffset) { if (priv->localStderrSource == NULL) { priv->localStderrSource = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM(priv->localStderr), NULL); g_source_set_callback(priv->localStderrSource, (GSourceFunc)do_console_raw_local_write, console, NULL); g_source_attach(priv->localStderrSource, g_main_context_default()); } } else { if (priv->localStderrSource) { g_source_destroy(priv->localStderrSource); g_source_unref(priv->localStderrSource); priv->localStderrSource = NULL; } } } if (priv->console) { GVirStreamIOCondition cond = 0; if (priv->localToConsoleOffset) cond |= GVIR_STREAM_IO_CONDITION_WRITABLE; if (priv->consoleToLocalOffset < priv->consoleToLocalLength) cond |= GVIR_STREAM_IO_CONDITION_READABLE; if (priv->consoleWatch) { g_source_remove(priv->consoleWatch); priv->consoleWatch = 0; } if (cond) { priv->consoleWatch = gvir_stream_add_watch(priv->console, cond, do_console_raw_stream_readwrite, console); } } else { if (priv->consoleToLocalOffset < priv->consoleToLocalLength) { if (priv->consoleInputSource == NULL) { priv->consoleInputSource = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM(priv->consoleInput), NULL); g_source_set_callback(priv->consoleInputSource, (GSourceFunc)do_console_raw_console_read, console, NULL); g_source_attach(priv->consoleInputSource, g_main_context_default()); } } else { if (priv->consoleInputSource) { g_source_destroy(priv->consoleInputSource); g_source_unref(priv->consoleInputSource); priv->consoleInputSource = NULL; } } if (priv->localToConsoleOffset) { if (priv->consoleOutputSource == NULL) { priv->consoleOutputSource = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM(priv->consoleOutput), NULL); g_source_set_callback(priv->consoleOutputSource, (GSourceFunc)do_console_raw_console_write, console, NULL); g_source_attach(priv->consoleOutputSource, g_main_context_default()); } } else { if (priv->consoleOutputSource) { g_source_destroy(priv->consoleOutputSource); g_source_unref(priv->consoleOutputSource); priv->consoleOutputSource = NULL; } } } }