X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgsocketconnection.c;h=9f490c84564c3bff82f08a2c81652b221b8348bd;hb=7a1aaaa1fa02679ecf335a19fffe3f55505921b5;hp=ac9ce74debd99f7b5141071562b08d1c238e6885;hpb=631d0c3534661e549f7df18fbb9832bdf19c5eaf;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gsocketconnection.c b/gio/gsocketconnection.c index ac9ce74..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,8 +29,9 @@ #include "gsocketoutputstream.h" #include "gsocketinputstream.h" +#include "gioprivate.h" #include -#include +#include #include "gunixconnection.h" #include "gtcpconnection.h" #include "glibintl.h" @@ -52,16 +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, @@ -74,6 +75,8 @@ struct _GSocketConnectionPrivate GInputStream *input_stream; GOutputStream *output_stream; + GSocketAddress *cached_remote_address; + gboolean in_dispose; }; @@ -89,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) { @@ -114,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 * @@ -159,6 +310,13 @@ g_socket_connection_get_local_address (GSocketConnection *connection, * * Try to get the remote address of a socket connection. * + * 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(). * @@ -168,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, @@ -224,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); @@ -253,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; @@ -281,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 @@ -320,29 +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_take_gerror_in_idle (G_OBJECT (stream), - callback, user_data, - 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 @@ -350,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 { @@ -404,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. * @@ -443,12 +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 (); - (a_type); /* To avoid -Wunused-but-set-variable */ + g_type_ensure (G_TYPE_TCP_CONNECTION); } /** @@ -458,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. *