Bumps documentation to 93% symbol coverage, touching most
[platform/upstream/glib.git] / gio / gsocketoutputstream.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
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.
9  *
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.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include <config.h>
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <poll.h>
32
33 #include <glib.h>
34 #include <glib/gstdio.h>
35 #include "gioerror.h"
36 #include "gsocketoutputstream.h"
37 #include "gcancellable.h"
38 #include "gsimpleasyncresult.h"
39 #include "gasynchelper.h"
40 #include "glibintl.h"
41
42 /**
43  * SECTION:gsocketoutputstream
44  * @short_description: Socket Output Stream
45  * @see_also: #GOutputStream.
46  *
47  * #GSocketOutputStream implements #GOutputStream for writing to a socket, including
48  * asynchronous operations.
49  **/
50
51 G_DEFINE_TYPE (GSocketOutputStream, g_socket_output_stream, G_TYPE_OUTPUT_STREAM);
52
53
54 struct _GSocketOutputStreamPrivate {
55   int fd;
56   gboolean close_fd_at_close;
57 };
58
59 static gssize   g_socket_output_stream_write        (GOutputStream              *stream,
60                                                      const void                 *buffer,
61                                                      gsize                       count,
62                                                      GCancellable               *cancellable,
63                                                      GError                    **error);
64 static gboolean g_socket_output_stream_close        (GOutputStream              *stream,
65                                                      GCancellable               *cancellable,
66                                                      GError                    **error);
67 static void     g_socket_output_stream_write_async  (GOutputStream              *stream,
68                                                      const void                 *buffer,
69                                                      gsize                       count,
70                                                      int                         io_priority,
71                                                      GCancellable               *cancellable,
72                                                      GAsyncReadyCallback         callback,
73                                                      gpointer                    data);
74 static gssize   g_socket_output_stream_write_finish (GOutputStream              *stream,
75                                                      GAsyncResult               *result,
76                                                      GError                    **error);
77 static void     g_socket_output_stream_close_async  (GOutputStream              *stream,
78                                                      int                         io_priority,
79                                                      GCancellable               *cancellable,
80                                                      GAsyncReadyCallback         callback,
81                                                      gpointer                    data);
82 static gboolean g_socket_output_stream_close_finish (GOutputStream              *stream,
83                                                      GAsyncResult               *result,
84                                                      GError                    **error);
85
86
87 static void
88 g_socket_output_stream_finalize (GObject *object)
89 {
90   GSocketOutputStream *stream;
91   
92   stream = G_SOCKET_OUTPUT_STREAM (object);
93
94   if (G_OBJECT_CLASS (g_socket_output_stream_parent_class)->finalize)
95     (*G_OBJECT_CLASS (g_socket_output_stream_parent_class)->finalize) (object);
96 }
97
98 static void
99 g_socket_output_stream_class_init (GSocketOutputStreamClass *klass)
100 {
101   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
102   GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
103   
104   g_type_class_add_private (klass, sizeof (GSocketOutputStreamPrivate));
105   
106   gobject_class->finalize = g_socket_output_stream_finalize;
107
108   stream_class->write = g_socket_output_stream_write;
109   stream_class->close = g_socket_output_stream_close;
110   stream_class->write_async = g_socket_output_stream_write_async;
111   stream_class->write_finish = g_socket_output_stream_write_finish;
112   stream_class->close_async = g_socket_output_stream_close_async;
113   stream_class->close_finish = g_socket_output_stream_close_finish;
114 }
115
116 static void
117 g_socket_output_stream_init (GSocketOutputStream *socket)
118 {
119   socket->priv = G_TYPE_INSTANCE_GET_PRIVATE (socket,
120                                               G_TYPE_SOCKET_OUTPUT_STREAM,
121                                               GSocketOutputStreamPrivate);
122 }
123
124
125 /**
126  * g_socket_output_stream_new:
127  * @fd: socket's file descriptor.
128  * @close_fd_at_close: a #gboolean.
129  * 
130  * Creates a new socket output stream for @fd. If @close_fd_at_close
131  * is %TRUE, the socket will be closed when the output stream is destroyed.
132  * 
133  * Returns: #GOutputStream. If @close_fd_at_close is %TRUE, then
134  * @fd will be closed when the #GOutputStream is closed.
135  **/
136 GOutputStream *
137 g_socket_output_stream_new (int fd,
138                            gboolean close_fd_at_close)
139 {
140   GSocketOutputStream *stream;
141
142   g_return_val_if_fail (fd != -1, NULL);
143
144   stream = g_object_new (G_TYPE_SOCKET_OUTPUT_STREAM, NULL);
145
146   stream->priv->fd = fd;
147   stream->priv->close_fd_at_close = close_fd_at_close;
148   
149   return G_OUTPUT_STREAM (stream);
150 }
151
152 static gssize
153 g_socket_output_stream_write (GOutputStream *stream,
154                               const void    *buffer,
155                               gsize          count,
156                               GCancellable  *cancellable,
157                               GError       **error)
158 {
159   GSocketOutputStream *socket_stream;
160   gssize res;
161   struct pollfd poll_fds[2];
162   int poll_ret;
163   int cancel_fd;
164
165   socket_stream = G_SOCKET_OUTPUT_STREAM (stream);
166
167   cancel_fd = g_cancellable_get_fd (cancellable);
168   if (cancel_fd != -1)
169     {
170       do
171         {
172           poll_fds[0].events = POLLOUT;
173           poll_fds[0].fd = socket_stream->priv->fd;
174           poll_fds[1].events = POLLIN;
175           poll_fds[1].fd = cancel_fd;
176           poll_ret = poll (poll_fds, 2, -1);
177         }
178       while (poll_ret == -1 && errno == EINTR);
179       
180       if (poll_ret == -1)
181         {
182           g_set_error (error, G_IO_ERROR,
183                        g_io_error_from_errno (errno),
184                        _("Error writing to socket: %s"),
185                        g_strerror (errno));
186           return -1;
187         }
188     }
189       
190   while (1)
191     {
192       if (g_cancellable_set_error_if_cancelled (cancellable, error))
193         return -1;
194
195       res = write (socket_stream->priv->fd, buffer, count);
196       if (res == -1)
197         {
198           if (errno == EINTR)
199             continue;
200           
201           g_set_error (error, G_IO_ERROR,
202                        g_io_error_from_errno (errno),
203                        _("Error writing to socket: %s"),
204                        g_strerror (errno));
205         }
206       
207       break;
208     }
209   
210   return res;
211 }
212
213 static gboolean
214 g_socket_output_stream_close (GOutputStream *stream,
215                               GCancellable  *cancellable,
216                               GError       **error)
217 {
218   GSocketOutputStream *socket_stream;
219   int res;
220
221   socket_stream = G_SOCKET_OUTPUT_STREAM (stream);
222
223   if (!socket_stream->priv->close_fd_at_close)
224     return TRUE;
225   
226   while (1)
227     {
228       /* This might block during the close. Doesn't seem to be a way to avoid it though. */
229       res = close (socket_stream->priv->fd);
230       if (res == -1)
231         {
232           g_set_error (error, G_IO_ERROR,
233                        g_io_error_from_errno (errno),
234                        _("Error closing socket: %s"),
235                        g_strerror (errno));
236         }
237       break;
238     }
239
240   return res != -1;
241 }
242
243 typedef struct {
244   gsize count;
245   const void *buffer;
246   GAsyncReadyCallback callback;
247   gpointer user_data;
248   GCancellable *cancellable;
249   GSocketOutputStream *stream;
250 } WriteAsyncData;
251
252 static gboolean
253 write_async_cb (WriteAsyncData *data,
254                 GIOCondition condition,
255                 int fd)
256 {
257   GSimpleAsyncResult *simple;
258   GError *error = NULL;
259   gssize count_written;
260
261   while (1)
262     {
263       if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
264         {
265           count_written = -1;
266           break;
267         }
268       
269       count_written = write (data->stream->priv->fd, data->buffer, data->count);
270       if (count_written == -1)
271         {
272           if (errno == EINTR)
273             continue;
274           
275           g_set_error (&error, G_IO_ERROR,
276                        g_io_error_from_errno (errno),
277                        _("Error reading from socket: %s"),
278                        g_strerror (errno));
279         }
280       break;
281     }
282
283   simple = g_simple_async_result_new (G_OBJECT (data->stream),
284                                       data->callback,
285                                       data->user_data,
286                                       g_socket_output_stream_write_async);
287   
288   g_simple_async_result_set_op_res_gssize (simple, count_written);
289
290   if (count_written == -1)
291     {
292       g_simple_async_result_set_from_error (simple, error);
293       g_error_free (error);
294     }
295
296   /* Complete immediately, not in idle, since we're already in a mainloop callout */
297   g_simple_async_result_complete (simple);
298   g_object_unref (simple);
299
300   return FALSE;
301 }
302
303 static void
304 g_socket_output_stream_write_async (GOutputStream      *stream,
305                                     const void         *buffer,
306                                     gsize               count,
307                                     int                 io_priority,
308                                     GCancellable       *cancellable,
309                                     GAsyncReadyCallback callback,
310                                     gpointer            user_data)
311 {
312   GSource *source;
313   GSocketOutputStream *socket_stream;
314   WriteAsyncData *data;
315
316   socket_stream = G_SOCKET_OUTPUT_STREAM (stream);
317
318   data = g_new0 (WriteAsyncData, 1);
319   data->count = count;
320   data->buffer = buffer;
321   data->callback = callback;
322   data->user_data = user_data;
323   data->cancellable = cancellable;
324   data->stream = socket_stream;
325
326   source = _g_fd_source_new (socket_stream->priv->fd,
327                              POLLOUT,
328                              cancellable);
329   
330   g_source_set_callback (source, (GSourceFunc)write_async_cb, data, g_free);
331   g_source_attach (source, NULL);
332   
333   g_source_unref (source);
334 }
335
336 static gssize
337 g_socket_output_stream_write_finish (GOutputStream *stream,
338                                      GAsyncResult *result,
339                                      GError **error)
340 {
341   GSimpleAsyncResult *simple;
342   gssize nwritten;
343
344   simple = G_SIMPLE_ASYNC_RESULT (result);
345   g_assert (g_simple_async_result_get_source_tag (simple) == g_socket_output_stream_write_async);
346   
347   nwritten = g_simple_async_result_get_op_res_gssize (simple);
348   return nwritten;
349 }
350
351 typedef struct {
352   GOutputStream *stream;
353   GAsyncReadyCallback callback;
354   gpointer user_data;
355 } CloseAsyncData;
356
357 static gboolean
358 close_async_cb (CloseAsyncData *data)
359 {
360   GSocketOutputStream *socket_stream;
361   GSimpleAsyncResult *simple;
362   GError *error = NULL;
363   gboolean result;
364   int res;
365
366   socket_stream = G_SOCKET_OUTPUT_STREAM (data->stream);
367
368   if (!socket_stream->priv->close_fd_at_close)
369     {
370       result = TRUE;
371       goto out;
372     }
373   
374   while (1)
375     {
376       res = close (socket_stream->priv->fd);
377       if (res == -1)
378         {
379           g_set_error (&error, G_IO_ERROR,
380                        g_io_error_from_errno (errno),
381                        _("Error closing socket: %s"),
382                        g_strerror (errno));
383         }
384       break;
385     }
386   
387   result = res != -1;
388   
389  out:
390   simple = g_simple_async_result_new (G_OBJECT (data->stream),
391                                       data->callback,
392                                       data->user_data,
393                                       g_socket_output_stream_close_async);
394
395   if (!result)
396     {
397       g_simple_async_result_set_from_error (simple, error);
398       g_error_free (error);
399     }
400
401   /* Complete immediately, not in idle, since we're already in a mainloop callout */
402   g_simple_async_result_complete (simple);
403   g_object_unref (simple);
404   
405   return FALSE;
406 }
407
408 static void
409 g_socket_output_stream_close_async (GOutputStream       *stream,
410                                     int                 io_priority,
411                                     GCancellable       *cancellable,
412                                     GAsyncReadyCallback callback,
413                                     gpointer            user_data)
414 {
415   GSource *idle;
416   CloseAsyncData *data;
417
418   data = g_new0 (CloseAsyncData, 1);
419
420   data->stream = stream;
421   data->callback = callback;
422   data->user_data = user_data;
423   
424   idle = g_idle_source_new ();
425   g_source_set_callback (idle, (GSourceFunc)close_async_cb, data, g_free);
426   g_source_attach (idle, NULL);
427   g_source_unref (idle);
428 }
429
430 static gboolean
431 g_socket_output_stream_close_finish (GOutputStream              *stream,
432                                      GAsyncResult              *result,
433                                      GError                   **error)
434 {
435   /* Failures handled in generic close_finish code */
436   return TRUE;
437 }