changeset 8629:fdff0f31002d

[gaim-migrate @ 9381] Rendezvous updates: Advertise txt stuff for Gaim; just a step toward having Gaim users show up in iChat rendezvous buddy lists. Also a fix to make away people show up as away and available people to not show up as away. No one should be using this yet. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sun, 11 Apr 2004 03:27:11 +0000
parents 54baaec95c05
children ff2c1e946a5c
files src/protocols/rendezvous/mdns.c src/protocols/rendezvous/mdns.h src/protocols/rendezvous/rendezvous.c
diffstat 3 files changed, 138 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/rendezvous/mdns.c	Sat Apr 10 20:55:58 2004 +0000
+++ b/src/protocols/rendezvous/mdns.c	Sun Apr 11 03:27:11 2004 +0000
@@ -135,6 +135,23 @@
 /***************************************/
 
 static int
+mdns_getlength_RR_txt(void *rdata)
+{
+	GSList *cur;
+	ResourceRecordTXTRDataNode *node;
+	int rdlength = 0;
+
+	for (cur = (GSList *)rdata; cur != NULL; cur = cur->next) {
+		node = (ResourceRecordTXTRDataNode *)cur->data;
+		rdlength += 1 + strlen(node->name);
+		if (node->value != NULL)
+			rdlength += 1 + strlen(node->value);
+	}
+
+	return rdlength;
+}
+
+static int
 mdns_getlength_RR(const ResourceRecord *rr)
 {
 	int ret = 0;
@@ -146,6 +163,10 @@
 		case RENDEZVOUS_RRTYPE_PTR:
 			ret += strlen((const char *)rr->rdata) + 2;
 		break;
+
+		case RENDEZVOUS_RRTYPE_TXT:
+			ret += mdns_getlength_RR_txt(rr->rdata);
+		break;
 	}
 
 	return ret;
@@ -180,12 +201,36 @@
 	i += util_put16(&data[offset + i], rr->type);
 	i += util_put16(&data[offset + i], rr->class);
 	i += util_put32(&data[offset + i], rr->ttl);
-	i += util_put16(&data[offset + i], rr->rdlength);
 
 	switch (rr->type) {
 		case RENDEZVOUS_RRTYPE_PTR:
+			i += util_put16(&data[offset + i], strlen((const char *)rr->rdata) + 2);
 			i += mdns_put_name(data, datalen, offset + i, (const char *)rr->rdata);
 		break;
+
+		case RENDEZVOUS_RRTYPE_TXT: {
+			GSList *cur;
+			ResourceRecordTXTRDataNode *node;
+			int rdlength = mdns_getlength_RR_txt(rr->rdata);
+			int mylength;
+
+			i += util_put16(&data[offset + i], rdlength);
+			for (cur = (GSList *)rr->rdata; cur != NULL; cur = cur->next) {
+				node = (ResourceRecordTXTRDataNode *)cur->data;
+				mylength = 1 + strlen(node->name);
+				if (node->value)
+					mylength += 1 + strlen(node->value);
+				i += util_put8(&data[offset + i], mylength - 1);
+				memcpy(&data[offset + i], node->name, strlen(node->name));
+				i += strlen(node->name);
+				if (node->value) {
+					data[offset + i] = '=';
+					i++;
+					memcpy(&data[offset + i], node->value, strlen(node->value));
+					i += strlen(node->value);
+				}
+			}
+		} break;
 	}
 
 	return i;
@@ -314,7 +359,7 @@
 	dns->answers[0].type = RENDEZVOUS_RRTYPE_PTR;
 	dns->answers[0].class = 0x0001;
 	dns->answers[0].ttl = 0x00001c20;
-	dns->answers[0].rdlength = strlen(domain) + 2;
+	dns->answers[0].rdlength = 0x0000; /* Set automatically */
 	dns->answers[0].rdata = (void *)g_strdup(domain);
 
 	dns->authority = NULL;
@@ -327,6 +372,46 @@
 	return ret;
 }
 
+int
+mdns_advertise_txt(int fd, const char *name, const GSList *rdata)
+{
+	int ret;
+	DNSPacket *dns;
+
+	if ((strlen(name) > 255)) {
+		return -EINVAL;
+	}
+
+	dns = (DNSPacket *)g_malloc(sizeof(DNSPacket));
+	dns->header.id = 0x0000;
+	dns->header.flags = 0x8400;
+	dns->header.numquestions = 0x0000;
+	dns->header.numanswers = 0x0001;
+	dns->header.numauthority = 0x0000;
+	dns->header.numadditional = 0x0000;
+	dns->questions = NULL;
+
+	dns->answers = (ResourceRecord *)g_malloc(1 * sizeof(ResourceRecord));
+	dns->answers[0].name = g_strdup(name);
+	dns->answers[0].type = RENDEZVOUS_RRTYPE_TXT;
+	dns->answers[0].class = 0x0001;
+	dns->answers[0].ttl = 0x00001c20;
+	dns->answers[0].rdlength = 0x0000; /* Set automatically */
+	dns->answers[0].rdata = (void *)rdata;
+
+	dns->authority = NULL;
+	dns->additional = NULL;
+
+	mdns_send_dns(fd, dns);
+
+	/* The hash table should be freed by the caller of this function */
+	dns->answers[0].rdata = NULL;
+
+	mdns_free(dns);
+
+	return ret;
+}
+
 /***************************************/
 /* Functions for parsing mDNS messages */
 /***************************************/
--- a/src/protocols/rendezvous/mdns.h	Sat Apr 10 20:55:58 2004 +0000
+++ b/src/protocols/rendezvous/mdns.h	Sun Apr 11 03:27:11 2004 +0000
@@ -89,6 +89,13 @@
 	void *rdata;
 } ResourceRecord;
 
+typedef struct _ResourceRecordTXTRDataNode {
+	char *name;
+	char *value;
+} ResourceRecordTXTRDataNode;
+
+typedef GSList ResourceRecordTXTRData;
+
 typedef GHashTable ResourceRecordTXT;
 
 typedef struct _ResourceRecordSRV {
@@ -146,6 +153,7 @@
 int mdns_query(int fd, const char *domain);
 
 int mdns_advertise_ptr(int fd, const char *name, const char *domain);
+int mdns_advertise_txt(int fd, const char *name, const GSList *txt);
 
 /**
  * Read a UDP packet from the given file descriptor and parse it
--- a/src/protocols/rendezvous/rendezvous.c	Sat Apr 10 20:55:58 2004 +0000
+++ b/src/protocols/rendezvous/rendezvous.c	Sun Apr 11 03:27:11 2004 +0000
@@ -36,6 +36,7 @@
 typedef struct _RendezvousData {
 	int fd;
 	GHashTable *buddies;
+	GSList *mytxtdata;
 } RendezvousData;
 
 typedef struct _RendezvousBuddy {
@@ -224,7 +225,7 @@
 
 	tmp1 = g_hash_table_lookup(rdata, "status");
 	if (tmp1 != NULL) {
-		if (!strcmp(tmp1, "dnd")) {
+		if (!strcmp(tmp1, "avail")) {
 			/* Available */
 			rb->status = 0;
 		} else if (!strcmp(tmp1, "away")) {
@@ -233,7 +234,7 @@
 			rb->idle = atoi(tmp2);
 			gaim_debug_error("XXX", "User has been idle since %d\n", rb->idle);
 			rb->status = UC_IDLE;
-		} else if (!strcmp(tmp1, "avail")) {
+		} else if (!strcmp(tmp1, "dnd")) {
 			/* Away */
 			rb->status = UC_UNAVAILABLE;
 		}
@@ -405,6 +406,36 @@
 	mdns_free(dns);
 }
 
+static void rendezvous_add_to_txt(RendezvousData *rd, const char *name, const char *value)
+{
+	ResourceRecordTXTRDataNode *node;
+	node = g_malloc(sizeof(ResourceRecordTXTRDataNode));
+	node->name = g_strdup(name);
+	node->value = value != NULL ? g_strdup(value) : NULL;
+	rd->mytxtdata = g_slist_append(rd->mytxtdata, node);
+}
+
+static void rendezvous_send_online(GaimConnection *gc)
+{
+	RendezvousData *rd = gc->proto_data;
+	GaimAccount *account = gaim_connection_get_account(gc);
+
+	mdns_advertise_ptr(rd->fd, "_presence._tcp.local", "mark@diverge._presence._tcp.local");
+
+	rendezvous_add_to_txt(rd, "txtvers", "1");
+	rendezvous_add_to_txt(rd, "status", "avail");
+	rendezvous_add_to_txt(rd, "1st", gaim_account_get_string(account, "first", "Gaim"));
+	rendezvous_add_to_txt(rd, "AIM", "markdoliner");
+	rendezvous_add_to_txt(rd, "version", "1");
+	rendezvous_add_to_txt(rd, "port.p2pj", "5298");
+	rendezvous_add_to_txt(rd, "last", gaim_account_get_string(account, "last", _("User")));
+	mdns_advertise_txt(rd->fd, "mark@diverge._presence._tcp.local", rd->mytxtdata);
+
+#if 0
+	mdns_advertise_srv(rd->fd, "mark@diverge._presence._tcp.local", port 5298, IP?);
+#endif
+}
+
 static void rendezvous_prpl_login(GaimAccount *account)
 {
 	GaimConnection *gc = gaim_account_get_connection(account);
@@ -428,24 +459,13 @@
 	gaim_connection_set_state(gc, GAIM_CONNECTED);
 
 	mdns_query(rd->fd, "_presence._tcp.local");
-	/* mdns_advertise_ptr(rd->fd, "_presence._tcp.local", "mark@diverge._presence._tcp.local"); */
-
-#if 0
-	text_record_add("txtvers", "1");
-	text_record_add("status", "avail");
-	text_record_add("1st", gaim_account_get_string(account, "first", "Gaim"));
-	text_record_add("AIM", "markdoliner");
-	text_record_add("version", "1");
-	text_record_add("port.p2pj", "5298");
-	text_record_add("last", gaim_account_get_string(account, "last", _("User")));
-
-	publish(account->username, "_presence._tcp", 5298);
-#endif
+	rendezvous_send_online(gc);
 }
 
 static void rendezvous_prpl_close(GaimConnection *gc)
 {
 	RendezvousData *rd = (RendezvousData *)gc->proto_data;
+	ResourceRecordTXTRDataNode *node;
 
 	if (gc->inpa)
 		gaim_input_remove(gc->inpa);
@@ -460,6 +480,14 @@
 
 	g_hash_table_destroy(rd->buddies);
 
+	while (rd->mytxtdata != NULL) {
+		node = rd->mytxtdata->data;
+		rd->mytxtdata = g_slist_remove(rd->mytxtdata, node);
+		g_free(node->name);
+		g_free(node->value);
+		g_free(node);
+	}
+
 	g_free(rd);
 }