diff options
author | Philip Withnall <philip.withnall@collabora.co.uk> | 2014-08-08 13:35:17 +0100 |
---|---|---|
committer | Olivier Crête <olivier.crete@collabora.com> | 2014-08-21 14:33:11 -0400 |
commit | 859fcb9ef3b43baf49f3d6cb7f757847d068bbb3 (patch) | |
tree | badb34b9e80eed496385c48adf90cf0f07175114 /agent/outputstream.c | |
parent | 4bc5a9c728b47a65d82192f36be7755541f653a1 (diff) | |
download | libnice-859fcb9ef3b43baf49f3d6cb7f757847d068bbb3.tar.gz |
agent: Close pseudo-TCP streams when closing G[IO|Input|Output]Streams
This means that users of the Nice[Input|Output|IO]Stream API can easily
close TCP connections without having to hack around with libnice
internals.
Diffstat (limited to 'agent/outputstream.c')
-rw-r--r-- | agent/outputstream.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/agent/outputstream.c b/agent/outputstream.c index 4de37dc..fbde6ce 100644 --- a/agent/outputstream.c +++ b/agent/outputstream.c @@ -50,8 +50,8 @@ * component triple, and will be closed as soon as that stream is removed from * the agent (e.g. if nice_agent_remove_stream() is called from another thread). * If g_output_stream_close() is called on a #NiceOutputStream, the output - * stream will be marked as closed, but the underlying #NiceAgent stream will - * not be removed. Use nice_agent_remove_stream() to do that. + * stream and underlying #NiceAgent stream will be closed, but the underlying + * stream will not be removed. Use nice_agent_remove_stream() to do that. * * The output stream can only be used once the * #NiceAgent::reliable-transport-writable signal has been received for the @@ -104,6 +104,8 @@ static void nice_output_stream_set_property (GObject *object, guint prop_id, static gssize nice_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error); +static gboolean nice_output_stream_close (GOutputStream *stream, + GCancellable *cancellable, GError **error); static gboolean nice_output_stream_is_writable (GPollableOutputStream *stream); static gssize nice_output_stream_write_nonblocking ( @@ -122,6 +124,7 @@ nice_output_stream_class_init (NiceOutputStreamClass *klass) g_type_class_add_private (klass, sizeof (NiceOutputStreamPrivate)); stream_class->write_fn = nice_output_stream_write; + stream_class->close_fn = nice_output_stream_close; gobject_class->set_property = nice_output_stream_set_property; gobject_class->get_property = nice_output_stream_get_property; @@ -185,6 +188,11 @@ 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); @@ -464,6 +472,36 @@ nice_output_stream_write (GOutputStream *stream, const void *buffer, gsize count } static gboolean +nice_output_stream_close (GOutputStream *stream, GCancellable *cancellable, + GError **error) +{ + NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv; + Component *component = NULL; + Stream *_stream = NULL; + NiceAgent *agent; /* owned */ + + /* Has the agent disappeared? */ + agent = g_weak_ref_get (&priv->agent_ref); + if (agent == NULL) + return TRUE; + + agent_lock (); + + /* Shut down the write side of the pseudo-TCP stream. */ + if (agent_find_component (agent, priv->stream_id, priv->component_id, + &_stream, &component) && + component->tcp != NULL) { + pseudo_tcp_socket_shutdown (component->tcp, PSEUDO_TCP_SHUTDOWN_WR); + } + + agent_unlock (); + + g_object_unref (agent); + + return TRUE; +} + +static gboolean nice_output_stream_is_writable (GPollableOutputStream *stream) { NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv; |