changeset 8631:7b8f2818f38a

[gaim-migrate @ 9383] More rendezvous stuff. You still shouldn't be using this. I refactored a few of the mDNS sending functions and unhardcoded some of the username and hostname values. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sun, 11 Apr 2004 17:04:33 +0000
parents ff2c1e946a5c
children 127cd17ee215
files src/protocols/rendezvous/mdns.c src/protocols/rendezvous/mdns.h src/protocols/rendezvous/rendezvous.c
diffstat 3 files changed, 141 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/rendezvous/mdns.c	Sun Apr 11 16:09:06 2004 +0000
+++ b/src/protocols/rendezvous/mdns.c	Sun Apr 11 17:04:33 2004 +0000
@@ -76,7 +76,7 @@
 		return -1;
 	}
 
-	/* Ensure loopback is enabled (it should be enabled by default, by let's be sure) */
+	/* Ensure loopback is enabled (it should be enabled by default, but let's be sure) */
 	loop = 1;
 	if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(unsigned char)) == -1) {
 		gaim_debug_error("mdns", "Error calling setsockopt for IP_MULTICAST_LOOP\n");
@@ -135,39 +135,51 @@
 /***************************************/
 
 static int
-mdns_getlength_RR_txt(void *rdata)
+mdns_getlength_name(const void *name)
 {
-	GSList *cur;
-	ResourceRecordTXTRDataNode *node;
+	return strlen((const char *)name) + 2;
+}
+
+static int
+mdns_getlength_RR_rdata(unsigned short type, const void *rdata)
+{
 	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);
+	switch (type) {
+		case RENDEZVOUS_RRTYPE_PTR:
+			rdlength = mdns_getlength_name(rdata);
+		break;
+
+		case RENDEZVOUS_RRTYPE_TXT: {
+			GSList *cur;
+			ResourceRecordRDataTXTNode *node;
+
+			for (cur = (GSList *)rdata; cur != NULL; cur = cur->next) {
+				node = (ResourceRecordRDataTXTNode *)cur->data;
+				rdlength += 1 + strlen(node->name);
+				if (node->value != NULL)
+					rdlength += 1 + strlen(node->value);
+			}
+		} break;
+
+		case RENDEZVOUS_RRTYPE_SRV:
+			rdlength = 6 + mdns_getlength_name(((const ResourceRecordRDataSRV *)rdata)->target);
+		break;
 	}
 
 	return rdlength;
 }
 
 static int
-mdns_getlength_RR(const ResourceRecord *rr)
+mdns_getlength_RR(ResourceRecord *rr)
 {
 	int ret = 0;
 
+	rr->rdlength = mdns_getlength_RR_rdata(rr->type, rr->rdata);
+
 	ret += strlen(rr->name) + 2;
 	ret += 10;
-
-	switch (rr->type) {
-		case RENDEZVOUS_RRTYPE_PTR:
-			ret += strlen((const char *)rr->rdata) + 2;
-		break;
-
-		case RENDEZVOUS_RRTYPE_TXT:
-			ret += mdns_getlength_RR_txt(rr->rdata);
-		break;
-	}
+	ret += rr->rdlength;
 
 	return ret;
 }
@@ -201,22 +213,20 @@
 	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);
+			ResourceRecordRDataTXTNode *node;
 			int mylength;
 
-			i += util_put16(&data[offset + i], rdlength);
 			for (cur = (GSList *)rr->rdata; cur != NULL; cur = cur->next) {
-				node = (ResourceRecordTXTRDataNode *)cur->data;
+				node = (ResourceRecordRDataTXTNode *)cur->data;
 				mylength = 1 + strlen(node->name);
 				if (node->value)
 					mylength += 1 + strlen(node->value);
@@ -231,6 +241,14 @@
 				}
 			}
 		} break;
+
+		case RENDEZVOUS_RRTYPE_SRV: {
+			ResourceRecordRDataSRV *srv = rr->rdata;
+			i += util_put16(&data[offset + i], 0);
+			i += util_put16(&data[offset + i], 0);
+			i += util_put16(&data[offset + i], srv->port);
+			i += mdns_put_name(data, datalen, offset + i, srv->target);
+		} break;
 	}
 
 	return i;
@@ -253,7 +271,7 @@
 
 	/* Questions */
 	for (i = 0; i < dns->header.numquestions; i++)
-		datalen += strlen(dns->questions[i].name) + 2 + 4;
+		datalen += mdns_getlength_name(dns->questions[i].name) + 4;
 
 	/* Resource records */
 	for (i = 0; i < dns->header.numanswers; i++)
@@ -357,7 +375,7 @@
 	dns->answers = (ResourceRecord *)g_malloc(1 * sizeof(ResourceRecord));
 	dns->answers[0].name = g_strdup(name);
 	dns->answers[0].type = RENDEZVOUS_RRTYPE_PTR;
-	dns->answers[0].class = 0x0001;
+	dns->answers[0].class = 0x8001;
 	dns->answers[0].ttl = 0x00001c20;
 	dns->answers[0].rdlength = 0x0000; /* Set automatically */
 	dns->answers[0].rdata = (void *)g_strdup(domain);
@@ -394,7 +412,7 @@
 	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].class = 0x8001;
 	dns->answers[0].ttl = 0x00001c20;
 	dns->answers[0].rdlength = 0x0000; /* Set automatically */
 	dns->answers[0].rdata = (void *)rdata;
@@ -404,7 +422,52 @@
 
 	mdns_send_dns(fd, dns);
 
-	/* The hash table should be freed by the caller of this function */
+	/* The rdata should be freed by the caller of this function */
+	dns->answers[0].rdata = NULL;
+
+	mdns_free(dns);
+
+	return ret;
+}
+
+int
+mdns_advertise_srv(int fd, const char *name, unsigned short port, const char *target)
+{
+	int ret;
+	DNSPacket *dns;
+	ResourceRecordRDataSRV *rdata;
+
+	if ((strlen(target) > 255)) {
+		return -EINVAL;
+	}
+
+	rdata = g_malloc(sizeof(ResourceRecordRDataSRV));
+	rdata->port = port;
+	rdata->target = target;
+
+	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_SRV;
+	dns->answers[0].class = 0x8001;
+	dns->answers[0].ttl = 0x00001c20;
+	dns->answers[0].rdlength = 0x0000; /* Set automatically */
+	dns->answers[0].rdata = rdata;
+
+	dns->authority = NULL;
+	dns->additional = NULL;
+
+	mdns_send_dns(fd, dns);
+
+	g_free(dns->answers[0].rdata);
 	dns->answers[0].rdata = NULL;
 
 	mdns_free(dns);
@@ -418,6 +481,7 @@
 
 /*
  * XXX - Needs bounds checking!
+ * XXX - Also make sure you don't backtrack and infinitely loop.
  *
  * Read in a domain name from the given buffer starting at the given
  * offset.  This handles using domain name compression to jump around
@@ -803,7 +867,8 @@
 mdns_free_rr(ResourceRecord *rr)
 {
 	g_free(rr->name);
-	mdns_free_rr_rdata(rr->type, rr->rdata);
+	if (rr->rdata != NULL)
+		mdns_free_rr_rdata(rr->type, rr->rdata);
 }
 
 void
--- a/src/protocols/rendezvous/mdns.h	Sun Apr 11 16:09:06 2004 +0000
+++ b/src/protocols/rendezvous/mdns.h	Sun Apr 11 17:04:33 2004 +0000
@@ -89,14 +89,17 @@
 	void *rdata;
 } ResourceRecord;
 
-typedef struct _ResourceRecordTXTRDataNode {
+typedef struct _ResourceRecordRDataTXTNode {
 	char *name;
 	char *value;
-} ResourceRecordTXTRDataNode;
+} ResourceRecordRDataTXTNode;
+
+typedef GSList ResourceRecordRDataTXT;
 
-typedef GSList ResourceRecordTXTRData;
-
-typedef GHashTable ResourceRecordTXT;
+typedef struct _ResourceRecordRDataSRV {
+	unsigned short port;
+	const char *target;
+} ResourceRecordRDataSRV;
 
 typedef struct _ResourceRecordSRV {
 	unsigned int priority;
@@ -154,6 +157,7 @@
 
 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_srv(int fd, const char *name, unsigned short port, const char *target);
 
 /**
  * Read a UDP packet from the given file descriptor and parse it
--- a/src/protocols/rendezvous/rendezvous.c	Sun Apr 11 16:09:06 2004 +0000
+++ b/src/protocols/rendezvous/rendezvous.c	Sun Apr 11 17:04:33 2004 +0000
@@ -204,7 +204,7 @@
 	g_free(rb->firstandlast);
 	rb->firstandlast = g_strdup_printf("%s%s%s",
 							(tmp1 ? tmp1 : ""),
-							(tmp1 || tmp2 ? " " : ""),
+							(tmp1 && tmp2 ? " " : ""),
 							(tmp2 ? tmp2 : ""));
 	serv_got_alias(gc, name, rb->firstandlast);
 
@@ -408,8 +408,8 @@
 
 static void rendezvous_add_to_txt(RendezvousData *rd, const char *name, const char *value)
 {
-	ResourceRecordTXTRDataNode *node;
-	node = g_malloc(sizeof(ResourceRecordTXTRDataNode));
+	ResourceRecordRDataTXTNode *node;
+	node = g_malloc(sizeof(ResourceRecordRDataTXTNode));
 	node->name = g_strdup(name);
 	node->value = value != NULL ? g_strdup(value) : NULL;
 	rd->mytxtdata = g_slist_append(rd->mytxtdata, node);
@@ -419,21 +419,40 @@
 {
 	RendezvousData *rd = gc->proto_data;
 	GaimAccount *account = gaim_connection_get_account(gc);
+	const char *me;
+	char *myname, *mycomp;
 
-	mdns_advertise_ptr(rd->fd, "_presence._tcp.local", "mark@diverge._presence._tcp.local");
+	me = gaim_account_get_username(account);
+	myname = g_strdup_printf("%s._presence._tcp.local", me);
+	mycomp = g_strdup_printf("%s.local", strchr(me, '@') + 1);
+
+	mdns_advertise_ptr(rd->fd, "_presence._tcp.local", myname);
+	mdns_advertise_srv(rd->fd, myname, 5298, mycomp);
 
 	rendezvous_add_to_txt(rd, "txtvers", "1");
 	rendezvous_add_to_txt(rd, "status", "avail");
+	/* rendezvous_add_to_txt(rd, "vc", "A!"); */
+	/* rendezvous_add_to_txt(rd, "phsh", "96f15dec163cf4a8cfa0cf08109cc9766f7bd5a0"); */
 	rendezvous_add_to_txt(rd, "1st", gaim_account_get_string(account, "first", "Gaim"));
-	rendezvous_add_to_txt(rd, "AIM", "markdoliner");
+	if (gaim_account_get_bool(account, "shareaim", FALSE)) {
+		GList *l;
+		GaimAccount *cur;
+		for (l = gaim_accounts_get_all(); l != NULL; l = l->next) {
+			cur = (GaimAccount *)l->data;
+			if (!strcmp(gaim_account_get_protocol_id(cur), "prpl-oscar")) {
+				rendezvous_add_to_txt(rd, "AIM", gaim_account_get_username(cur));
+				break;
+			}
+		}
+	}
 	rendezvous_add_to_txt(rd, "version", "1");
+	rendezvous_add_to_txt(rd, "msg", "Groovin'");
 	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);
+	mdns_advertise_txt(rd->fd, myname, rd->mytxtdata);
 
-#if 0
-	mdns_advertise_srv(rd->fd, "mark@diverge._presence._tcp.local", port 5298, IP?);
-#endif
+	g_free(myname);
+	g_free(mycomp);
 }
 
 static void rendezvous_prpl_login(GaimAccount *account)
@@ -465,7 +484,7 @@
 static void rendezvous_prpl_close(GaimConnection *gc)
 {
 	RendezvousData *rd = (RendezvousData *)gc->proto_data;
-	ResourceRecordTXTRDataNode *node;
+	ResourceRecordRDataTXTNode *node;
 
 	if (gc->inpa)
 		gaim_input_remove(gc->inpa);
@@ -591,9 +610,15 @@
 {
 	GaimAccountUserSplit *split;
 	GaimAccountOption *option;
+	char hostname[255];
+
+	if (gethostname(hostname, 255) != 0) {
+		gaim_debug_warning("rendezvous", "Error %d when getting host name.  Using \"localhost.\"\n", errno);
+		strcpy(hostname, "localhost");
+	}
 
 	/* Try to avoid making this configurable... */
-	split = gaim_account_user_split_new(_("Host Name"), "localhost", '@');
+	split = gaim_account_user_split_new(_("Host Name"), hostname, '@');
 	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
 
 	option = gaim_account_option_string_new(_("First Name"), "first", "Gaim");
@@ -604,7 +629,7 @@
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 											   option);
 
-	option = gaim_account_option_bool_new(_("Share AIM screen name"), "shareaim", TRUE);
+	option = gaim_account_option_bool_new(_("Share AIM screen name"), "shareaim", FALSE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 											   option);