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.
14 * SECTION:gtcpconnection
15 * @title: GTcpConnection
16 * @short_description: A TCP GSocketConnection
18 * @see_also: #GSocketConnection.
20 * This is the subclass of #GSocketConnection that is created
27 #include "gtcpconnection.h"
28 #include "gasyncresult.h"
30 #include "giostream.h"
33 struct _GTcpConnectionPrivate
35 guint graceful_disconnect : 1;
38 G_DEFINE_TYPE_WITH_CODE (GTcpConnection, g_tcp_connection,
39 G_TYPE_SOCKET_CONNECTION,
40 G_ADD_PRIVATE (GTcpConnection)
41 g_socket_connection_factory_register_type (g_define_type_id,
44 G_SOCKET_PROTOCOL_DEFAULT);
45 g_socket_connection_factory_register_type (g_define_type_id,
48 G_SOCKET_PROTOCOL_DEFAULT);
49 g_socket_connection_factory_register_type (g_define_type_id,
52 G_SOCKET_PROTOCOL_TCP);
53 g_socket_connection_factory_register_type (g_define_type_id,
56 G_SOCKET_PROTOCOL_TCP);
59 static gboolean g_tcp_connection_close (GIOStream *stream,
60 GCancellable *cancellable,
62 static void g_tcp_connection_close_async (GIOStream *stream,
64 GCancellable *cancellable,
65 GAsyncReadyCallback callback,
72 PROP_GRACEFUL_DISCONNECT
76 g_tcp_connection_init (GTcpConnection *connection)
78 connection->priv = g_tcp_connection_get_instance_private (connection);
79 connection->priv->graceful_disconnect = FALSE;
83 g_tcp_connection_get_property (GObject *object,
88 GTcpConnection *connection = G_TCP_CONNECTION (object);
92 case PROP_GRACEFUL_DISCONNECT:
93 g_value_set_boolean (value, connection->priv->graceful_disconnect);
97 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
102 g_tcp_connection_set_property (GObject *object,
107 GTcpConnection *connection = G_TCP_CONNECTION (object);
111 case PROP_GRACEFUL_DISCONNECT:
112 g_tcp_connection_set_graceful_disconnect (connection,
113 g_value_get_boolean (value));
117 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
122 g_tcp_connection_class_init (GTcpConnectionClass *class)
124 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
125 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (class);
127 gobject_class->set_property = g_tcp_connection_set_property;
128 gobject_class->get_property = g_tcp_connection_get_property;
130 stream_class->close_fn = g_tcp_connection_close;
131 stream_class->close_async = g_tcp_connection_close_async;
133 g_object_class_install_property (gobject_class, PROP_GRACEFUL_DISCONNECT,
134 g_param_spec_boolean ("graceful-disconnect",
135 P_("Graceful Disconnect"),
136 P_("Whether or not close does a graceful disconnect"),
138 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
143 g_tcp_connection_close (GIOStream *stream,
144 GCancellable *cancellable,
147 GTcpConnection *connection = G_TCP_CONNECTION (stream);
153 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
156 if (connection->priv->graceful_disconnect &&
157 !g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */)
159 if (!g_socket_shutdown (socket, FALSE, TRUE, error))
161 error = NULL; /* Ignore further errors */
168 ret = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer),
169 TRUE, cancellable, error);
182 return G_IO_STREAM_CLASS (g_tcp_connection_parent_class)
183 ->close_fn (stream, cancellable, error) && !had_error;
186 /* consumes @error */
188 async_close_finish (GTask *task,
191 GIOStreamClass *parent = G_IO_STREAM_CLASS (g_tcp_connection_parent_class);
192 GIOStream *stream = g_task_get_source_object (task);
193 GCancellable *cancellable = g_task_get_cancellable (task);
195 /* Close underlying stream, ignoring further errors if we already
199 parent->close_fn (stream, cancellable, NULL);
201 parent->close_fn (stream, cancellable, &error);
204 g_task_return_error (task, error);
206 g_task_return_boolean (task, TRUE);
211 close_read_ready (GSocket *socket,
212 GIOCondition condition,
215 GError *error = NULL;
219 ret = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer),
220 FALSE, g_task_get_cancellable (task),
224 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
226 g_error_free (error);
231 async_close_finish (task, error);
232 g_object_unref (task);
239 async_close_finish (task, NULL);
248 g_tcp_connection_close_async (GIOStream *stream,
250 GCancellable *cancellable,
251 GAsyncReadyCallback callback,
254 GTcpConnection *connection = G_TCP_CONNECTION (stream);
260 if (connection->priv->graceful_disconnect &&
261 !g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */)
263 task = g_task_new (stream, cancellable, callback, user_data);
264 g_task_set_priority (task, io_priority);
266 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
269 if (!g_socket_shutdown (socket, FALSE, TRUE, &error))
271 g_task_return_error (task, error);
272 g_object_unref (task);
276 source = g_socket_create_source (socket, G_IO_IN, cancellable);
277 g_task_attach_source (task, source, (GSourceFunc) close_read_ready);
278 g_source_unref (source);
283 G_IO_STREAM_CLASS (g_tcp_connection_parent_class)
284 ->close_async (stream, io_priority, cancellable, callback, user_data);
288 * g_tcp_connection_set_graceful_disconnect:
289 * @connection: a #GTcpConnection
290 * @graceful_disconnect: Whether to do graceful disconnects or not
292 * This enabled graceful disconnects on close. A graceful disconnect
293 * means that we signal the receiving end that the connection is terminated
294 * and wait for it to close the connection before closing the connection.
296 * A graceful disconnect means that we can be sure that we successfully sent
297 * all the outstanding data to the other end, or get an error reported.
298 * However, it also means we have to wait for all the data to reach the
299 * other side and for it to acknowledge this by closing the socket, which may
300 * take a while. For this reason it is disabled by default.
305 g_tcp_connection_set_graceful_disconnect (GTcpConnection *connection,
306 gboolean graceful_disconnect)
308 graceful_disconnect = !!graceful_disconnect;
309 if (graceful_disconnect != connection->priv->graceful_disconnect)
311 connection->priv->graceful_disconnect = graceful_disconnect;
312 g_object_notify (G_OBJECT (connection), "graceful-disconnect");
317 * g_tcp_connection_get_graceful_disconnect:
318 * @connection: a #GTcpConnection
320 * Checks if graceful disconnects are used. See
321 * g_tcp_connection_set_graceful_disconnect().
323 * Returns: %TRUE if graceful disconnect is used on close, %FALSE otherwise
328 g_tcp_connection_get_graceful_disconnect (GTcpConnection *connection)
330 return connection->priv->graceful_disconnect;