loudmouth/lm-old-socket.c
changeset 476 08d36982e998
parent 475 001da49d7fd1
child 502 4b69fbfa8797
--- a/loudmouth/lm-old-socket.c	Fri Aug 01 16:31:23 2008 +0200
+++ b/loudmouth/lm-old-socket.c	Tue Aug 05 01:06:53 2008 +0200
@@ -121,10 +121,6 @@
 static gboolean     socket_buffered_write_cb  (GIOChannel     *source, 
 					       GIOCondition    condition,
 					       LmOldSocket       *socket);
-static gboolean     socket_parse_srv_response (unsigned char  *srv, 
-					       int             srv_len, 
-					       gchar         **out_server, 
-					       guint          *out_port);
 static void         socket_close_io_channel   (GIOChannel     *io_channel);
 static gboolean     old_socket_output_is_buffered    (LmOldSocket       *socket,
                                                       const gchar    *buffer,
@@ -151,6 +147,10 @@
 		g_string_free (socket->out_buf, TRUE);
 	}
 
+        if (socket->resolver) {
+                g_object_unref (socket->resolver);
+        }
+
 	g_free (socket);
 }
 
@@ -419,7 +419,9 @@
 	socket->fd = connect_data->fd;
 	socket->io_channel = connect_data->io_channel;
 
-	freeaddrinfo (connect_data->resolved_addrs);
+        g_object_unref (socket->resolver);
+        socket->resolver = NULL;
+
 	socket->connect_data = NULL;
 	g_free (connect_data);
 
@@ -473,7 +475,7 @@
 	
 	socket = lm_old_socket_ref (connect_data->socket);
 
-	connect_data->current_addr = connect_data->current_addr->ai_next;
+	connect_data->current_addr = lm_resolver_results_get_next (socket->resolver);
 	
 	if (socket->watch_connect) {
 		g_source_destroy (socket->watch_connect);
@@ -491,7 +493,10 @@
 		
 		 /* if the user callback called connection_close(), this is already freed */
 		if (socket->connect_data != NULL) {
-			freeaddrinfo (connect_data->resolved_addrs);
+			if (socket->resolver) {
+                                g_object_unref (socket->resolver);
+                        }
+
 			socket->connect_data = NULL;
 			g_free (connect_data);
 		}
@@ -748,68 +753,6 @@
 	return TRUE;
 }
 
-static gboolean
-socket_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
 socket_close_io_channel (GIOChannel *io_channel)
 {
@@ -825,208 +768,66 @@
 	_lm_sock_close (fd);
 }
 
-static void
-_lm_old_socket_create_phase1 (LmOldSocket *socket, unsigned char *srv_ans, int len);
-static void
-_lm_old_socket_create_phase2 (LmOldSocket *socket, struct addrinfo *ans);
-
-#ifdef HAVE_ASYNCNS
-#define PHASE_1 0
-#define PHASE_2 1
-
-static gboolean
-_lm_old_socket_resolver_done (GSource *source,
-                              GIOCondition condition,
-                              gpointer data);
-
-
+/* FIXME: Need to have a way to only get srv reply and then decide if the 
+ *        resolver should continue to look the host up. 
+ *
+ *        This is needed for the case when we do a SRV lookup to lookup the 
+ *        real host of the service and then connect to it through a proxy.
+ */
 static void
-old_socket_asyncns_done (LmOldSocket *socket)
-{
-	if (socket->resolv_channel != NULL) {
-		g_io_channel_unref (socket->resolv_channel);
-		socket->resolv_channel = NULL;
-	}
- 
-	if (socket->watch_resolv) {
-		g_source_destroy(socket->watch_resolv);
-		socket->watch_resolv = NULL;
-	}
-
-	if (socket->asyncns_ctx) {
-		asyncns_free (socket->asyncns_ctx);
-		socket->asyncns_ctx = NULL;
-	}
-
- 	socket->resolv_query = NULL;
-}
-
-static gboolean
-old_socket_asyncns_prep (LmOldSocket *socket, GError **error)
+old_socket_resolver_srv_cb (LmResolver       *resolver,
+                            LmResolverResult  result,
+                            gpointer          user_data)
 {
-	if (socket->asyncns_ctx) {
-		return TRUE;
-	}
-
-	socket->asyncns_ctx = asyncns_new (1);
-	if (socket->asyncns_ctx == NULL) {
-		g_set_error (error,
-				LM_ERROR,                 
-				LM_ERROR_CONNECTION_FAILED,   
-				"can't initialise libasyncns");
-		return FALSE;
-	}
-
-	socket->resolv_channel =
-		g_io_channel_unix_new (asyncns_fd (socket->asyncns_ctx));
+        LmOldSocket *socket = (LmOldSocket *) user_data;
+        const gchar *remote_addr;
 
-	socket->watch_resolv = 
-		lm_misc_add_io_watch (socket->context,
-				      socket->resolv_channel,
-				      G_IO_IN,
-				      (GIOFunc) _lm_old_socket_resolver_done,
-				      socket);
-
-	return TRUE;
-}
+        if (result != LM_RESOLVER_RESULT_OK) {
+		lm_verbose ("SRV lookup failed, trying jid domain\n");
+                socket->server = g_strdup (socket->domain);
+        } else {
+                g_object_get (resolver, "host", &socket->server, NULL);
+                g_object_get (resolver, "port", &socket->port, NULL);
+        }
 
-static gboolean
-_lm_old_socket_resolver_done (GSource *source,
-                              GIOCondition condition,
-                              gpointer data)
-{
-	LmOldSocket	*socket = lm_old_socket_ref ((LmOldSocket *) data);
-	struct addrinfo	*ans;
-	unsigned char   *srv_ans;
-	int 		 err;
-	gboolean         result = FALSE;
-
-	/* process pending data */
-	asyncns_wait (socket->asyncns_ctx, FALSE);
-
-	if (!asyncns_isdone (socket->asyncns_ctx, socket->resolv_query)) {
-		result = TRUE;
+        if (socket->proxy) {
+                remote_addr = lm_proxy_get_server (socket->proxy);
 	} else {
-		switch ((guint) asyncns_getuserdata (socket->asyncns_ctx, socket->resolv_query)) {
-		case PHASE_1:
-			err = asyncns_res_done (socket->asyncns_ctx, socket->resolv_query, &srv_ans);
-			socket->resolv_query = NULL;
-			_lm_old_socket_create_phase1 (socket, (err <= 0) ? NULL : srv_ans, err);
-			result = TRUE;
-			break;
-		case PHASE_2:
-			err = asyncns_getaddrinfo_done (socket->asyncns_ctx, socket->resolv_query, &ans);
-			socket->resolv_query = NULL;
-			_lm_old_socket_create_phase2 (socket, (err) ? NULL : ans);
-			old_socket_asyncns_done (socket);
-			break;
-		default:
-                        g_assert_not_reached();
-			break;
-		}
+                remote_addr = socket->server;
 	}
-
-	lm_old_socket_unref(socket);
-	
-	return result;
-}
-
-#endif
-
-static void
-_lm_old_socket_create_phase1 (LmOldSocket *socket,
-                              unsigned char *srv_ans,
-                              int len)
-{
-	const char          *remote_addr;
-	LmConnectData       *data;
-	struct addrinfo      req;
-#ifndef HAVE_ASYNCNS
-	struct addrinfo *ans;
-	int              err;
-#endif
+       
+        g_object_set (resolver, 
+                      "host", remote_addr, 
+                      "type", LM_RESOLVER_HOST,
+                      NULL);
 
-	if (srv_ans != NULL) {
-		gchar    *new_server;
-		guint     new_port;
-		gboolean  result;
-		result = socket_parse_srv_response (srv_ans, len, 
-						    &new_server, 
-						    &new_port);
-		if (result == TRUE) {
-			g_free (socket->server);
-			socket->server = new_server;
-			socket->port = new_port;
-		}
-	}
-
-	/* If server wasn't specified and SRV failed, use domain */
-	if (!socket->server) {
-		lm_verbose ("SRV lookup failed, trying jid domain\n");
-		socket->server = g_strdup (socket->domain);
-	}
-
-	if (socket->proxy) {
-		remote_addr = lm_proxy_get_server (socket->proxy);
-	} else {
-		remote_addr = socket->server;
-	}
-
-	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
-	       "Going to connect to %s%s:%u\n", (socket->proxy) ? "proxy " : "",
-	       remote_addr, socket->port);
-
-	data = g_new0 (LmConnectData, 1);
-
-	data->socket        = socket;
-	data->connection    = socket->connection;
-	data->fd            = -1;
-	socket->connect_data = data;
-
-	memset (&req, 0, sizeof(req));
-	req.ai_family   = AF_UNSPEC;
-	req.ai_socktype = SOCK_STREAM;
-	req.ai_protocol = IPPROTO_TCP;
-
-#ifdef HAVE_ASYNCNS
-	if (!old_socket_asyncns_prep (socket, NULL))
-		return;
-
-	socket->resolv_query =
-	  	asyncns_getaddrinfo (socket->asyncns_ctx,
-		    		     remote_addr,
-				     NULL,
-				     &req);
-
-	asyncns_setuserdata (socket->asyncns_ctx,
-			     socket->resolv_query,
-			     (gpointer) PHASE_2);
-#else
-	err = getaddrinfo (remote_addr, NULL, &req, &ans);
-	_lm_old_socket_create_phase2 (socket, (err) ? NULL : ans);
-	if (err != 0) {
-		return;
-	}
-#endif
+        lm_resolver_lookup (resolver);
 }
 
 static void
-_lm_old_socket_create_phase2 (LmOldSocket *socket, struct addrinfo *ans)
+old_socket_resolver_host_cb (LmResolver       *resolver,
+                             LmResolverResult  result,
+                             gpointer          user_data)
 {
-	if (ans == NULL) {
-		lm_verbose ("error while resolving, bailing out\n");
+        LmOldSocket *socket = (LmOldSocket *) user_data;
+
+        if (result != LM_RESOLVER_RESULT_OK) {
+           	lm_verbose ("error while resolving, bailing out\n");
 		if (socket->connect_func) {
 			(socket->connect_func) (socket, FALSE, socket->user_data);
 		}
+                g_object_unref (socket->resolver);
+                socket->resolver = NULL;
 		g_free (socket->connect_data);
 		socket->connect_data = NULL;
-		return;
-	}
 
-	socket->connect_data->resolved_addrs = ans;
-	socket->connect_data->current_addr   = ans;
+                return;
+        }
+        
+        socket->connect_data->current_addr = 
+                lm_resolver_results_get_next (resolver);
 
-	socket_do_connect (socket->connect_data);
+        socket_do_connect (socket->connect_data);
 }
 
 LmOldSocket *
@@ -1044,13 +845,8 @@
                       LmProxy           *proxy,
                       GError           **error)
 {
-	LmOldSocket        *socket;
+        LmOldSocket  *socket;
 
-#ifndef HAVE_ASYNCNS
-	unsigned char    srv_ans[SRV_LEN];
-	int              len;
-#endif
-	
 	g_return_val_if_fail (domain != NULL, NULL);
 	g_return_val_if_fail ((port >= LM_MIN_PORT && port <= LM_MAX_PORT), NULL);
 	g_return_val_if_fail (data_func != NULL, NULL);
@@ -1080,30 +876,30 @@
 	}
 
 	if (!server) {
-		char          *srv;
-		srv = g_strdup_printf ("_xmpp-client._tcp.%s", socket->domain);
-		lm_verbose ("Performing a SRV lookup for %s\n", srv);
+                socket->resolver = lm_resolver_new_for_service (socket->domain,
+                                                                "xmpp-client",
+                                                                "tcp",
+                                                                old_socket_resolver_srv_cb, 
+                                                                socket);
+        } else {
+                socket->resolver = 
+                        lm_resolver_new_for_host (socket->server ? socket->server : socket->domain,
+                                                  old_socket_resolver_host_cb,
+                                                  socket);
+        }
 
-#ifdef HAVE_ASYNCNS
-		if (!old_socket_asyncns_prep (socket, error)) {
-                        return NULL;
-                }
-		
-		socket->resolv_query =
-			asyncns_res_query (socket->asyncns_ctx, srv, C_IN, T_SRV);
-		asyncns_setuserdata (socket->asyncns_ctx, socket->resolv_query, (gpointer) PHASE_1);
-#else
-		res_init ();
+        if (socket->context) {
+                g_object_set (socket->resolver, "context", context, NULL);
+        }
 
-		len = res_query (srv, C_IN, T_SRV, srv_ans, SRV_LEN);
-		_lm_old_socket_create_phase1 (socket, (len < 1) ? NULL : srv_ans, len);
-		g_free (srv);
-#endif
-	} else {
-		lm_verbose ("SRV lookup disabled for %s\n", socket->server);
-		_lm_old_socket_create_phase1 (socket, NULL, 0);
-	}
+	socket->data_func = data_func;
+	socket->closed_func = closed_func;
+	socket->connect_func = connect_func;
+	socket->user_data = user_data; 
+        
+        lm_resolver_lookup (socket->resolver);
 
+#if 0
 	if (socket->connect_data == NULL) {
 		/* Open failed synchronously, probably a DNS lookup problem */
 		lm_old_socket_unref(socket);
@@ -1116,16 +912,7 @@
 		return NULL;
 	}
 		
-
-	/* If the connection fails synchronously, we don't want to call the
-	 * connect_func to indicate an error, we return an error indication
-	 * instead. So, we delay saving the functions until after we know
-	 * we are going to return success.
-	 */
-	socket->data_func = data_func;
-	socket->closed_func = closed_func;
-	socket->connect_func = connect_func;
-	socket->user_data = user_data;
+#endif 
 	
 	return socket;
 }
@@ -1153,11 +940,15 @@
 	
 	data = socket->connect_data;
 	if (data) {
-		freeaddrinfo (data->resolved_addrs);
 		socket->connect_data = NULL;
 		g_free (data);
 	}
 
+        if (socket->resolver) {
+                g_object_unref (socket->resolver);
+                socket->resolver = NULL;
+        }
+
 	if (socket->io_channel) {
 		if (socket->watch_in) {
 			g_source_destroy (socket->watch_in);
@@ -1231,19 +1022,11 @@
 void
 lm_old_socket_asyncns_cancel (LmOldSocket *socket)
 {
-#ifdef HAVE_ASYNCNS
-        if (socket == NULL)
-		return;
+        if (!socket->resolver) {
+                return;
+        }
 
-	if (socket->asyncns_ctx) {
-                if (socket->resolv_query)
-                        asyncns_cancel (socket->asyncns_ctx, socket->resolv_query);
-
-                old_socket_asyncns_done (socket);
-	}
-#else
-        return;
-#endif /* HAVE_ASYNCNS */
+        lm_resolver_cancel (socket->resolver);
 }
 
 gboolean