summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2009-05-08 19:01:38 (GMT)
committerAlexander Larsson <alexl@redhat.com>2009-05-08 19:11:48 (GMT)
commit55f5fa6eab407f3c4b2ebb285769429356bc8676 (patch)
treea8f57730f7d14e7a93533e278faa8c335a2980b7
parent73e9962366e8256227eb1da6d93fcb33f71de17c (diff)
downloadgnio-55f5fa6eab407f3c4b2ebb285769429356bc8676.tar.gz
gnio-55f5fa6eab407f3c4b2ebb285769429356bc8676.tar.xz
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
-rw-r--r--examples/client.c2
-rw-r--r--gio/gtcpclient.c318
-rw-r--r--gio/gtcpclient.h4
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);