1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright 2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see
17 * <http://www.gnu.org/licenses/>.
19 * In addition, when the library is used with OpenSSL, a special
20 * exception applies. Refer to the LICENSE_EXCEPTION file for details.
24 #include "gtlsoutputstream-base.h"
26 #include <glib/gi18n.h>
28 static void g_tls_output_stream_base_pollable_iface_init (GPollableOutputStreamInterface *iface);
30 G_DEFINE_TYPE_WITH_CODE (GTlsOutputStreamBase, g_tls_output_stream_base, G_TYPE_OUTPUT_STREAM,
31 G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, g_tls_output_stream_base_pollable_iface_init)
34 struct _GTlsOutputStreamBasePrivate
40 g_tls_output_stream_base_dispose (GObject *object)
42 GTlsOutputStreamBase *stream = G_TLS_OUTPUT_STREAM_BASE (object);
44 g_weak_ref_set (&stream->priv->weak_conn, NULL);
46 G_OBJECT_CLASS (g_tls_output_stream_base_parent_class)->dispose (object);
50 g_tls_output_stream_base_finalize (GObject *object)
52 GTlsOutputStreamBase *stream = G_TLS_OUTPUT_STREAM_BASE (object);
54 g_weak_ref_clear (&stream->priv->weak_conn);
56 G_OBJECT_CLASS (g_tls_output_stream_base_parent_class)->finalize (object);
60 g_tls_output_stream_base_write (GOutputStream *stream,
63 GCancellable *cancellable,
66 GTlsOutputStreamBase *tls_stream = G_TLS_OUTPUT_STREAM_BASE (stream);
67 GTlsConnectionBase *conn;
70 conn = g_weak_ref_get (&tls_stream->priv->weak_conn);
73 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
74 _("Connection is closed"));
78 ret = g_tls_connection_base_write (conn, buffer, count, TRUE,
80 g_object_unref (conn);
85 g_tls_output_stream_base_pollable_is_writable (GPollableOutputStream *pollable)
87 GTlsOutputStreamBase *tls_stream = G_TLS_OUTPUT_STREAM_BASE (pollable);
88 GTlsConnectionBase *conn;
91 conn = g_weak_ref_get (&tls_stream->priv->weak_conn);
92 g_return_val_if_fail (conn != NULL, FALSE);
94 ret = g_tls_connection_base_check (conn, G_IO_OUT);
96 g_object_unref (conn);
102 g_tls_output_stream_base_pollable_create_source (GPollableOutputStream *pollable,
103 GCancellable *cancellable)
105 GTlsOutputStreamBase *tls_stream = G_TLS_OUTPUT_STREAM_BASE (pollable);
106 GTlsConnectionBase *conn;
109 conn = g_weak_ref_get (&tls_stream->priv->weak_conn);
110 g_return_val_if_fail (conn != NULL, NULL);
112 ret = g_tls_connection_base_create_source (conn,
115 g_object_unref (conn);
120 g_tls_output_stream_base_pollable_write_nonblocking (GPollableOutputStream *pollable,
125 GTlsOutputStreamBase *tls_stream = G_TLS_OUTPUT_STREAM_BASE (pollable);
126 GTlsConnectionBase *conn;
129 conn = g_weak_ref_get (&tls_stream->priv->weak_conn);
130 g_return_val_if_fail (conn != NULL, -1);
132 ret = g_tls_connection_base_write (conn, buffer, size, FALSE, NULL, error);
134 g_object_unref (conn);
139 g_tls_output_stream_base_close (GOutputStream *stream,
140 GCancellable *cancellable,
143 GTlsOutputStreamBase *tls_stream = G_TLS_OUTPUT_STREAM_BASE (stream);
147 conn = g_weak_ref_get (&tls_stream->priv->weak_conn);
149 /* Special case here because this is called by the finalize
150 * of the main GTlsConnection object.
155 ret = g_tls_connection_base_close_internal (conn, G_TLS_DIRECTION_WRITE,
158 g_object_unref (conn);
162 /* We do async close as synchronous-in-a-thread so we don't need to
163 * implement G_IO_IN/G_IO_OUT flip-flopping just for this one case
164 * (since handshakes are also done synchronously now).
167 close_thread (GTask *task,
170 GCancellable *cancellable)
172 GTlsOutputStreamBase *tls_stream = object;
173 GError *error = NULL;
176 conn = g_weak_ref_get (&tls_stream->priv->weak_conn);
178 if (conn && !g_tls_connection_base_close_internal (conn,
179 G_TLS_DIRECTION_WRITE,
180 cancellable, &error))
181 g_task_return_error (task, error);
183 g_task_return_boolean (task, TRUE);
186 g_object_unref (conn);
191 g_tls_output_stream_base_close_async (GOutputStream *stream,
193 GCancellable *cancellable,
194 GAsyncReadyCallback callback,
199 task = g_task_new (stream, cancellable, callback, user_data);
200 g_task_set_source_tag (task, g_tls_output_stream_base_close_async);
201 g_task_set_priority (task, io_priority);
202 g_task_run_in_thread (task, close_thread);
203 g_object_unref (task);
207 g_tls_output_stream_base_close_finish (GOutputStream *stream,
208 GAsyncResult *result,
211 g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
212 g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) ==
213 g_tls_output_stream_base_close_async, FALSE);
215 return g_task_propagate_boolean (G_TASK (result), error);
219 g_tls_output_stream_base_class_init (GTlsOutputStreamBaseClass *klass)
221 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
222 GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (klass);
224 g_type_class_add_private (klass, sizeof (GTlsOutputStreamBasePrivate));
226 gobject_class->dispose = g_tls_output_stream_base_dispose;
227 gobject_class->finalize = g_tls_output_stream_base_finalize;
229 output_stream_class->write_fn = g_tls_output_stream_base_write;
230 output_stream_class->close_fn = g_tls_output_stream_base_close;
231 output_stream_class->close_async = g_tls_output_stream_base_close_async;
232 output_stream_class->close_finish = g_tls_output_stream_base_close_finish;
236 g_tls_output_stream_base_pollable_iface_init (GPollableOutputStreamInterface *iface)
238 iface->is_writable = g_tls_output_stream_base_pollable_is_writable;
239 iface->create_source = g_tls_output_stream_base_pollable_create_source;
240 iface->write_nonblocking = g_tls_output_stream_base_pollable_write_nonblocking;
244 g_tls_output_stream_base_init (GTlsOutputStreamBase *stream)
246 stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, G_TYPE_TLS_OUTPUT_STREAM_BASE, GTlsOutputStreamBasePrivate);
250 g_tls_output_stream_base_new (GTlsConnectionBase *conn)
252 GTlsOutputStreamBase *tls_stream;
254 tls_stream = g_object_new (G_TYPE_TLS_OUTPUT_STREAM_BASE, NULL);
255 g_weak_ref_init (&tls_stream->priv->weak_conn, conn);
257 return G_OUTPUT_STREAM (tls_stream);