X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgsocketconnection.c;h=9f490c84564c3bff82f08a2c81652b221b8348bd;hb=356a3987cee7ceddcb3fe623edf0bd2881895add;hp=12ea7127d87a0066a701adf422324a94cb99b281;hpb=a0e1b226a21ca498b301981b0c89e89ad9a31eb1;p=platform%2Fupstream%2Fglib.git
diff --git a/gio/gsocketconnection.c b/gio/gsocketconnection.c
index 12ea712..9f490c8 100644
--- a/gio/gsocketconnection.c
+++ b/gio/gsocketconnection.c
@@ -15,9 +15,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Public License along with this library; if not, see .
*
* Authors: Christian Kellner
* Samuel Cormier-Iijima
@@ -31,13 +29,13 @@
#include "gsocketoutputstream.h"
#include "gsocketinputstream.h"
+#include "gioprivate.h"
#include
-#include
+#include
#include "gunixconnection.h"
#include "gtcpconnection.h"
#include "glibintl.h"
-#include "gioalias.h"
/**
* SECTION:gsocketconnection
@@ -53,17 +51,18 @@
* depends on the type of the underlying socket that is in use. For
* instance, for a TCP/IP connection it will be a #GTcpConnection.
*
- * Chosing what type of object to construct is done with the socket
+ * Choosing what type of object to construct is done with the socket
* connection factory, and it is possible for 3rd parties to register
* custom socket connection types for specific combination of socket
* family/type/protocol using g_socket_connection_factory_register_type().
*
+ * To close a #GSocketConnection, use g_io_stream_close(). Closing both
+ * substreams of the #GIOStream separately will not close the underlying
+ * #GSocket.
+ *
* Since: 2.22
*/
-G_DEFINE_TYPE (GSocketConnection,
- g_socket_connection, G_TYPE_IO_STREAM);
-
enum
{
PROP_NONE,
@@ -76,6 +75,8 @@ struct _GSocketConnectionPrivate
GInputStream *input_stream;
GOutputStream *output_stream;
+ GSocketAddress *cached_remote_address;
+
gboolean in_dispose;
};
@@ -91,6 +92,8 @@ static gboolean g_socket_connection_close_finish (GIOStream *stream,
GAsyncResult *result,
GError **error);
+G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM)
+
static GInputStream *
g_socket_connection_get_input_stream (GIOStream *io_stream)
{
@@ -116,6 +119,152 @@ g_socket_connection_get_output_stream (GIOStream *io_stream)
}
/**
+ * g_socket_connection_is_connected:
+ * @connection: a #GSocketConnection
+ *
+ * Checks if @connection is connected. This is equivalent to calling
+ * g_socket_is_connected() on @connection's underlying #GSocket.
+ *
+ * Returns: whether @connection is connected
+ *
+ * Since: 2.32
+ */
+gboolean
+g_socket_connection_is_connected (GSocketConnection *connection)
+{
+ return g_socket_is_connected (connection->priv->socket);
+}
+
+/**
+ * g_socket_connection_connect:
+ * @connection: a #GSocketConnection
+ * @address: a #GSocketAddress specifying the remote address.
+ * @cancellable: (allow-none): a %GCancellable or %NULL
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Connect @connection to the specified remote address.
+ *
+ * Returns: %TRUE if the connection succeeded, %FALSE on error
+ *
+ * Since: 2.32
+ */
+gboolean
+g_socket_connection_connect (GSocketConnection *connection,
+ GSocketAddress *address,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
+ g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
+
+ return g_socket_connect (connection->priv->socket, address,
+ cancellable, error);
+}
+
+static gboolean g_socket_connection_connect_callback (GSocket *socket,
+ GIOCondition condition,
+ gpointer user_data);
+
+/**
+ * g_socket_connection_connect_async:
+ * @connection: a #GSocketConnection
+ * @address: a #GSocketAddress specifying the remote address.
+ * @cancellable: (allow-none): a %GCancellable or %NULL
+ * @callback: (scope async): a #GAsyncReadyCallback
+ * @user_data: (closure): user data for the callback
+ *
+ * Asynchronously connect @connection to the specified remote address.
+ *
+ * This clears the #GSocket:blocking flag on @connection's underlying
+ * socket if it is currently set.
+ *
+ * Use g_socket_connection_connect_finish() to retrieve the result.
+ *
+ * Since: 2.32
+ */
+void
+g_socket_connection_connect_async (GSocketConnection *connection,
+ GSocketAddress *address,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ GError *tmp_error = NULL;
+
+ g_return_if_fail (G_IS_SOCKET_CONNECTION (connection));
+ g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
+
+ task = g_task_new (connection, cancellable, callback, user_data);
+
+ g_socket_set_blocking (connection->priv->socket, FALSE);
+
+ if (g_socket_connect (connection->priv->socket, address,
+ cancellable, &tmp_error))
+ {
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ }
+ else if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_PENDING))
+ {
+ GSource *source;
+
+ g_error_free (tmp_error);
+ source = g_socket_create_source (connection->priv->socket,
+ G_IO_OUT, cancellable);
+ g_task_attach_source (task, source,
+ (GSourceFunc) g_socket_connection_connect_callback);
+ g_source_unref (source);
+ }
+ else
+ {
+ g_task_return_error (task, tmp_error);
+ g_object_unref (task);
+ }
+}
+
+static gboolean
+g_socket_connection_connect_callback (GSocket *socket,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ GTask *task = user_data;
+ GSocketConnection *connection = g_task_get_source_object (task);
+ GError *error = NULL;
+
+ if (g_socket_check_connect_result (connection->priv->socket, &error))
+ g_task_return_boolean (task, TRUE);
+ else
+ g_task_return_error (task, error);
+
+ g_object_unref (task);
+ return FALSE;
+}
+
+/**
+ * g_socket_connection_connect_finish:
+ * @connection: a #GSocketConnection
+ * @result: the #GAsyncResult
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Gets the result of a g_socket_connection_connect_async() call.
+ *
+ * Returns: %TRUE if the connection succeeded, %FALSE on error
+ *
+ * Since: 2.32
+ */
+gboolean
+g_socket_connection_connect_finish (GSocketConnection *connection,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+/**
* g_socket_connection_get_socket:
* @connection: a #GSocketConnection
*
@@ -123,7 +272,7 @@ g_socket_connection_get_output_stream (GIOStream *io_stream)
* This can be useful if you want to do something unusual on it
* not supported by the #GSocketConnection APIs.
*
- * Returns: a #GSocketAddress or %NULL on error.
+ * Returns: (transfer none): a #GSocketAddress or %NULL on error.
*
* Since: 2.22
*/
@@ -142,7 +291,7 @@ g_socket_connection_get_socket (GSocketConnection *connection)
*
* Try to get the local address of a socket connection.
*
- * Returns: a #GSocketAddress or %NULL on error.
+ * Returns: (transfer full): a #GSocketAddress or %NULL on error.
* Free the returned object with g_object_unref().
*
* Since: 2.22
@@ -161,7 +310,14 @@ g_socket_connection_get_local_address (GSocketConnection *connection,
*
* Try to get the remote address of a socket connection.
*
- * Returns: a #GSocketAddress or %NULL on error.
+ * Since GLib 2.40, when used with g_socket_client_connect() or
+ * g_socket_client_connect_async(), during emission of
+ * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
+ * address that will be used for the connection. This allows
+ * applications to print e.g. "Connecting to example.com
+ * (10.42.77.3)...".
+ *
+ * Returns: (transfer full): a #GSocketAddress or %NULL on error.
* Free the returned object with g_object_unref().
*
* Since: 2.22
@@ -170,9 +326,27 @@ GSocketAddress *
g_socket_connection_get_remote_address (GSocketConnection *connection,
GError **error)
{
+ if (!g_socket_is_connected (connection->priv->socket))
+ {
+ return connection->priv->cached_remote_address ?
+ g_object_ref (connection->priv->cached_remote_address) : NULL;
+ }
return g_socket_get_remote_address (connection->priv->socket, error);
}
+/* Private API allowing applications to retrieve the resolved address
+ * now, before we start connecting.
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=712547
+ */
+void
+g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
+ GSocketAddress *address)
+{
+ g_clear_object (&connection->priv->cached_remote_address);
+ connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
+}
+
static void
g_socket_connection_get_property (GObject *object,
guint prop_id,
@@ -226,6 +400,8 @@ g_socket_connection_dispose (GObject *object)
connection->priv->in_dispose = TRUE;
+ g_clear_object (&connection->priv->cached_remote_address);
+
G_OBJECT_CLASS (g_socket_connection_parent_class)
->dispose (object);
@@ -255,8 +431,6 @@ g_socket_connection_class_init (GSocketConnectionClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
- g_type_class_add_private (klass, sizeof (GSocketConnectionPrivate));
-
gobject_class->set_property = g_socket_connection_set_property;
gobject_class->get_property = g_socket_connection_get_property;
gobject_class->constructed = g_socket_connection_constructed;
@@ -283,9 +457,7 @@ g_socket_connection_class_init (GSocketConnectionClass *klass)
static void
g_socket_connection_init (GSocketConnection *connection)
{
- connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
- G_TYPE_SOCKET_CONNECTION,
- GSocketConnectionPrivate);
+ connection->priv = g_socket_connection_get_instance_private (connection);
}
static gboolean
@@ -322,30 +494,23 @@ g_socket_connection_close_async (GIOStream *stream,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GSimpleAsyncResult *res;
+ GTask *task;
GIOStreamClass *class;
GError *error;
class = G_IO_STREAM_GET_CLASS (stream);
+ task = g_task_new (stream, cancellable, callback, user_data);
+
/* socket close is not blocked, just do it! */
error = NULL;
if (class->close_fn &&
!class->close_fn (stream, cancellable, &error))
- {
- g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
- callback, user_data,
- error);
- g_error_free (error);
- return;
- }
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
- res = g_simple_async_result_new (G_OBJECT (stream),
- callback,
- user_data,
- g_socket_connection_close_async);
- g_simple_async_result_complete_in_idle (res);
- g_object_unref (res);
+ g_object_unref (task);
}
static gboolean
@@ -353,7 +518,7 @@ g_socket_connection_close_finish (GIOStream *stream,
GAsyncResult *result,
GError **error)
{
- return TRUE;
+ return g_task_propagate_boolean (G_TASK (result), error);
}
typedef struct {
@@ -407,7 +572,7 @@ G_LOCK_DEFINE_STATIC(connection_factories);
* @protocol: a protocol id
*
* Looks up the #GType to be used when creating socket connections on
- * sockets with the specified @family,@type and @protocol.
+ * sockets with the specified @family, @type and @protocol.
*
* If no type is registered, the #GSocketConnection base type is returned.
*
@@ -446,11 +611,10 @@ g_socket_connection_factory_register_type (GType g_type,
static void
init_builtin_types (void)
{
- volatile GType a_type;
#ifndef G_OS_WIN32
- a_type = g_unix_connection_get_type ();
+ g_type_ensure (G_TYPE_UNIX_CONNECTION);
#endif
- a_type = g_tcp_connection_get_type ();
+ g_type_ensure (G_TYPE_TCP_CONNECTION);
}
/**
@@ -460,7 +624,7 @@ init_builtin_types (void)
* @protocol_id: a protocol id
*
* Looks up the #GType to be used when creating socket connections on
- * sockets with the specified @family,@type and @protocol_id.
+ * sockets with the specified @family, @type and @protocol_id.
*
* If no type is registered, the #GSocketConnection base type is returned.
*
@@ -505,7 +669,7 @@ g_socket_connection_factory_lookup_type (GSocketFamily family,
* Creates a #GSocketConnection subclass of the right type for
* @socket.
*
- * Returns: a #GSocketConnection
+ * Returns: (transfer full): a #GSocketConnection
*
* Since: 2.22
*/
@@ -519,6 +683,3 @@ g_socket_connection_factory_create_connection (GSocket *socket)
g_socket_get_protocol (socket));
return g_object_new (type, "socket", socket, NULL);
}
-
-#define __G_SOCKET_CONNECTION_C__
-#include "gioaliasdef.c"