Clean up GSettingsSchema logic
[glib.git] / gio / gtcpconnection.c
blob2348c3169938ea4fdd44e2703a3044d9e3c32d52
1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright © 2008, 2009 Codethink Limited
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published
7 * by the Free Software Foundation; either version 2 of the licence or (at
8 * your option) any later version.
10 * See the included COPYING file for more information.
13 /**
14 * SECTION:gtcpconnection
15 * @title: GTcpConnection
16 * @short_description: A TCP GSocketConnection
17 * @see_also: #GSocketConnection.
19 * This is the subclass of #GSocketConnection that is created
20 * for TCP/IP sockets.
22 * Since: 2.22
25 #include "config.h"
26 #include "gtcpconnection.h"
27 #include "gasyncresult.h"
28 #include "gtask.h"
29 #include "giostream.h"
30 #include "glibintl.h"
32 struct _GTcpConnectionPrivate
34 guint graceful_disconnect : 1;
37 G_DEFINE_TYPE_WITH_CODE (GTcpConnection, g_tcp_connection,
38 G_TYPE_SOCKET_CONNECTION,
39 G_ADD_PRIVATE (GTcpConnection)
40 g_socket_connection_factory_register_type (g_define_type_id,
41 G_SOCKET_FAMILY_IPV4,
42 G_SOCKET_TYPE_STREAM,
43 G_SOCKET_PROTOCOL_DEFAULT);
44 g_socket_connection_factory_register_type (g_define_type_id,
45 G_SOCKET_FAMILY_IPV6,
46 G_SOCKET_TYPE_STREAM,
47 G_SOCKET_PROTOCOL_DEFAULT);
48 g_socket_connection_factory_register_type (g_define_type_id,
49 G_SOCKET_FAMILY_IPV4,
50 G_SOCKET_TYPE_STREAM,
51 G_SOCKET_PROTOCOL_TCP);
52 g_socket_connection_factory_register_type (g_define_type_id,
53 G_SOCKET_FAMILY_IPV6,
54 G_SOCKET_TYPE_STREAM,
55 G_SOCKET_PROTOCOL_TCP);
58 static gboolean g_tcp_connection_close (GIOStream *stream,
59 GCancellable *cancellable,
60 GError **error);
61 static void g_tcp_connection_close_async (GIOStream *stream,
62 int io_priority,
63 GCancellable *cancellable,
64 GAsyncReadyCallback callback,
65 gpointer user_data);
68 enum
70 PROP_0,
71 PROP_GRACEFUL_DISCONNECT
74 static void
75 g_tcp_connection_init (GTcpConnection *connection)
77 connection->priv = g_tcp_connection_get_instance_private (connection);
78 connection->priv->graceful_disconnect = FALSE;
81 static void
82 g_tcp_connection_get_property (GObject *object,
83 guint prop_id,
84 GValue *value,
85 GParamSpec *pspec)
87 GTcpConnection *connection = G_TCP_CONNECTION (object);
89 switch (prop_id)
91 case PROP_GRACEFUL_DISCONNECT:
92 g_value_set_boolean (value, connection->priv->graceful_disconnect);
93 break;
95 default:
96 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
100 static void
101 g_tcp_connection_set_property (GObject *object,
102 guint prop_id,
103 const GValue *value,
104 GParamSpec *pspec)
106 GTcpConnection *connection = G_TCP_CONNECTION (object);
108 switch (prop_id)
110 case PROP_GRACEFUL_DISCONNECT:
111 g_tcp_connection_set_graceful_disconnect (connection,
112 g_value_get_boolean (value));
113 break;
115 default:
116 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
120 static void
121 g_tcp_connection_class_init (GTcpConnectionClass *class)
123 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
124 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (class);
126 gobject_class->set_property = g_tcp_connection_set_property;
127 gobject_class->get_property = g_tcp_connection_get_property;
129 stream_class->close_fn = g_tcp_connection_close;
130 stream_class->close_async = g_tcp_connection_close_async;
132 g_object_class_install_property (gobject_class, PROP_GRACEFUL_DISCONNECT,
133 g_param_spec_boolean ("graceful-disconnect",
134 P_("Graceful Disconnect"),
135 P_("Whether or not close does a graceful disconnect"),
136 FALSE,
137 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
141 static gboolean
142 g_tcp_connection_close (GIOStream *stream,
143 GCancellable *cancellable,
144 GError **error)
146 GTcpConnection *connection = G_TCP_CONNECTION (stream);
147 GSocket *socket;
148 char buffer[1024];
149 gssize ret;
150 gboolean had_error;
152 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
153 had_error = FALSE;
155 if (connection->priv->graceful_disconnect &&
156 !g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */)
158 if (!g_socket_shutdown (socket, FALSE, TRUE, error))
160 error = NULL; /* Ignore further errors */
161 had_error = TRUE;
163 else
165 while (TRUE)
167 ret = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer),
168 TRUE, cancellable, error);
169 if (ret < 0)
171 had_error = TRUE;
172 error = NULL;
173 break;
175 if (ret == 0)
176 break;
181 return G_IO_STREAM_CLASS (g_tcp_connection_parent_class)
182 ->close_fn (stream, cancellable, error) && !had_error;
185 /* consumes @error */
186 static void
187 async_close_finish (GTask *task,
188 GError *error)
190 GIOStreamClass *parent = G_IO_STREAM_CLASS (g_tcp_connection_parent_class);
191 GIOStream *stream = g_task_get_source_object (task);
192 GCancellable *cancellable = g_task_get_cancellable (task);
194 /* Close underlying stream, ignoring further errors if we already
195 * have one.
197 if (error)
198 parent->close_fn (stream, cancellable, NULL);
199 else
200 parent->close_fn (stream, cancellable, &error);
202 if (error)
203 g_task_return_error (task, error);
204 else
205 g_task_return_boolean (task, TRUE);
209 static gboolean
210 close_read_ready (GSocket *socket,
211 GIOCondition condition,
212 GTask *task)
214 GError *error = NULL;
215 char buffer[1024];
216 gssize ret;
218 ret = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer),
219 FALSE, g_task_get_cancellable (task),
220 &error);
221 if (ret < 0)
223 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
225 g_error_free (error);
226 return TRUE;
228 else
230 async_close_finish (task, error);
231 g_object_unref (task);
232 return FALSE;
236 if (ret == 0)
238 async_close_finish (task, NULL);
239 return FALSE;
242 return TRUE;
246 static void
247 g_tcp_connection_close_async (GIOStream *stream,
248 int io_priority,
249 GCancellable *cancellable,
250 GAsyncReadyCallback callback,
251 gpointer user_data)
253 GTcpConnection *connection = G_TCP_CONNECTION (stream);
254 GSocket *socket;
255 GSource *source;
256 GError *error;
257 GTask *task;
259 if (connection->priv->graceful_disconnect &&
260 !g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */)
262 task = g_task_new (stream, cancellable, callback, user_data);
263 g_task_set_priority (task, io_priority);
265 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
267 error = NULL;
268 if (!g_socket_shutdown (socket, FALSE, TRUE, &error))
270 g_task_return_error (task, error);
271 g_object_unref (task);
272 return;
275 source = g_socket_create_source (socket, G_IO_IN, cancellable);
276 g_task_attach_source (task, source, (GSourceFunc) close_read_ready);
277 g_source_unref (source);
279 return;
282 G_IO_STREAM_CLASS (g_tcp_connection_parent_class)
283 ->close_async (stream, io_priority, cancellable, callback, user_data);
287 * g_tcp_connection_set_graceful_disconnect:
288 * @connection: a #GTcpConnection
289 * @graceful_disconnect: Whether to do graceful disconnects or not
291 * This enabled graceful disconnects on close. A graceful disconnect
292 * means that we signal the receiving end that the connection is terminated
293 * and wait for it to close the connection before closing the connection.
295 * A graceful disconnect means that we can be sure that we successfully sent
296 * all the outstanding data to the other end, or get an error reported.
297 * However, it also means we have to wait for all the data to reach the
298 * other side and for it to acknowledge this by closing the socket, which may
299 * take a while. For this reason it is disabled by default.
301 * Since: 2.22
303 void
304 g_tcp_connection_set_graceful_disconnect (GTcpConnection *connection,
305 gboolean graceful_disconnect)
307 graceful_disconnect = !!graceful_disconnect;
308 if (graceful_disconnect != connection->priv->graceful_disconnect)
310 connection->priv->graceful_disconnect = graceful_disconnect;
311 g_object_notify (G_OBJECT (connection), "graceful-disconnect");
316 * g_tcp_connection_get_graceful_disconnect:
317 * @connection: a #GTcpConnection
319 * Checks if graceful disconnects are used. See
320 * g_tcp_connection_set_graceful_disconnect().
322 * Returns: %TRUE if graceful disconnect is used on close, %FALSE otherwise
324 * Since: 2.22
326 gboolean
327 g_tcp_connection_get_graceful_disconnect (GTcpConnection *connection)
329 return connection->priv->graceful_disconnect;