# HG changeset patch # User Mark Doliner # Date 1108350523 0 # Node ID 913ec44675c34a64ece2464ec97157eea62daed0 # Parent de34037a02c7310056fca566ee2e48475414503f [gaim-migrate @ 12011] Get some rendezvous stuff out of my tree. No, you still can't get or send IMs. committer: Tailor Script diff -r de34037a02c7 -r 913ec44675c3 src/protocols/rendezvous/direct.c --- a/src/protocols/rendezvous/direct.c Mon Feb 14 03:07:06 2005 +0000 +++ b/src/protocols/rendezvous/direct.c Mon Feb 14 03:08:43 2005 +0000 @@ -27,42 +27,33 @@ #include "direct.h" #include "rendezvous.h" -#if 0 -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) +rendezvous_find_buddy_by_ipv4(gpointer key, gpointer value, gpointer user_data) { RendezvousBuddy *rb = value; if (rb->ipv4 == NULL) return FALSE; -printf("looking at ip=%hu.%hu.%hu.%hu\n", rb->ipv4[0], rb->ipv4[1], rb->ipv4[2], rb->ipv4[3]); +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); } -#endif + +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) @@ -72,10 +63,7 @@ int fd; struct sockaddr_in6 addr; socklen_t addrlen = sizeof(addr); -#if 0 - gchar *ip; -#endif - RendezvousBuddy *rb; + RendezvousBuddy *rb = NULL; fd = accept(rd->listener, (struct sockaddr *)&addr, &addrlen); if (fd == -1) { @@ -83,17 +71,10 @@ return; } -#if 0 - 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); + 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) - 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); -#endif + 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 */ @@ -104,4 +85,80 @@ 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 de34037a02c7 -r 913ec44675c3 src/protocols/rendezvous/direct.h --- a/src/protocols/rendezvous/direct.h Mon Feb 14 03:07:06 2005 +0000 +++ b/src/protocols/rendezvous/direct.h Mon Feb 14 03:08:43 2005 +0000 @@ -29,6 +29,10 @@ #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 de34037a02c7 -r 913ec44675c3 src/protocols/rendezvous/mdns.c --- a/src/protocols/rendezvous/mdns.c Mon Feb 14 03:07:06 2005 +0000 +++ b/src/protocols/rendezvous/mdns.c Mon Feb 14 03:08:43 2005 +0000 @@ -847,6 +847,12 @@ 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; @@ -859,7 +865,7 @@ rr->name = g_strdup(name); rr->type = RENDEZVOUS_RRTYPE_PTR; rr->class = 0x8001; - rr->ttl = 0x00001c20; + rr->ttl = ttl; rr->rdata = (void *)g_strdup(domain); rr->rdlength = mdns_getlength_rr_rdata(rr->type, rr->rdata); diff -r de34037a02c7 -r 913ec44675c3 src/protocols/rendezvous/mdns.h --- a/src/protocols/rendezvous/mdns.h Mon Feb 14 03:07:06 2005 +0000 +++ b/src/protocols/rendezvous/mdns.h Mon Feb 14 03:08:43 2005 +0000 @@ -23,6 +23,10 @@ * */ +/* + * TODO: Need to document a lot of these. + */ + #ifndef _MDNS_H_ #define _MDNS_H_ @@ -131,7 +135,6 @@ */ int mdns_socket_establish(); - /** * Close a multicast socket. This also clears the MDNS * cache. @@ -140,7 +143,6 @@ */ void mdns_socket_close(int fd); - /** * Sends a multicast DNS datagram. Generally this is called * by other convenience functions such as mdns_query(), however @@ -169,6 +171,7 @@ 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); @@ -195,6 +198,7 @@ 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); diff -r de34037a02c7 -r 913ec44675c3 src/protocols/rendezvous/rendezvous.c --- a/src/protocols/rendezvous/rendezvous.c Mon Feb 14 03:07:06 2005 +0000 +++ b/src/protocols/rendezvous/rendezvous.c Mon Feb 14 03:08:43 2005 +0000 @@ -123,6 +123,7 @@ 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); @@ -188,16 +189,48 @@ } } +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; - rb = rendezvous_find_or_create_rendezvousbuddy(gc, name); - memcpy(rb->ipv4, rdata, 4); } @@ -277,13 +310,29 @@ 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; - rb = rendezvous_find_or_create_rendezvousbuddy(gc, name); - memcpy(rb->ipv6, rdata, 16); } @@ -313,11 +362,7 @@ switch (rr->type) { case RENDEZVOUS_RRTYPE_A: { - name = rendezvous_extract_name(rr->name); - if (name != NULL) { - rendezvous_handle_rr_a(gc, rr, name); - g_free(name); - } + rendezvous_handle_rr_a(gc, rr, rr->name); } break; case RENDEZVOUS_RRTYPE_NULL: { @@ -358,11 +403,7 @@ } break; case RENDEZVOUS_RRTYPE_AAAA: { - name = rendezvous_extract_name(rr->name); - if (name != NULL) { - rendezvous_handle_rr_aaaa(gc, rr, name); - g_free(name); - } + rendezvous_handle_rr_aaaa(gc, rr, rr->name); } break; case RENDEZVOUS_RRTYPE_SRV: { @@ -376,85 +417,6 @@ } /****************************/ -/* Icon and Emblem 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_full(GAIM_STATUS_ONLINE, "online", _("Online"), FALSE, TRUE, FALSE); - status_types = g_list_append(status_types, type); - - return status_types; -} - -/****************************/ /* Connection Functions */ /****************************/ static void @@ -599,8 +561,7 @@ 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")) { - /* XXX - Should the name be normalized? */ - rendezvous_add_to_txt(rd, "AIM", gaim_account_get_username(cur)); + rendezvous_add_to_txt(rd, "AIM", gaim_normalize(cur, gaim_account_get_username(cur))); break; } } @@ -619,6 +580,99 @@ } 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_full(GAIM_STATUS_ONLINE, "online", _("Online"), FALSE, TRUE, FALSE); + 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); @@ -646,7 +700,12 @@ 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); @@ -659,6 +718,8 @@ RendezvousData *rd = (RendezvousData *)gc->proto_data; ResourceRecordRDataTXTNode *node; + rendezvous_send_offline(gc); + if (gc->inpa) gaim_input_remove(gc->inpa); @@ -691,18 +752,13 @@ static int rendezvous_prpl_send_im(GaimConnection *gc, const char *who, const char *message, GaimConvImFlags flags) { - RendezvousData *rd = gc->proto_data; - RendezvousBuddy *rb; - gaim_debug_info("rendezvous", "Sending IM\n"); - 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); - } - - /* TODO: Establish a direct connection then send IM. Will need to queue the message somewhere. */ + /* + * TODO: Need to interpret any GaimConvImFlags here, before + * calling rendezvous_direct_send_message(). + */ + rendezvous_direct_send_message(gc, who, message); return 1; }