Skip to content

Commit 6470a33

Browse files
author
Philip Withnall
committed
gnutls: Implement half-duplex close in GTlsInputStreamGnutls
https://bugzilla.gnome.org/show_bug.cgi?id=735754
1 parent 8d43835 commit 6470a33

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

tls/gnutls/gtlsinputstream-gnutls.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,86 @@ g_tls_input_stream_gnutls_pollable_read_nonblocking (GPollableInputStream *poll
126126
return ret;
127127
}
128128

129+
static gboolean
130+
g_tls_input_stream_gnutls_close (GInputStream *stream,
131+
GCancellable *cancellable,
132+
GError **error)
133+
{
134+
GTlsInputStreamGnutls *tls_stream = G_TLS_INPUT_STREAM_GNUTLS (stream);
135+
GIOStream *conn;
136+
gboolean ret;
137+
138+
conn = g_weak_ref_get (&tls_stream->priv->weak_conn);
139+
140+
/* Special case here because this is called by the finalize
141+
* of the main GTlsConnection object.
142+
*/
143+
if (conn == NULL)
144+
return TRUE;
145+
146+
ret = g_tls_connection_gnutls_close_internal (conn, G_TLS_DIRECTION_READ,
147+
cancellable, error);
148+
149+
g_object_unref (conn);
150+
return ret;
151+
}
152+
153+
/* We do async close as synchronous-in-a-thread so we don't need to
154+
* implement G_IO_IN/G_IO_OUT flip-flopping just for this one case
155+
* (since handshakes are also done synchronously now).
156+
*/
157+
static void
158+
close_thread (GTask *task,
159+
gpointer object,
160+
gpointer task_data,
161+
GCancellable *cancellable)
162+
{
163+
GTlsInputStreamGnutls *tls_stream = object;
164+
GError *error = NULL;
165+
GIOStream *conn;
166+
167+
conn = g_weak_ref_get (&tls_stream->priv->weak_conn);
168+
169+
if (conn && !g_tls_connection_gnutls_close_internal (conn,
170+
G_TLS_DIRECTION_READ,
171+
cancellable, &error))
172+
g_task_return_error (task, error);
173+
else
174+
g_task_return_boolean (task, TRUE);
175+
176+
if (conn)
177+
g_object_unref (conn);
178+
}
179+
180+
181+
static void
182+
g_tls_input_stream_gnutls_close_async (GInputStream *stream,
183+
int io_priority,
184+
GCancellable *cancellable,
185+
GAsyncReadyCallback callback,
186+
gpointer user_data)
187+
{
188+
GTask *task;
189+
190+
task = g_task_new (stream, cancellable, callback, user_data);
191+
g_task_set_source_tag (task, g_tls_input_stream_gnutls_close_async);
192+
g_task_set_priority (task, io_priority);
193+
g_task_run_in_thread (task, close_thread);
194+
g_object_unref (task);
195+
}
196+
197+
static gboolean
198+
g_tls_input_stream_gnutls_close_finish (GInputStream *stream,
199+
GAsyncResult *result,
200+
GError **error)
201+
{
202+
g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
203+
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) ==
204+
g_tls_input_stream_gnutls_close_async, FALSE);
205+
206+
return g_task_propagate_boolean (G_TASK (result), error);
207+
}
208+
129209
static void
130210
g_tls_input_stream_gnutls_class_init (GTlsInputStreamGnutlsClass *klass)
131211
{
@@ -138,6 +218,9 @@ g_tls_input_stream_gnutls_class_init (GTlsInputStreamGnutlsClass *klass)
138218
gobject_class->finalize = g_tls_input_stream_gnutls_finalize;
139219

140220
input_stream_class->read_fn = g_tls_input_stream_gnutls_read;
221+
input_stream_class->close_fn = g_tls_input_stream_gnutls_close;
222+
input_stream_class->close_async = g_tls_input_stream_gnutls_close_async;
223+
input_stream_class->close_finish = g_tls_input_stream_gnutls_close_finish;
141224
}
142225

143226
static void

0 commit comments

Comments
 (0)