[gnio/connection-factory] Simplify GTcpClient



commit 55f5fa6eab407f3c4b2ebb285769429356bc8676
Author: Alexander Larsson <alexl redhat com>
Date:   Fri May 8 21:01:38 2009 +0200

    Simplify GTcpClient
    
    Don't allow ports in the hostname, this looks kinda dangerous as its
    easy for apps to not be aware the the hostname can have a port, and
    it doesn't fit well with how ports seem to be used in non-commandline apps.
    
    Pass port as int, don't allow lookup by name. Lookup by name is not reliable
    since using it for any newish protocol would mean you need to do an "os
    update" to get it working (i.e. update to /etc/services). But ports are
    a public ABI anyway, so you might as well hardcode them in apps so it
    always works.
    
    g_network_service_new and g_network_service_new always succeeds
---
 examples/client.c |    2 +-
 gio/gtcpclient.c  |  318 ++--------------------------------------------------
 gio/gtcpclient.h  |    4 +-
 3 files changed, 16 insertions(+), 308 deletions(-)

diff --git a/examples/client.c b/examples/client.c
index 39b67b5..87f83f7 100644
--- a/examples/client.c
+++ b/examples/client.c
@@ -66,7 +66,7 @@ main (void)
 
   client = g_tcp_client_new ();
   g_tcp_client_connect_to_host_async (client, "mail.desrt.ca",
-                                      "imap", NULL, ready, NULL);
+                                      143, NULL, ready, NULL);
 
   g_main_loop_run (g_main_loop_new (NULL, FALSE));
   g_error ("hi?");
diff --git a/gio/gtcpclient.c b/gio/gtcpclient.c
index 4647507..9f6fb82 100644
--- a/gio/gtcpclient.c
+++ b/gio/gtcpclient.c
@@ -26,12 +26,6 @@
 #include "gtcpclient.h"
 
 #include <string.h>
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
 
 #include <gio/gsimpleasyncresult.h>
 #include <gio/gsocketconnectable.h>
@@ -146,252 +140,11 @@ g_tcp_client_connect_finish (GTcpClient    *client,
     return NULL;
 }
 
-static GSocketConnectable *
-g_tcp_client_get_connectable (const gchar  *host,
-                              const gchar  *default_port,
-                              GError      **error)
-{
-  GSocketConnectable *connectable;
-  GInetAddress *addr;
-  const gchar *port;
-  guint16 portnum;
-  gchar *name;
-
-  g_return_val_if_fail (host != NULL, NULL);
-
-  if (host[0] == '[')
-    /* escaped host part (to allow, eg. "[2001:db8::1]:888") */
-    {
-      const gchar *end;
-
-      end = strchr (host, ']');
-
-      if (end == NULL)
-        {
-          g_set_error (error, 0, 0, /* XXX */
-                       "Hostname '%s' contains '[' but not ']'.", host);
-          return NULL;
-        }
-
-      if (end[1] == '\0')
-          port = NULL;
-
-      else if (end[1] == ':')
-          port = &end[2];
-
-      else
-        {
-          g_set_error (error, 0, 0, /* XXX */
-                       "The ']' character (in hostname '%s') must come at the"
-                       " end or be immediately followed by ':' and a port.",
-                       host);
-          return NULL;
-        }
-
-      name = g_strndup (host + 1, end - host - 1);
-    }
-
-  else if ((port = strchr (host, ':')))
-    /* string has a ':' in it */
-    {
-      /* skip ':' */
-      port++;
-
-      if (strchr (port, ':'))
-        /* more than one ':' in string */
-        {
-          /* this is actually an unescaped IPv6 address */
-          name = g_strdup (host);
-          port = NULL;
-        }
-      else
-        name = g_strndup (host, port - host - 1);
-    }
-
-  else
-    /* plain hostname, no port */
-    name = g_strdup (host);
-
-  if (port == NULL)
-    {
-      if (default_port == NULL)
-        {
-          g_set_error (error, 0, 0, /* XXX */
-                       "No port was specified in hostname '%s' (and there "
-                       " is no default).", host);
-          g_free (name);
-          return NULL;
-        }
-
-      port = default_port;
-    }
-
-  if (port[0] == '\0')
-    {
-      g_set_error (error, 0, 0, /* XXX */
-                   "If a ':' character is given, it must be followed by a "
-                   "port (in hostname '%s').", host);
-      g_free (name);
-      return NULL;
-    }
-
-  else if ('0' <= port[0] && port[0] <= '9')
-    {
-      const gchar *end;
-      guint64 value;
-
-      value = g_ascii_strtoull (port, (gchar **) &end, 10);
-
-      if (*end != '\0' || value == 0 || value > G_MAXUINT16)
-        {
-          g_set_error (error, 0, 0, /* XXX */
-                       "Invalid numeric port '%s' specified in hostname '%s'",
-                       port, host);
-          g_free (name);
-          return NULL;
-        }
-
-      portnum = value;
-    }
-
-  else
-    {
-      struct servent *entry;
-
-      entry = getservbyname (port, "tcp");
-
-      if (entry == NULL)
-        {
-          g_set_error (error, 0, 0, /* XXX */
-                       "Unknown service '%s' specified in hostname '%s'",
-                       port, host);
-#ifdef HAVE_ENDSERVENT
-          endservent ();
-#endif
-          g_free (name);
-          return NULL;
-        }
-
-      portnum = g_ntohs (entry->s_port);
-
-#ifdef HAVE_ENDSERVENT
-      endservent ();
-#endif
-    }
-
-#if 1
-  if ((addr = g_inet_address_new_from_string (host)))
-    /* it was an IP address */
-    {
-      GSocketAddress *sockaddr;
-
-      sockaddr = g_inet_socket_address_new (addr, portnum);
-      connectable = G_SOCKET_CONNECTABLE (sockaddr);
-    }
-
-  else
-    /* not an IP address.  try DNS. */
-    connectable = g_network_address_new (name, portnum);
-
-  g_free (name);
-
-  return connectable;
-#else
-  /* more complicated way to do the same.  wrote
-   * it first.  keeping it around just in case
-   * the first one doesn't work for some reason.
-   */
-  if (strchr (name, ':'))
-    /* ipv6 address */
-    {
-      GSocketAddress *sockaddr;
-      GInetAddress *addr;
-
-      addr = g_inet_address_new_from_string (name);
-
-      if (addr == NULL)
-        {
-          g_set_error (error, 0, 0,
-                       "Invalid network address '%s'", name);
-          g_free (name);
-
-          return NULL;
-        }
-
-      g_free (name);
-
-      sockaddr = g_inet_socket_address_new (addr, portnum);
-
-      return G_SOCKET_CONNECTABLE (sockaddr);
-    }
-
-  else
-    {
-      gint digits = 0;
-      gint dots = 0;
-      gint part = 0;
-      gint i;
-
-      /* IPv4 address detection:
-       * eschew exotic ipv4 address representations.
-       * only accept a.b.c.d for 0 <= (a,b,c,d) < 256.
-       */
-      for (i = 0; name[i]; i++)
-        {
-          if ('0' <= name[i] && name[i] <= '9')
-            {
-              if (++digits > 3)
-                break;
-
-              if ((part = part * 10 + (name[i] - '0')) > 255)
-                break;
-            }
-          else if (name[i] == '.')
-            {
-              digits = 0;
-              part = 0;
-              dots++;
-            }
-          else
-            break;
-        }
-
-      if (name[i] == '\0' && dots == 3)
-        /* ipv4 address */
-        {
-          GSocketAddress *sockaddr;
-          GInetAddress *addr;
-
-          addr = g_inet_address_new_from_string (name);
-
-          /* we checked it.  it should be ok. */
-          g_assert (addr != NULL);
-          g_free (name);
-
-          sockaddr = g_inet_socket_address_new (addr, portnum);
-
-          return G_SOCKET_CONNECTABLE (sockaddr);
-        }
-
-      else
-        /* neither ipv6 or ipv4 address.  try DNS. */
-        {
-          GSocketConnectable *dns;
-
-          dns = g_network_address_new (name, portnum);
-          g_free (name);
-
-          return dns;
-        }
-    }
-#endif
-}
-
 /**
  * g_tcp_client_connect_to_host:
  * @client: a #GTcpClient
  * @host: the name of the host to connect to
- * @default_port: the default port to connect to
+ * @port: the port to connect to
  * @cancellable: a #GCancellable, or %NULL
  * @error: a pointer to a #GError, or %NULL
  * @returns: a #GTcpConnection if successful, or %NULL on error
@@ -400,18 +153,7 @@ g_tcp_client_get_connectable (const gchar  *host,
  *
  * @host may be in any of a number of recognised formats: an IPv6
  * address, an IPv4 address, or a domain name (in which case a DNS
- * lookup is performed).  Quoting with [] is supported for all address
- * types.  A port override may be specified in the usual way with a
- * colon.  Ports may be given as decimal numbers or symbolic names (in
- * which case an /etc/services lookup is performed).
- *
- * If no port override is given in @host then @default_port will be
- * used as the port to connect to.  This may also be given as a
- * decimal number or a symbolic name.
- *
- * In general, @host 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.
+ * lookup is performed).
  *
  * In the case that an IP address is given, a single connection
  * attempt is made.  In the case that a name is given, multiple
@@ -429,7 +171,7 @@ g_tcp_client_get_connectable (const gchar  *host,
 GTcpConnection *
 g_tcp_client_connect_to_host (GTcpClient    *client,
                               const gchar   *host,
-                              const gchar   *default_port,
+                              int            port,
                               GCancellable  *cancellable,
                               GError       **error)
 {
@@ -438,16 +180,10 @@ g_tcp_client_connect_to_host (GTcpClient    *client,
 
   g_return_val_if_fail (G_IS_TCP_CLIENT (client), NULL);
 
-  connectable = g_tcp_client_get_connectable (host, default_port, error);
-
-  if (connectable)
-    {
-      connection = g_tcp_client_connect (client, connectable,
-                                         cancellable, error);
-      g_object_unref (connectable);
-    }
-  else
-    connection = NULL;
+  connectable = g_network_address_new (host, port);
+  connection = g_tcp_client_connect (client, connectable,
+				     cancellable, error);
+  g_object_unref (connectable);
 
   return connection;
 }
@@ -456,7 +192,7 @@ g_tcp_client_connect_to_host (GTcpClient    *client,
  * g_tcp_client_connect_to_host_async:
  * @client: a #GTcpClient
  * @host: the name of the host to connect to
- * @default_port: the default port to connect to
+ * @port: the port to connect to
  * @cancellable: a #GCancellable, or %NULL
  * @callback: a #GAsyncReadyCallback
  * @user_data: user data for the callback
@@ -466,27 +202,16 @@ g_tcp_client_connect_to_host (GTcpClient    *client,
 void
 g_tcp_client_connect_to_host_async (GTcpClient          *client,
                                     const gchar         *host,
-                                    const gchar         *default_port,
+				    int                  port,
                                     GCancellable        *cancellable,
                                     GAsyncReadyCallback  callback,
                                     gpointer             user_data)
 {
   GSocketConnectable *connectable;
-  GError *error = NULL;
 
   g_return_if_fail (G_IS_TCP_CLIENT (client));
 
-  connectable = g_tcp_client_get_connectable (host, default_port, &error);
-
-  if (!connectable)
-    {
-      g_simple_async_report_gerror_in_idle (G_OBJECT (client), callback,
-                                            user_data, error);
-      g_error_free (error);
-
-      return;
-    }
-
+  connectable = g_network_address_new (host, port);
   g_tcp_client_connect_async (client,
                               connectable, cancellable,
                               callback, user_data);
@@ -548,15 +273,9 @@ g_tcp_client_connect_to_service (GTcpClient    *client,
   g_return_val_if_fail (G_IS_TCP_CLIENT (client), NULL);
 
   connectable = g_network_service_new (service, "tcp", domain);
-
-  if (connectable)
-    {
-      connection = g_tcp_client_connect (client, connectable,
-                                         cancellable, error);
-      g_object_unref (connectable);
-    }
-  else
-    connection = NULL;
+  connection = g_tcp_client_connect (client, connectable,
+				     cancellable, error);
+  g_object_unref (connectable);
 
   return connection;
 }
@@ -582,21 +301,10 @@ g_tcp_client_connect_to_service_async (GTcpClient          *client,
                                        gpointer             user_data)
 {
   GSocketConnectable *connectable;
-  GError *error = NULL;
 
   g_return_if_fail (G_IS_TCP_CLIENT (client));
 
   connectable = g_network_service_new (service, "tcp", domain);
-
-  if (!connectable)
-    {
-      g_simple_async_report_gerror_in_idle (G_OBJECT (client), callback,
-                                            user_data, error);
-      g_error_free (error);
-
-      return;
-    }
-
   g_tcp_client_connect_async (client,
                               connectable, cancellable,
                               callback, user_data);
diff --git a/gio/gtcpclient.h b/gio/gtcpclient.h
index cf23633..6e48453 100644
--- a/gio/gtcpclient.h
+++ b/gio/gtcpclient.h
@@ -73,12 +73,12 @@ GTcpConnection *        g_tcp_client_connect_finish                     (GTcpCli
 
 GTcpConnection *        g_tcp_client_connect_to_host                    (GTcpClient           *client,
                                                                          const gchar          *host,
-                                                                         const gchar          *default_port,
+                                                                         int                   port,
                                                                          GCancellable         *cancellable,
                                                                          GError              **error);
 void                    g_tcp_client_connect_to_host_async              (GTcpClient           *client,
                                                                          const gchar          *host,
-                                                                         const gchar          *default_port,
+                                                                         int                   port,
                                                                          GCancellable         *cancelalble,
                                                                          GAsyncReadyCallback   callback,
                                                                          gpointer              user_data);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]