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
17 * @see_also: #GSocketConnection.
19 * This is the subclass of #GSocketConnection that is created
22 * It is currently empty; it offers no additional functionality
23 * over its base class.
25 * Eventually, some TCP-specific socket stuff will be added.
31 #include "gtcpconnection.h"
32 #include "gasyncresult.h"
33 #include "gsimpleasyncresult.h"
34 #include "giostream.h"
39 G_DEFINE_TYPE_WITH_CODE (GTcpConnection, g_tcp_connection,
40 G_TYPE_SOCKET_CONNECTION,
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,
68 struct _GTcpConnectionPrivate
70 guint graceful_disconnect : 1;
77 PROP_GRACEFUL_DISCONNECT
81 g_tcp_connection_init (GTcpConnection *connection)
83 connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
84 G_TYPE_TCP_CONNECTION,
85 GTcpConnectionPrivate);
86 connection->priv->graceful_disconnect = FALSE;
90 g_tcp_connection_get_property (GObject *object,
95 GTcpConnection *connection = G_TCP_CONNECTION (object);
99 case PROP_GRACEFUL_DISCONNECT:
100 g_value_set_boolean (value, connection->priv->graceful_disconnect);
104 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
109 g_tcp_connection_set_property (GObject *object,
114 GTcpConnection *connection = G_TCP_CONNECTION (object);
118 case PROP_GRACEFUL_DISCONNECT:
119 g_tcp_connection_set_graceful_disconnect (connection,
120 g_value_get_boolean (value));
124 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
129 g_tcp_connection_class_init (GTcpConnectionClass *class)
131 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
132 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (class);
134 g_type_class_add_private (class, sizeof (GTcpConnectionPrivate));
136 gobject_class->set_property = g_tcp_connection_set_property;
137 gobject_class->get_property = g_tcp_connection_get_property;
139 stream_class->close_fn = g_tcp_connection_close;
140 stream_class->close_async = g_tcp_connection_close_async;
142 g_object_class_install_property (gobject_class, PROP_GRACEFUL_DISCONNECT,
143 g_param_spec_boolean ("graceful-disconnect",
144 P_("Graceful Disconnect"),
145 P_("Whether or not close does a graceful disconnect"),
147 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
152 g_tcp_connection_close (GIOStream *stream,
153 GCancellable *cancellable,
156 GTcpConnection *connection = G_TCP_CONNECTION (stream);
163 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
166 if (connection->priv->graceful_disconnect &&
167 !g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */)
169 if (!g_socket_shutdown (socket, FALSE, TRUE, error))
171 error = NULL; /* Ignore further errors */
178 if (!g_socket_condition_wait (socket,
179 G_IO_IN, cancellable, error))
187 ret = g_socket_receive (socket, buffer, sizeof (buffer),
191 if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
192 g_error_free (my_error);
196 g_propagate_error (error, my_error);
207 return G_IO_STREAM_CLASS (g_tcp_connection_parent_class)
208 ->close_fn (stream, cancellable, error) && !had_error;
212 GSimpleAsyncResult *res;
213 GCancellable *cancellable;
217 close_async_data_free (CloseAsyncData *data)
219 g_object_unref (data->res);
220 if (data->cancellable)
221 g_object_unref (data->cancellable);
226 async_close_finish (CloseAsyncData *data, GError *error, gboolean in_mainloop)
228 GIOStreamClass *parent = G_IO_STREAM_CLASS (g_tcp_connection_parent_class);
232 stream = G_IO_STREAM (g_async_result_get_source_object (G_ASYNC_RESULT (data->res)));
234 /* Doesn't block, ignore error */
237 parent->close_fn (stream, data->cancellable, NULL);
238 g_simple_async_result_set_from_error (data->res, error);
243 parent->close_fn (stream, data->cancellable, &my_error);
246 g_simple_async_result_set_from_error (data->res, my_error);
247 g_error_free (my_error);
252 g_simple_async_result_complete (data->res);
254 g_simple_async_result_complete_in_idle (data->res);
258 close_read_ready (GSocket *socket,
259 GIOCondition condition,
260 CloseAsyncData *data)
262 GError *error = NULL;
266 if (g_cancellable_set_error_if_cancelled (data->cancellable,
269 async_close_finish (data, error, TRUE);
270 g_error_free (error);
274 ret = g_socket_receive (socket, buffer, sizeof (buffer), &error);
277 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
278 g_error_free (error);
281 async_close_finish (data, error, TRUE);
282 g_error_free (error);
289 async_close_finish (data, NULL, TRUE);
298 g_tcp_connection_close_async (GIOStream *stream,
300 GCancellable *cancellable,
301 GAsyncReadyCallback callback,
304 GTcpConnection *connection = G_TCP_CONNECTION (stream);
305 CloseAsyncData *data;
310 if (connection->priv->graceful_disconnect &&
311 !g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */)
313 data = g_new (CloseAsyncData, 1);
315 g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
316 g_tcp_connection_close_async);
318 data->cancellable = g_object_ref (cancellable);
320 data->cancellable = NULL;
322 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
325 if (!g_socket_shutdown (socket, FALSE, TRUE, &error))
327 async_close_finish (data, error, FALSE);
328 g_error_free (error);
329 close_async_data_free (data);
333 source = g_socket_create_source (socket, G_IO_IN, cancellable);
334 g_source_set_callback (source,
335 (GSourceFunc) close_read_ready,
336 data, (GDestroyNotify)close_async_data_free);
337 g_source_attach (source, NULL);
338 g_source_unref (source);
344 return G_IO_STREAM_CLASS (g_tcp_connection_parent_class)
345 ->close_async (stream, io_priority, cancellable, callback, user_data);
351 * g_tcp_connection_set_graceful_disconnect:
352 * @connection: a #GTcpConnection
353 * @graceful_disconnect: Whether to do graceful disconnects or not
355 * This enabled graceful disconnects on close. A graceful disconnect
356 * means that we signal the recieving end that the connection is terminated
357 * and wait for it to close the connection before closing the connection.
359 * A graceful disconnect means that we can be sure that we successfully sent
360 * all the outstanding data to the other end, or get an error reported.
361 * However, it also means we have to wait for all the data to reach the
362 * other side and for it to acknowledge this by closing the socket, which may
363 * take a while. For this reason it is disabled by default.
368 g_tcp_connection_set_graceful_disconnect (GTcpConnection *connection,
369 gboolean graceful_disconnect)
371 graceful_disconnect = !!graceful_disconnect;
372 if (graceful_disconnect != connection->priv->graceful_disconnect)
374 connection->priv->graceful_disconnect = graceful_disconnect;
375 g_object_notify (G_OBJECT (connection), "graceful-disconnect");
380 * g_tcp_connection_get_graceful_disconnect:
381 * @connection: a #GTcpConnection
383 * Checks if graceful disconnects are used. See
384 * g_tcp_connection_set_graceful_disconnect().
386 * Returns: %TRUE if graceful disconnect is used on close, %FALSE otherwise
391 g_tcp_connection_get_graceful_disconnect (GTcpConnection *connection)
393 return connection->priv->graceful_disconnect;
397 #define __G_TCP_CONNECTION_C__
398 #include "gioaliasdef.c"