changeset 10321:782c1b564906

[gaim-migrate @ 11528] Some rendezvous changes I've had sitting around for a while. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sun, 05 Dec 2004 21:25:44 +0000
parents 61852117568f
children 2a132b73a6e6
files src/protocols/rendezvous/direct.c src/protocols/rendezvous/direct.h src/protocols/rendezvous/mdns.c src/protocols/rendezvous/rendezvous.c src/protocols/rendezvous/rendezvous.h
diffstat 5 files changed, 320 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/rendezvous/direct.c	Sun Dec 05 21:25:44 2004 +0000
@@ -0,0 +1,102 @@
+/*
+ * gaim - Rendezvous Protocol Plugin
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "internal.h"
+
+#include "connection.h"
+#include "network.h"
+
+#include "direct.h"
+#include "rendezvous.h"
+
+/*
+gchar *
+gaim_network_convert_ipv4_to_string(void *ip)
+{
+	gchar *ret;
+	unsigned char *ipv4 = (unsigned char *)ip;
+
+	ret = g_strdup_printf("::ffff:%02hhx%02hhx:%02hhx%02hhx", ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
+
+	return ret;
+}
+
+gchar *
+gaim_network_convert_ipv6_to_string(void *ip)
+{
+	gchar *ret;
+
+	//ret = g_strdup_printf("%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx", ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]);
+	ret = g_malloc0(INET6_ADDRSTRLEN + 1);
+	inet_ntop(AF_INET6, ip, ret, sizeof(ret));
+
+	return ret;
+}
+*/
+
+static gboolean rendezvous_find_buddy_by_ip(gpointer key, gpointer value, gpointer user_data)
+{
+	RendezvousBuddy *rb = value;
+
+printf("looking at ip=%s\n", rb->ip);
+	if ((rb->ip != NULL) && !strcasecmp(rb->ip, user_data))
+		return TRUE;
+
+	return FALSE;
+}
+
+void rendezvous_direct_acceptconnection(gpointer data, gint source, GaimInputCondition condition)
+{
+	GaimConnection *gc = (GaimConnection *)data;
+	RendezvousData *rd = gc->proto_data;
+	int fd;
+	struct sockaddr_in6 addr;
+	socklen_t addrlen = sizeof(addr);
+	gchar *ip;
+	RendezvousBuddy *rb;
+
+	fd = accept(rd->listener, (struct sockaddr *)&addr, &addrlen);
+	if (fd == -1) {
+		gaim_debug_warning("rendezvous", "accept: %s\n", strerror(errno));
+		return;
+	}
+/*
+	printf("\nsa_family=%d\n\n", ((struct sockaddr *)&addr)->sa_family);
+	if (((struct sockaddr *)&addr)->sa_family == AF_INET)
+		ip = gaim_network_convert_ipv4_to_string((unsigned char *)&ip);
+	else if (((struct sockaddr *)&addr)->sa_family == AF_INET6)
+		ip = gaim_network_convert_ipv6_to_string((unsigned char *)&(addr.sin6_addr));
+	printf("\nip=%s\n", ip);
+
+	rb = g_hash_table_find(rd->buddies, rendezvous_find_buddy_by_ip, ip);
+	g_free(ip);
+*/
+	if (rb == NULL) {
+		/* We don't want to talk to people that don't advertise themselves */
+printf("\ndid not find rb\n\n");
+		close(fd);
+		return;
+	}
+printf("\nip belongs to=%s\n\n", rb->aim);
+
+	rb->fd = fd;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/rendezvous/direct.h	Sun Dec 05 21:25:44 2004 +0000
@@ -0,0 +1,34 @@
+/**
+ * @file direct.h Code to handle rendezvous direct connection.  This
+ * is basically a mini Jabber implementation.
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _DIRECT_H_
+#define _DIRECT_H_
+
+#include "eventloop.h"
+
+void rendezvous_direct_acceptconnection(gpointer data, gint source, GaimInputCondition condition);
+
+#endif /* _DIRECT_H_ */
--- a/src/protocols/rendezvous/mdns.c	Sun Dec 05 21:05:52 2004 +0000
+++ b/src/protocols/rendezvous/mdns.c	Sun Dec 05 21:25:44 2004 +0000
@@ -174,6 +174,7 @@
 /* Functions for duplicating a DNS structure  */
 /**********************************************/
 
+#if 0
 static Question *
 mdns_copy_q(const Question *q)
 {
@@ -204,6 +205,7 @@
 
 	return ret;
 }
+#endif
 
 static void *
 mdns_copy_rr_rdata_txt(const ResourceRecordRDataTXT *rdata)
@@ -275,6 +277,7 @@
 	return ret;
 }
 
+#if 0
 ResourceRecord *
 mdns_copy_rr(const ResourceRecord *rr)
 {
@@ -331,6 +334,7 @@
 
 	return ret;
 }
+#endif
 
 /******************************************/
 /* Functions for connection establishment */
@@ -1383,7 +1387,6 @@
 /**
  * If invalid data is encountered at any point when parsing data
  * then the entire packet is discarded and NULL is returned.
- *
  */
 DNSPacket *
 mdns_read(int fd)
--- a/src/protocols/rendezvous/rendezvous.c	Sun Dec 05 21:05:52 2004 +0000
+++ b/src/protocols/rendezvous/rendezvous.c	Sun Dec 05 21:25:44 2004 +0000
@@ -29,19 +29,26 @@
 #include "network.h"
 #include "prpl.h"
 #include "sha.h"
-#include "util.h"
 #include "version.h"
 
+#include "direct.h"
+#include "mdns.h"
 #include "rendezvous.h"
-#include "mdns.h"
+#include "util.h"
 
 /****************************/
 /* Utility Functions        */
 /****************************/
-static void rendezvous_buddy_free(gpointer data)
+static void
+rendezvous_buddy_free(gpointer data)
 {
 	RendezvousBuddy *rb = data;
 
+	if (rb->fd >= 0)
+		close(rb->fd);
+	if (rb->watcher >= 0)
+		gaim_input_remove(rb->watcher);
+
 	g_free(rb->firstandlast);
 	g_free(rb->msg);
 	g_free(rb);
@@ -57,11 +64,12 @@
  *         the given domain.  This string should be g_free'd
  *         when no longer needed.
  */
-static gchar *rendezvous_extract_name(gchar *domain)
+static gchar *
+rendezvous_extract_name(gchar *domain)
 {
 	gchar *ret, *suffix;
 
-	if (!g_str_has_suffix(domain, "._presence._tcp.local"))
+	if (!gaim_str_has_suffix(domain, "._presence._tcp.local"))
 		return NULL;
 
 	suffix = strstr(domain, "._presence._tcp.local");
@@ -74,7 +82,8 @@
 /* Buddy List Functions     */
 /****************************/
 
-static void rendezvous_addtolocal(GaimConnection *gc, const char *name, const char *domain)
+static void
+rendezvous_addtolocal(GaimConnection *gc, const char *name, const char *domain)
 {
 	GaimAccount *account = gaim_connection_get_account(gc);
 	GaimBuddy *b;
@@ -109,7 +118,8 @@
 #endif
 }
 
-static void rendezvous_removefromlocal(GaimConnection *gc, const char *name, const char *domain)
+static void
+rendezvous_removefromlocal(GaimConnection *gc, const char *name, const char *domain)
 {
 	GaimAccount *account = gaim_connection_get_account(gc);
 	GaimBuddy *b;
@@ -134,7 +144,8 @@
 	 */
 }
 
-static void rendezvous_removeallfromlocal(GaimConnection *gc)
+static void
+rendezvous_removeallfromlocal(GaimConnection *gc)
 {
 	GaimAccount *account = gaim_connection_get_account(gc);
 	GaimBuddyList *blist;
@@ -163,7 +174,8 @@
 	}
 }
 
-static void rendezvous_handle_rr_a(GaimConnection *gc, ResourceRecord *rr, const gchar *name)
+static void
+rendezvous_handle_rr_a(GaimConnection *gc, ResourceRecord *rr, const gchar *name)
 {
 	RendezvousData *rd = gc->proto_data;
 	RendezvousBuddy *rb;
@@ -177,12 +189,11 @@
 		g_hash_table_insert(rd->buddies, g_strdup(name), rb);
 	}
 
-#if 0
-	memcpy(rb->ip, rdata, 4);
-#endif
+	/* rb->ipv4 = gaim_network_convert_ipv4_to_string((unsigned char *)rdata); */
 }
 
-static void rendezvous_handle_rr_txt(GaimConnection *gc, ResourceRecord *rr, const gchar *name)
+static void
+rendezvous_handle_rr_txt(GaimConnection *gc, ResourceRecord *rr, const gchar *name)
 {
 	RendezvousData *rd = gc->proto_data;
 	GaimAccount *account = gaim_connection_get_account(gc);
@@ -258,7 +269,26 @@
 	}
 }
 
-static void rendezvous_handle_rr_srv(GaimConnection *gc, ResourceRecord *rr, const gchar *name)
+static void
+rendezvous_handle_rr_aaaa(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);
+	}
+
+	/* rb->ip = gaim_network_convert_ipv6_to_string((unsigned char *)rdata); */
+}
+
+static void
+rendezvous_handle_rr_srv(GaimConnection *gc, ResourceRecord *rr, const gchar *name)
 {
 	RendezvousData *rd = gc->proto_data;
 	RendezvousBuddy *rb;
@@ -278,12 +308,13 @@
 /*
  * Parse a resource record and do stuff if we need to.
  */
-static void rendezvous_handle_rr(GaimConnection *gc, ResourceRecord *rr)
+static void
+rendezvous_handle_rr(GaimConnection *gc, ResourceRecord *rr)
 {
 	RendezvousData *rd = gc->proto_data;
 	gchar *name;
 
-	gaim_debug_misc("rendezvous", "Parsing resource record with domain name %s\n", rr->name);
+	gaim_debug_misc("rendezvous", "Parsing resource record with domain name %s and type %d\n", rr->name, rr->type);
 
 	switch (rr->type) {
 		case RENDEZVOUS_RRTYPE_A: {
@@ -331,6 +362,14 @@
 			}
 		} break;
 
+		case RENDEZVOUS_RRTYPE_AAAA: {
+			name = rendezvous_extract_name(rr->name);
+			if (name != NULL) {
+				rendezvous_handle_rr_aaaa(gc, rr, name);
+				g_free(name);
+			}
+		} break;
+
 		case RENDEZVOUS_RRTYPE_SRV: {
 			name = rendezvous_extract_name(rr->name);
 			if (name != NULL) {
@@ -344,12 +383,14 @@
 /****************************/
 /* Icon and Emblem Functions */
 /****************************/
-static const char* rendezvous_prpl_list_icon(GaimAccount *a, GaimBuddy *b)
+static const char *
+rendezvous_prpl_list_icon(GaimAccount *a, GaimBuddy *b)
 {
 	return "rendezvous";
 }
 
-static void rendezvous_prpl_list_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne)
+static void
+rendezvous_prpl_list_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne)
 {
 	if (GAIM_BUDDY_IS_ONLINE(b)) {
 		if (b->uc & UC_UNAVAILABLE)
@@ -359,7 +400,8 @@
 	}
 }
 
-static gchar *rendezvous_prpl_status_text(GaimBuddy *b)
+static gchar *
+rendezvous_prpl_status_text(GaimBuddy *b)
 {
 	GaimConnection *gc = b->account->gc;
 	RendezvousData *rd = gc->proto_data;
@@ -375,7 +417,8 @@
 	return ret;
 }
 
-static gchar *rendezvous_prpl_tooltip_text(GaimBuddy *b)
+static gchar *
+rendezvous_prpl_tooltip_text(GaimBuddy *b)
 {
 	GaimConnection *gc = b->account->gc;
 	RendezvousData *rd = gc->proto_data;
@@ -404,7 +447,8 @@
 /****************************/
 /* Connection Functions      */
 /****************************/
-static void rendezvous_callback(gpointer data, gint source, GaimInputCondition condition)
+static void
+rendezvous_callback(gpointer data, gint source, GaimInputCondition condition)
 {
 	GaimConnection *gc = data;
 	RendezvousData *rd = gc->proto_data;
@@ -428,7 +472,8 @@
 	mdns_free(dns);
 }
 
-static void rendezvous_add_to_txt(RendezvousData *rd, const char *name, const char *value)
+static void
+rendezvous_add_to_txt(RendezvousData *rd, const char *name, const char *value)
 {
 	ResourceRecordRDataTXTNode *node;
 	node = g_malloc(sizeof(ResourceRecordRDataTXTNode));
@@ -437,7 +482,8 @@
 	rd->mytxtdata = g_slist_append(rd->mytxtdata, node);
 }
 
-static guchar *rendezvous_read_icon_data(const char *filename, unsigned short *length)
+static guchar *
+rendezvous_read_icon_data(const char *filename, unsigned short *length)
 {
 	struct stat st;
 	FILE *file;
@@ -461,7 +507,8 @@
 	return data;
 }
 
-static void rendezvous_add_to_txt_iconhash(RendezvousData *rd, const char *iconfile)
+static void
+rendezvous_add_to_txt_iconhash(RendezvousData *rd, const char *iconfile)
 {
 	guchar *icondata;
 	unsigned short iconlength;
@@ -482,7 +529,8 @@
 	g_free(base16);
 }
 
-static void rendezvous_send_icon(GaimConnection *gc)
+static void
+rendezvous_send_icon(GaimConnection *gc)
 {
 	RendezvousData *rd = gc->proto_data;
 	GaimAccount *account = gaim_connection_get_account(gc);
@@ -503,26 +551,28 @@
 	g_free(rdata);
 }
 
-static void rendezvous_send_online(GaimConnection *gc)
+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[4];
+	gchar *myname, *mycomp, *myport;
+	unsigned char myipv4[4];
 
 	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 = gaim_network_ip_atoi(gaim_network_get_local_system_ip(-1)); */
-	myip[0] = 192;
-	myip[1] = 168;
-	myip[2] = 1;
-	myip[3] = 41;
+	/* myipv4 = gaim_network_ip_atoi(gaim_network_get_local_system_ip(-1)); */
+	myipv4[0] = 192;
+	myipv4[1] = 168;
+	myipv4[2] = 1;
+	myipv4[3] = 41;
+	myport = g_strdup_printf("%d", rd->listener_port);
 
-	mdns_advertise_a(rd->fd, mycomp, myip);
+	mdns_advertise_a(rd->fd, mycomp, myipv4);
 	mdns_advertise_ptr(rd->fd, "_presence._tcp.local", myname);
-	mdns_advertise_srv(rd->fd, myname, 5298, mycomp);
+	mdns_advertise_srv(rd->fd, myname, rd->listener_port, mycomp);
 
 	rendezvous_add_to_txt(rd, "txtvers", "1");
 	rendezvous_add_to_txt(rd, "status", "avail");
@@ -543,7 +593,7 @@
 	}
 	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, "port.p2pj", myport);
 	rendezvous_add_to_txt(rd, "last", gaim_account_get_string(account, "last", _("User")));
 	mdns_advertise_txt(rd->fd, myname, rd->mytxtdata);
 
@@ -551,9 +601,11 @@
 
 	g_free(myname);
 	g_free(mycomp);
+	g_free(myport);
 }
 
-static void rendezvous_prpl_login(GaimAccount *account)
+static void
+rendezvous_prpl_login(GaimAccount *account)
 {
 	GaimConnection *gc = gaim_account_get_connection(account);
 	RendezvousData *rd;
@@ -565,10 +617,18 @@
 	gaim_connection_update_progress(gc, _("Preparing Buddy List"), 0, RENDEZVOUS_CONNECT_STEPS);
 	rendezvous_removeallfromlocal(gc);
 
+	rd->listener = gaim_network_listen_range(5298, 5308);
+	if (rd->listener == -1) {
+		gaim_connection_error(gc, _("Unable to establish listening port."));
+		return;
+	}
+	rd->listener_watcher = gaim_input_add(rd->listener, GAIM_INPUT_READ, rendezvous_direct_acceptconnection, gc);
+	rd->listener_port = gaim_network_get_port_from_fd(rd->listener);
+
 	gaim_connection_update_progress(gc, _("Connecting"), 1, RENDEZVOUS_CONNECT_STEPS);
 	rd->fd = mdns_socket_establish();
 	if (rd->fd == -1) {
-		gaim_connection_error(gc, _("Unable to login to rendezvous"));
+		gaim_connection_error(gc, _("Unable to establish mDNS socket."));
 		return;
 	}
 
@@ -579,7 +639,8 @@
 	rendezvous_send_online(gc);
 }
 
-static void rendezvous_prpl_close(GaimConnection *gc)
+static void
+rendezvous_prpl_close(GaimConnection *gc)
 {
 	RendezvousData *rd = (RendezvousData *)gc->proto_data;
 	ResourceRecordRDataTXTNode *node;
@@ -589,11 +650,17 @@
 
 	rendezvous_removeallfromlocal(gc);
 
-	if (!rd)
+	if (rd == NULL)
 		return;
 
 	mdns_socket_close(rd->fd);
 
+	if (rd->listener >= 0)
+		close(rd->listener);
+
+	if (rd->listener_watcher != 0)
+		gaim_input_remove(rd->listener_watcher);
+
 	g_hash_table_destroy(rd->buddies);
 
 	while (rd->mytxtdata != NULL) {
@@ -607,13 +674,20 @@
 	g_free(rd);
 }
 
-static int rendezvous_prpl_send_im(GaimConnection *gc, const char *who, const char *message, GaimConvImFlags flags)
+static int
+rendezvous_prpl_send_im(GaimConnection *gc, const char *who, const char *message, GaimConvImFlags flags)
 {
 	gaim_debug_info("rendezvous", "Sending IM\n");
 
 	return 1;
 }
 
+static void
+rendezvous_prpl_set_status(GaimAccount *account, GaimStatus *status)
+{
+	gaim_debug_error("rendezvous", "Set status to %s\n", gaim_status_get_name(status));
+}
+
 static GaimPlugin *my_protocol = NULL;
 
 static GaimPluginProtocolInfo prpl_info;
@@ -669,6 +743,7 @@
 	prpl_info.login					= rendezvous_prpl_login;
 	prpl_info.close					= rendezvous_prpl_close;
 	prpl_info.send_im				= rendezvous_prpl_send_im;
+	prpl_info.set_status			= rendezvous_prpl_set_status;
 
 	if (gethostname(hostname, 255) != 0) {
 		gaim_debug_warning("rendezvous", "Error %d when getting host name.  Using \"localhost.\"\n", errno);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/rendezvous/rendezvous.h	Sun Dec 05 21:25:44 2004 +0000
@@ -0,0 +1,64 @@
+/**
+ * @file rendezvous.h The Gaim interface to mDNS and peer to peer Jabber.
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _RENDEZVOUS_H_
+#define _RENDEZVOUS_H_
+
+#include "internal.h"
+#include "debug.h"
+
+#include "mdns.h"
+
+#define RENDEZVOUS_CONNECT_STEPS 2
+
+#define UC_UNAVAILABLE 1
+#define UC_IDLE 2
+
+typedef struct _RendezvousData {
+	int fd;
+	GHashTable *buddies;
+	GSList *mytxtdata;
+	unsigned short listener_port;
+	int listener;
+	int listener_watcher;
+} RendezvousData;
+
+typedef struct _RendezvousBuddy {
+#if 0
+	guint ttltimer;
+#endif
+	gchar *firstandlast;
+	gchar *aim;
+	gchar *ipv4; /* String representation of an IPv4 address */
+	gchar *ipv6; /* String representation of an IPv6 address */
+	unsigned short p2pjport;
+	int status;
+	int idle;		/**< Current idle time in seconds since the epoch.	*/
+	gchar *msg;		/**< Current status message of this buddy.			*/
+	int fd;			/**< File descriptor of the P2PJ socket.			*/
+	int watcher;	/**< Handle for the watcher of the P2PJ socket.		*/
+} RendezvousBuddy;
+
+#endif /* _RENDEZVOUS_H_ */