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