• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-io-stream.c
4  *
5  * Copyright 2012 Red Hat, Inc.
6  */
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #include "soup-io-stream.h"
13 #include "soup.h"
14 #include "soup-filter-input-stream.h"
15 
16 struct _SoupIOStreamPrivate {
17 	GIOStream *base_iostream;
18 	gboolean close_on_dispose;
19 
20 	GInputStream *istream;
21 	GOutputStream *ostream;
22 	gboolean disposing;
23 };
24 
25 enum {
26 	PROP_0,
27 
28 	PROP_BASE_IOSTREAM,
29 	PROP_CLOSE_ON_DISPOSE
30 };
31 
G_DEFINE_TYPE_WITH_PRIVATE(SoupIOStream,soup_io_stream,G_TYPE_IO_STREAM)32 G_DEFINE_TYPE_WITH_PRIVATE (SoupIOStream, soup_io_stream, G_TYPE_IO_STREAM)
33 
34 static void
35 soup_io_stream_init (SoupIOStream *stream)
36 {
37 	stream->priv = soup_io_stream_get_instance_private (stream);
38 }
39 
40 static void
soup_io_stream_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)41 soup_io_stream_set_property (GObject *object, guint prop_id,
42 			     const GValue *value, GParamSpec *pspec)
43 {
44 	SoupIOStream *siostream = SOUP_IO_STREAM (object);
45 	GIOStream *io;
46 
47 	switch (prop_id) {
48 	case PROP_BASE_IOSTREAM:
49 		io = siostream->priv->base_iostream = g_value_dup_object (value);
50 		if (io) {
51 			siostream->priv->istream =
52 				soup_filter_input_stream_new (g_io_stream_get_input_stream (io));
53 			siostream->priv->ostream =
54 				g_object_ref (g_io_stream_get_output_stream (io));
55 		} else {
56 			g_clear_object (&siostream->priv->istream);
57 			g_clear_object (&siostream->priv->ostream);
58 		}
59 		break;
60 	case PROP_CLOSE_ON_DISPOSE:
61 		siostream->priv->close_on_dispose = g_value_get_boolean (value);
62 		break;
63 	default:
64 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
65 		break;
66 	}
67 }
68 
69 static void
soup_io_stream_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)70 soup_io_stream_get_property (GObject *object, guint prop_id,
71 			     GValue *value, GParamSpec *pspec)
72 {
73 	SoupIOStream *siostream = SOUP_IO_STREAM (object);
74 
75 	switch (prop_id) {
76 	case PROP_BASE_IOSTREAM:
77 		g_value_set_object (value, siostream->priv->base_iostream);
78 		break;
79 	case PROP_CLOSE_ON_DISPOSE:
80 		g_value_set_boolean (value, siostream->priv->close_on_dispose);
81 		break;
82 	default:
83 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
84 		break;
85 	}
86 }
87 
88 static void
soup_io_stream_dispose(GObject * object)89 soup_io_stream_dispose (GObject *object)
90 {
91 	SoupIOStream *siostream = SOUP_IO_STREAM (object);
92 
93 	siostream->priv->disposing = TRUE;
94 
95 	G_OBJECT_CLASS (soup_io_stream_parent_class)->dispose (object);
96 }
97 
98 static void
soup_io_stream_finalize(GObject * object)99 soup_io_stream_finalize (GObject *object)
100 {
101 	SoupIOStream *siostream = SOUP_IO_STREAM (object);
102 
103 	g_clear_object (&siostream->priv->base_iostream);
104 	g_clear_object (&siostream->priv->istream);
105 	g_clear_object (&siostream->priv->ostream);
106 
107 	G_OBJECT_CLASS (soup_io_stream_parent_class)->finalize (object);
108 }
109 
110 static GInputStream *
soup_io_stream_get_input_stream(GIOStream * stream)111 soup_io_stream_get_input_stream (GIOStream *stream)
112 {
113 	return SOUP_IO_STREAM (stream)->priv->istream;
114 }
115 
116 static GOutputStream *
soup_io_stream_get_output_stream(GIOStream * stream)117 soup_io_stream_get_output_stream (GIOStream *stream)
118 {
119 	return SOUP_IO_STREAM (stream)->priv->ostream;
120 }
121 
122 
123 static gboolean
soup_io_stream_close(GIOStream * stream,GCancellable * cancellable,GError ** error)124 soup_io_stream_close (GIOStream     *stream,
125 		      GCancellable  *cancellable,
126 		      GError       **error)
127 {
128 	SoupIOStream *siostream = SOUP_IO_STREAM (stream);
129 
130 	if (siostream->priv->disposing &&
131 	    !siostream->priv->close_on_dispose)
132 		return TRUE;
133 
134 	return g_io_stream_close (siostream->priv->base_iostream,
135 				  cancellable, error);
136 }
137 
138 static void
close_async_complete(GObject * object,GAsyncResult * result,gpointer user_data)139 close_async_complete (GObject      *object,
140 		      GAsyncResult *result,
141 		      gpointer      user_data)
142 {
143 	GTask *task = user_data;
144 	GError *error = NULL;
145 
146 	if (g_io_stream_close_finish (G_IO_STREAM (object), result, &error))
147 		g_task_return_boolean (task, TRUE);
148 	else
149 		g_task_return_error (task, error);
150 	g_object_unref (task);
151 }
152 
153 static void
soup_io_stream_close_async(GIOStream * stream,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)154 soup_io_stream_close_async (GIOStream           *stream,
155 			    int                  io_priority,
156 			    GCancellable        *cancellable,
157 			    GAsyncReadyCallback  callback,
158 			    gpointer             user_data)
159 {
160 	GTask *task;
161 
162 	task = g_task_new (stream, cancellable, callback, user_data);
163 	g_io_stream_close_async (SOUP_IO_STREAM (stream)->priv->base_iostream,
164 				 io_priority, cancellable,
165 				 close_async_complete, task);
166 }
167 
168 static gboolean
soup_io_stream_close_finish(GIOStream * stream,GAsyncResult * result,GError ** error)169 soup_io_stream_close_finish (GIOStream     *stream,
170                              GAsyncResult  *result,
171 			     GError       **error)
172 {
173 	return g_task_propagate_boolean (G_TASK (result), error);
174 }
175 
176 static void
soup_io_stream_class_init(SoupIOStreamClass * stream_class)177 soup_io_stream_class_init (SoupIOStreamClass *stream_class)
178 {
179 	GObjectClass *object_class = G_OBJECT_CLASS (stream_class);
180 	GIOStreamClass *io_stream_class = G_IO_STREAM_CLASS (stream_class);
181 
182 	object_class->set_property = soup_io_stream_set_property;
183 	object_class->get_property = soup_io_stream_get_property;
184 	object_class->dispose = soup_io_stream_dispose;
185 	object_class->finalize = soup_io_stream_finalize;
186 
187 	io_stream_class->get_input_stream = soup_io_stream_get_input_stream;
188 	io_stream_class->get_output_stream = soup_io_stream_get_output_stream;
189 	io_stream_class->close_fn = soup_io_stream_close;
190 	io_stream_class->close_async = soup_io_stream_close_async;
191 	io_stream_class->close_finish = soup_io_stream_close_finish;
192 
193 	g_object_class_install_property (
194 		object_class, PROP_BASE_IOSTREAM,
195 		g_param_spec_object ("base-iostream",
196 				     "Base IOStream",
197 				     "Base GIOStream",
198 				     G_TYPE_IO_STREAM,
199 				     G_PARAM_READWRITE |
200 				     G_PARAM_CONSTRUCT_ONLY |
201 				     G_PARAM_STATIC_STRINGS));
202 	g_object_class_install_property (
203 		object_class, PROP_CLOSE_ON_DISPOSE,
204 		g_param_spec_boolean ("close-on-dispose",
205 				      "Close base stream",
206 				      "Close base GIOStream when closing",
207 				      TRUE,
208 				      G_PARAM_READWRITE |
209 				      G_PARAM_CONSTRUCT_ONLY |
210 				      G_PARAM_STATIC_STRINGS));
211 }
212 
213 GIOStream *
soup_io_stream_new(GIOStream * base_iostream,gboolean close_on_dispose)214 soup_io_stream_new (GIOStream *base_iostream,
215 		    gboolean   close_on_dispose)
216 {
217 	return g_object_new (SOUP_TYPE_IO_STREAM,
218 			     "base-iostream", base_iostream,
219 			     "close-on-dispose", close_on_dispose,
220 			     NULL);
221 }
222 
223 GIOStream *
soup_io_stream_get_base_iostream(SoupIOStream * stream)224 soup_io_stream_get_base_iostream (SoupIOStream *stream)
225 {
226 	g_return_val_if_fail (SOUP_IS_IO_STREAM (stream), NULL);
227 
228 	return stream->priv->base_iostream;
229 }
230