| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | /* GIO - GLib Input, Output and Streaming Library
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright © 2008, 2009 Codethink Limited | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU Lesser General Public License as published | 
					
						
							|  |  |  |  * by the Free Software Foundation; either version 2 of the licence or (at | 
					
						
							|  |  |  |  * your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See the included COPYING file for more information. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2011-02-01 16:17:23 -02:00
										 |  |  |  * SECTION:gtcpconnection | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * @title: GTcpConnection | 
					
						
							| 
									
										
										
										
											2010-11-28 23:55:43 -05:00
										 |  |  |  * @short_description: A TCP GSocketConnection | 
					
						
							| 
									
										
										
										
											2014-01-07 22:55:43 -05:00
										 |  |  |  * @include: gio/gio.h | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |  * @see_also: #GSocketConnection. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This is the subclass of #GSocketConnection that is created | 
					
						
							|  |  |  |  * for TCP/IP sockets. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.22 | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "config.h"
 | 
					
						
							|  |  |  | #include "gtcpconnection.h"
 | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | #include "gasyncresult.h"
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | #include "gtask.h"
 | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | #include "giostream.h"
 | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | #include "glibintl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-11 00:29:58 +01:00
										 |  |  | struct _GTcpConnectionPrivate | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   guint graceful_disconnect : 1; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | G_DEFINE_TYPE_WITH_CODE (GTcpConnection, g_tcp_connection, | 
					
						
							|  |  |  | 			 G_TYPE_SOCKET_CONNECTION, | 
					
						
							| 
									
										
										
										
											2013-06-11 00:29:58 +01:00
										 |  |  |                          G_ADD_PRIVATE (GTcpConnection) | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |   g_socket_connection_factory_register_type (g_define_type_id, | 
					
						
							|  |  |  | 					     G_SOCKET_FAMILY_IPV4, | 
					
						
							|  |  |  | 					     G_SOCKET_TYPE_STREAM, | 
					
						
							| 
									
										
										
										
											2009-05-20 12:01:29 +02:00
										 |  |  | 					     G_SOCKET_PROTOCOL_DEFAULT); | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |   g_socket_connection_factory_register_type (g_define_type_id, | 
					
						
							|  |  |  | 					     G_SOCKET_FAMILY_IPV6, | 
					
						
							|  |  |  | 					     G_SOCKET_TYPE_STREAM, | 
					
						
							| 
									
										
										
										
											2009-05-20 12:01:29 +02:00
										 |  |  | 					     G_SOCKET_PROTOCOL_DEFAULT); | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |   g_socket_connection_factory_register_type (g_define_type_id, | 
					
						
							|  |  |  | 					     G_SOCKET_FAMILY_IPV4, | 
					
						
							|  |  |  | 					     G_SOCKET_TYPE_STREAM, | 
					
						
							| 
									
										
										
										
											2009-05-20 12:01:29 +02:00
										 |  |  | 					     G_SOCKET_PROTOCOL_TCP); | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  |   g_socket_connection_factory_register_type (g_define_type_id, | 
					
						
							|  |  |  | 					     G_SOCKET_FAMILY_IPV6, | 
					
						
							|  |  |  | 					     G_SOCKET_TYPE_STREAM, | 
					
						
							| 
									
										
										
										
											2009-05-20 12:01:29 +02:00
										 |  |  | 					     G_SOCKET_PROTOCOL_TCP); | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | 			 ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | static gboolean g_tcp_connection_close       (GIOStream            *stream, | 
					
						
							|  |  |  | 					      GCancellable         *cancellable, | 
					
						
							|  |  |  | 					      GError              **error); | 
					
						
							|  |  |  | static void     g_tcp_connection_close_async (GIOStream            *stream, | 
					
						
							|  |  |  | 					      int                   io_priority, | 
					
						
							|  |  |  | 					      GCancellable         *cancellable, | 
					
						
							|  |  |  | 					      GAsyncReadyCallback   callback, | 
					
						
							|  |  |  | 					      gpointer              user_data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PROP_0, | 
					
						
							|  |  |  |   PROP_GRACEFUL_DISCONNECT | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | static void | 
					
						
							|  |  |  | g_tcp_connection_init (GTcpConnection *connection) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-24 15:43:04 +01:00
										 |  |  |   connection->priv = g_tcp_connection_get_instance_private (connection); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |   connection->priv->graceful_disconnect = FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_tcp_connection_get_property (GObject    *object, | 
					
						
							|  |  |  | 			       guint       prop_id, | 
					
						
							|  |  |  | 			       GValue     *value, | 
					
						
							|  |  |  | 			       GParamSpec *pspec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GTcpConnection *connection = G_TCP_CONNECTION (object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (prop_id) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       case PROP_GRACEFUL_DISCONNECT: | 
					
						
							|  |  |  | 	g_value_set_boolean (value, connection->priv->graceful_disconnect); | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  | 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_tcp_connection_set_property (GObject      *object, | 
					
						
							|  |  |  | 			       guint         prop_id, | 
					
						
							|  |  |  | 			       const GValue *value, | 
					
						
							|  |  |  | 			       GParamSpec   *pspec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GTcpConnection *connection = G_TCP_CONNECTION (object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (prop_id) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       case PROP_GRACEFUL_DISCONNECT: | 
					
						
							|  |  |  | 	g_tcp_connection_set_graceful_disconnect (connection, | 
					
						
							|  |  |  | 						  g_value_get_boolean (value)); | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  | 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-15 21:26:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_tcp_connection_class_init (GTcpConnectionClass *class) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |   GObjectClass *gobject_class = G_OBJECT_CLASS (class); | 
					
						
							|  |  |  |   GIOStreamClass *stream_class = G_IO_STREAM_CLASS (class); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   gobject_class->set_property = g_tcp_connection_set_property; | 
					
						
							|  |  |  |   gobject_class->get_property = g_tcp_connection_get_property; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   stream_class->close_fn = g_tcp_connection_close; | 
					
						
							|  |  |  |   stream_class->close_async = g_tcp_connection_close_async; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_object_class_install_property (gobject_class, PROP_GRACEFUL_DISCONNECT, | 
					
						
							|  |  |  | 				   g_param_spec_boolean ("graceful-disconnect", | 
					
						
							|  |  |  | 							 P_("Graceful Disconnect"), | 
					
						
							|  |  |  | 							 P_("Whether or not close does a graceful disconnect"), | 
					
						
							|  |  |  | 							 FALSE, | 
					
						
							|  |  |  | 							 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  | g_tcp_connection_close (GIOStream     *stream, | 
					
						
							|  |  |  | 			GCancellable  *cancellable, | 
					
						
							|  |  |  | 			GError       **error) | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   GTcpConnection *connection = G_TCP_CONNECTION (stream); | 
					
						
							|  |  |  |   GSocket *socket; | 
					
						
							|  |  |  |   char buffer[1024]; | 
					
						
							|  |  |  |   gssize ret; | 
					
						
							|  |  |  |   gboolean had_error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream)); | 
					
						
							|  |  |  |   had_error = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (connection->priv->graceful_disconnect && | 
					
						
							|  |  |  |       !g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (!g_socket_shutdown (socket, FALSE, TRUE, error)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  error = NULL; /* Ignore further errors */ | 
					
						
							|  |  |  | 	  had_error = TRUE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  while (TRUE) | 
					
						
							|  |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | 	      ret = g_socket_receive_with_blocking (socket,  buffer, sizeof (buffer), | 
					
						
							|  |  |  | 						    TRUE, cancellable, error); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | 	      if (ret < 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | 		  had_error = TRUE; | 
					
						
							|  |  |  | 		  error = NULL; | 
					
						
							|  |  |  | 		  break; | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	      if (ret == 0) | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return G_IO_STREAM_CLASS (g_tcp_connection_parent_class) | 
					
						
							|  |  |  |     ->close_fn (stream, cancellable, error) && !had_error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | /* consumes @error */ | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | async_close_finish (GTask    *task, | 
					
						
							|  |  |  |                     GError   *error) | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   GIOStreamClass *parent = G_IO_STREAM_CLASS (g_tcp_connection_parent_class); | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   GIOStream *stream = g_task_get_source_object (task); | 
					
						
							|  |  |  |   GCancellable *cancellable = g_task_get_cancellable (task); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   /* Close underlying stream, ignoring further errors if we already
 | 
					
						
							|  |  |  |    * have one. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |   if (error) | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |     parent->close_fn (stream, cancellable, NULL); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |     parent->close_fn (stream, cancellable, &error); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   if (error) | 
					
						
							|  |  |  |     g_task_return_error (task, error); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |     g_task_return_boolean (task, TRUE); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | static gboolean | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  | close_read_ready (GSocket        *socket, | 
					
						
							|  |  |  | 		  GIOCondition    condition, | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | 		  GTask          *task) | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   GError *error = NULL; | 
					
						
							|  |  |  |   char buffer[1024]; | 
					
						
							|  |  |  |   gssize ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   ret = g_socket_receive_with_blocking (socket,  buffer, sizeof (buffer), | 
					
						
							|  |  |  |                                         FALSE, g_task_get_cancellable (task), | 
					
						
							|  |  |  |                                         &error); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |   if (ret < 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  g_error_free (error); | 
					
						
							|  |  |  | 	  return TRUE; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | 	  async_close_finish (task, error); | 
					
						
							|  |  |  | 	  g_object_unref (task); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | 	  return FALSE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ret == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |       async_close_finish (task, NULL); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  | g_tcp_connection_close_async (GIOStream           *stream, | 
					
						
							|  |  |  | 			      int                  io_priority, | 
					
						
							|  |  |  | 			      GCancellable        *cancellable, | 
					
						
							|  |  |  | 			      GAsyncReadyCallback  callback, | 
					
						
							|  |  |  | 			      gpointer             user_data) | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   GTcpConnection *connection = G_TCP_CONNECTION (stream); | 
					
						
							|  |  |  |   GSocket *socket; | 
					
						
							|  |  |  |   GSource *source; | 
					
						
							|  |  |  |   GError *error; | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |   GTask *task; | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (connection->priv->graceful_disconnect && | 
					
						
							|  |  |  |       !g_cancellable_is_cancelled (cancellable) /* Cancelled -> close fast */) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |       task = g_task_new (stream, cancellable, callback, user_data); | 
					
						
							| 
									
										
										
										
											2016-06-16 19:39:38 -04:00
										 |  |  |       g_task_set_source_tag (task, g_tcp_connection_close_async); | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |       g_task_set_priority (task, io_priority); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       error = NULL; | 
					
						
							|  |  |  |       if (!g_socket_shutdown (socket, FALSE, TRUE, &error)) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  | 	  g_task_return_error (task, error); | 
					
						
							|  |  |  | 	  g_object_unref (task); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | 	  return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       source = g_socket_create_source (socket, G_IO_IN, cancellable); | 
					
						
							| 
									
										
										
										
											2012-08-02 15:48:22 -04:00
										 |  |  |       g_task_attach_source (task, source, (GSourceFunc) close_read_ready); | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |       g_source_unref (source); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-30 11:18:35 -04:00
										 |  |  |   G_IO_STREAM_CLASS (g_tcp_connection_parent_class) | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |     ->close_async (stream, io_priority, cancellable, callback, user_data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_tcp_connection_set_graceful_disconnect: | 
					
						
							|  |  |  |  * @connection: a #GTcpConnection | 
					
						
							|  |  |  |  * @graceful_disconnect: Whether to do graceful disconnects or not | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-10-20 19:05:26 -05:00
										 |  |  |  * This enables graceful disconnects on close. A graceful disconnect | 
					
						
							| 
									
										
										
										
											2011-04-20 19:08:06 +02:00
										 |  |  |  * means that we signal the receiving end that the connection is terminated | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  |  * and wait for it to close the connection before closing the connection. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * A graceful disconnect means that we can be sure that we successfully sent | 
					
						
							|  |  |  |  * all the outstanding data to the other end, or get an error reported. | 
					
						
							|  |  |  |  * However, it also means we have to wait for all the data to reach the | 
					
						
							|  |  |  |  * other side and for it to acknowledge this by closing the socket, which may | 
					
						
							|  |  |  |  * take a while. For this reason it is disabled by default. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.22 | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | void | 
					
						
							|  |  |  | g_tcp_connection_set_graceful_disconnect (GTcpConnection *connection, | 
					
						
							|  |  |  | 					  gboolean        graceful_disconnect) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   graceful_disconnect = !!graceful_disconnect; | 
					
						
							|  |  |  |   if (graceful_disconnect != connection->priv->graceful_disconnect) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       connection->priv->graceful_disconnect = graceful_disconnect; | 
					
						
							|  |  |  |       g_object_notify (G_OBJECT (connection), "graceful-disconnect"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_tcp_connection_get_graceful_disconnect: | 
					
						
							|  |  |  |  * @connection: a #GTcpConnection | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Checks if graceful disconnects are used. See | 
					
						
							|  |  |  |  * g_tcp_connection_set_graceful_disconnect(). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns: %TRUE if graceful disconnect is used on close, %FALSE otherwise | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since: 2.22 | 
					
						
							| 
									
										
										
										
											2009-05-27 18:20:08 -04:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-05-20 11:19:47 +02:00
										 |  |  | gboolean | 
					
						
							|  |  |  | g_tcp_connection_get_graceful_disconnect (GTcpConnection *connection) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return connection->priv->graceful_disconnect; | 
					
						
							|  |  |  | } |