Moved MIN_PORT and MAX_PORT to lm-internals.h and renamed them.
authorMikael Hallendal <micke@imendio.com>
Thu, 17 Jul 2008 00:07:42 +0200
changeset 463 158aebfa7b7c
parent 462 11f85004aa32
child 464 e4e3b9afd58a
Moved MIN_PORT and MAX_PORT to lm-internals.h and renamed them. Now call the LM_MIN_PORT and LM_MAX_PORT to make it clear they are defined inside of Loudmouth. Also more work on the DNS cleanups.
loudmouth/lm-blocking-resolver.c
loudmouth/lm-internals.h
loudmouth/lm-old-socket.c
loudmouth/lm-resolver.c
--- a/loudmouth/lm-blocking-resolver.c	Mon Jul 14 23:53:27 2008 +0200
+++ b/loudmouth/lm-blocking-resolver.c	Thu Jul 17 00:07:42 2008 +0200
@@ -20,11 +20,25 @@
 
 #include <config.h>
 
+#include <string.h>
+#include <sys/types.h>
+#include <netdb.h>
+
+/* Needed on Mac OS X */
+#if HAVE_ARPA_NAMESER_COMPAT_H
+#include <arpa/nameser_compat.h>
+#endif
+
+#include <arpa/nameser.h>
+#include <resolv.h>
+
 #include "lm-marshal.h"
 #include "lm-misc.h"
 
 #include "lm-blocking-resolver.h"
 
+#define SRV_LEN 8192
+
 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), LM_TYPE_BLOCKING_RESOLVER, LmBlockingResolverPriv))
 
 typedef struct LmBlockingResolverPriv LmBlockingResolverPriv;
@@ -77,15 +91,101 @@
 static void
 blocking_resolver_lookup_host (LmBlockingResolver *resolver)
 {
-        gchar *host;
+        gchar           *host;
+        struct addrinfo  req;
+        struct addrinfo *ans;
+        int              err;
 
         g_object_get (resolver, "host", &host, NULL);
 
         /* Lookup */
 
+	memset (&req, 0, sizeof(req));
+	req.ai_family   = AF_UNSPEC;
+	req.ai_socktype = SOCK_STREAM;
+	req.ai_protocol = IPPROTO_TCP;
+
+        err = getaddrinfo (host, NULL, &req, &ans);
+
+	if (err != 0) {
+                /* FIXME: Report error */
+		return;
+	}
+
+        if (ans == NULL) {
+                /* Couldn't find any results */
+                /* FIXME: Report no results  */
+        }
+
+        /* FIXME: How to set and iterate the results */
+        /*priv->results    = ans;
+        priv->cur_result = ans; */
+
         g_free (host);
 }
 
+static gboolean
+blocking_resolver_parse_srv_response (unsigned char  *srv, 
+                                      int             srv_len, 
+                                      gchar         **out_server, 
+                                      guint          *out_port)
+{
+	int                  qdcount;
+	int                  ancount;
+	int                  len;
+	const unsigned char *pos;
+	unsigned char       *end;
+	HEADER              *head;
+	char                 name[256];
+	char                 pref_name[256];
+	guint                pref_port = 0;
+	guint                pref_prio = 9999;
+
+	pref_name[0] = 0;
+
+	pos = srv + sizeof (HEADER);
+	end = srv + srv_len;
+	head = (HEADER *) srv;
+
+	qdcount = ntohs (head->qdcount);
+	ancount = ntohs (head->ancount);
+
+	/* Ignore the questions */
+	while (qdcount-- > 0 && (len = dn_expand (srv, end, pos, name, 255)) >= 0) {
+		g_assert (len >= 0);
+		pos += len + QFIXEDSZ;
+	}
+
+	/* Parse the answers */
+	while (ancount-- > 0 && (len = dn_expand (srv, end, pos, name, 255)) >= 0) {
+		/* Ignore the initial string */
+		uint16_t pref, weight, port;
+
+		g_assert (len >= 0);
+		pos += len;
+		/* Ignore type, ttl, class and dlen */
+		pos += 10;
+		GETSHORT (pref, pos);
+		GETSHORT (weight, pos);
+		GETSHORT (port, pos);
+
+		len = dn_expand (srv, end, pos, name, 255);
+		if (pref < pref_prio) {
+			pref_prio = pref;
+			strcpy (pref_name, name);
+			pref_port = port;
+		}
+		pos += len;
+	}
+
+	if (pref_name[0]) {
+		*out_server = g_strdup (pref_name);
+		*out_port = pref_port;
+		return TRUE;
+	} 
+	return FALSE;
+}
+
 static void
 blocking_resolver_lookup_service (LmBlockingResolver *resolver)
 {
@@ -93,6 +193,11 @@
         gchar *service;
         gchar *protocol;
         gchar *srv;
+        gchar *new_server = NULL;
+        guint  new_port = 0;
+        gboolean  result;
+	unsigned char    srv_ans[SRV_LEN];
+	int              len;
 
         g_object_get (resolver,
                       "domain", &domain,
@@ -102,8 +207,24 @@
 
         srv = lm_resolver_create_srv_string (domain, service, protocol);
 
-        /* Lookup */
+        res_init ();
+
+        len = res_query (srv, C_IN, T_SRV, srv_ans, SRV_LEN);
 
+        result = blocking_resolver_parse_srv_response (srv_ans, len, 
+                                                       &new_server, &new_port);
+        if (result == FALSE) {
+                /* FIXME: Report error */
+        }
+
+        g_object_set (resolver, 
+                      "host", new_server,
+                      "port", new_port,
+                      NULL);
+
+        /* Lookup the new server and the new port */
+
+        g_free (new_server);
         g_free (srv);
         g_free (domain);
         g_free (service);
--- a/loudmouth/lm-internals.h	Mon Jul 14 23:53:27 2008 +0200
+++ b/loudmouth/lm-internals.h	Thu Jul 17 00:07:42 2008 +0200
@@ -34,6 +34,9 @@
 #include "lm-sock.h"
 #include "lm-old-socket.h"
 
+#define LM_MIN_PORT 1
+#define LM_MAX_PORT 65536
+
 #ifndef G_OS_WIN32
 typedef int LmOldSocketT;
 #else  /* G_OS_WIN32 */
--- a/loudmouth/lm-old-socket.c	Mon Jul 14 23:53:27 2008 +0200
+++ b/loudmouth/lm-old-socket.c	Thu Jul 17 00:07:42 2008 +0200
@@ -54,8 +54,6 @@
 #endif
 
 #define IN_BUFFER_SIZE 1024
-#define MIN_PORT 1
-#define MAX_PORT 65536
 #define SRV_LEN 8192
 
 struct _LmOldSocket {
@@ -1051,7 +1049,7 @@
 #endif
 	
 	g_return_val_if_fail (domain != NULL, NULL);
-	g_return_val_if_fail ((port >= MIN_PORT && port <= MAX_PORT), NULL);
+	g_return_val_if_fail ((port >= LM_MIN_PORT && port <= LM_MAX_PORT), NULL);
 	g_return_val_if_fail (data_func != NULL, NULL);
 	g_return_val_if_fail (closed_func != NULL, NULL);
 	g_return_val_if_fail (connect_func != NULL, NULL);
--- a/loudmouth/lm-resolver.c	Mon Jul 14 23:53:27 2008 +0200
+++ b/loudmouth/lm-resolver.c	Thu Jul 17 00:07:42 2008 +0200
@@ -20,6 +20,7 @@
 
 #include <config.h>
 
+#include "lm-internals.h"
 #include "lm-marshal.h"
 #include "lm-resolver.h"
 
@@ -35,6 +36,7 @@
         /* -- Properties -- */
         LmResolverType      type;
         gchar              *host;
+        guint               port;
 
         /* For SRV lookups */
         gchar              *domain;
@@ -59,6 +61,7 @@
         PROP_CONTEXT,
         PROP_TYPE,
         PROP_HOST,
+        PROP_PORT,
         PROP_DOMAIN,
         PROP_SERVICE,
         PROP_PROTOCOL
@@ -96,7 +99,17 @@
 							      "Host",
 							      "Host to lookup",
                                                               NULL,
-                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+                                                              G_PARAM_READWRITE));
+
+        g_object_class_install_property (object_class,
+                                         PROP_PORT,
+                                         g_param_spec_uint ("port",
+                                                            "Port",
+                                                            "Port number",
+                                                            0,
+                                                            LM_MIN_PORT,
+                                                            LM_MAX_PORT, 
+                                                            G_PARAM_READWRITE));
 
         g_object_class_install_property (object_class,
                                          PROP_DOMAIN,
@@ -172,6 +185,9 @@
         case PROP_HOST:
 		g_value_set_string (value, priv->host);
 		break;
+        case PROP_PORT:
+                g_value_set_uint (value, priv->port);
+                break;
 	case PROP_DOMAIN:
 		g_value_set_string (value, priv->domain);
 		break;
@@ -213,6 +229,9 @@
                 g_free (priv->host);
 		priv->host = g_value_dup_string (value);
 		break;
+        case PROP_PORT:
+                priv->port = g_value_get_uint (value);
+                break;
 	case PROP_DOMAIN:
                 g_free (priv->domain);
 		priv->domain = g_value_dup_string (value);