changeset 8834:beb7be215db3

[gaim-migrate @ 9598] I removed account->ip because it isn't used anywhere and I think it's dumb. Also added handling for a and aaaa records to rendezvous. Gaim peeps show up in iChat rendezvous lists now. There are still problems. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Wed, 28 Apr 2004 00:48:21 +0000
parents 61fdef863ffa
children 7f38bf98e4e9
files plugins/tcl/tcl_cmds.c src/account.c src/account.h src/gtkprefs.c src/network.c src/network.h src/protocols/rendezvous/mdns.c src/protocols/rendezvous/mdns.h src/protocols/rendezvous/mdns_cache.c src/protocols/rendezvous/mdns_cache.h src/protocols/rendezvous/rendezvous.c
diffstat 11 files changed, 273 insertions(+), 129 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/tcl/tcl_cmds.c	Tue Apr 27 23:17:12 2004 +0000
+++ b/plugins/tcl/tcl_cmds.c	Wed Apr 28 00:48:21 2004 +0000
@@ -77,15 +77,15 @@
 {
 	Tcl_Obj *result = Tcl_GetObjResult(interp), *list, *elem;
 	char *cmds[] = { "alias", "connect", "connection", "disconnect", "find",
-			 "handle", "isconnected", "list", "public_ip",
+			 "handle", "isconnected", "list",
 			 "protocol", "username", NULL };
 	enum { CMD_ACCOUNT_ALIAS, CMD_ACCOUNT_CONNECT, CMD_ACCOUNT_CONNECTION,
 	       CMD_ACCOUNT_DISCONNECT, CMD_ACCOUNT_FIND, CMD_ACCOUNT_HANDLE,
-	       CMD_ACCOUNT_ISCONNECTED, CMD_ACCOUNT_LIST, CMD_ACCOUNT_PUBLIC_IP,
+	       CMD_ACCOUNT_ISCONNECTED, CMD_ACCOUNT_LIST,
 	       CMD_ACCOUNT_PROTOCOL, CMD_ACCOUNT_USERNAME } cmd;
 	char *listopts[] = { "-all", "-online", NULL };
 	enum { CMD_ACCOUNTLIST_ALL, CMD_ACCOUNTLIST_ONLINE } listopt;
-	const char *alias, *ip;
+	const char *alias;
 	GList *cur;
 	GaimAccount *account;
 	int error;
@@ -188,17 +188,6 @@
 		}
 		Tcl_SetObjResult(interp, list);
 		break;
-	case CMD_ACCOUNT_PUBLIC_IP:
-		if (objc != 3) {
-			Tcl_WrongNumArgs(interp, 2, objv, "account");
-			return TCL_ERROR;
-		}
-		error = Tcl_GetIntFromObj(interp, objv[2], (int *)&account);
-		if (error || !tcl_validate_account(account, interp))
-			return TCL_ERROR;
-		ip = gaim_account_get_public_ip(account);
-		Tcl_SetStringObj(result, ip != NULL ? (char *)ip : "", -1);
-		break;
 	case CMD_ACCOUNT_PROTOCOL:
 		if (objc != 3) {
 			Tcl_WrongNumArgs(interp, 2, objv, "account");
--- a/src/account.c	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/account.c	Wed Apr 28 00:48:21 2004 +0000
@@ -43,7 +43,6 @@
 	TAG_ALIAS,
 	TAG_USERINFO,
 	TAG_BUDDYICON,
-	TAG_PUBLIC_IP,
 	TAG_SETTING,
 	TAG_TYPE,
 	TAG_HOST,
@@ -509,19 +508,6 @@
 }
 
 void
-gaim_account_set_public_ip(GaimAccount *account, const char *ip)
-{
-	g_return_if_fail(account != NULL);
-
-	if (account->ip != NULL)
-		g_free(account->ip);
-
-	account->ip = (ip == NULL ? NULL : g_strdup(ip));
-
-	schedule_accounts_save();
-}
-
-void
 gaim_account_set_proxy_info(GaimAccount *account, GaimProxyInfo *info)
 {
 	g_return_if_fail(account != NULL);
@@ -786,14 +772,6 @@
 	return gaim_account_get_ui_bool(account, ui, "auto-login", FALSE);
 }
 
-const char *
-gaim_account_get_public_ip(const GaimAccount *account)
-{
-	g_return_val_if_fail(account != NULL, NULL);
-
-	return account->ip;
-}
-
 GaimProxyInfo *
 gaim_account_get_proxy_info(const GaimAccount *account)
 {
@@ -1005,8 +983,6 @@
 		data->tag = TAG_USERINFO;
 	else if (!strcmp(element_name, "buddyicon"))
 		data->tag = TAG_BUDDYICON;
-	else if (!strcmp(element_name, "public-ip"))
-		data->tag = TAG_PUBLIC_IP;
 	else if (!strcmp(element_name, "proxy")) {
 		data->in_proxy = TRUE;
 
@@ -1095,10 +1071,6 @@
 		if (*buffer != '\0')
 			gaim_account_set_buddy_icon(data->account, buffer);
 	}
-	else if (data->tag == TAG_PUBLIC_IP) {
-		if (*buffer != '\0')
-			gaim_account_set_public_ip(data->account, buffer);
-	}
 	else if (data->tag == TAG_TYPE) {
 		if (data->in_proxy) {
 			if (!strcmp(buffer, "global"))
@@ -1307,7 +1279,7 @@
 {
 	GaimProxyInfo *proxy_info;
 	GaimProxyType proxy_type;
-	const char *password, *alias, *user_info, *buddy_icon, *ip;
+	const char *password, *alias, *user_info, *buddy_icon;
 	char *esc;
 
 	fprintf(fp, " <account>\n");
@@ -1342,10 +1314,6 @@
 		g_free(esc);
 	}
 
-	if ((ip = gaim_account_get_public_ip(account)) != NULL) {
-		fprintf(fp, "  <public-ip>%s</public-ip>\n", ip);
-	}
-
 	fprintf(fp, "  <settings>\n");
 	g_hash_table_foreach(account->settings, write_setting, fp);
 	fprintf(fp, "  </settings>\n");
--- a/src/account.h	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/account.h	Wed Apr 28 00:48:21 2004 +0000
@@ -64,7 +64,6 @@
 	GHashTable *settings;       /**< Protocol-specific settings.          */
 	GHashTable *ui_settings;    /**< UI-specific settings.                */
 
-	char *ip;                   /**< The IP address for transfers.        */
 	GaimProxyInfo *proxy_info;  /**< Proxy information.  This will be set */
 								/*   to NULL when the account inherits    */
 								/*   proxy settings from global prefs.    */
@@ -251,15 +250,6 @@
 								 gboolean value);
 
 /**
- * Sets the public IP address the account will use for such things
- * as file transfer.
- *
- * @param account The account.
- * @param ip      The IP address.
- */
-void gaim_account_set_public_ip(GaimAccount *account, const char *ip);
-
-/**
  * Sets the account's proxy information.
  *
  * @param account The account.
@@ -448,15 +438,6 @@
 									 const char *ui);
 
 /**
- * Returns the account's public IP address.
- *
- * @param account The account.
- *
- * @return The IP address.
- */
-const char *gaim_account_get_public_ip(const GaimAccount *account);
-
-/**
  * Returns the account's proxy information.
  *
  * @param account The account.
--- a/src/gtkprefs.c	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/gtkprefs.c	Wed Apr 28 00:48:21 2004 +0000
@@ -1050,7 +1050,7 @@
 
 static void network_ip_changed(GtkEntry *entry, gpointer data)
 {
-	gaim_prefs_set_string("/core/network/public_ip", gtk_entry_get_text(entry));
+	gaim_network_set_public_ip(gtk_entry_get_text(entry));
 }
 
 GtkWidget *network_page() {
@@ -1083,9 +1083,9 @@
 	g_signal_connect(G_OBJECT(entry), "changed",
 					 G_CALLBACK(network_ip_changed), NULL);
 
-	if (gaim_network_get_local_ip() != NULL)
+	if (gaim_network_get_public_ip() != NULL)
 		gtk_entry_set_text(GTK_ENTRY(entry),
-		                   gaim_network_get_local_ip());
+		                   gaim_network_get_public_ip());
 
 	gaim_set_accessible_label (entry, label);
 
--- a/src/network.c	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/network.c	Wed Apr 28 00:48:21 2004 +0000
@@ -31,7 +31,7 @@
 #include "prefs.h"
 
 void
-gaim_network_set_local_ip(const char *ip)
+gaim_network_set_public_ip(const char *ip)
 {
 	g_return_if_fail(ip != NULL);
 
@@ -39,13 +39,10 @@
 }
 
 const char *
-gaim_network_get_local_ip(void)
+gaim_network_get_public_ip(void)
 {
 	const char *ip;
 
-	if (gaim_prefs_get_bool("/core/network/auto_ip"))
-		return NULL;
-
 	ip = gaim_prefs_get_string("/core/network/public_ip");
 
 	if (ip == NULL || *ip == '\0')
@@ -111,15 +108,21 @@
 const char *
 gaim_network_get_ip_for_account(const GaimAccount *account, int fd)
 {
-	if (account && (gaim_account_get_public_ip(account) != NULL))
-		return gaim_account_get_public_ip(account);
-	else if (gaim_network_get_local_ip() != NULL)
-		return gaim_network_get_local_ip();
-	else
-		return gaim_network_get_local_system_ip(fd);
+	const char *ip = NULL;
+
+	/* Check if the user specified an IP manually */
+	if (!gaim_prefs_get_bool("/core/network/auto_ip")) {
+		ip = gaim_network_get_public_ip();
+		if (ip != NULL)
+			return ip;
+	}
+
+	/* Just fetch the IP of the local system */
+	return gaim_network_get_local_system_ip(fd);
 }
 
-static int gaim_network_do_listen(unsigned short port)
+static int
+gaim_network_do_listen(unsigned short port)
 {
 #if HAVE_GETADDRINFO
 	int listenfd;
@@ -189,14 +192,16 @@
 	return listenfd;
 }
 
-int gaim_network_listen(unsigned short port)
+int
+gaim_network_listen(unsigned short port)
 {
 	g_return_val_if_fail(port != 0, -1);
 
 	return gaim_network_do_listen(port);
 }
 
-int gaim_network_listen_range(unsigned short start, unsigned short end)
+int
+gaim_network_listen_range(unsigned short start, unsigned short end)
 {
 	int ret = -1;
 
@@ -217,7 +222,8 @@
 	return ret;
 }
 
-short gaim_network_get_port_from_fd(int fd)
+unsigned short
+gaim_network_get_port_from_fd(int fd)
 {
 	struct sockaddr_in addr;
 	socklen_t len;
--- a/src/network.h	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/network.h	Wed Apr 28 00:48:21 2004 +0000
@@ -30,26 +30,29 @@
 #endif
 
 /**************************************************************************/
-/** @name Network API                                     */
+/** @name Network API                                                     */
 /**************************************************************************/
 /*@{*/
 
 /**
- * Sets the IP address of the local system in preferences.
+ * Sets the IP address of the local system in preferences.  This
+ * is the IP address that should be used for incoming connections
+ * (file transfer, direct IM, etc.) and should therefore be
+ * publicly accessible.
  *
  * @param ip The local IP address.
  */
-void gaim_network_set_local_ip(const char *ip);
+void gaim_network_set_public_ip(const char *ip);
 
 /**
  * Returns the IP address of the local system set in preferences.
  *
- * This returns the value set via gaim_network_set_local_ip().
+ * This returns the value set via gaim_network_set_public_ip().
  * You probably want to use gaim_network_get_ip_for_account() instead.
  *
  * @return The local IP address set in preferences.
  */
-const char *gaim_network_get_local_ip(void);
+const char *gaim_network_get_public_ip(void);
 
 /**
  * Returns the IP address of the local system.
@@ -66,15 +69,14 @@
 const char *gaim_network_get_local_system_ip(int fd);
 
 /**
- * Returns the IP address that should be used for the specified account.
- *
- * First, if @a account is not @c NULL, the IP associated with @a account
- * is tried, via a call to gaim_account_get_local_ip().
+ * Returns the IP address that should be used anywhere a
+ * public IP addresses is needed (listening for an incoming
+ * file transfer, etc).
  *
- * If that IP is not set, the IP set in preferences is tried.
- *
- * If that IP is not set, the system's local IP is tried, via a call to
- * gaim_network_get_local_ip().
+ * If the user has manually specified an IP address via
+ * preferences, then this IP is returned.  Otherwise the
+ * IP address returned by gaim_network_get_local_system_ip()
+ * is returned.
  *
  * @note The returned string is a pointer to a static buffer. If this
  *       function is called twice, it may be important to make a copy
@@ -140,7 +142,7 @@
  *           possible bug will inspire new and valuable contributors to Gaim.
  * @return The port number, in host byte order.
  */
-short gaim_network_get_port_from_fd(int fd);
+unsigned short gaim_network_get_port_from_fd(int fd);
 
 /**
  * Initializes the network subsystem.
--- a/src/protocols/rendezvous/mdns.c	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/protocols/rendezvous/mdns.c	Wed Apr 28 00:48:21 2004 +0000
@@ -89,8 +89,10 @@
 		return;
 
 	switch (type) {
+			case RENDEZVOUS_RRTYPE_A:
 			case RENDEZVOUS_RRTYPE_NULL:
 			case RENDEZVOUS_RRTYPE_PTR:
+			case RENDEZVOUS_RRTYPE_AAAA:
 				g_free(rdata);
 			break;
 
@@ -237,18 +239,26 @@
 		return NULL;
 
 	switch (type) {
+		case RENDEZVOUS_RRTYPE_A:
+			ret = g_memdup(rdata, rdlength);
+		break;
+
 		case RENDEZVOUS_RRTYPE_NULL:
 			ret = g_memdup(rdata, rdlength);
 		break;
 
 		case RENDEZVOUS_RRTYPE_PTR:
-			ret = g_memdup(rdata, rdlength);
+			ret = g_strdup(rdata);
 		break;
 
 		case RENDEZVOUS_RRTYPE_TXT:
 			ret = mdns_copy_rr_rdata_txt(rdata);
 		break;
 
+		case RENDEZVOUS_RRTYPE_AAAA:
+			ret = g_memdup(rdata, rdlength);
+		break;
+
 		case RENDEZVOUS_RRTYPE_SRV:
 			ret = mdns_copy_rr_rdata_srv(rdata);
 		break;
@@ -319,7 +329,7 @@
 /******************************************/
 
 int
-mdns_establish_socket()
+mdns_socket_establish()
 {
 	int fd = -1;
 	struct sockaddr_in addr;
@@ -381,6 +391,15 @@
 	return fd;
 }
 
+void
+mdns_socket_close(int fd)
+{
+	if (fd >= 0)
+		close(fd);
+
+	mdns_cache_remove_all();
+}
+
 /**
  * Multicast raw data over a file descriptor.
  *
@@ -457,6 +476,10 @@
 	int rdlength = 0;
 
 	switch (type) {
+		case RENDEZVOUS_RRTYPE_A:
+			rdlength = 4;
+		break;
+
 		case RENDEZVOUS_RRTYPE_PTR:
 			rdlength = mdns_getlength_name(rdata);
 		break;
@@ -473,6 +496,10 @@
 			}
 		} break;
 
+		case RENDEZVOUS_RRTYPE_AAAA:
+			rdlength = 16;
+		break;
+
 		case RENDEZVOUS_RRTYPE_SRV:
 			rdlength = 6 + mdns_getlength_name(((const ResourceRecordRDataSRV *)rdata)->target);
 		break;
@@ -580,6 +607,11 @@
 	i += util_put16(&data[offset + i], rr->rdlength);
 
 	switch (rr->type) {
+		case RENDEZVOUS_RRTYPE_A:
+			memcpy(&data[offset + i], rr->rdata, rr->rdlength);
+			i += rr->rdlength;
+		break;
+
 		case RENDEZVOUS_RRTYPE_NULL:
 			memcpy(&data[offset + i], rr->rdata, rr->rdlength);
 			i += rr->rdlength;
@@ -611,6 +643,11 @@
 			}
 		} break;
 
+		case RENDEZVOUS_RRTYPE_AAAA:
+			memcpy(&data[offset + i], rr->rdata, rr->rdlength);
+			i += rr->rdlength;
+		break;
+
 		case RENDEZVOUS_RRTYPE_SRV: {
 			ResourceRecordRDataSRV *srv = rr->rdata;
 			i += util_put16(&data[offset + i], 0);
@@ -735,6 +772,37 @@
 }
 
 int
+mdns_advertise_a(int fd, const char *name, unsigned char *ip)
+{
+	int ret;
+	ResourceRecord *rr;
+	ResourceRecordRDataA *rdata;
+	int i;
+
+	if ((name == NULL) || (strlen(name) > 255)) {
+		return -EINVAL;
+	}
+
+	rdata = g_malloc(4);
+	for (i = 0; i < 4; i++)
+		util_put8(&rdata[i], ip[i]);
+
+	rr = (ResourceRecord *)g_malloc(sizeof(ResourceRecord));
+	rr->name = g_strdup(name);
+	rr->type = RENDEZVOUS_RRTYPE_A;
+	rr->class = 0x0001;
+	rr->ttl = 0x000000f0;
+	rr->rdlength = 4;
+	rr->rdata = mdns_copy_rr_rdata(rr->type, rdata, rr->rdlength);
+
+	ret = mdns_send_rr(fd, rr);
+
+	mdns_free_rr(rr);
+
+	return ret;
+}
+
+int
 mdns_advertise_null(int fd, const char *name, const char *rdata, unsigned short rdlength)
 {
 	int ret;
@@ -810,6 +878,37 @@
 }
 
 int
+mdns_advertise_aaaa(int fd, const char *name, unsigned char *ip)
+{
+	int ret;
+	ResourceRecord *rr;
+	ResourceRecordRDataA *rdata;
+	int i;
+
+	if ((name == NULL) || (strlen(name) > 255)) {
+		return -EINVAL;
+	}
+
+	rdata = g_malloc(16);
+	for (i = 0; i < 16; i++)
+		util_put8(&rdata[i], ip[i]);
+
+	rr = (ResourceRecord *)g_malloc(sizeof(ResourceRecord));
+	rr->name = g_strdup(name);
+	rr->type = RENDEZVOUS_RRTYPE_A;
+	rr->class = 0x0001;
+	rr->ttl = 0x000000f0;
+	rr->rdlength = 16;
+	rr->rdata = mdns_copy_rr_rdata(rr->type, rdata, rr->rdlength);
+
+	ret = mdns_send_rr(fd, rr);
+
+	mdns_free_rr(rr);
+
+	return ret;
+}
+
+int
 mdns_advertise_srv(int fd, const char *name, unsigned short port, const char *target)
 {
 	int ret;
@@ -1194,7 +1293,14 @@
 	*offset += 2;
 
 	/* RDATA */
-	if (rr->type == RENDEZVOUS_RRTYPE_NULL) {
+	if (rr->type == RENDEZVOUS_RRTYPE_A) {
+		rr->rdata = mdns_read_rr_rdata_null(data, datalen, *offset, rr->rdlength);
+		if (rr->rdata == NULL) {
+			mdns_free_rr(rr);
+			return NULL;
+		}
+
+	} else if (rr->type == RENDEZVOUS_RRTYPE_NULL) {
 		rr->rdata = mdns_read_rr_rdata_null(data, datalen, *offset, rr->rdlength);
 		if (rr->rdata == NULL) {
 			mdns_free_rr(rr);
@@ -1215,6 +1321,13 @@
 			return NULL;
 		}
 
+	} else if (rr->type == RENDEZVOUS_RRTYPE_AAAA) {
+		rr->rdata = mdns_read_rr_rdata_null(data, datalen, *offset, rr->rdlength);
+		if (rr->rdata == NULL) {
+			mdns_free_rr(rr);
+			return NULL;
+		}
+
 	} else if (rr->type == RENDEZVOUS_RRTYPE_SRV) {
 		rr->rdata = mdns_read_rr_rdata_srv(data, datalen, *offset, rr->rdlength);
 		if (rr->rdata == NULL) {
@@ -1298,11 +1411,6 @@
 	/* For the flags, some bits must be 0 and some must be 1, the rest are ignored */
 	dns->header.flags = util_get16(&data[offset]); /* Flags (QR, OPCODE, AA, TC, RD, RA, Z, AD, CD, and RCODE */
 	offset += 2;
-	if ((dns->header.flags & 0x8000) == 0) {
-		/* QR should be 1 */
-		g_free(dns);
-		return NULL;
-	}
 	if ((dns->header.flags & 0x7800) != 0) {
 		/* OPCODE should be all 0's */
 		g_free(dns);
--- a/src/protocols/rendezvous/mdns.h	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/protocols/rendezvous/mdns.h	Wed Apr 28 00:48:21 2004 +0000
@@ -60,6 +60,7 @@
 #define RENDEZVOUS_RRTYPE_NULL	10
 #define RENDEZVOUS_RRTYPE_PTR	12
 #define RENDEZVOUS_RRTYPE_TXT	16
+#define RENDEZVOUS_RRTYPE_AAAA	28
 #define RENDEZVOUS_RRTYPE_SRV	33
 #define RENDEZVOUS_RRTYPE_ALL	255
 
@@ -90,6 +91,8 @@
 	void *rdata;
 } ResourceRecord;
 
+typedef unsigned char ResourceRecordRDataA;
+
 typedef struct _ResourceRecordRDataTXTNode {
 	char *name;
 	char *value;
@@ -97,6 +100,8 @@
 
 typedef GSList ResourceRecordRDataTXT;
 
+typedef unsigned char ResourceRecordRDataAAAA;
+
 typedef struct _ResourceRecordRDataSRV {
 	unsigned int priority;
 	unsigned int weight;
@@ -124,7 +129,16 @@
  * @return The file descriptor of the new socket, or -1 if
  *         there was an error establishing the socket.
  */
-int mdns_establish_socket();
+int mdns_socket_establish();
+
+
+/**
+ * Close a multicast socket.  This also clears the MDNS
+ * cache.
+ *
+ * @param The file descriptor of the multicast socket.
+ */
+void mdns_socket_close(int fd);
 
 
 /**
@@ -152,9 +166,11 @@
 int mdns_query(int fd, const char *domain, unsigned short type);
 
 int mdns_send_rr(int fd, ResourceRecord *rr);
+int mdns_advertise_a(int fd, const char *name, unsigned char *ip);
 int mdns_advertise_null(int fd, const char *name, const char *data, unsigned short rdlength);
 int mdns_advertise_ptr(int fd, const char *name, const char *domain);
 int mdns_advertise_txt(int fd, const char *name, const GSList *txt);
+int mdns_advertise_aaaa(int fd, const char *name, unsigned char *ip);
 int mdns_advertise_srv(int fd, const char *name, unsigned short port, const char *target);
 
 /**
--- a/src/protocols/rendezvous/mdns_cache.c	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/protocols/rendezvous/mdns_cache.c	Wed Apr 28 00:48:21 2004 +0000
@@ -27,29 +27,56 @@
 #include "debug.h"
 
 #include "mdns.h"
+#include "mdns_cache.h"
 
-/* XXX - Make sure this is freed when we sign off */
 GSList *rrs = NULL;
 
+static ResourceRecord *
+mdns_cache_find(gchar *name, unsigned short type)
+{
+	ResourceRecord *rr;
+	GSList *cur;
+
+	g_return_val_if_fail(name != NULL, NULL);
+	g_return_val_if_fail((type != 0) || (type != RENDEZVOUS_RRTYPE_ALL), NULL);
+
+	for (cur = rrs; cur != NULL; cur = cur->next) {
+		rr = cur->data;
+		if ((type == rr->type) && (!strcmp(name, rr->name)))
+			return rr;
+	}
+
+	return NULL;
+}
+
 void
 mdns_cache_add(const ResourceRecord *rr)
 {
 	ResourceRecord *new;
 
 	g_return_if_fail(rr != NULL);
+	g_return_if_fail((rr->type != 0) && (rr->type != RENDEZVOUS_RRTYPE_ALL));
 
+	mdns_cache_remove(rr->name, rr->type);
+
+	printf("caching %d\n", rr->type);
 	new = mdns_copy_rr(rr);
-
 	rrs = g_slist_prepend(rrs, new);
 }
 
 void
-mdns_cache_remove(ResourceRecord *rr)
+mdns_cache_remove(gchar *name, unsigned short type)
 {
-	g_return_if_fail(rr != NULL);
+	ResourceRecord *rr;
+
+	g_return_if_fail(name != NULL);
+	g_return_if_fail((type != 0) && (type != RENDEZVOUS_RRTYPE_ALL));
 
-	rrs = g_slist_remove_all(rrs, rr);
+	rr = mdns_cache_find(name, type);
+	if (rr == NULL)
+		return;
 
+	rrs = g_slist_remove(rrs, rr);
 	mdns_free_rr(rr);
 }
 
@@ -66,10 +93,13 @@
 	ResourceRecord *cur;
 
 	g_return_if_fail(q != NULL);
+	printf("query for q->type=%d, q->name=%s\n", q->type, q->name);
 
-	for (slist = rrs; slist != NULL; slist = g_slist_next(slist)) {
+	for (slist = rrs; slist != NULL; slist = slist->next) {
 		cur = slist->data;
-		if ((q->type == cur->type) && (!strcmp(q->name, cur->name)))
-			mdns_send_rr(fd, cur);
+		if ((q->type == cur->type) && (!strcmp(q->name, cur->name))) {
+			printf("responding to cur->type=%d, cur->name=%s\n", cur->type, cur->name);
+			//mdns_send_rr(fd, cur);
+		}
 	}
 }
--- a/src/protocols/rendezvous/mdns_cache.h	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/protocols/rendezvous/mdns_cache.h	Wed Apr 28 00:48:21 2004 +0000
@@ -39,7 +39,7 @@
 /**
  *
  */
-void mdns_cache_remove(ResourceRecord *rr);
+void mdns_cache_remove(gchar *name, unsigned short type);
 
 /**
  *
--- a/src/protocols/rendezvous/rendezvous.c	Tue Apr 27 23:17:12 2004 +0000
+++ b/src/protocols/rendezvous/rendezvous.c	Wed Apr 28 00:48:21 2004 +0000
@@ -26,6 +26,7 @@
 #include "blist.h"
 #include "conversation.h"
 #include "debug.h"
+#include "network.h"
 #include "prpl.h"
 
 #include "mdns.h"
@@ -45,6 +46,7 @@
 #endif
 	gchar *firstandlast;
 	gchar *aim;
+	int ip[4];
 	int p2pjport;
 	int status;
 	int idle;
@@ -179,6 +181,23 @@
 	}
 }
 
+static void rendezvous_handle_rr_a(GaimConnection *gc, ResourceRecord *rr, const gchar *name)
+{
+	RendezvousData *rd = gc->proto_data;
+	RendezvousBuddy *rb;
+	ResourceRecordRDataSRV *rdata;
+
+	rdata = rr->rdata;
+
+	rb = g_hash_table_lookup(rd->buddies, name);
+	if (rb == NULL) {
+		rb = g_malloc0(sizeof(RendezvousBuddy));
+		g_hash_table_insert(rd->buddies, g_strdup(name), rb);
+	}
+
+	memcpy(rb->ip, rdata, 4);
+}
+
 static void rendezvous_handle_rr_txt(GaimConnection *gc, ResourceRecord *rr, const gchar *name)
 {
 	RendezvousData *rd = gc->proto_data;
@@ -278,15 +297,18 @@
 
 	gaim_debug_misc("rendezvous", "Parsing resource record with domain name %s\n", rr->name);
 
-	/*
-	 * XXX - Cache resource records from this function, if needed.
-	 * Use the TTL value of the rr to cause this data to expire, but let
-	 * the mdns_cache stuff handle that as much as possible.
-	 */
+	switch (rr->type) {
+		case RENDEZVOUS_RRTYPE_A: {
+			name = rendezvous_extract_name(rr->name);
+			if (name != NULL) {
+				rendezvous_handle_rr_a(gc, rr, name);
+				g_free(name);
+			}
+		} break;
 
-	switch (rr->type) {
 		case RENDEZVOUS_RRTYPE_NULL: {
-			if ((name = rendezvous_extract_name(rr->name)) != NULL) {
+			name = rendezvous_extract_name(rr->name);
+			if (name != NULL) {
 				if (rr->rdlength > 0) {
 					/* Data is a buddy icon */
 					gaim_buddy_icons_set_for_user(gaim_connection_get_account(gc), name, rr->rdata, rr->rdlength);
@@ -298,7 +320,9 @@
 
 		case RENDEZVOUS_RRTYPE_PTR: {
 			gchar *rdata = rr->rdata;
-			if ((name = rendezvous_extract_name(rdata)) != NULL) {
+
+			name = rendezvous_extract_name(rdata);
+			if (name != NULL) {
 				if (rr->ttl > 0) {
 					/* Add them to our buddy list and request their icon */
 					rendezvous_addtolocal(gc, name, "Rendezvous");
@@ -312,14 +336,16 @@
 		} break;
 
 		case RENDEZVOUS_RRTYPE_TXT: {
-			if ((name = rendezvous_extract_name(rr->name)) != NULL) {
+			name = rendezvous_extract_name(rr->name);
+			if (name != NULL) {
 				rendezvous_handle_rr_txt(gc, rr, name);
 				g_free(name);
 			}
 		} break;
 
 		case RENDEZVOUS_RRTYPE_SRV: {
-			if ((name = rendezvous_extract_name(rr->name)) != NULL) {
+			name = rendezvous_extract_name(rr->name);
+			if (name != NULL) {
 				rendezvous_handle_rr_srv(gc, rr, name);
 				g_free(name);
 			}
@@ -455,17 +481,36 @@
 	g_free(rdata);
 }
 
+static int *rendezvous_get_ip_as_int_array(int fd)
+{
+	static int ret[4];
+	const char *ip, *nexttoken;
+	int i = 0;
+
+	ip = gaim_network_get_local_system_ip(fd);
+	nexttoken = strtok((char *)ip, ".");
+	while (nexttoken && i < 4) {
+		ret[i] = atoi(nexttoken);
+		nexttoken = strtok(NULL, ".");
+	}
+
+	return ret;
+}
+
 static void rendezvous_send_online(GaimConnection *gc)
 {
 	RendezvousData *rd = gc->proto_data;
 	GaimAccount *account = gaim_connection_get_account(gc);
 	const gchar *me;
 	gchar *myname, *mycomp;
+	unsigned char *myip;
 
 	me = gaim_account_get_username(account);
 	myname = g_strdup_printf("%s._presence._tcp.local", me);
 	mycomp = g_strdup_printf("%s.local", strchr(me, '@') + 1);
+	myip = rendezvous_get_ip_as_int_array(rd->fd);
 
+	mdns_advertise_a(rd->fd, mycomp, myip);
 	mdns_advertise_ptr(rd->fd, "_presence._tcp.local", myname);
 	mdns_advertise_srv(rd->fd, myname, 5298, mycomp);
 
@@ -511,7 +556,7 @@
 	rendezvous_removeallfromlocal(gc);
 
 	gaim_connection_update_progress(gc, _("Connecting"), 1, RENDEZVOUS_CONNECT_STEPS);
-	rd->fd = mdns_establish_socket();
+	rd->fd = mdns_socket_establish();
 	if (rd->fd == -1) {
 		gaim_connection_error(gc, _("Unable to login to rendezvous"));
 		return;
@@ -537,8 +582,7 @@
 	if (!rd)
 		return;
 
-	if (rd->fd >= 0)
-		close(rd->fd);
+	mdns_socket_close(rd->fd);
 
 	g_hash_table_destroy(rd->buddies);