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_source_tag (task
, g_tcp_connection_close_async
);
265 g_task_set_priority (task
, io_priority
);
267 socket
= g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream
));
270 if (!g_socket_shutdown (socket
, FALSE
, TRUE
, &error
))
272 g_task_return_error (task
, error
);
273 g_object_unref (task
);
277 source
= g_socket_create_source (socket
, G_IO_IN
, cancellable
);
278 g_task_attach_source (task
, source
, (GSourceFunc
) close_read_ready
);
279 g_source_unref (source
);
284 G_IO_STREAM_CLASS (g_tcp_connection_parent_class
)
285 ->close_async (stream
, io_priority
, cancellable
, callback
, user_data
);
289 * g_tcp_connection_set_graceful_disconnect:
290 * @connection: a #GTcpConnection
291 * @graceful_disconnect: Whether to do graceful disconnects or not
293 * This enables graceful disconnects on close. A graceful disconnect
294 * means that we signal the receiving end that the connection is terminated
295 * and wait for it to close the connection before closing the connection.
297 * A graceful disconnect means that we can be sure that we successfully sent
298 * all the outstanding data to the other end, or get an error reported.
299 * However, it also means we have to wait for all the data to reach the
300 * other side and for it to acknowledge this by closing the socket, which may
301 * take a while. For this reason it is disabled by default.
306 g_tcp_connection_set_graceful_disconnect (GTcpConnection
*connection
,
307 gboolean graceful_disconnect
)
309 graceful_disconnect
= !!graceful_disconnect
;
310 if (graceful_disconnect
!= connection
->priv
->graceful_disconnect
)
312 connection
->priv
->graceful_disconnect
= graceful_disconnect
;
313 g_object_notify (G_OBJECT (connection
), "graceful-disconnect");
318 * g_tcp_connection_get_graceful_disconnect:
319 * @connection: a #GTcpConnection
321 * Checks if graceful disconnects are used. See
322 * g_tcp_connection_set_graceful_disconnect().
324 * Returns: %TRUE if graceful disconnect is used on close, %FALSE otherwise
329 g_tcp_connection_get_graceful_disconnect (GTcpConnection
*connection
)
331 return connection
->priv
->graceful_disconnect
;