static void test_io_stream_properties (NiceAddress *addr) { NiceAgent *agent; guint stream_id; GIOStream *io_stream; GInputStream *input_stream; GOutputStream *output_stream; agent = nice_agent_new_reliable (NULL, NICE_COMPATIBILITY_RFC5245); nice_agent_add_local_address (agent, addr); 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 various initial properties. */ g_assert (!g_io_stream_is_closed (G_IO_STREAM (io_stream))); g_assert (!g_io_stream_has_pending (G_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_INPUT_STREAM (input_stream)); g_assert (NICE_IS_INPUT_STREAM (input_stream)); g_assert (!g_input_stream_is_closed (input_stream)); g_assert (!g_input_stream_has_pending (input_stream)); /* Check the output stream’s properties. */ output_stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream)); g_assert (G_IS_OUTPUT_STREAM (output_stream)); g_assert (NICE_IS_OUTPUT_STREAM (output_stream)); g_assert (!g_output_stream_is_closing (output_stream)); g_assert (!g_output_stream_is_closed (output_stream)); g_assert (!g_output_stream_has_pending (output_stream)); /* Remove the component and check that the I/O streams close. */ nice_agent_remove_stream (agent, stream_id); g_assert (g_io_stream_is_closed (G_IO_STREAM (io_stream))); g_assert (g_input_stream_is_closed (input_stream)); g_assert (g_output_stream_is_closed (output_stream)); g_object_unref (io_stream); g_object_unref (agent); }
static GSource * nice_output_stream_create_source (GPollableOutputStream *stream, GCancellable *cancellable) { NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv; GSource *component_source = NULL; NiceComponent *component = NULL; NiceStream *_stream = NULL; NiceAgent *agent; /* owned */ component_source = g_pollable_source_new (G_OBJECT (stream)); if (cancellable) { GSource *cancellable_source = g_cancellable_source_new (cancellable); g_source_set_dummy_callback (cancellable_source); g_source_add_child_source (component_source, cancellable_source); g_source_unref (cancellable_source); } /* Closed streams cannot have sources. */ if (g_output_stream_is_closed (G_OUTPUT_STREAM (stream))) return component_source; /* Has the agent disappeared? */ agent = g_weak_ref_get (&priv->agent_ref); if (agent == NULL) return component_source; agent_lock (); /* Grab the socket for this component. */ if (!agent_find_component (agent, priv->stream_id, priv->component_id, &_stream, &component)) { g_warning ("Could not find component %u in stream %u", priv->component_id, priv->stream_id); goto done; } if (component->tcp_writable_cancellable) { GSource *cancellable_source = g_cancellable_source_new (component->tcp_writable_cancellable); g_source_set_dummy_callback (cancellable_source); g_source_add_child_source (component_source, cancellable_source); g_source_unref (cancellable_source); } done: agent_unlock (); g_object_unref (agent); return component_source; }
static gboolean nice_output_stream_is_writable (GPollableOutputStream *stream) { NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv; NiceComponent *component = NULL; NiceStream *_stream = NULL; gboolean retval = FALSE; NiceAgent *agent; /* owned */ /* Closed streams are not writeable. */ if (g_output_stream_is_closed (G_OUTPUT_STREAM (stream))) return FALSE; /* Has the agent disappeared? */ agent = g_weak_ref_get (&priv->agent_ref); if (agent == NULL) return FALSE; agent_lock (); if (!agent_find_component (agent, priv->stream_id, priv->component_id, &_stream, &component)) { g_warning ("Could not find component %u in stream %u", priv->component_id, priv->stream_id); goto done; } if (component->selected_pair.local != NULL) { NiceSocket *sockptr = component->selected_pair.local->sockptr; /* If it’s a reliable agent, see if there’s any space in the pseudo-TCP * output buffer. */ if (!nice_socket_is_reliable (sockptr)) { retval = pseudo_tcp_socket_can_send (component->tcp); } else { retval = (g_socket_condition_check (sockptr->fileno, G_IO_OUT) != 0); } } done: agent_unlock (); g_object_unref (agent); return retval; }
static gssize nice_output_stream_write_nonblocking (GPollableOutputStream *stream, const void *buffer, gsize count, GError **error) { NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv; NiceAgent *agent; /* owned */ gint n_sent; /* Closed streams are not writeable. */ if (g_output_stream_is_closed (G_OUTPUT_STREAM (stream))) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, "Stream is closed."); return -1; } /* Has the agent disappeared? */ agent = g_weak_ref_get (&priv->agent_ref); if (agent == NULL) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, "Stream is closed due to the NiceAgent being finalised."); return -1; } if (count == 0) { n_sent = 0; goto done; } n_sent = nice_agent_send (agent, priv->stream_id, priv->component_id, count, buffer); if (n_sent == -1) g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, g_strerror (EAGAIN)); done: g_object_unref (agent); return n_sent; }
static void soup_cache_input_stream_write_next_buffer (SoupCacheInputStream *istream) { SoupCacheInputStreamPrivate *priv = istream->priv; SoupBuffer *buffer = g_queue_pop_head (priv->buffer_queue); int priority; g_assert (priv->output_stream && !g_output_stream_is_closed (priv->output_stream)); g_clear_pointer (&priv->current_writing_buffer, soup_buffer_free); priv->current_writing_buffer = buffer; if (priv->buffer_queue->length > 10) priority = G_PRIORITY_DEFAULT; else priority = G_PRIORITY_LOW; g_output_stream_write_async (priv->output_stream, buffer->data, buffer->length, priority, priv->cancellable, (GAsyncReadyCallback) write_ready_cb, g_object_ref (istream)); }
static void nice_output_stream_dispose (GObject *object) { NiceOutputStream *self = NICE_OUTPUT_STREAM (object); NiceAgent *agent; /* Ensure the stream is closed first, otherwise the agent can’t be found in * the close handler called by the parent implementation. */ if (!g_output_stream_is_closed (G_OUTPUT_STREAM (object))) g_output_stream_close (G_OUTPUT_STREAM (object), NULL, NULL); agent = g_weak_ref_get (&self->priv->agent_ref); if (agent != NULL) { g_signal_handlers_disconnect_by_func (agent, streams_removed_cb, self); g_object_unref (agent); } g_weak_ref_clear (&self->priv->agent_ref); g_clear_object (&self->priv->closed_cancellable); G_OBJECT_CLASS (nice_output_stream_parent_class)->dispose (object); }
static gboolean gst_gio_base_sink_start (GstBaseSink * base_sink) { GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink); GstGioBaseSinkClass *gbsink_class = GST_GIO_BASE_SINK_GET_CLASS (sink); sink->position = 0; /* FIXME: This will likely block */ sink->stream = gbsink_class->get_stream (sink); if (G_UNLIKELY (!G_IS_OUTPUT_STREAM (sink->stream))) { GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), ("No output stream provided by subclass")); return FALSE; } else if (G_UNLIKELY (g_output_stream_is_closed (sink->stream))) { GST_ELEMENT_ERROR (sink, LIBRARY, FAILED, (NULL), ("Output stream is already closed")); return FALSE; } GST_DEBUG_OBJECT (sink, "started sink"); return TRUE; }
static gssize nice_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error) { NiceOutputStream *self = NICE_OUTPUT_STREAM (stream); const gchar* buf = buffer; gssize len = 0; gint n_sent; NiceAgent *agent = NULL; /* owned */ gulong cancel_id = 0, closed_cancel_id, writeable_id; WriteData *write_data; /* Closed streams are not writeable. */ if (g_output_stream_is_closed (stream)) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, "Stream is closed."); return -1; } /* Has the agent disappeared? */ agent = g_weak_ref_get (&self->priv->agent_ref); if (agent == NULL) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, "Stream is closed due to the NiceAgent being finalised."); return -1; } if (count == 0) { g_object_unref (agent); return 0; } /* FIXME: nice_agent_send() is non-blocking, which is a bit unexpected * since nice_agent_recv() is blocking. Currently this uses a fairly dodgy * GCond solution; would be much better for nice_agent_send() to block * properly in the main loop. */ write_data = g_slice_new0 (WriteData); write_data->ref_count = 1; g_mutex_init (&write_data->mutex); g_cond_init (&write_data->cond); if (cancellable != NULL) { cancel_id = g_cancellable_connect (cancellable, (GCallback) write_cancelled_cb, write_data_ref (write_data), (GDestroyNotify) write_data_unref); } closed_cancel_id = g_cancellable_connect (self->priv->closed_cancellable, (GCallback) write_cancelled_cb, write_data_ref (write_data), (GDestroyNotify) write_data_unref); g_mutex_lock (&write_data->mutex); writeable_id = g_signal_connect_data (G_OBJECT (agent), "reliable-transport-writable", (GCallback) reliable_transport_writeable_cb, write_data_ref (write_data), (GClosureNotify) write_data_unref, 0); do { /* Have to unlock while calling into the agent because * it will take the agent lock which will cause a deadlock if one of * the callbacks is called. */ if (g_cancellable_is_cancelled (cancellable) || g_cancellable_is_cancelled (self->priv->closed_cancellable)) break; write_data->writable = FALSE; g_mutex_unlock (&write_data->mutex); n_sent = nice_agent_send (agent, self->priv->stream_id, self->priv->component_id, count - len, buf + len); g_mutex_lock (&write_data->mutex); if (n_sent <= 0) { if (!write_data->writable && !write_data->cancelled) g_cond_wait (&write_data->cond, &write_data->mutex); } else if (n_sent > 0) { /* Success. */ len += n_sent; } } while ((gsize) len < count); g_signal_handler_disconnect (G_OBJECT (agent), writeable_id); g_mutex_unlock (&write_data->mutex); if (cancel_id) g_cancellable_disconnect (cancellable, cancel_id); g_cancellable_disconnect (self->priv->closed_cancellable, closed_cancel_id); if (len == 0) { len = -1; if (!g_cancellable_set_error_if_cancelled (cancellable, error)) { if (g_cancellable_is_cancelled (self->priv->closed_cancellable)) g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, "Stream has been removed from agent"); } } write_data_unref (write_data); g_object_unref (agent); g_assert (len != 0); return len; }
static VALUE rg_closed_p(VALUE self) { return CBOOL2RVAL(g_output_stream_is_closed(_SELF(self))); }