Merge remote branch 'gvdb/master'
[platform/upstream/glib.git] / gio / gsocketclient.c
index 944b73c..7908aec 100644 (file)
@@ -36,6 +36,7 @@
 #include <gio/gioerror.h>
 #include <gio/gsocket.h>
 #include <gio/gnetworkaddress.h>
+#include <gio/gnetworkservice.h>
 #include <gio/gsocketaddress.h>
 #include "glibintl.h"
 
@@ -59,7 +60,7 @@
  * it will be a #GTcpConnection.
  *
  * Since: 2.22
- **/
+ */
 
 
 G_DEFINE_TYPE (GSocketClient, g_socket_client, G_TYPE_OBJECT);
@@ -136,7 +137,7 @@ g_socket_client_init (GSocketClient *client)
  *     Free the returned object with g_object_unref().
  *
  * Since: 2.22
- **/
+ */
 GSocketClient *
 g_socket_client_new (void)
 {
@@ -228,7 +229,7 @@ g_socket_client_set_property (GObject      *object,
  * Returns: a #GSocketFamily
  *
  * Since: 2.22
- **/
+ */
 GSocketFamily
 g_socket_client_get_family (GSocketClient *client)
 {
@@ -250,10 +251,10 @@ g_socket_client_get_family (GSocketClient *client)
  * be an ipv6 mapped to ipv4 address.
  *
  * Since: 2.22
- **/
+ */
 void
 g_socket_client_set_family (GSocketClient *client,
-                           GSocketFamily family)
+                           GSocketFamily  family)
 {
   if (client->priv->family == family)
     return;
@@ -273,7 +274,7 @@ g_socket_client_set_family (GSocketClient *client,
  * Returns: a #GSocketFamily
  *
  * Since: 2.22
- **/
+ */
 GSocketType
 g_socket_client_get_socket_type (GSocketClient *client)
 {
@@ -293,10 +294,10 @@ g_socket_client_get_socket_type (GSocketClient *client)
  * as GSocketClient is used for connection oriented services.
  *
  * Since: 2.22
- **/
+ */
 void
 g_socket_client_set_socket_type (GSocketClient *client,
-                                GSocketType type)
+                                GSocketType    type)
 {
   if (client->priv->type == type)
     return;
@@ -307,7 +308,7 @@ g_socket_client_set_socket_type (GSocketClient *client,
 
 /**
  * g_socket_client_get_protocol:
- * @client: a #GSocketClient.
+ * @client: a #GSocketClient
  *
  * Gets the protocol name type of the socket client.
  *
@@ -316,7 +317,7 @@ g_socket_client_set_socket_type (GSocketClient *client,
  * Returns: a #GSocketProtocol
  *
  * Since: 2.22
- **/
+ */
 GSocketProtocol
 g_socket_client_get_protocol (GSocketClient *client)
 {
@@ -336,10 +337,10 @@ g_socket_client_get_protocol (GSocketClient *client)
  * protocol for the socket family and type.
  *
  * Since: 2.22
- **/
+ */
 void
-g_socket_client_set_protocol (GSocketClient *client,
-                             GSocketProtocol protocol)
+g_socket_client_set_protocol (GSocketClient   *client,
+                             GSocketProtocol  protocol)
 {
   if (client->priv->protocol == protocol)
     return;
@@ -359,7 +360,7 @@ g_socket_client_set_protocol (GSocketClient *client,
  * Returns: a #GSocketAddres or %NULL. don't free
  *
  * Since: 2.22
- **/
+ */
 GSocketAddress *
 g_socket_client_get_local_address (GSocketClient *client)
 {
@@ -380,10 +381,10 @@ g_socket_client_get_local_address (GSocketClient *client)
  * a specific interface.
  *
  * Since: 2.22
- **/
+ */
 void
-g_socket_client_set_local_address (GSocketClient        *client,
-                                  GSocketAddress       *address)
+g_socket_client_set_local_address (GSocketClient  *client,
+                                  GSocketAddress *address)
 {
   if (address)
   g_object_ref (address);
@@ -413,7 +414,9 @@ g_socket_client_class_init (GSocketClientClass *class)
                                                      P_("The sockets address family to use for socket construction"),
                                                      G_TYPE_SOCKET_FAMILY,
                                                      G_SOCKET_FAMILY_INVALID,
-                                                     G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                     G_PARAM_CONSTRUCT |
+                                                      G_PARAM_READWRITE |
+                                                      G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_TYPE,
                                   g_param_spec_enum ("type",
@@ -421,7 +424,9 @@ g_socket_client_class_init (GSocketClientClass *class)
                                                      P_("The sockets type to use for socket construction"),
                                                      G_TYPE_SOCKET_TYPE,
                                                      G_SOCKET_TYPE_STREAM,
-                                                     G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                     G_PARAM_CONSTRUCT |
+                                                      G_PARAM_READWRITE |
+                                                      G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_PROTOCOL,
                                   g_param_spec_enum ("protocol",
@@ -429,14 +434,18 @@ g_socket_client_class_init (GSocketClientClass *class)
                                                      P_("The protocol to use for socket construction, or 0 for default"),
                                                      G_TYPE_SOCKET_PROTOCOL,
                                                      G_SOCKET_PROTOCOL_DEFAULT,
-                                                     G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                     G_PARAM_CONSTRUCT |
+                                                      G_PARAM_READWRITE |
+                                                      G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class, PROP_LOCAL_ADDRESS,
                                   g_param_spec_object ("local-address",
                                                        P_("Local address"),
                                                        P_("The local address constructed sockets will be bound to"),
                                                        G_TYPE_SOCKET_ADDRESS,
-                                                       G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                                                       G_PARAM_CONSTRUCT |
+                                                        G_PARAM_READWRITE |
+                                                        G_PARAM_STATIC_STRINGS));
 }
 
 /**
@@ -468,7 +477,7 @@ g_socket_client_class_init (GSocketClientClass *class)
  * Returns: a #GSocketConnection on success, %NULL on error.
  *
  * Since: 2.22
- **/
+ */
 GSocketConnection *
 g_socket_client_connect (GSocketClient       *client,
                         GSocketConnectable  *connectable,
@@ -505,11 +514,11 @@ g_socket_client_connect (GSocketClient       *client,
            }
          else if (last_error)
            {
-             g_propagate_error (error, tmp_error);
+             g_propagate_error (error, last_error);
            }
          else
-           g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                        _("Unknown error on connect"));
+            g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                                 _("Unknown error on connect"));
          break;
        }
 
@@ -519,7 +528,7 @@ g_socket_client_connect (GSocketClient       *client,
       socket = create_socket (client, address, &last_error);
       if (socket != NULL)
        {
-         if (g_socket_connect (socket, address, &last_error))
+         if (g_socket_connect (socket, address, cancellable, &last_error))
            connection = g_socket_connection_factory_create_connection (socket);
 
          g_object_unref (socket);
@@ -557,7 +566,7 @@ g_socket_client_connect (GSocketClient       *client,
  * In general, @host_and_port is expected to be provided by the user (allowing
  * them to give the hostname, and a port overide if necessary) and
  * @default_port is expected to be provided by the application.
-
+ *
  * In the case that an IP address is given, a single connection
  * attempt is made.  In the case that a name is given, multiple
  * connection attempts may be made, in turn and according to the
@@ -574,13 +583,13 @@ g_socket_client_connect (GSocketClient       *client,
  Returns: a #GSocketConnection on success, %NULL on error.
  *
  * Since: 2.22
- **/
+ */
 GSocketConnection *
-g_socket_client_connect_to_host (GSocketClient        *client,
-                                const char           *host_and_port,
-                                int                   default_port,
-                                GCancellable         *cancellable,
-                                GError              **error)
+g_socket_client_connect_to_host (GSocketClient  *client,
+                                const gchar    *host_and_port,
+                                guint16         default_port,
+                                GCancellable   *cancellable,
+                                GError        **error)
 {
   GSocketConnectable *connectable;
   GSocketConnection *connection;
@@ -596,6 +605,48 @@ g_socket_client_connect_to_host (GSocketClient        *client,
   return connection;
 }
 
+/**
+ * g_socket_client_connect_to_service:
+ * @client: a #GSocketConnection
+ * @domain: a domain name
+ * @service: the name of the service to connect to
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a pointer to a #GError, or %NULL
+ * @returns: a #GSocketConnection if successful, or %NULL on error
+ *
+ * Attempts to create a TCP connection to a service.
+ *
+ * This call looks up the SRV record for @service at @domain for the
+ * "tcp" protocol.  It then attempts to connect, in turn, to each of
+ * the hosts providing the service until either a connection succeeds
+ * or there are no hosts remaining.
+ *
+ * Upon a successful connection, a new #GSocketConnection is constructed
+ * and returned.  The caller owns this new object and must drop their
+ * reference to it when finished with it.
+ *
+ * In the event of any failure (DNS error, service not found, no hosts
+ * connectable) %NULL is returned and @error (if non-%NULL) is set
+ * accordingly.
+ */
+GSocketConnection *
+g_socket_client_connect_to_service (GSocketClient  *client,
+                                   const gchar    *domain,
+                                   const gchar    *service,
+                                   GCancellable   *cancellable,
+                                   GError        **error)
+{
+  GSocketConnectable *connectable;
+  GSocketConnection *connection;
+
+  connectable = g_network_service_new (service, "tcp", domain);
+  connection = g_socket_client_connect (client, connectable,
+                                       cancellable, error);
+  g_object_unref (connectable);
+
+  return connection;
+}
+
 typedef struct
 {
   GSimpleAsyncResult *result;
@@ -625,6 +676,7 @@ g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
       g_socket_set_blocking (data->current_socket, TRUE);
 
       connection = g_socket_connection_factory_create_connection (data->current_socket);
+      g_object_unref (data->current_socket);
       g_simple_async_result_set_op_res_gpointer (data->result,
                                                 connection,
                                                 g_object_unref);
@@ -632,6 +684,8 @@ g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
 
   g_simple_async_result_complete (data->result);
   g_object_unref (data->result);
+  g_object_unref (data->enumerator);
+  g_slice_free (GSocketClientAsyncConnectData, data);
 }
 
 
@@ -712,8 +766,8 @@ g_socket_client_enumerator_callback (GObject      *object,
       if (tmp_error)
        set_last_error (data, tmp_error);
       else if (data->last_error == NULL)
-       g_set_error (&data->last_error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                    _("Unknown error on connect"));
+        g_set_error_literal (&data->last_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                             _("Unknown error on connect"));
 
       g_socket_client_async_connect_complete (data);
       return;
@@ -725,7 +779,7 @@ g_socket_client_enumerator_callback (GObject      *object,
   if (socket != NULL)
     {
       g_socket_set_blocking (socket, FALSE);
-      if (g_socket_connect (socket, address, &tmp_error))
+      if (g_socket_connect (socket, address, data->cancellable, &tmp_error))
        {
          data->current_socket = socket;
          g_socket_client_async_connect_complete (data);
@@ -745,7 +799,7 @@ g_socket_client_enumerator_callback (GObject      *object,
          g_source_set_callback (source,
                                 (GSourceFunc) g_socket_client_socket_callback,
                                 data, NULL);
-         g_source_attach (source, NULL);
+         g_source_attach (source, g_main_context_get_thread_default ());
          g_source_unref (source);
 
          g_object_unref (address);
@@ -780,7 +834,7 @@ g_socket_client_enumerator_callback (GObject      *object,
  * the result of the operation.
  *
  * Since: 2.22
- **/
+ */
 void
 g_socket_client_connect_async (GSocketClient       *client,
                               GSocketConnectable  *connectable,
@@ -826,11 +880,11 @@ g_socket_client_connect_async (GSocketClient       *client,
  * the result of the operation.
  *
  * Since: 2.22
- **/
+ */
 void
 g_socket_client_connect_to_host_async (GSocketClient        *client,
-                                      const char           *host_and_port,
-                                      int                   default_port,
+                                      const gchar          *host_and_port,
+                                      guint16               default_port,
                                       GCancellable         *cancellable,
                                       GAsyncReadyCallback   callback,
                                       gpointer              user_data)
@@ -857,6 +911,37 @@ g_socket_client_connect_to_host_async (GSocketClient        *client,
 }
 
 /**
+ * g_socket_client_connect_to_service_async:
+ * @client: a #GSocketClient
+ * @domain: a domain name
+ * @service: the name of the service to connect to
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: a #GAsyncReadyCallback
+ * @user_data: user data for the callback
+ *
+ * This is the asynchronous version of
+ * g_socket_client_connect_to_service().
+ *
+ * Since: 2.22
+ */
+void
+g_socket_client_connect_to_service_async (GSocketClient       *client,
+                                         const gchar         *domain,
+                                         const gchar         *service,
+                                         GCancellable        *cancellable,
+                                         GAsyncReadyCallback  callback,
+                                         gpointer             user_data)
+{
+  GSocketConnectable *connectable;
+
+  connectable = g_network_service_new (service, "tcp", domain);
+  g_socket_client_connect_async (client,
+                                connectable, cancellable,
+                                callback, user_data);
+  g_object_unref (connectable);
+}
+
+/**
  * g_socket_client_connect_finish:
  * @client: a #GSocketClient.
  * @result: a #GAsyncResult.
@@ -868,7 +953,7 @@ g_socket_client_connect_to_host_async (GSocketClient        *client,
  * Returns: a #GSocketConnection on success, %NULL on error.
  *
  * Since: 2.22
- **/
+ */
 GSocketConnection *
 g_socket_client_connect_finish (GSocketClient  *client,
                                GAsyncResult   *result,
@@ -894,11 +979,32 @@ g_socket_client_connect_finish (GSocketClient  *client,
  * Returns: a #GSocketConnection on success, %NULL on error.
  *
  * Since: 2.22
- **/
+ */
+GSocketConnection *
+g_socket_client_connect_to_host_finish (GSocketClient  *client,
+                                       GAsyncResult   *result,
+                                       GError        **error)
+{
+  return g_socket_client_connect_finish (client, result, error);
+}
+
+/**
+ * g_socket_client_connect_to_service_finish:
+ * @client: a #GSocketClient.
+ * @result: a #GAsyncResult.
+ * @error: a #GError location to store the error occuring, or %NULL to
+ * ignore.
+ *
+ * Finishes an async connect operation. See g_socket_client_connect_to_service_async()
+ *
+ * Returns: a #GSocketConnection on success, %NULL on error.
+ *
+ * Since: 2.22
+ */
 GSocketConnection *
-g_socket_client_connect_to_host_finish (GSocketClient        *client,
-                                       GAsyncResult         *result,
-                                       GError              **error)
+g_socket_client_connect_to_service_finish (GSocketClient  *client,
+                                          GAsyncResult   *result,
+                                          GError        **error)
 {
   return g_socket_client_connect_finish (client, result, error);
 }