137c97628522ee2bac60b5dae8ca08119ab6aa8c
[platform/upstream/glib.git] / gio / giostream.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2008 codethink
4  * Copyright © 2009 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General
17  * Public License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  * Authors: Ryan Lortie <desrt@desrt.ca>
22  *          Alexander Larsson <alexl@redhat.com>
23  */
24
25 #include "config.h"
26 #include <glib.h>
27 #include "glibintl.h"
28
29 #include "giostream.h"
30 #include <gio/gsimpleasyncresult.h>
31 #include <gio/gasyncresult.h>
32
33
34 G_DEFINE_ABSTRACT_TYPE (GIOStream, g_io_stream, G_TYPE_OBJECT);
35
36 /**
37  * SECTION:giostream
38  * @short_description: Base class for implementing read/write streams
39  * @include: gio/gio.h
40  * @see_also: #GInputStream, #GOutputStream
41  *
42  * GIOStream represents an object that has both read and write streams.
43  * Generally the two streams acts as separate input and output streams,
44  * but they share some common resources and state. For instance, for
45  * seekable streams they may use the same position in both streams.
46  *
47  * Examples of #GIOStream objects are #GSocketConnection which represents
48  * a two-way network connection, and #GFileIOStream which represent a
49  * file handle opened in read-write mode.
50  *
51  * To do the actual reading and writing you need to get the substreams
52  * with g_io_stream_get_input_stream() and g_io_stream_get_output_stream().
53  *
54  * The #GIOStream object owns the input and the output streams, not the other
55  * way around, so keeping the substreams alive will not keep the #GIOStream
56  * object alive. If the #GIOStream object is freed it will be closed, thus
57  * closing the substream, so even if the substreams stay alive they will
58  * always just return a %G_IO_ERROR_CLOSED for all operations.
59  *
60  * To close a stream use g_io_stream_close() which will close the common
61  * stream object and also the individual substreams. You can also close
62  * the substreams themselves. In most cases this only marks the
63  * substream as closed, so further I/O on it fails. However, some streams
64  * may support "half-closed" states where one direction of the stream
65  * is actually shut down.
66  *
67  * Since: 2.22
68  */
69
70 enum
71 {
72   PROP_0,
73   PROP_INPUT_STREAM,
74   PROP_OUTPUT_STREAM,
75   PROP_CLOSED
76 };
77
78 struct _GIOStreamPrivate {
79   guint closed : 1;
80   guint pending : 1;
81   GAsyncReadyCallback outstanding_callback;
82 };
83
84 static gboolean g_io_stream_real_close        (GIOStream            *stream,
85                                                GCancellable         *cancellable,
86                                                GError              **error);
87 static void     g_io_stream_real_close_async  (GIOStream            *stream,
88                                                int                   io_priority,
89                                                GCancellable         *cancellable,
90                                                GAsyncReadyCallback   callback,
91                                                gpointer              user_data);
92 static gboolean g_io_stream_real_close_finish (GIOStream            *stream,
93                                                GAsyncResult         *result,
94                                                GError              **error);
95
96 static void
97 g_io_stream_finalize (GObject *object)
98 {
99   G_OBJECT_CLASS (g_io_stream_parent_class)->finalize (object);
100 }
101
102 static void
103 g_io_stream_dispose (GObject *object)
104 {
105   GIOStream *stream;
106
107   stream = G_IO_STREAM (object);
108
109   if (!stream->priv->closed)
110     g_io_stream_close (stream, NULL, NULL);
111
112   G_OBJECT_CLASS (g_io_stream_parent_class)->dispose (object);
113 }
114
115 static void
116 g_io_stream_init (GIOStream *stream)
117 {
118   stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
119                                               G_TYPE_IO_STREAM,
120                                               GIOStreamPrivate);
121 }
122
123 static void
124 g_io_stream_get_property (GObject    *object,
125                           guint       prop_id,
126                           GValue     *value,
127                           GParamSpec *pspec)
128 {
129   GIOStream *stream = G_IO_STREAM (object);
130
131   switch (prop_id)
132     {
133       case PROP_CLOSED:
134         g_value_set_boolean (value, stream->priv->closed);
135         break;
136
137       case PROP_INPUT_STREAM:
138         g_value_set_object (value, g_io_stream_get_input_stream (stream));
139         break;
140
141       case PROP_OUTPUT_STREAM:
142         g_value_set_object (value, g_io_stream_get_output_stream (stream));
143         break;
144
145       default:
146         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
147     }
148 }
149
150 static void
151 g_io_stream_set_property (GObject      *object,
152                           guint         prop_id,
153                           const GValue *value,
154                           GParamSpec   *pspec)
155 {
156   switch (prop_id)
157     {
158     default:
159       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
160     }
161 }
162
163 static void
164 g_io_stream_class_init (GIOStreamClass *klass)
165 {
166   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
167
168   g_type_class_add_private (klass, sizeof (GIOStreamPrivate));
169
170   gobject_class->finalize = g_io_stream_finalize;
171   gobject_class->dispose = g_io_stream_dispose;
172   gobject_class->set_property = g_io_stream_set_property;
173   gobject_class->get_property = g_io_stream_get_property;
174
175   klass->close_fn = g_io_stream_real_close;
176   klass->close_async = g_io_stream_real_close_async;
177   klass->close_finish = g_io_stream_real_close_finish;
178
179   g_object_class_install_property (gobject_class, PROP_CLOSED,
180                                    g_param_spec_boolean ("closed",
181                                                          P_("Closed"),
182                                                          P_("Is the stream closed"),
183                                                          FALSE,
184                                                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
185
186   g_object_class_install_property (gobject_class, PROP_INPUT_STREAM,
187                                    g_param_spec_object ("input-stream",
188                                                         P_("Input stream"),
189                                                         P_("The GInputStream to read from"),
190                                                         G_TYPE_INPUT_STREAM,
191                                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
192   g_object_class_install_property (gobject_class, PROP_OUTPUT_STREAM,
193                                    g_param_spec_object ("output-stream",
194                                                         P_("Output stream"),
195                                                         P_("The GOutputStream to write to"),
196                                                         G_TYPE_OUTPUT_STREAM,
197                                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
198 }
199
200 /**
201  * g_io_stream_is_closed:
202  * @stream: a #GIOStream
203  *
204  * Checks if a stream is closed.
205  *
206  * Returns: %TRUE if the stream is closed.
207  *
208  * Since: 2.22
209  */
210 gboolean
211 g_io_stream_is_closed (GIOStream *stream)
212 {
213   g_return_val_if_fail (G_IS_IO_STREAM (stream), TRUE);
214
215   return stream->priv->closed;
216 }
217
218 /**
219  * g_io_stream_get_input_stream:
220  * @stream: a #GIOStream
221  *
222  * Gets the input stream for this object. This is used
223  * for reading.
224  *
225  * Returns: (transfer none): a #GInputStream, owned by the #GIOStream.
226  * Do not free.
227  *
228  * Since: 2.22
229  */
230 GInputStream *
231 g_io_stream_get_input_stream (GIOStream *stream)
232 {
233   GIOStreamClass *klass;
234
235   klass = G_IO_STREAM_GET_CLASS (stream);
236
237   g_assert (klass->get_input_stream != NULL);
238
239   return klass->get_input_stream (stream);
240 }
241
242 /**
243  * g_io_stream_get_output_stream:
244  * @stream: a #GIOStream
245  *
246  * Gets the output stream for this object. This is used for
247  * writing.
248  *
249  * Returns: (transfer none): a #GOutputStream, owned by the #GIOStream.
250  * Do not free.
251  *
252  * Since: 2.22
253  */
254 GOutputStream *
255 g_io_stream_get_output_stream (GIOStream *stream)
256 {
257   GIOStreamClass *klass;
258
259   klass = G_IO_STREAM_GET_CLASS (stream);
260
261   g_assert (klass->get_output_stream != NULL);
262   return klass->get_output_stream (stream);
263 }
264
265 /**
266  * g_io_stream_has_pending:
267  * @stream: a #GIOStream
268  *
269  * Checks if a stream has pending actions.
270  *
271  * Returns: %TRUE if @stream has pending actions.
272  *
273  * Since: 2.22
274  **/
275 gboolean
276 g_io_stream_has_pending (GIOStream *stream)
277 {
278   g_return_val_if_fail (G_IS_IO_STREAM (stream), FALSE);
279
280   return stream->priv->pending;
281 }
282
283 /**
284  * g_io_stream_set_pending:
285  * @stream: a #GIOStream
286  * @error: a #GError location to store the error occuring, or %NULL to
287  *     ignore
288  *
289  * Sets @stream to have actions pending. If the pending flag is
290  * already set or @stream is closed, it will return %FALSE and set
291  * @error.
292  *
293  * Return value: %TRUE if pending was previously unset and is now set.
294  *
295  * Since: 2.22
296  */
297 gboolean
298 g_io_stream_set_pending (GIOStream  *stream,
299                          GError    **error)
300 {
301   g_return_val_if_fail (G_IS_IO_STREAM (stream), FALSE);
302
303   if (stream->priv->closed)
304     {
305       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
306                            _("Stream is already closed"));
307       return FALSE;
308     }
309
310   if (stream->priv->pending)
311     {
312       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
313                            /* Translators: This is an error you get if there is
314                             * already an operation running against this stream when
315                             * you try to start one */
316                            _("Stream has outstanding operation"));
317       return FALSE;
318     }
319
320   stream->priv->pending = TRUE;
321   return TRUE;
322 }
323
324 /**
325  * g_io_stream_clear_pending:
326  * @stream: a #GIOStream
327  *
328  * Clears the pending flag on @stream.
329  *
330  * Since: 2.22
331  */
332 void
333 g_io_stream_clear_pending (GIOStream *stream)
334 {
335   g_return_if_fail (G_IS_IO_STREAM (stream));
336
337   stream->priv->pending = FALSE;
338 }
339
340 static gboolean
341 g_io_stream_real_close (GIOStream     *stream,
342                         GCancellable  *cancellable,
343                         GError       **error)
344 {
345   gboolean res;
346
347   res = g_output_stream_close (g_io_stream_get_output_stream (stream),
348                                cancellable, error);
349
350   /* If this errored out, unset error so that we don't report
351      further errors, but still do the following ops */
352   if (error != NULL && *error != NULL)
353     error = NULL;
354
355   res &= g_input_stream_close (g_io_stream_get_input_stream (stream),
356                                cancellable, error);
357
358   return res;
359 }
360
361 /**
362  * g_io_stream_close:
363  * @stream: a #GIOStream
364  * @cancellable: optional #GCancellable object, %NULL to ignore
365  * @error: location to store the error occuring, or %NULL to ignore
366  *
367  * Closes the stream, releasing resources related to it. This will also
368  * closes the individual input and output streams, if they are not already
369  * closed.
370  *
371  * Once the stream is closed, all other operations will return
372  * %G_IO_ERROR_CLOSED. Closing a stream multiple times will not
373  * return an error.
374  *
375  * Closing a stream will automatically flush any outstanding buffers
376  * in the stream.
377  *
378  * Streams will be automatically closed when the last reference
379  * is dropped, but you might want to call this function to make sure
380  * resources are released as early as possible.
381  *
382  * Some streams might keep the backing store of the stream (e.g. a file
383  * descriptor) open after the stream is closed. See the documentation for
384  * the individual stream for details.
385  *
386  * On failure the first error that happened will be reported, but the
387  * close operation will finish as much as possible. A stream that failed
388  * to close will still return %G_IO_ERROR_CLOSED for all operations.
389  * Still, it is important to check and report the error to the user,
390  * otherwise there might be a loss of data as all data might not be written.
391  *
392  * If @cancellable is not NULL, then the operation can be cancelled by
393  * triggering the cancellable object from another thread. If the operation
394  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
395  * Cancelling a close will still leave the stream closed, but some streams
396  * can use a faster close that doesn't block to e.g. check errors.
397  *
398  * The default implementation of this method just calls close on the
399  * individual input/output streams.
400  *
401  * Return value: %TRUE on success, %FALSE on failure
402  *
403  * Since: 2.22
404  */
405 gboolean
406 g_io_stream_close (GIOStream     *stream,
407                    GCancellable  *cancellable,
408                    GError       **error)
409 {
410   GIOStreamClass *class;
411   gboolean res;
412
413   g_return_val_if_fail (G_IS_IO_STREAM (stream), FALSE);
414
415   class = G_IO_STREAM_GET_CLASS (stream);
416
417   if (stream->priv->closed)
418     return TRUE;
419
420   if (!g_io_stream_set_pending (stream, error))
421     return FALSE;
422
423   if (cancellable)
424     g_cancellable_push_current (cancellable);
425
426   res = TRUE;
427   if (class->close_fn)
428     res = class->close_fn (stream, cancellable, error);
429
430   if (cancellable)
431     g_cancellable_pop_current (cancellable);
432
433   stream->priv->closed = TRUE;
434   g_io_stream_clear_pending (stream);
435
436   return res;
437 }
438
439 static void
440 async_ready_close_callback_wrapper (GObject      *source_object,
441                                     GAsyncResult *res,
442                                     gpointer      user_data)
443 {
444   GIOStream *stream = G_IO_STREAM (source_object);
445
446   stream->priv->closed = TRUE;
447   g_io_stream_clear_pending (stream);
448   if (stream->priv->outstanding_callback)
449     (*stream->priv->outstanding_callback) (source_object, res, user_data);
450   g_object_unref (stream);
451 }
452
453 /**
454  * g_io_stream_close_async:
455  * @stream: a #GIOStream
456  * @io_priority: the io priority of the request
457  * @callback: callback to call when the request is satisfied
458  * @user_data: the data to pass to callback function
459  * @cancellable: optional cancellable object
460  *
461  * Requests an asynchronous close of the stream, releasing resources
462  * related to it. When the operation is finished @callback will be
463  * called. You can then call g_io_stream_close_finish() to get
464  * the result of the operation.
465  *
466  * For behaviour details see g_io_stream_close().
467  *
468  * The asynchronous methods have a default fallback that uses threads
469  * to implement asynchronicity, so they are optional for inheriting
470  * classes. However, if you override one you must override all.
471  *
472  * Since: 2.22
473  */
474 void
475 g_io_stream_close_async (GIOStream           *stream,
476                          int                  io_priority,
477                          GCancellable        *cancellable,
478                          GAsyncReadyCallback  callback,
479                          gpointer             user_data)
480 {
481   GIOStreamClass *class;
482   GSimpleAsyncResult *simple;
483   GError *error = NULL;
484
485   g_return_if_fail (G_IS_IO_STREAM (stream));
486
487   if (stream->priv->closed)
488     {
489       simple = g_simple_async_result_new (G_OBJECT (stream),
490                                           callback,
491                                           user_data,
492                                           g_io_stream_close_async);
493       g_simple_async_result_complete_in_idle (simple);
494       g_object_unref (simple);
495       return;
496     }
497
498   if (!g_io_stream_set_pending (stream, &error))
499     {
500       g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream),
501                                             callback,
502                                             user_data,
503                                             error);
504       return;
505     }
506
507   class = G_IO_STREAM_GET_CLASS (stream);
508   stream->priv->outstanding_callback = callback;
509   g_object_ref (stream);
510   class->close_async (stream, io_priority, cancellable,
511                       async_ready_close_callback_wrapper, user_data);
512 }
513
514 /**
515  * g_io_stream_close_finish:
516  * @stream: a #GIOStream
517  * @result: a #GAsyncResult
518  * @error: a #GError location to store the error occuring, or %NULL to
519  *    ignore
520  *
521  * Closes a stream.
522  *
523  * Returns: %TRUE if stream was successfully closed, %FALSE otherwise.
524  *
525  * Since: 2.22
526  */
527 gboolean
528 g_io_stream_close_finish (GIOStream     *stream,
529                           GAsyncResult  *result,
530                           GError       **error)
531 {
532   GSimpleAsyncResult *simple;
533   GIOStreamClass *class;
534
535   g_return_val_if_fail (G_IS_IO_STREAM (stream), FALSE);
536   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
537
538   if (G_IS_SIMPLE_ASYNC_RESULT (result))
539     {
540       simple = G_SIMPLE_ASYNC_RESULT (result);
541       if (g_simple_async_result_propagate_error (simple, error))
542         return FALSE;
543
544       /* Special case already closed */
545       if (g_simple_async_result_get_source_tag (simple) == g_io_stream_close_async)
546         return TRUE;
547     }
548
549   class = G_IO_STREAM_GET_CLASS (stream);
550   return class->close_finish (stream, result, error);
551 }
552
553
554 static void
555 close_async_thread (GSimpleAsyncResult *res,
556                     GObject            *object,
557                     GCancellable       *cancellable)
558 {
559   GIOStreamClass *class;
560   GError *error = NULL;
561   gboolean result;
562
563   /* Auto handling of cancelation disabled, and ignore cancellation,
564    * since we want to close things anyway, although possibly in a
565    * quick-n-dirty way. At least we never want to leak open handles
566    */
567   class = G_IO_STREAM_GET_CLASS (object);
568   if (class->close_fn)
569     {
570       result = class->close_fn (G_IO_STREAM (object), cancellable, &error);
571       if (!result)
572         g_simple_async_result_take_error (res, error);
573     }
574 }
575
576 static void
577 g_io_stream_real_close_async (GIOStream           *stream,
578                               int                  io_priority,
579                               GCancellable        *cancellable,
580                               GAsyncReadyCallback  callback,
581                               gpointer             user_data)
582 {
583   GSimpleAsyncResult *res;
584
585   res = g_simple_async_result_new (G_OBJECT (stream),
586                                    callback,
587                                    user_data,
588                                    g_io_stream_real_close_async);
589
590   g_simple_async_result_set_handle_cancellation (res, FALSE);
591
592   g_simple_async_result_run_in_thread (res,
593                                        close_async_thread,
594                                        io_priority,
595                                        cancellable);
596   g_object_unref (res);
597 }
598
599 static gboolean
600 g_io_stream_real_close_finish (GIOStream     *stream,
601                                GAsyncResult  *result,
602                                GError       **error)
603 {
604   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
605   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) ==
606                   g_io_stream_real_close_async);
607   return TRUE;
608 }
609
610 typedef struct
611 {
612   GIOStream *stream1;
613   GIOStream *stream2;
614   GIOStreamSpliceFlags flags;
615   gint io_priority;
616   GCancellable *cancellable;
617   gulong cancelled_id;
618   GCancellable *op1_cancellable;
619   GCancellable *op2_cancellable;
620   guint completed;
621   GError *error;
622 } SpliceContext;
623
624 static void
625 splice_context_free (SpliceContext *ctx)
626 {
627   g_object_unref (ctx->stream1);
628   g_object_unref (ctx->stream2);
629   if (ctx->cancellable != NULL)
630     g_object_unref (ctx->cancellable);
631   g_object_unref (ctx->op1_cancellable);
632   g_object_unref (ctx->op2_cancellable);
633   g_clear_error (&ctx->error);
634   g_slice_free (SpliceContext, ctx);
635 }
636
637 static void
638 splice_complete (GSimpleAsyncResult *simple,
639                  SpliceContext      *ctx)
640 {
641   if (ctx->cancelled_id != 0)
642     g_cancellable_disconnect (ctx->cancellable, ctx->cancelled_id);
643   ctx->cancelled_id = 0;
644
645   if (ctx->error != NULL)
646     g_simple_async_result_set_from_error (simple, ctx->error);
647   g_simple_async_result_complete (simple);
648 }
649
650 static void
651 splice_close_cb (GObject      *iostream,
652                  GAsyncResult *res,
653                  gpointer      user_data)
654 {
655   GSimpleAsyncResult *simple = user_data;
656   SpliceContext *ctx;
657   GError *error = NULL;
658
659   g_io_stream_close_finish (G_IO_STREAM (iostream), res, &error);
660
661   ctx = g_simple_async_result_get_op_res_gpointer (simple);
662   ctx->completed++;
663
664   /* Keep the first error that occured */
665   if (error != NULL && ctx->error == NULL)
666     ctx->error = error;
667   else
668     g_clear_error (&error);
669
670   /* If all operations are done, complete now */
671   if (ctx->completed == 4)
672     splice_complete (simple, ctx);
673
674   g_object_unref (simple);
675 }
676
677 static void
678 splice_cb (GObject      *ostream,
679            GAsyncResult *res,
680            gpointer      user_data)
681 {
682   GSimpleAsyncResult *simple = user_data;
683   SpliceContext *ctx;
684   GError *error = NULL;
685
686   g_output_stream_splice_finish (G_OUTPUT_STREAM (ostream), res, &error);
687
688   ctx = g_simple_async_result_get_op_res_gpointer (simple);
689   ctx->completed++;
690
691   /* ignore cancellation error if it was not requested by the user */
692   if (error != NULL &&
693       g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
694       (ctx->cancellable == NULL ||
695        !g_cancellable_is_cancelled (ctx->cancellable)))
696     g_clear_error (&error);
697
698   /* Keep the first error that occured */
699   if (error != NULL && ctx->error == NULL)
700     ctx->error = error;
701   else
702     g_clear_error (&error);
703
704    if (ctx->completed == 1 &&
705        (ctx->flags & G_IO_STREAM_SPLICE_WAIT_FOR_BOTH) == 0)
706     {
707       /* We don't want to wait for the 2nd operation to finish, cancel it */
708       g_cancellable_cancel (ctx->op1_cancellable);
709       g_cancellable_cancel (ctx->op2_cancellable);
710     }
711   else if (ctx->completed == 2)
712     {
713       if (ctx->cancellable == NULL ||
714           !g_cancellable_is_cancelled (ctx->cancellable))
715         {
716           g_cancellable_reset (ctx->op1_cancellable);
717           g_cancellable_reset (ctx->op2_cancellable);
718         }
719
720       /* Close the IO streams if needed */
721       if ((ctx->flags & G_IO_STREAM_SPLICE_CLOSE_STREAM1) != 0)
722         g_io_stream_close_async (ctx->stream1, ctx->io_priority,
723             ctx->op1_cancellable, splice_close_cb, g_object_ref (simple));
724       else
725         ctx->completed++;
726
727       if ((ctx->flags & G_IO_STREAM_SPLICE_CLOSE_STREAM2) != 0)
728         g_io_stream_close_async (ctx->stream2, ctx->io_priority,
729             ctx->op2_cancellable, splice_close_cb, g_object_ref (simple));
730       else
731         ctx->completed++;
732
733       /* If all operations are done, complete now */
734       if (ctx->completed == 4)
735         splice_complete (simple, ctx);
736     }
737
738   g_object_unref (simple);
739 }
740
741 static void
742 splice_cancelled_cb (GCancellable       *cancellable,
743                      GSimpleAsyncResult *simple)
744 {
745   SpliceContext *ctx;
746
747   ctx = g_simple_async_result_get_op_res_gpointer (simple);
748   g_cancellable_cancel (ctx->op1_cancellable);
749   g_cancellable_cancel (ctx->op2_cancellable);
750 }
751
752 /**
753  * g_io_stream_splice_async:
754  * @stream1: a #GIOStream.
755  * @stream2: a #GIOStream.
756  * @flags: a set of #GIOStreamSpliceFlags.
757  * @io_priority: the io priority of the request.
758  * @cancellable: optional #GCancellable object, %NULL to ignore.
759  * @callback: a #GAsyncReadyCallback.
760  * @user_data: user data passed to @callback.
761  *
762  * Asyncronously splice the output stream of @stream1 to the input stream of
763  * @stream2, and splice the output stream of @stream2 to the input stream of
764  * @stream1.
765  *
766  * When the operation is finished @callback will be called.
767  * You can then call g_io_stream_splice_finish() to get the
768  * result of the operation.
769  **/
770 void
771 g_io_stream_splice_async (GIOStream            *stream1,
772                           GIOStream            *stream2,
773                           GIOStreamSpliceFlags  flags,
774                           gint                  io_priority,
775                           GCancellable         *cancellable,
776                           GAsyncReadyCallback   callback,
777                           gpointer              user_data)
778 {
779   GSimpleAsyncResult *simple;
780   SpliceContext *ctx;
781   GInputStream *istream;
782   GOutputStream *ostream;
783
784   if (cancellable != NULL && g_cancellable_is_cancelled (cancellable))
785     {
786       g_simple_async_report_error_in_idle (NULL, callback,
787           user_data, G_IO_ERROR, G_IO_ERROR_CANCELLED,
788           "Operation has been cancelled");
789       return;
790     }
791
792   ctx = g_slice_new0 (SpliceContext);
793   ctx->stream1 = g_object_ref (stream1);
794   ctx->stream2 = g_object_ref (stream2);
795   ctx->flags = flags;
796   ctx->io_priority = io_priority;
797   ctx->op1_cancellable = g_cancellable_new ();
798   ctx->op2_cancellable = g_cancellable_new ();
799   ctx->completed = 0;
800
801   simple = g_simple_async_result_new (NULL, callback, user_data,
802       g_io_stream_splice_finish);
803   g_simple_async_result_set_op_res_gpointer (simple, ctx,
804       (GDestroyNotify) splice_context_free);
805
806   if (cancellable != NULL)
807     {
808       ctx->cancellable = g_object_ref (cancellable);
809       ctx->cancelled_id = g_cancellable_connect (cancellable,
810           G_CALLBACK (splice_cancelled_cb), g_object_ref (simple),
811           g_object_unref);
812     }
813
814   istream = g_io_stream_get_input_stream (stream1);
815   ostream = g_io_stream_get_output_stream (stream2);
816   g_output_stream_splice_async (ostream, istream, G_OUTPUT_STREAM_SPLICE_NONE,
817       io_priority, ctx->op1_cancellable, splice_cb,
818       g_object_ref (simple));
819
820   istream = g_io_stream_get_input_stream (stream2);
821   ostream = g_io_stream_get_output_stream (stream1);
822   g_output_stream_splice_async (ostream, istream, G_OUTPUT_STREAM_SPLICE_NONE,
823       io_priority, ctx->op2_cancellable, splice_cb,
824       g_object_ref (simple));
825
826   g_object_unref (simple);
827 }
828
829 /**
830  * g_io_stream_splice_finish:
831  * @result: a #GAsyncResult.
832  * @error: a #GError location to store the error occuring, or %NULL to
833  * ignore.
834  *
835  * Finishes an asynchronous io stream splice operation.
836  *
837  * Returns: %TRUE on success, %FALSE otherwise.
838  **/
839 gboolean
840 g_io_stream_splice_finish (GAsyncResult  *result,
841                            GError       **error)
842 {
843   GSimpleAsyncResult *simple;
844
845   g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
846
847   simple = G_SIMPLE_ASYNC_RESULT (result);
848
849   if (g_simple_async_result_propagate_error (simple, error))
850     return FALSE;
851
852   g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
853       g_io_stream_splice_finish), FALSE);
854
855   return TRUE;
856 }