@@ -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+
129209static void
130210g_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
143226static void
0 commit comments