# HG changeset patch # User Mark Doliner # Date 1123891762 0 # Node ID 6ee53c79d6303ffdccc89d9d1adf31ad540d84ab # Parent a511b77a368b4a27ea96a15cdfc242ba19c59632 [gaim-migrate @ 13409] Remove the old rendezvous PRPL from CVS HEAD. This will be replaced by Juanjo's bonjour PRPL. committer: Tailor Script diff -r a511b77a368b -r 6ee53c79d630 configure.ac --- a/configure.ac Fri Aug 12 23:53:28 2005 +0000 +++ b/configure.ac Sat Aug 13 00:09:22 2005 +0000 @@ -174,7 +174,6 @@ napster) static_napster=yes ;; novell) static_novell=yes ;; oscar) static_oscar=yes ;; - rendezvous) static_rendezvous=yes ;; sametime) static_sametime=yes ;; silc) static_silc=yes ;; simple) static_simple=yes ;; @@ -192,7 +191,6 @@ AM_CONDITIONAL(STATIC_NAPSTER, test "x$static_napster" = "xyes") AM_CONDITIONAL(STATIC_NOVELL, test "x$static_novell" = "xyes") AM_CONDITIONAL(STATIC_OSCAR, test "x$static_oscar" = "xyes") -AM_CONDITIONAL(STATIC_RENDEZVOUS, test "x$static_rendezvous" = "xyes") AM_CONDITIONAL(STATIC_SAMETIME, test "x$static_sametime" = "xyes") AM_CONDITIONAL(STATIC_SILC, test "x$static_silc" = "xyes" -a "x$silcincludes" = "xyes" -a "x$silcclient" = "xyes") AM_CONDITIONAL(STATIC_SIMPLE, test "x$static_simple" = "xyes") @@ -221,7 +219,6 @@ napster) dynamic_napster=yes ;; novell) dynamic_novell=yes ;; oscar) dynamic_oscar=yes ;; - rendezvous) dynamic_rendezvous=yes ;; sametime) dynamic_sametime=yes ;; silc) dynamic_silc=yes ;; simple) dynamic_simple=yes ;; @@ -239,7 +236,6 @@ AM_CONDITIONAL(DYNAMIC_NAPSTER, test "x$dynamic_napster" = "xyes") AM_CONDITIONAL(DYNAMIC_NOVELL, test "x$dynamic_novell" = "xyes") AM_CONDITIONAL(DYNAMIC_OSCAR, test "x$dynamic_oscar" = "xyes") -AM_CONDITIONAL(DYNAMIC_RENDEZVOUS, test "x$dynamic_rendezvous" = "xyes") AM_CONDITIONAL(DYNAMIC_SAMETIME, test "x$dynamic_sametime" = "xyes") AM_CONDITIONAL(DYNAMIC_SILC, test "x$dynamic_silc" = "xyes" -a "x$silcincludes" = "xyes" -a "x$silcclient" = "xyes") AM_CONDITIONAL(DYNAMIC_SIMPLE, test "x$dynamic_simple" = "xyes") @@ -1310,7 +1306,6 @@ src/protocols/napster/Makefile src/protocols/novell/Makefile src/protocols/oscar/Makefile - src/protocols/rendezvous/Makefile src/protocols/sametime/Makefile src/protocols/sametime/meanwhile/Makefile src/protocols/silc/Makefile diff -r a511b77a368b -r 6ee53c79d630 pixmaps/status/default/Makefile.am --- a/pixmaps/status/default/Makefile.am Fri Aug 12 23:53:28 2005 +0000 +++ b/pixmaps/status/default/Makefile.am Sat Aug 13 00:09:22 2005 +0000 @@ -5,6 +5,7 @@ aol.png \ away.png \ blocked.png \ + bonjour.png \ dnd.png \ extendedaway.png \ female.png \ @@ -32,7 +33,6 @@ occupied.png \ offline.png \ op.png \ - rendezvous.png \ secure.png \ silc.png \ trepia.png \ diff -r a511b77a368b -r 6ee53c79d630 pixmaps/status/default/bonjour.png Binary file pixmaps/status/default/bonjour.png has changed diff -r a511b77a368b -r 6ee53c79d630 pixmaps/status/default/rendezvous.png Binary file pixmaps/status/default/rendezvous.png has changed diff -r a511b77a368b -r 6ee53c79d630 src/protocols/Makefile.am --- a/src/protocols/Makefile.am Fri Aug 12 23:53:28 2005 +0000 +++ b/src/protocols/Makefile.am Sat Aug 13 00:09:22 2005 +0000 @@ -1,3 +1,3 @@ -DIST_SUBDIRS = gg irc jabber msn napster novell oscar rendezvous sametime silc toc trepia yahoo zephyr +DIST_SUBDIRS = gg irc jabber msn napster novell oscar sametime silc toc trepia yahoo zephyr SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS) diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/.cvsignore --- a/src/protocols/rendezvous/.cvsignore Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -Makefile.in -Makefile -.deps -.libs -librendezvous.def -librendezvous.dll -librendezvous.lib -*.la -*.lo diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/Makefile.am --- a/src/protocols/rendezvous/Makefile.am Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -EXTRA_DIST = \ - Makefile.mingw - -pkgdir = $(libdir)/gaim - -RENDEZVOUSSOURCES = \ - direct.c \ - direct.h \ - mdns.c \ - mdns.h \ - mdns_cache.c \ - mdns_cache.h \ - rendezvous.c - -AM_CFLAGS = $(st) - -librendezvous_la_LDFLAGS = -module -avoid-version $(GLIB_LIBS) - -if STATIC_RENDEZVOUS - -st = -DGAIM_STATIC_PRPL -noinst_LIBRARIES = librendezvous.a -librendezvous_a_SOURCES = $(RENDEZVOUSSOURCES) -librendezvous_a_CFLAGS = $(AM_CFLAGS) - -else - -st = -pkg_LTLIBRARIES = librendezvous.la -librendezvous_la_SOURCES = $(RENDEZVOUSSOURCES) - -endif - - -AM_CPPFLAGS = \ - -I$(top_srcdir)/src \ - $(GLIB_CFLAGS) \ - $(DEBUG_CFLAGS) diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/Makefile.mingw --- a/src/protocols/rendezvous/Makefile.mingw Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -# -# Makefile.mingw -# -# Description: Makefile for win32 (mingw) version of librendezvous -# - -# -# PATHS -# - -INCLUDE_DIR := . -GTK_TOP := ../../../../win32-dev/gtk_2_0 -GAIM_TOP := ../../.. -RENDEZVOUS_ROOT := . -GAIM_INSTALL_DIR := $(GAIM_TOP)/win32-install-dir - -## -## VARIABLE DEFINITIONS -## - -TARGET = librendezvous - -# Compiler Options - -CFLAGS = - -DEFINES = - -# Static or Plugin... -ifeq ($(TYPE),STATIC) - DEFINES += -DSTATIC - DLL_INSTALL_DIR = $(GAIM_INSTALL_DIR) -else -ifeq ($(TYPE),PLUGIN) - DLL_INSTALL_DIR = $(GAIM_INSTALL_DIR)/plugins -endif -endif - - -## -## INCLUDE MAKEFILES -## - -include $(GAIM_TOP)/src/win32/global.mak - -## -## INCLUDE PATHS -## - -INCLUDE_PATHS += -I$(RENDEZVOUS_ROOT) \ - -I$(GTK_TOP)/include \ - -I$(GTK_TOP)/include/gtk-2.0 \ - -I$(GTK_TOP)/include/glib-2.0 \ - -I$(GTK_TOP)/include/pango-1.0 \ - -I$(GTK_TOP)/include/atk-1.0 \ - -I$(GTK_TOP)/lib/glib-2.0/include \ - -I$(GTK_TOP)/lib/gtk-2.0/include \ - -I$(GAIM_TOP)/src \ - -I$(GAIM_TOP)/src/win32 \ - -I$(GAIM_TOP) - - -LIB_PATHS = -L$(GTK_TOP)/lib \ - -L$(GAIM_TOP)/src - - -## -## SOURCES, OBJECTS -## - -C_SRC = direct.c \ - mdns.c \ - mdns_cache.c \ - rendezvous.c - - -OBJECTS = $(C_SRC:%.c=%.o) - - -## -## LIBRARIES -## - -LIBS = -lgtk-win32-2.0 \ - -lglib-2.0 \ - -lgdk-win32-2.0 \ - -lgmodule-2.0 \ - -lgobject-2.0 \ - -lws2_32 \ - -lintl \ - -lgaim - - -## -## RULES -## - -# How to make a C file - -%.o: %.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@ -c $< - -## -## TARGET DEFINITIONS -## - -.PHONY: all clean - -all: $(TARGET).dll - -install: - cp $(RENDEZVOUS_ROOT)/$(TARGET).dll $(DLL_INSTALL_DIR) - - -## -## BUILD Dependencies -## - -$(GAIM_TOP)/src/gaim.lib: - $(MAKE) -C $(GAIM_TOP)/src -f Makefile.mingw gaim.lib - -## -## BUILD DLL -## - -$(TARGET).dll: $(OBJECTS) $(GAIM_TOP)/src/gaim.lib - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--out-implib,$(TARGET).lib -o $(TARGET).dll - -## -## CLEAN RULES -## - -clean: - rm -rf *.o - rm -rf $(TARGET).dll - rm -rf $(TARGET).lib diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/direct.c --- a/src/protocols/rendezvous/direct.c Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/* - * 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" - -static gboolean -rendezvous_find_buddy_by_ipv4(gpointer key, gpointer value, gpointer user_data) -{ - RendezvousBuddy *rb = value; - - if (rb->ipv4 == NULL) - return FALSE; - -int *ipv4 = user_data; -printf("looking for ip=%hu.%hu.%hu.%hu\n", ipv4[0], ipv4[1], ipv4[2], ipv4[3]); -printf("looking at ip=%hu.%hu.%hu.%hu, %s\n", rb->ipv4[0], rb->ipv4[1], rb->ipv4[2], rb->ipv4[3], rb->firstandlast); - return !memcmp(rb->ipv4, user_data, 4); -} - -static gboolean -rendezvous_find_buddy_by_ipv6(gpointer key, gpointer value, gpointer user_data) -{ - RendezvousBuddy *rb = value; - - if (rb->ipv6 == NULL) - return FALSE; - -int *ipv6 = user_data; -printf("looking for ip=%hx%hx:%hx%hx:%hx%hx:%hx%hx:%hx%hx:%hx%hx:%hx%hx:%hx%hx\n", ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5], ipv6[6], ipv6[7], ipv6[8], ipv6[9], ipv6[10], ipv6[11], ipv6[12], ipv6[13], ipv6[14], ipv6[15]); -printf("looking at ip=%hx%hx:%hx%hx:%hx%hx:%hx%hx:%hx%hx:%hx%hx:%hx%hx:%hx%hx, %s\n", rb->ipv6[0], rb->ipv6[1], rb->ipv6[2], rb->ipv6[3], rb->ipv6[4], rb->ipv6[5], rb->ipv6[6], rb->ipv6[7], rb->ipv6[8], rb->ipv6[9], rb->ipv6[10], rb->ipv6[11], rb->ipv6[12], rb->ipv6[13], rb->ipv6[14], rb->ipv6[15], rb->firstandlast); - return !memcmp(rb->ipv6, user_data, 16); -} - -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); - RendezvousBuddy *rb = NULL; - - fd = accept(rd->listener, (struct sockaddr *)&addr, &addrlen); - if (fd == -1) { - gaim_debug_warning("rendezvous", "accept: %s\n", strerror(errno)); - return; - } - - if (((struct sockaddr *)&addr)->sa_family == AF_INET) - rb = g_hash_table_find(rd->buddies, rendezvous_find_buddy_by_ipv4, &(((struct sockaddr_in *)&addr)->sin_addr)); - else if (((struct sockaddr *)&addr)->sa_family == AF_INET6) - rb = g_hash_table_find(rd->buddies, rendezvous_find_buddy_by_ipv6, &(addr.sin6_addr.s6_addr)); - - 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; - - /* TODO: Add a watcher on the connection. */ -} - -static void -rendezvous_direct_connect(RendezvousBuddy *rb) -{ - struct sockaddr_in addr; - - /* If we already have a connection then do nothing */ - if (rb->fd != -1) - return; - - if ((rb->ipv4 == NULL) && (rb->ipv6 == NULL)) - { - gaim_debug_warning("rendezvous", "Could not connect: Unknown IP address.\n"); - /* TODO: Show an error message to the user. */ - return; - } - - if ((rb->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) - { - gaim_debug_warning("rendezvous", "Could not connect: %s.\n", strerror(errno)); - /* TODO: Show an error message to the user. */ - return; - } - - addr.sin_family = AF_INET; - addr.sin_port = rb->p2pjport; - memcpy(&addr.sin_addr, rb->ipv4, 4); - memset(&addr.sin_zero, 0, 8); - - if (connect(rb->fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) - { - gaim_debug_warning("rendezvous", "Could not connect: %s.\n", strerror(errno)); - /* TODO: Show an error message to the user. */ - return; - } - - /* TODO: Connect a watcher */ -} - -static void -rendezvous_direct_write_message_to_socket(int fd, const char *message) -{ - -} - -/* - * TODO: Establish a direct connection, then send IM. Will need to - * queue the message somewhere, while the connection is established. - */ -void -rendezvous_direct_send_message(GaimConnection *gc, const char *who, const char *message) -{ - RendezvousData *rd = gc->proto_data; - RendezvousBuddy *rb; - - rb = g_hash_table_lookup(rd->buddies, who); - if (rb == NULL) - { - /* TODO: Should print an error to the user, here */ - gaim_debug_error("rendezvous", "Could not send message to %s: Could not find user information.\n", who); - return; - } - - if (rb->fd == -1) - { - rendezvous_direct_connect(rb); - /* TODO: Queue message */ - /* gaim_debug_warning("rendezvous", "Could not send message to %s: Unable to establish connection.\n", who); */ - } - else - { - rendezvous_direct_write_message_to_socket(rb->fd, message); - } -} diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/direct.h --- a/src/protocols/rendezvous/direct.h Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/** - * @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" - -#include "rendezvous.h" - -void rendezvous_direct_acceptconnection(gpointer data, gint source, GaimInputCondition condition); - -void rendezvous_direct_send_message(GaimConnection *gc, const char *who, const char *message); - -#endif /* _DIRECT_H_ */ diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/mdns.c --- a/src/protocols/rendezvous/mdns.c Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1490 +0,0 @@ -/** - * @file mdns.c Multicast DNS connection code used by rendezvous. - * - * 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 - * - */ - -/* - * If you want to understand this, read RFC1035 and - * draft-cheshire-dnsext-multicastdns.txt, and buy - * me a doughnut. thx k bye. - */ - -/* - * XXX - This entire file could use another pair of eyes to audit for - * any possible buffer overflow exploits. It doesn't even HAVE to be - * a pair, neither--one eye would suffice. Oh, snap, somebody call - * One Eyed Willie. - */ - -/* - * XXX - Store data for NULL ResourceRecords so that rr->rdata contains - * both the length and the data. This length will always be equal to - * rr->rdlength... but it fits in more with the rest of the code. - * rr->rdata should not need a separate length value to determine - * how many bytes it will take. - */ - -#include "internal.h" -#include "debug.h" - -#include "mdns.h" -#include "mdns_cache.h" -#include "util.h" - -/******************************************/ -/* Functions for freeing a DNS structure */ -/******************************************/ - -/** - * Free a given question - * - * @param q The question to free. - */ -static void -mdns_free_q(Question *q) -{ - g_free(q->name); - g_free(q); -} - -/** - * Free a given list of questions. - * - * @param qs The list of questions to free. - */ -static void -mdns_free_qs(GSList *qs) -{ - Question *q; - - while (qs != NULL) { - q = qs->data; - mdns_free_q(q); - qs = g_slist_remove(qs, q); - } -} - -/** - * Free the rdata associated with a given resource record. - * - * @param type The type of the resource record you are freeing. - * @param rdata The rdata of the resource record you are freeing. - */ -static void -mdns_free_rr_rdata(unsigned short type, void *rdata) -{ - if (rdata == NULL) - return; - - switch (type) { - case RENDEZVOUS_RRTYPE_A: - case RENDEZVOUS_RRTYPE_NULL: - case RENDEZVOUS_RRTYPE_PTR: - case RENDEZVOUS_RRTYPE_AAAA: - g_free(rdata); - break; - - case RENDEZVOUS_RRTYPE_TXT: { - GSList *cur = rdata; - ResourceRecordRDataTXTNode *node; - while (cur != NULL) { - node = cur->data; - cur = g_slist_remove(cur, node); - g_free(node->name); - g_free(node->value); - g_free(node); - } - } break; - - case RENDEZVOUS_RRTYPE_SRV: - g_free(((ResourceRecordRDataSRV *)rdata)->target); - g_free(rdata); - break; - } -} - -/** - * Free a given resource record. - * - * @param rr The resource record to free. - */ -void -mdns_free_rr(ResourceRecord *rr) -{ - g_free(rr->name); - mdns_free_rr_rdata(rr->type, rr->rdata); - g_free(rr); -} - -/** - * Free a given list of resource records. - * - * @param rrs The list of resource records to free. - */ -void -mdns_free_rrs(GSList *rrs) -{ - ResourceRecord *rr; - - while (rrs != NULL) { - rr = rrs->data; - mdns_free_rr(rr); - rrs = g_slist_remove(rrs, rr); - } -} - -/** - * Free a given DNS packet. This frees all the questions and all - * the resource records. - * - * @param dns The DNS packet to free. - */ -void -mdns_free(DNSPacket *dns) -{ - mdns_free_qs(dns->questions); - mdns_free_rrs(dns->answers); - mdns_free_rrs(dns->authority); - mdns_free_rrs(dns->additional); - - g_free(dns); -} - -/**********************************************/ -/* Functions for duplicating a DNS structure */ -/**********************************************/ - -#if 0 -static Question * -mdns_copy_q(const Question *q) -{ - Question *ret; - - if (q == NULL) - return NULL; - - ret = g_malloc(sizeof(Question)); - ret->name = g_strdup(q->name); - ret->type = q->type; - ret->class = q->class; - - return ret; -} - -static GSList * -mdns_copy_qs(const GSList *qs) -{ - GSList *ret = NULL; - GSList *cur; - Question *new; - - for (cur = (GSList *)qs; cur != NULL; cur = cur->next) { - new = mdns_copy_q(cur->data); - ret = g_slist_append(ret, new); - } - - return ret; -} -#endif - -static void * -mdns_copy_rr_rdata_txt(const ResourceRecordRDataTXT *rdata) -{ - GSList *ret = NULL; - GSList *cur; - ResourceRecordRDataTXTNode *node, *copy; - - for (cur = (GSList *)rdata; cur != NULL; cur = cur->next) { - node = cur->data; - copy = g_malloc0(sizeof(ResourceRecordRDataTXTNode)); - copy->name = g_strdup(node->name); - if (node->value != NULL) - copy->value = g_strdup(node->value); - ret = g_slist_append(ret, copy); - } - - return ret; -} - -static void * -mdns_copy_rr_rdata_srv(const ResourceRecordRDataSRV *rdata) -{ - ResourceRecordRDataSRV *ret; - - ret = g_malloc(sizeof(ResourceRecordRDataSRV)); - ret->priority = rdata->priority; - ret->weight = rdata->weight; - ret->port = rdata->port; - ret->target = g_strdup(rdata->target); - - return ret; -} - -void * -mdns_copy_rr_rdata(unsigned short type, const void *rdata, unsigned int rdlength) -{ - void *ret; - - if (rdata == NULL) - 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_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; - } - - return ret; -} - -ResourceRecord * -mdns_copy_rr(const ResourceRecord *rr) -{ - ResourceRecord *ret; - - if (rr == NULL) - return NULL; - - ret = g_malloc(sizeof(ResourceRecord)); - ret->name = g_strdup(rr->name); - ret->type = rr->type; - ret->class = rr->class; - ret->ttl = rr->ttl; - ret->rdlength = rr->rdlength; - ret->rdata = mdns_copy_rr_rdata(rr->type, rr->rdata, rr->rdlength); - - return ret; -} - -#if 0 -static GSList * -mdns_copy_rrs(const GSList *rrs) -{ - GSList *ret = NULL; - GSList *cur; - ResourceRecord *new; - - for (cur = (GSList *)rrs; cur != NULL; cur = cur->next) { - new = mdns_copy_rr(cur->data); - ret = g_slist_append(ret, new); - } - - return ret; -} - -static DNSPacket * -mdns_copy(const DNSPacket *dns) -{ - DNSPacket *ret; - - if (dns == NULL) - return NULL; - - ret = g_malloc0(sizeof(DNSPacket)); - ret->header.id = dns->header.id; - ret->header.flags = dns->header.flags; - ret->header.numquestions = dns->header.numquestions; - ret->header.numanswers = dns->header.numanswers; - ret->header.numauthority = dns->header.numauthority; - ret->header.numadditional = dns->header.numadditional; - ret->questions = mdns_copy_qs(dns->questions); - ret->answers = mdns_copy_rrs(dns->answers); - ret->authority = mdns_copy_rrs(dns->authority); - ret->additional = mdns_copy_rrs(dns->additional); - - return ret; -} -#endif - -/******************************************/ -/* Functions for connection establishment */ -/******************************************/ - -int -mdns_socket_establish() -{ - int fd = -1; - struct sockaddr_in addr; - struct ip_mreq mreq; - unsigned char loop; - unsigned char ttl; - int reuseaddr; - - gaim_debug_info("mdns", "Establishing multicast socket\n"); - - /* What's the difference between AF_INET and PF_INET? */ - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - gaim_debug_error("mdns", "Unable to create socket: %s\n", strerror(errno)); - return -1; - } - - /* Make the socket non-blocking (although it shouldn't matter) */ - fcntl(fd, F_SETFL, O_NONBLOCK); - - /* Bind the socket to a local IP and port */ - addr.sin_family = AF_INET; - addr.sin_port = htons(5353); - addr.sin_addr.s_addr = INADDR_ANY; - if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { - gaim_debug_error("mdns", "Unable to bind socket to interface.\n"); - gaim_debug_error("mdns", "%s\n", strerror(errno)); - close(fd); - return -1; - } - - /* 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"); - } - - /* Set TTL to 255--required by mDNS */ - ttl = 255; - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(unsigned char)) == -1) { - gaim_debug_error("mdns", "Error calling setsockopt for IP_MULTICAST_TTL\n"); - close(fd); - return -1; - } - - /* Join the .local multicast group */ - mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.251"); - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -1) { - gaim_debug_error("mdns", "Error calling setsockopt for IP_ADD_MEMBERSHIP\n"); - close(fd); - return -1; - } - - /* Make the local IP re-usable */ - reuseaddr = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1) { - gaim_debug_error("mdns", "Error calling setsockopt for SO_REUSEADDR: %s\n", strerror(errno)); - } - - return fd; -} - -void -mdns_socket_close(int fd) -{ - if (fd >= 0) - close(fd); - - mdns_cache_remove_all(); -} - -/** - * Multicast raw data over a file descriptor. - * - * @param fd A file descriptor that is a socket bound to a UDP port. - * @param datalen The length of the data you wish to send. - * @param data The data you wish to send. - * @return 0 on success, otherwise return -1. - */ -static int -mdns_send_raw(int fd, unsigned int datalen, unsigned char *data) -{ - struct sockaddr_in addr; - int n; - - addr.sin_family = AF_INET; - addr.sin_port = htons(5353); - addr.sin_addr.s_addr = inet_addr("224.0.0.251"); - n = sendto(fd, data, datalen, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); - - if (n == -1) { - gaim_debug_error("mdns", "Error sending packet: %d\n", errno); - return -1; - } else if (n != datalen) { - gaim_debug_error("mdns", "Only sent %d of %d bytes of data.\n", n, datalen); - return -1; - } - - return 0; -} - -/***************************************/ -/* Functions for sending mDNS messages */ -/***************************************/ - -/** - * - */ -static int -mdns_getlength_name(const void *name) -{ - return strlen((const char *)name) + 2; -} - -/** - * - */ -static int -mdns_getlength_q(const Question *q) -{ - return mdns_getlength_name(q->name) + 4; -} - -/** - * - */ -static int -mdns_getlength_qs(const GSList *qs) -{ - int length = 0; - GSList *cur; - - for (cur = (GSList *)qs; cur != NULL; cur = cur->next) - length += mdns_getlength_q(cur->data); - - return length; -} - -/** - * - */ -static int -mdns_getlength_rr_rdata(unsigned short type, const void *rdata) -{ - int rdlength = 0; - - switch (type) { - case RENDEZVOUS_RRTYPE_A: - rdlength = 4; - break; - - 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_AAAA: - rdlength = 16; - 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) -{ - int rdlength = mdns_getlength_rr_rdata(rr->type, rr->rdata); - - if ((rdlength == 0) && (rr->rdata != NULL)) - rdlength = rr->rdlength; - - return mdns_getlength_name(rr->name) + 10 + rdlength; -} - -/** - * - */ -static int -mdns_getlength_rrs(const GSList *rrs) -{ - int length = 0; - GSList *cur; - - for (cur = (GSList *)rrs; cur != NULL; cur = cur->next) - length += mdns_getlength_rr(cur->data); - - return length; -} - -/** - * - */ -static int -mdns_getlength_dns(const DNSPacket *dns) -{ - int length = 0; - - /* Header */ - length += 12; - - /* Questions */ - length += mdns_getlength_qs(dns->questions); - - /* Resource records */ - length += mdns_getlength_rrs(dns->answers); - length += mdns_getlength_rrs(dns->authority); - length += mdns_getlength_rrs(dns->additional); - - return length; -} - -/** - * - */ -static int -mdns_put_name(char *data, unsigned int datalen, unsigned int offset, const char *name) -{ - int i = 0; - char *b, *c; - - b = (char *)name; - while ((c = strchr(b, '.'))) { - i += util_put8(&data[offset + i], c - b); /* Length of domain-name segment */ - memcpy(&data[offset + i], b, c - b); /* Domain-name segment */ - i += c - b; /* Increment the destination pointer */ - b = c + 1; - } - i += util_put8(&data[offset + i], strlen(b)); /* Length of domain-name segment */ - strcpy(&data[offset + i], b); /* Domain-name segment */ - i += strlen(b) + 1; /* Increment the destination pointer */ - - return i; -} - -/** - * - */ -static int -mdns_put_q(char *data, unsigned int datalen, unsigned int offset, const Question *q) -{ - int i = 0; - - i += mdns_put_name(data, datalen, offset + i, q->name); /* QNAME */ - i += util_put16(&data[offset + i], q->type); /* QTYPE */ - i += util_put16(&data[offset + i], q->class); /* QCLASS */ - - return i; -} - -/** - * - */ -static int -mdns_put_rr(char *data, unsigned int datalen, unsigned int offset, const ResourceRecord *rr) -{ - int i = 0; - - i += mdns_put_name(data, datalen, offset + i, rr->name); - 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_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; - break; - - case RENDEZVOUS_RRTYPE_PTR: - i += mdns_put_name(data, datalen, offset + i, (const char *)rr->rdata); - break; - - case RENDEZVOUS_RRTYPE_TXT: { - GSList *cur; - ResourceRecordRDataTXTNode *node; - int mylength; - - for (cur = (GSList *)rr->rdata; cur != NULL; cur = cur->next) { - node = (ResourceRecordRDataTXTNode *)cur->data; - mylength = 1 + strlen(node->name); - if (node->value != NULL) - 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 != NULL) { - data[offset + i] = '='; - i++; - memcpy(&data[offset + i], node->value, strlen(node->value)); - i += strlen(node->value); - } - } - } 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); - 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; -} - -int -mdns_send_dns(int fd, const DNSPacket *dns) -{ - int ret; - unsigned int datalen; - unsigned char *data; - unsigned int offset; - GSList *cur; - - /* Calculate the length of the buffer we'll need to hold the DNS packet */ - datalen = mdns_getlength_dns(dns); - - /* Allocate a buffer */ - if (!(data = (unsigned char *)g_malloc(datalen))) { - return -ENOMEM; - } - - /* Construct the datagram */ - /* Header */ - offset = 0; - offset += util_put16(&data[offset], dns->header.id); /* ID */ - offset += util_put16(&data[offset], dns->header.flags); - offset += util_put16(&data[offset], dns->header.numquestions); /* QDCOUNT */ - offset += util_put16(&data[offset], dns->header.numanswers); /* ANCOUNT */ - offset += util_put16(&data[offset], dns->header.numauthority); /* NSCOUNT */ - offset += util_put16(&data[offset], dns->header.numadditional); /* ARCOUNT */ - - /* Questions */ - for (cur = dns->questions; cur != NULL; cur = cur->next) - offset += mdns_put_q(data, datalen, offset, cur->data); - - /* Resource records */ - for (cur = dns->answers; cur != NULL; cur = cur->next) - offset += mdns_put_rr(data, datalen, offset, cur->data); - for (cur = dns->authority; cur != NULL; cur = cur->next) - offset += mdns_put_rr(data, datalen, offset, cur->data); - for (cur = dns->additional; cur != NULL; cur = cur->next) - offset += mdns_put_rr(data, datalen, offset, cur->data); - - /* Send the datagram */ - /* Offset can be shorter than datalen because of name compression */ - ret = mdns_send_raw(fd, offset, data); - - g_free(data); - - return ret; -} - -int -mdns_query(int fd, const char *domain, unsigned short type) -{ - int ret; - DNSPacket *dns; - Question *q; - - if ((domain == NULL) || strlen(domain) > 255) { - return -EINVAL; - } - - dns = (DNSPacket *)g_malloc(sizeof(DNSPacket)); - dns->header.id = 0x0000; - dns->header.flags = 0x0000; - dns->header.numquestions = 0x0001; - dns->header.numanswers = 0x0000; - dns->header.numauthority = 0x0000; - dns->header.numadditional = 0x0000; - - q = (Question *)g_malloc(sizeof(Question)); - q->name = g_strdup(domain); - q->type = type; - q->class = 0x0001; - dns->questions = g_slist_append(NULL, q); - - dns->answers = NULL; - dns->authority = NULL; - dns->additional = NULL; - - ret = mdns_send_dns(fd, dns); - - mdns_free(dns); - - return ret; -} - -int -mdns_send_rr(int fd, ResourceRecord *rr) -{ - int ret; - DNSPacket *dns; - - g_return_val_if_fail(rr != NULL, -1); - - 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 = g_slist_append(NULL, mdns_copy_rr(rr)); - dns->authority = NULL; - dns->additional = NULL; - - ret = mdns_send_dns(fd, dns); - - mdns_free(dns); - - return ret; -} - -int -mdns_advertise_a(int fd, const char *name, const unsigned char *ip) -{ - int ret; - ResourceRecord *rr; - ResourceRecordRDataA *rdata; - int i; - - g_return_val_if_fail(name != NULL, -EINVAL); - g_return_val_if_fail(strlen(name) <= 255, -EINVAL); - g_return_val_if_fail(ip != NULL, -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; - ResourceRecord *rr; - - g_return_val_if_fail(name != NULL, -EINVAL); - g_return_val_if_fail(strlen(name) <= 255, -EINVAL); - - rr = (ResourceRecord *)g_malloc(sizeof(ResourceRecord)); - rr->name = g_strdup(name); - rr->type = RENDEZVOUS_RRTYPE_NULL; - rr->class = 0x0001; - rr->ttl = 0x00001c20; - rr->rdlength = rdlength; - 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_ptr(int fd, const char *name, const char *domain) -{ - return mdns_advertise_ptr_with_ttl(fd, name, domain, 0x00001c20); -} - -int -mdns_advertise_ptr_with_ttl(int fd, const char *name, const char *domain, int ttl) -{ - int ret; - ResourceRecord *rr; - - g_return_val_if_fail(name != NULL, -EINVAL); - g_return_val_if_fail(strlen(name) <= 255, -EINVAL); - g_return_val_if_fail(domain != NULL, -EINVAL); - g_return_val_if_fail(strlen(domain) <= 255, -EINVAL); - - rr = (ResourceRecord *)g_malloc(sizeof(ResourceRecord)); - rr->name = g_strdup(name); - rr->type = RENDEZVOUS_RRTYPE_PTR; - rr->class = 0x8001; - rr->ttl = ttl; - rr->rdata = (void *)g_strdup(domain); - rr->rdlength = mdns_getlength_rr_rdata(rr->type, rr->rdata); - - ret = mdns_send_rr(fd, rr); - - mdns_free_rr(rr); - - return ret; -} - -int -mdns_advertise_txt(int fd, const char *name, const GSList *rdata) -{ - int ret; - ResourceRecord *rr; - - g_return_val_if_fail(name != NULL, -EINVAL); - g_return_val_if_fail(strlen(name) <= 255, -EINVAL); - - rr = (ResourceRecord *)g_malloc(sizeof(ResourceRecord)); - rr->name = g_strdup(name); - rr->type = RENDEZVOUS_RRTYPE_TXT; - rr->class = 0x8001; - rr->ttl = 0x00001c20; - rr->rdlength = mdns_getlength_rr_rdata(rr->type, rdata); - 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_aaaa(int fd, const char *name, const unsigned char *ip) -{ - int ret; - ResourceRecord *rr; - ResourceRecordRDataA *rdata; - int i; - - g_return_val_if_fail(name != NULL, -EINVAL); - g_return_val_if_fail(strlen(name) <= 255, -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; - ResourceRecord *rr; - ResourceRecordRDataSRV *rdata; - - g_return_val_if_fail(name != NULL, -EINVAL); - g_return_val_if_fail(strlen(name) <= 255, -EINVAL); - - rdata = g_malloc(sizeof(ResourceRecordRDataSRV)); - rdata->port = port; - rdata->target = g_strdup(target); - - rr = (ResourceRecord *)g_malloc(sizeof(ResourceRecord)); - rr->name = g_strdup(name); - rr->type = RENDEZVOUS_RRTYPE_SRV; - rr->class = 0x8001; - rr->ttl = 0x00001c20; - rr->rdata = rdata; - rr->rdlength = mdns_getlength_rr_rdata(rr->type, rr->rdata); - - ret = mdns_send_rr(fd, rr); - - mdns_free_rr(rr); - - return ret; -} - -/***************************************/ -/* Functions for parsing mDNS messages */ -/***************************************/ - -/** - * Read in a domain name from the given buffer starting at the given - * offset. This handles using domain name compression to jump around - * the data buffer, if needed. - * - * @return A null-terminated string representation of the domain name. - * This should be g_free'd when no longer needed. - */ -static gchar * -mdns_read_name(const char *data, int datalen, unsigned int offset) -{ - GString *ret = g_string_new(""); - unsigned char tmp, newoffset; - - while ((offset <= datalen) && ((tmp = util_get8(&data[offset])) != 0)) { - offset++; - - if ((tmp & 0xc0) == 0) { /* First two bits are 00 */ - if (offset + tmp > datalen) - /* Attempt to read past end of data! Bailing! */ - return g_string_free(ret, TRUE); - if (*ret->str != '\0') - g_string_append_c(ret, '.'); - g_string_append_len(ret, &data[offset], tmp); - offset += tmp; - - } else if ((tmp & 0x40) == 0) { /* First two bits are 10 */ - /* Reserved for future use */ - - } else if ((tmp & 0x80) == 1) { /* First two bits are 01 */ - /* Reserved for future use */ - - } else { /* First two bits are 11 */ - /* Jump to another position in the data */ - newoffset = util_get8(&data[offset]); - if (newoffset >= offset) - /* Invalid pointer! Could lead to infinite recursion! Bailing! */ - return g_string_free(ret, TRUE); - offset = newoffset; - } - } - - if (offset > datalen) - return g_string_free(ret, TRUE); - - return g_string_free(ret, FALSE); -} - -/** - * Determine how many bytes long a portion of the domain name is - * at the given offset. This does NOT jump around the data array - * in the case of domain name compression. - * - * @return The length of the portion of the domain name. - */ -static int -mdns_read_name_len(const char *data, unsigned int datalen, unsigned int offset) -{ - int startoffset = offset; - unsigned char tmp; - - while ((offset <= datalen) && ((tmp = util_get8(&data[offset])) != 0)) { - offset++; - - if ((tmp & 0xc0) == 0) { /* First two bits are 00 */ - if (offset + tmp > datalen) - /* Attempt to read past end of data! Bailing! */ - return 0; - offset += tmp; - - } else if ((tmp & 0x40) == 0) { /* First two bits are 10 */ - /* Reserved for future use */ - - } else if ((tmp & 0x80) == 1) { /* First two bits are 01 */ - /* Reserved for future use */ - - } else { /* First two bits are 11 */ - /* End of this portion of the domain name */ - break; - - } - } - - return offset - startoffset + 1; -} - -/** - * - * - */ -static Question * -mdns_read_q(const char *data, unsigned int datalen, int *offset) -{ - Question *q; - - q = (Question *)g_malloc0(sizeof(Question)); - q->name = mdns_read_name(data, datalen, *offset); - *offset += mdns_read_name_len(data, datalen, *offset); - if (*offset + 4 > datalen) { - mdns_free_q(q); - return NULL; - } - - q->type = util_get16(&data[*offset]); /* QTYPE */ - *offset += 2; - q->class = util_get16(&data[*offset]); /* QCLASS */ - *offset += 2; - if (*offset > datalen) { - mdns_free_q(q); - return NULL; - } - - return q; -} - -/** - * - * - */ -static GSList * -mdns_read_questions(int numquestions, const char *data, unsigned int datalen, int *offset) -{ - GSList *ret = NULL; - Question *q; - int i; - - for (i = 0; i < numquestions; i++) { - q = mdns_read_q(data, datalen, offset); - if (q == NULL) - break; - ret = g_slist_append(ret, q); - } - - /* Malformed packet check */ - if (i < numquestions) { - mdns_free_qs(ret); - return NULL; - } - - return ret; -} - -/** - * Read in a chunk of data, probably a buddy icon. - * - */ -static unsigned char * -mdns_read_rr_rdata_null(const char *data, unsigned int datalen, unsigned int offset, unsigned short rdlength) -{ - unsigned char *ret = NULL; - - if (offset + rdlength > datalen) - return NULL; - - ret = (unsigned char *)g_malloc(rdlength); - memcpy(ret, &data[offset], rdlength); - - return ret; -} - -/** - * Read in a compressed name. - * - */ -static char * -mdns_read_rr_rdata_ptr(const char *data, unsigned int datalen, unsigned int offset) -{ - return mdns_read_name(data, datalen, offset); -} - -ResourceRecordRDataTXTNode * -mdns_txt_find(const GSList *ret, const char *name) -{ - ResourceRecordRDataTXTNode *node; - GSList *cur; - - for (cur = (GSList *)ret; cur != NULL; cur = cur->next) { - node = cur->data; - if (!strcasecmp(node->name, name)) - return node; - } - - return NULL; -} - -/** - * - * - */ -GSList * -mdns_txt_add(GSList *ret, const char *name, const char *value, gboolean replace) -{ - ResourceRecordRDataTXTNode *node; - - node = mdns_txt_find(ret, name); - - if (node == NULL) { - /* Add a new node */ - node = g_malloc(sizeof(ResourceRecordRDataTXTNode)); - node->name = g_strdup(name); - node->value = value != NULL ? g_strdup(value) : NULL; - ret = g_slist_append(ret, node); - } else { - /* Replace the value of the old node, or do nothing */ - if (replace) { - g_free(node->value); - node->value = value != NULL ? g_strdup(value) : NULL; - } - } - - return ret; -} - -/** - * Read in a list of name=value pairs as a GSList of - * ResourceRecordRDataTXTNodes. - * - */ -static GSList * -mdns_read_rr_rdata_txt(const char *data, unsigned int datalen, unsigned int offset, unsigned short rdlength) -{ - GSList *ret = NULL; - int endoffset = offset + rdlength; - unsigned char tmp; - char buf[256], *name, *value; - - while (offset < endoffset) { - /* Read in the length of the next name/value pair */ - tmp = util_get8(&data[offset]); - offset++; - - /* Malformed packet check */ - if (offset + tmp > endoffset) - break; - - /* Read in the next name/value pair */ - strncpy(buf, &data[offset], tmp); - offset += tmp; - - if (buf[0] == '=') { - /* Name/value pairs beginning with = are silently ignored */ - continue; - } - - /* The value is a substring of buf, starting just after the = */ - buf[tmp] = '\0'; - value = strchr(buf, '='); - if (value != NULL) { - value[0] = '\0'; - value++; - } - - /* Make the name all lowercase */ - name = g_utf8_strdown(buf, -1); - ret = mdns_txt_add(ret, name, value, FALSE); - g_free(name); - } - - /* Malformed packet check */ - if ((offset > datalen) || (offset != endoffset)) { - mdns_free_rr_rdata(RENDEZVOUS_RRTYPE_TXT, ret); - return NULL; - } - - return ret; -} - -/** - * - * - */ -static ResourceRecordRDataSRV * -mdns_read_rr_rdata_srv(const char *data, unsigned int datalen, unsigned int offset, unsigned short rdlength) -{ - ResourceRecordRDataSRV *ret = NULL; - int endoffset = offset + rdlength; - - /* Malformed packet check */ - if (offset + 7 > endoffset) - return NULL; - - ret = g_malloc(sizeof(ResourceRecordRDataSRV)); - - /* Read in the priority */ - ret->priority = util_get16(&data[offset]); - offset += 2; - - /* Read in the weight */ - ret->weight = util_get16(&data[offset]); - offset += 2; - - /* Read in the port */ - ret->port = util_get16(&data[offset]); - offset += 2; - - /* Read in the target name */ - /* - * XXX - RFC2782 says it's not supposed to be an alias... - * but it was in the packet capture I looked at from iChat. - */ - ret->target = mdns_read_name(data, datalen, offset); - offset += mdns_read_name_len(data, datalen, offset); - - /* Malformed packet check */ - if ((offset > endoffset) || (ret->target == NULL)) { - g_free(ret->target); - g_free(ret); - return NULL; - } - - return ret; -} - -/** - * - * - */ -static ResourceRecord * -mdns_read_rr(const char *data, unsigned int datalen, int *offset) -{ - ResourceRecord *rr; - - rr = (ResourceRecord *)g_malloc0(sizeof(ResourceRecord)); - - /* NAME */ - rr->name = mdns_read_name(data, datalen, *offset); - *offset += mdns_read_name_len(data, datalen, *offset); - - /* Malformed packet check */ - if (*offset + 10 > datalen) { - mdns_free_rr(rr); - return NULL; - } - - /* TYPE */ - rr->type = util_get16(&data[*offset]); - *offset += 2; - - /* CLASS */ - rr->class = util_get16(&data[*offset]); - *offset += 2; - - /* TTL */ - rr->ttl = util_get32(&data[*offset]); - *offset += 4; - - /* RDLENGTH */ - rr->rdlength = util_get16(&data[*offset]); - *offset += 2; - - /* RDATA */ - 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); - return NULL; - } - - } else if (rr->type == RENDEZVOUS_RRTYPE_PTR) { - rr->rdata = mdns_read_rr_rdata_ptr(data, datalen, *offset); - if (rr->rdata == NULL) { - mdns_free_rr(rr); - return NULL; - } - - } else if (rr->type == RENDEZVOUS_RRTYPE_TXT) { - rr->rdata = mdns_read_rr_rdata_txt(data, datalen, *offset, rr->rdlength); - if (rr->rdata == NULL) { - mdns_free_rr(rr); - 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) { - mdns_free_rr(rr); - return NULL; - } - - } - - /* Malformed packet check */ - *offset += rr->rdlength; - if (*offset > datalen) { - mdns_free_rr(rr); - return NULL; - } - - return rr; -} - -static GSList * -mdns_read_rrs(int numrecords, const char *data, unsigned int datalen, int *offset) -{ - GSList *ret = NULL; - ResourceRecord *rr; - int i; - - for (i = 0; i < numrecords; i++) { - rr = mdns_read_rr(data, datalen, offset); - if (rr == NULL) - break; - ret = g_slist_append(ret, rr); - } - - /* Malformed packet check */ - if (i < numrecords) { - mdns_free_rrs(ret); - return NULL; - } - - return ret; -} - -/** - * 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) -{ - DNSPacket *dns = NULL; - int offset; /* Current position in datagram */ - /* XXX - Find out what to use as a maximum incoming UDP packet size */ - /* XXX - Would making this static increase performance? */ - /* char data[512]; */ - char data[10096]; - unsigned int datalen; - struct sockaddr_in addr; - socklen_t addrlen; - GSList *cur; - - /* Read in an mDNS packet */ - addrlen = sizeof(struct sockaddr_in); - if ((datalen = recvfrom(fd, data, sizeof(data), 0, (struct sockaddr *)&addr, &addrlen)) == -1) { - gaim_debug_error("mdns", "Error reading packet: %d\n", errno); - return NULL; - } - - dns = (DNSPacket *)g_malloc0(sizeof(DNSPacket)); - - /* Parse the incoming packet, starting from 0 */ - offset = 0; - - if (offset + 12 > datalen) { - g_free(dns); - return NULL; - } - - /* The header section */ - dns->header.id = util_get16(&data[offset]); /* ID */ - offset += 2; - - /* 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 & 0x7800) != 0) { - /* OPCODE should be all 0's */ - g_free(dns); - return NULL; - } - - /* Read in the number of other things in the packet */ - dns->header.numquestions = util_get16(&data[offset]); - offset += 2; - dns->header.numanswers = util_get16(&data[offset]); - offset += 2; - dns->header.numauthority = util_get16(&data[offset]); - offset += 2; - dns->header.numadditional = util_get16(&data[offset]); - offset += 2; - - /* Read in all the questions */ - dns->questions = mdns_read_questions(dns->header.numquestions, data, datalen, &offset); - - /* Read in all resource records */ - dns->answers = mdns_read_rrs(dns->header.numanswers, data, datalen, &offset); - - /* Read in all authority records */ - dns->authority = mdns_read_rrs(dns->header.numauthority, data, datalen, &offset); - - /* Read in all additional records */ - dns->additional = mdns_read_rrs(dns->header.numadditional, data, datalen, &offset); - - /* Malformed packet check */ - if ((dns->header.numquestions > 0 && dns->questions == NULL) || - (dns->header.numanswers > 0 && dns->answers == NULL) || - (dns->header.numauthority > 0 && dns->authority == NULL) || - (dns->header.numadditional > 0 && dns->additional == NULL)) { - gaim_debug_error("mdns", "Received an invalid DNS packet.\n"); - return NULL; - } - - /* We should be at the end of the packet */ - if (offset != datalen) { - gaim_debug_error("mdns", "Finished parsing before end of DNS packet! Only parsed %d of %d bytes.", offset, datalen); - g_free(dns); - return NULL; - } - - for (cur = dns->answers; cur != NULL; cur = cur->next) - mdns_cache_add((ResourceRecord *)cur->data); - for (cur = dns->authority; cur != NULL; cur = cur->next) - mdns_cache_add((ResourceRecord *)cur->data); - for (cur = dns->additional; cur != NULL; cur = cur->next) - mdns_cache_add((ResourceRecord *)cur->data); - for (cur = dns->questions; cur != NULL; cur = cur->next) - mdns_cache_respond(fd, (Question *)cur->data); - - return dns; -} diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/mdns.h --- a/src/protocols/rendezvous/mdns.h Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -/** - * @file mdns.h Multicast DNS connection code used by rendezvous. - * - * 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 - * - */ - -/* - * TODO: Need to document a lot of these. - */ - -#ifndef _MDNS_H_ -#define _MDNS_H_ - -#include "internal.h" -#include "debug.h" - -/* - * Some #define's stolen from libfaim. Used to put - * binary data (bytes, shorts and ints) into an array. - */ -#define util_put8(buf, data) ((*(buf) = (unsigned char)(data)&0xff),1) -#define util_put16(buf, data) ( \ - (*(buf) = (unsigned char)((data)>>8)&0xff), \ - (*((buf)+1) = (unsigned char)(data)&0xff), \ - 2) -#define util_put32(buf, data) ( \ - (*((buf)) = (unsigned char)((data)>>24)&0xff), \ - (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \ - (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \ - (*((buf)+3) = (unsigned char)(data)&0xff), \ - 4) -#define util_get8(buf) ((*(buf))&0xff) -#define util_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff)) -#define util_get32(buf) ((((*(buf))<<24)&0xff000000) + \ - (((*((buf)+1))<<16)&0x00ff0000) + \ - (((*((buf)+2))<< 8)&0x0000ff00) + \ - (((*((buf)+3) )&0x000000ff))) - -/* - * Merriam-Webster's - */ -#define RENDEZVOUS_RRTYPE_A 1 -#define RENDEZVOUS_RRTYPE_NS 2 -#define RENDEZVOUS_RRTYPE_CNAME 5 -#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 - -/* - * Express for Men's - */ -typedef struct _Header { - unsigned short id; - unsigned short flags; - unsigned short numquestions; - unsigned short numanswers; - unsigned short numauthority; - unsigned short numadditional; -} Header; - -typedef struct _Question { - gchar *name; - unsigned short type; - unsigned short class; -} Question; - -typedef struct _ResourceRecord { - gchar *name; - unsigned short type; - unsigned short class; - int ttl; - unsigned short rdlength; - void *rdata; -} ResourceRecord; - -typedef unsigned char ResourceRecordRDataA; - -typedef struct _ResourceRecordRDataTXTNode { - char *name; - char *value; -} ResourceRecordRDataTXTNode; - -typedef GSList ResourceRecordRDataTXT; - -typedef unsigned char ResourceRecordRDataAAAA; - -typedef struct _ResourceRecordRDataSRV { - unsigned int priority; - unsigned int weight; - unsigned int port; - gchar *target; -} ResourceRecordRDataSRV; - -typedef struct _DNSPacket { - Header header; - GSList *questions; - GSList *answers; - GSList *authority; - GSList *additional; -} DNSPacket; - -/* - * Bring in 'Da Noise, Bring in 'Da Functions - */ - -/** - * Create a multicast socket that can be used for sending and - * receiving multicast DNS packets. The socket joins the - * link-local multicast group (224.0.0.251). - * - * @return The file descriptor of the new socket, or -1 if - * there was an error establishing the 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); - -/** - * Sends a multicast DNS datagram. Generally this is called - * by other convenience functions such as mdns_query(), however - * a client CAN construct its own DNSPacket if it wishes. - * - * @param fd The file descriptor of a pre-established socket to - * be used for sending the outgoing mDNS datagram. - * @param dns The DNS datagram you wish to send. - * @return 0 on success, otherwise return the error number. - */ -int mdns_send_dns(int fd, const DNSPacket *dns); - -/** - * Send a multicast DNS query for the given domain across the given - * socket. - * - * @param fd The file descriptor of a pre-established socket to - * be used for sending the outgoing mDNS datagram. - * @param domain This is the domain name you wish to query. It should - * be of the format "_presence._tcp.local" for example. - * @return 0 if successful. - */ -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, const 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_ptr_with_ttl(int fd, const char *name, const char *domain, int ttl); -int mdns_advertise_txt(int fd, const char *name, const GSList *txt); -int mdns_advertise_aaaa(int fd, const char *name, const unsigned char *ip); -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 - * into a DNSPacket. - * - * @param fd A UDP listening socket to read from. - * @return A newly allocated DNSPacket. This should be freed with - * mdns_free() when no longer needed. - */ -DNSPacket *mdns_read(int fd); - -/** - * Free a DNSPacket structure. - * - * @param dns The DNSPacket that you want to free. - */ -void mdns_free(DNSPacket *dns); -void mdns_free_rr(ResourceRecord *rr); -void mdns_free_rrs(GSList *rrs); - -ResourceRecord *mdns_copy_rr(const ResourceRecord *rr); - -ResourceRecordRDataTXTNode *mdns_txt_find(const GSList *ret, const char *name); - -GSList *mdns_txt_add(GSList *ret, const char *name, const char *value, gboolean replace); - - -#endif /* _MDNS_H_ */ diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/mdns_cache.c --- a/src/protocols/rendezvous/mdns_cache.c Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/** - * @file mdns_cache.c Multicast DNS resource record caching code. - * - * 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 - * - */ - -#include "internal.h" - -#include "mdns.h" -#include "mdns_cache.h" - -GSList *rrs = NULL; - -static ResourceRecord * -mdns_cache_find(const 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); - - new = mdns_copy_rr(rr); - rrs = g_slist_prepend(rrs, new); -} - -void -mdns_cache_remove(const gchar *name, unsigned short type) -{ - ResourceRecord *rr; - - g_return_if_fail(name != NULL); - g_return_if_fail((type != 0) && (type != RENDEZVOUS_RRTYPE_ALL)); - - rr = mdns_cache_find(name, type); - if (rr == NULL) - return; - - rrs = g_slist_remove(rrs, rr); - mdns_free_rr(rr); -} - -void -mdns_cache_remove_all() -{ - mdns_free_rrs(rrs); - rrs = NULL; -} - -void -mdns_cache_respond(int fd, const Question *q) -{ - GSList *slist; - ResourceRecord *cur; - - g_return_if_fail(q != NULL); - - for (slist = rrs; slist != NULL; slist = slist->next) { - cur = slist->data; - if (((q->type == RENDEZVOUS_RRTYPE_ALL) || (q->type == cur->type)) && (!strcmp(q->name, cur->name))) { - mdns_send_rr(fd, cur); - } - } -} diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/mdns_cache.h --- a/src/protocols/rendezvous/mdns_cache.h Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * @file mdns_cache.h Multicast DNS resource record caching code. - * - * 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 _MDNS_CACHE_H_ -#define _MDNS_CACHE_H_ - -#include "internal.h" -#include "debug.h" - -#include "mdns.h" - -/** - * - */ -void mdns_cache_add(const ResourceRecord *rr); - -/** - * - */ -void mdns_cache_remove(const gchar *name, unsigned short type); - -/** - * - */ -void mdns_cache_remove_all(); - -/** - * - */ -void mdns_cache_respond(int fd, const Question *q); - -#endif /* _MDNS_CACHE_H_ */ diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/rendezvous.c --- a/src/protocols/rendezvous/rendezvous.c Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,860 +0,0 @@ -/* - * 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 "account.h" -#include "accountopt.h" -#include "blist.h" -#include "conversation.h" -#include "cipher.h" -#include "debug.h" -#include "network.h" -#include "prpl.h" -#include "version.h" - -#include "direct.h" -#include "mdns.h" -#include "rendezvous.h" -#include "util.h" - -/****************************/ -/* Utility Functions */ -/****************************/ -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); -} - -/** - * Extract the "user@host" name from a full presence domain - * of the form "user@host._presence._tcp.local" - * - * @return If the domain is NOT a _presence._tcp.local domain - * then return NULL. Otherwise return a newly allocated - * null-terminated string containing the "user@host" for - * the given domain. This string should be g_free'd - * when no longer needed. - */ -static gchar * -rendezvous_extract_name(gchar *domain) -{ - gchar *ret, *suffix; - - if (!gaim_str_has_suffix(domain, "._presence._tcp.local")) - return NULL; - - suffix = strstr(domain, "._presence._tcp.local"); - ret = g_strndup(domain, suffix - domain); - - return ret; -} - -/****************************/ -/* Buddy List Functions */ -/****************************/ - -static RendezvousBuddy * -rendezvous_find_or_create_rendezvousbuddy(GaimConnection *gc, const char *name) -{ - RendezvousData *rd = gc->proto_data; - RendezvousBuddy *rb; - - rb = g_hash_table_lookup(rd->buddies, name); - if (rb == NULL) { - rb = g_malloc0(sizeof(RendezvousBuddy)); - rb->fd = -1; - rb->watcher = -1; - g_hash_table_insert(rd->buddies, g_strdup(name), rb); - } - - return rb; -} - -static void -rendezvous_addtolocal(GaimConnection *gc, const char *name, const char *domain) -{ - GaimAccount *account = gaim_connection_get_account(gc); - GaimBuddy *b; - GaimGroup *g; - - g = gaim_find_group(domain); - if (g == NULL) { - g = gaim_group_new(domain); - gaim_blist_add_group(g, NULL); - } - - b = gaim_find_buddy_in_group(account, name, g); - if (b != NULL) - return; - - b = gaim_buddy_new(account, name, NULL); - gaim_blist_node_set_flags((GaimBlistNode *)b, GAIM_BLIST_NODE_FLAG_NO_SAVE); - /* gaim_blist_node_set_flag(b, GAIM_BLIST_NODE_FLAG_NO_SAVE); */ - gaim_blist_add_buddy(b, NULL, g, NULL); - gaim_prpl_got_user_status(account, b->name, "online", NULL); - -#if 0 - /* Remove the buddy if the TTL on their PTR record expires */ - RendezvousBuddy *rb; - rb = rendezvous_find_or_create_rendezvousbuddy(gc, name); - rb->ttltimer = gaim_timeout_add(time * 10000, rendezvous_buddy_timeout, gc); - - gaim_timeout_remove(rb->ttltimer); - rb->ttltimer = 0; -#endif -} - -static void -rendezvous_removefromlocal(GaimConnection *gc, const char *name, const char *domain) -{ - GaimAccount *account = gaim_connection_get_account(gc); - GaimBuddy *b; - GaimGroup *g; - - g = gaim_find_group(domain); - if (g == NULL) - return; - - b = gaim_find_buddy_in_group(account, name, g); - if (b == NULL) - return; - - gaim_prpl_got_user_status(account, b->name, "offline", NULL); - gaim_blist_remove_buddy(b); - /* XXX - This results in incorrect group counts--needs to be fixed in the core */ - /* XXX - We also need to call remove_idle_buddy() in server.c for idle buddies */ - - /* - * XXX - Instead of removing immediately, wait 10 seconds and THEN remove - * them. If you do it immediately you don't see the door close icon. - */ -} - -static void -rendezvous_removeallfromlocal(GaimConnection *gc) -{ - GaimAccount *account = gaim_connection_get_account(gc); - GaimBuddyList *blist; - GaimBlistNode *gnode, *cnode, *bnode; - GaimBuddy *b; - - /* Go through and remove all buddies that belong to this account */ - if ((blist = gaim_get_blist()) != NULL) { - for (gnode = blist->root; gnode; gnode = gnode->next) { - if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) - continue; - for (cnode = gnode->child; cnode; cnode = cnode->next) { - if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for (bnode = cnode->child; bnode; bnode = bnode->next) { - if (!GAIM_BLIST_NODE_IS_BUDDY(bnode)) - continue; - b = (GaimBuddy *)bnode; - if (b->account != account) - continue; - gaim_prpl_got_user_status(account, b->name, "offline", NULL); - gaim_blist_remove_buddy(b); - } - } - } - } -} - -static gboolean -rendezvous_find_buddy_by_host(gpointer key, gpointer value, gpointer user_data) -{ - const gchar *domain; - - if (key == NULL) - return FALSE; - - domain = strchr(key, '@'); - if (domain == NULL) - return FALSE; - domain++; - - return !strcasecmp(user_data, domain); -} - -static void -rendezvous_handle_rr_a(GaimConnection *gc, ResourceRecord *rr, const gchar *name) -{ - RendezvousData *rd = gc->proto_data; - RendezvousBuddy *rb; - ResourceRecordRDataSRV *rdata; - const gchar *end; - gchar *domain; - - /* - * Remove the trailing ".local" from the domain. If there is no - * trailing ".local" then do nothing and exit - */ - end = g_strrstr(name, ".local"); - if (end == NULL) - return; - - domain = g_strndup(name, (gpointer)end - (gpointer)name); - rb = g_hash_table_find(rd->buddies, rendezvous_find_buddy_by_host, domain); - g_free(domain); - - if (rb == NULL) - return; - - rdata = rr->rdata; - - memcpy(rb->ipv4, rdata, 4); -} - -static void -rendezvous_handle_rr_txt(GaimConnection *gc, ResourceRecord *rr, const gchar *name) -{ - GaimAccount *account = gaim_connection_get_account(gc); - RendezvousBuddy *rb; - GSList *rdata; - ResourceRecordRDataTXTNode *node1, *node2; - - rdata = rr->rdata; - - /* Don't do a damn thing if the version is greater than 1 */ - node1 = mdns_txt_find(rdata, "version"); - if ((node1 == NULL) || (node1->value == NULL) || (strcmp(node1->value, "1"))) - return; - - rb = rendezvous_find_or_create_rendezvousbuddy(gc, name); - - node1 = mdns_txt_find(rdata, "1st"); - node2 = mdns_txt_find(rdata, "last"); - g_free(rb->firstandlast); - rb->firstandlast = g_strdup_printf("%s%s%s", - (node1 && node1->value ? node1->value : ""), - (node1 && node1->value && node2 && node2->value ? " " : ""), - (node2 && node2->value ? node2->value : "")); - serv_got_alias(gc, name, rb->firstandlast); - - node1 = mdns_txt_find(rdata, "aim"); - if ((node1 != NULL) && (node1->value != NULL)) { - g_free(rb->aim); - rb->aim = g_strdup(node1->value); - } - - /* - * We only want to use this port as a back-up. Ideally the port - * is specified in a separate, SRV resource record. - */ - if (rb->p2pjport == 0) { - node1 = mdns_txt_find(rdata, "port.p2pj"); - if ((node1 != NULL) && (node1->value)) - rb->p2pjport = atoi(node1->value); - } - - node1 = mdns_txt_find(rdata, "status"); - if ((node1 != NULL) && (node1->value != NULL)) { - if (!strcmp(node1->value, "avail")) { - /* Available */ - rb->status = 0; - } else if (!strcmp(node1->value, "away")) { - /* Idle */ - node2 = mdns_txt_find(rdata, "away"); - if ((node2 != NULL) && (node2->value)) { - /* Time is seconds since January 1st 2001 GMT */ - rb->idle = atoi(node2->value); - rb->idle += 978307200; /* convert to seconds-since-epoch */ - } - rb->status = UC_IDLE; - /* TODO: Do this when the user is added to the buddy list? Definitely not here! */ - /* gaim_prpl_got_user_idle(account, name, TRUE, rb->idle); */ - } else if (!strcmp(node1->value, "dnd")) { - /* Away */ - rb->status = UC_UNAVAILABLE; - } - gaim_prpl_got_user_status(account, name, "online", NULL); - /* XXX - Idle time is rb->idle and status is rb->status */ - } - - node1 = mdns_txt_find(rdata, "msg"); - if ((node1 != NULL) && (node1->value != NULL)) { - g_free(rb->msg); - rb->msg = g_strdup(node1->value); - } -} - -static void -rendezvous_handle_rr_aaaa(GaimConnection *gc, ResourceRecord *rr, const gchar *name) -{ - RendezvousData *rd = gc->proto_data; - RendezvousBuddy *rb; - ResourceRecordRDataSRV *rdata; - const gchar *end; - gchar *domain; - - /* - * Remove the trailing ".local" from the domain. If there is no - * trailing ".local" then do nothing and exit - */ - end = g_strrstr(name, ".local"); - if (end == NULL) - return; - - domain = g_strndup(name, (gpointer)end - (gpointer)name); - rb = g_hash_table_find(rd->buddies, rendezvous_find_buddy_by_host, domain); - g_free(domain); - - if (rb == NULL) - return; - - rdata = rr->rdata; - - memcpy(rb->ipv6, rdata, 16); -} - -static void -rendezvous_handle_rr_srv(GaimConnection *gc, ResourceRecord *rr, const gchar *name) -{ - RendezvousBuddy *rb; - ResourceRecordRDataSRV *rdata; - - rdata = rr->rdata; - - rb = rendezvous_find_or_create_rendezvousbuddy(gc, name); - - rb->p2pjport = rdata->port; -} - -/* - * Parse a resource record and do stuff if we need to. - */ -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 and type %d\n", rr->name, rr->type); - - switch (rr->type) { - case RENDEZVOUS_RRTYPE_A: { - rendezvous_handle_rr_a(gc, rr, rr->name); - } break; - - case RENDEZVOUS_RRTYPE_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); - } - - g_free(name); - } - } break; - - case RENDEZVOUS_RRTYPE_PTR: { - gchar *rdata = rr->rdata; - - 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"); - mdns_query(rd->fd, rdata, RENDEZVOUS_RRTYPE_NULL); - } else { - /* Remove them from our buddy list */ - rendezvous_removefromlocal(gc, name, "Rendezvous"); - } - g_free(name); - } - } break; - - case RENDEZVOUS_RRTYPE_TXT: { - name = rendezvous_extract_name(rr->name); - if (name != NULL) { - rendezvous_handle_rr_txt(gc, rr, name); - g_free(name); - } - } break; - - case RENDEZVOUS_RRTYPE_AAAA: { - rendezvous_handle_rr_aaaa(gc, rr, rr->name); - } break; - - case RENDEZVOUS_RRTYPE_SRV: { - name = rendezvous_extract_name(rr->name); - if (name != NULL) { - rendezvous_handle_rr_srv(gc, rr, name); - g_free(name); - } - } break; - } -} - -/****************************/ -/* Connection Functions */ -/****************************/ -static void -rendezvous_callback(gpointer data, gint source, GaimInputCondition condition) -{ - GaimConnection *gc = data; - RendezvousData *rd = gc->proto_data; - DNSPacket *dns; - GSList *cur; - - gaim_debug_misc("rendezvous", "Received rendezvous datagram\n"); - - dns = mdns_read(rd->fd); - if (dns == NULL) - return; - - /* Handle the DNS packet */ - for (cur = dns->answers; cur != NULL; cur = cur->next) - rendezvous_handle_rr(gc, cur->data); - for (cur = dns->authority; cur != NULL; cur = cur->next) - rendezvous_handle_rr(gc, cur->data); - for (cur = dns->additional; cur != NULL; cur = cur->next) - rendezvous_handle_rr(gc, cur->data); - - mdns_free(dns); -} - -static void -rendezvous_add_to_txt(RendezvousData *rd, const char *name, const char *value) -{ - 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); -} - -static guchar * -rendezvous_read_icon_data(const char *filename, unsigned short *length) -{ - struct stat st; - FILE *file; - guchar *data; - - *length = 0; - - g_return_val_if_fail(filename != NULL, NULL); - - if (g_stat(filename, &st)) - return NULL; - - if (!(file = g_fopen(filename, "rb"))) - return NULL; - - *length = st.st_size; - data = g_malloc(*length); - fread(data, 1, *length, file); - fclose(file); - - return data; -} - -static void -rendezvous_add_to_txt_iconhash(RendezvousData *rd, const char *iconfile) -{ - guchar *icondata; - unsigned short iconlength; - guchar hash[20]; - gchar *base16; - - g_return_if_fail(rd != NULL); - - if (iconfile == NULL) - return; - - icondata = rendezvous_read_icon_data(iconfile, &iconlength); - gaim_cipher_digest_region("sha1", (guchar *)icondata, iconlength, sizeof(hash), hash, NULL); - g_free(icondata); - - base16 = gaim_base16_encode(hash, 20); - rendezvous_add_to_txt(rd, "phsh", base16); - g_free(base16); -} - -static void -rendezvous_send_icon(GaimConnection *gc) -{ - RendezvousData *rd = gc->proto_data; - GaimAccount *account = gaim_connection_get_account(gc); - const char *iconfile = gaim_account_get_buddy_icon(account); - unsigned char *rdata; - unsigned short rdlength; - gchar *myname; - - if (iconfile == NULL) - return; - - rdata = rendezvous_read_icon_data(iconfile, &rdlength); - - myname = g_strdup_printf("%s._presence._tcp.local", gaim_account_get_username(account)); - mdns_advertise_null(rd->fd, myname, rdata, rdlength); - g_free(myname); - - g_free(rdata); -} - -static void -rendezvous_send_online(GaimConnection *gc) -{ - RendezvousData *rd = gc->proto_data; - GaimAccount *account = gaim_connection_get_account(gc); - const gchar *me, *myip; - gchar *myname, *mycomp, *myport; - gchar **mysplitip; - 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); - myport = g_strdup_printf("%d", rd->listener_port); - - myip = gaim_network_get_local_system_ip(-1); - mysplitip = g_strsplit(myip, ".", 0); - myipv4[0] = atoi(mysplitip[0]); - myipv4[1] = atoi(mysplitip[1]); - myipv4[2] = atoi(mysplitip[2]); - myipv4[3] = atoi(mysplitip[3]); - g_strfreev(mysplitip); - - mdns_advertise_a(rd->fd, mycomp, myipv4); - mdns_advertise_ptr(rd->fd, "_presence._tcp.local", myname); - mdns_advertise_srv(rd->fd, myname, rd->listener_port, 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_iconhash(rd, gaim_account_get_buddy_icon(account)); - rendezvous_add_to_txt(rd, "1st", gaim_account_get_string(account, "first", "Gaim")); - 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_normalize(cur, 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", myport); - rendezvous_add_to_txt(rd, "last", gaim_account_get_string(account, "last", _("User"))); - mdns_advertise_txt(rd->fd, myname, rd->mytxtdata); - - rendezvous_send_icon(gc); - - g_free(myname); - g_free(mycomp); - g_free(myport); -} - -static void -rendezvous_send_offline(GaimConnection *gc) -{ - RendezvousData *rd = gc->proto_data; - GaimAccount *account = gaim_connection_get_account(gc); - const gchar *me; - gchar *myname; - - me = gaim_account_get_username(account); - myname = g_strdup_printf("%s._presence._tcp.local", me); - - mdns_advertise_ptr_with_ttl(rd->fd, "_presence._tcp.local", myname, 0); -} - -/***********************************/ -/* All the PRPL Callback Functions */ -/***********************************/ -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) -{ - if (GAIM_BUDDY_IS_ONLINE(b)) { - if (b->uc & UC_UNAVAILABLE) - *se = "away"; - } else { - *se = "offline"; - } -} - -static gchar * -rendezvous_prpl_status_text(GaimBuddy *b) -{ - GaimConnection *gc = b->account->gc; - RendezvousData *rd = gc->proto_data; - RendezvousBuddy *rb; - gchar *ret; - - rb = g_hash_table_lookup(rd->buddies, b->name); - if ((rb == NULL) || (rb->msg == NULL)) - return NULL; - - ret = g_strdup(rb->msg); - - return ret; -} - -static gchar * -rendezvous_prpl_tooltip_text(GaimBuddy *b) -{ - GaimConnection *gc = b->account->gc; - RendezvousData *rd = gc->proto_data; - RendezvousBuddy *rb; - GString *ret; - - rb = g_hash_table_lookup(rd->buddies, b->name); - if (rb == NULL) - return NULL; - - ret = g_string_new(""); - - if (rb->aim != NULL) - g_string_append_printf(ret, "\n%s: %s", _("AIM Screen name"), rb->aim); - - if (rb->msg != NULL) { - if (rb->status == UC_UNAVAILABLE) - g_string_append_printf(ret, "\n%s: %s", _("Away"), rb->msg); - else - g_string_append_printf(ret, "\n%s: %s", _("Available"), rb->msg); - } - - return g_string_free(ret, FALSE); -} - -static GList * -rendezvous_prpl_status_types(GaimAccount *account) -{ - GList *status_types = NULL; - GaimStatusType *type; - - type = gaim_status_type_new_full(GAIM_STATUS_OFFLINE, "offline", _("Offline"), FALSE, TRUE, FALSE); - status_types = g_list_append(status_types, type); - - type = gaim_status_type_new_with_attrs(GAIM_STATUS_ONLINE, "available", _("Available"), FALSE, TRUE, FALSE, "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); - status_types = g_list_append(status_types, type); - - type = gaim_status_type_new_with_attrs(GAIM_STATUS_AWAY, "away", _("Away"), TRUE, TRUE, FALSE, "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); - status_types = g_list_append(status_types, type); - - return status_types; -} - -static void -rendezvous_prpl_login(GaimAccount *account, GaimStatus *status) -{ - GaimConnection *gc = gaim_account_get_connection(account); - RendezvousData *rd; - - rd = g_new0(RendezvousData, 1); - rd->buddies = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, rendezvous_buddy_free); - gc->proto_data = rd; - - 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 establish mDNS socket.")); - return; - } - - /* - * Watch our listening multicast UDP socket for incoming DNS - * packets. - */ - gc->inpa = gaim_input_add(rd->fd, GAIM_INPUT_READ, rendezvous_callback, gc); - - gaim_connection_set_state(gc, GAIM_CONNECTED); - - mdns_query(rd->fd, "_presence._tcp.local", RENDEZVOUS_RRTYPE_ALL); - rendezvous_send_online(gc); -} - -static void -rendezvous_prpl_close(GaimConnection *gc) -{ - RendezvousData *rd = (RendezvousData *)gc->proto_data; - ResourceRecordRDataTXTNode *node; - - rendezvous_send_offline(gc); - - if (gc->inpa) - gaim_input_remove(gc->inpa); - - rendezvous_removeallfromlocal(gc); - - 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) { - 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); -} - -static int -rendezvous_prpl_send_im(GaimConnection *gc, const char *who, const char *message, GaimConvImFlags flags) -{ - gaim_debug_info("rendezvous", "Sending IM\n"); - - /* - * TODO: Need to interpret any GaimConvImFlags here, before - * calling rendezvous_direct_send_message(). - */ - rendezvous_direct_send_message(gc, who, message); - - 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; - -static GaimPluginInfo info = -{ - GAIM_PLUGIN_MAGIC, - GAIM_MAJOR_VERSION, - GAIM_MINOR_VERSION, - GAIM_PLUGIN_PROTOCOL, /**< type */ - NULL, /**< ui_requirement */ - 0, /**< flags */ - NULL, /**< dependencies */ - GAIM_PRIORITY_DEFAULT, /**< priority */ - - "prpl-rendezvous", /**< id */ - "Rendezvous", /**< name */ - VERSION, /**< version */ - /** summary */ - N_("Rendezvous Protocol Plugin"), - /** description */ - N_("Rendezvous Protocol Plugin"), - NULL, /**< author */ - GAIM_WEBSITE, /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - NULL -}; - -static void init_plugin(GaimPlugin *plugin) -{ - GaimAccountUserSplit *split; - GaimAccountOption *option; - char hostname[255]; - - gaim_debug_register_category("mdns"); - gaim_debug_register_category("rendezvous"); - - prpl_info.options = OPT_PROTO_NO_PASSWORD; - prpl_info.icon_spec.format = "jpeg"; - prpl_info.icon_spec.min_width = 0; - prpl_info.icon_spec.min_height = 0; - prpl_info.icon_spec.max_width = 0; - prpl_info.icon_spec.max_height = 0; - prpl_info.icon_spec.scale_rules = 0; - prpl_info.list_icon = rendezvous_prpl_list_icon; - prpl_info.list_emblems = rendezvous_prpl_list_emblems; - prpl_info.status_text = rendezvous_prpl_status_text; - prpl_info.tooltip_text = rendezvous_prpl_tooltip_text; - prpl_info.status_types = rendezvous_prpl_status_types; - 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); - strcpy(hostname, "localhost"); - } - - /* Try to avoid making this configurable... */ - 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"); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - - option = gaim_account_option_string_new(_("Last name"), "last", _("User")); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - - option = gaim_account_option_bool_new(_("Share AIM screen name"), "shareaim", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - - my_protocol = plugin; -} - -GAIM_INIT_PLUGIN(rendezvous, init_plugin, info); diff -r a511b77a368b -r 6ee53c79d630 src/protocols/rendezvous/rendezvous.h --- a/src/protocols/rendezvous/rendezvous.h Fri Aug 12 23:53:28 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/** - * @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; - unsigned char ipv4[4]; /**< An IPv4 address */ - unsigned char ipv6[16]; /**< 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_ */