im.pidgin.pidgin: 3531b34b0f7b83dfa1705ca1d133ea83293d79b2
datallah at pidgin.im
datallah at pidgin.im
Fri Jan 4 15:45:48 EST 2008
-----------------------------------------------------------------
Revision: 3531b34b0f7b83dfa1705ca1d133ea83293d79b2
Ancestor: 79d3af412f1d67bac1a2a9614ace068e7dc753db
Author: datallah at pidgin.im
Date: 2008-01-04T20:41:08
Branch: im.pidgin.pidgin
Modified files:
libpurple/protocols/bonjour/mdns_win32.c
ChangeLog:
Detect the mdnsresponder crashing in the DnsSD implementation and disconnect the account instead of pegging the CPU.
-------------- next part --------------
============================================================
--- libpurple/protocols/bonjour/mdns_win32.c fc40611da25da58c5de43c1663d496070021755a
+++ libpurple/protocols/bonjour/mdns_win32.c 38ceb904cf4ad04b7a57106ac9887db1c8708f09
@@ -30,19 +30,21 @@ static GSList *pending_buddies = NULL;
static GSList *pending_buddies = NULL;
+typedef struct _dnssd_service_ref_handler {
+ DNSServiceRef sdRef;
+ PurpleAccount *account;
+ guint input_handler;
+} DnsSDServiceRefHandlerData;
+
/* data used by win32 bonjour implementation */
typedef struct _win32_session_impl_data {
- DNSServiceRef presence_svc;
- DNSServiceRef browser_svc;
+ DnsSDServiceRefHandlerData *presence_query;
+ DnsSDServiceRefHandlerData *browser_query;
DNSRecordRef buddy_icon_rec;
-
- guint presence_handler;
- guint browser_handler;
} Win32SessionImplData;
typedef struct _win32_buddy_service_resolver_data {
- DNSServiceRef txt_query;
- guint txt_query_handler;
+ DnsSDServiceRefHandlerData *txt_query;
uint32_t if_idx;
gchar *name;
gchar *type;
@@ -53,21 +55,20 @@ typedef struct _win32_buddy_impl_data {
typedef struct _win32_buddy_impl_data {
GSList *resolvers;
- DNSServiceRef null_query;
- guint null_query_handler;
+ DnsSDServiceRefHandlerData *null_query;
} Win32BuddyImplData;
/* data structure for the resolve callback */
typedef struct _ResolveCallbackArgs {
- DNSServiceRef resolver;
- guint resolver_handler;
+ DnsSDServiceRefHandlerData *resolver_query;
PurpleAccount *account;
BonjourBuddy *bb;
Win32SvcResolverData *res_data;
gchar *full_service_name;
- PurpleDnsQueryData *query;
+ PurpleDnsQueryData *dns_query;
} ResolveCallbackArgs;
+
static gint
_find_resolver_data(gconstpointer a, gconstpointer b) {
const Win32SvcResolverData *rd_a = a;
@@ -87,8 +88,9 @@ _cleanup_resolver_data(Win32SvcResolverD
static void
_cleanup_resolver_data(Win32SvcResolverData *rd) {
if (rd->txt_query != NULL) {
- purple_input_remove(rd->txt_query_handler);
- DNSServiceRefDeallocate(rd->txt_query);
+ purple_input_remove(rd->txt_query->input_handler);
+ DNSServiceRefDeallocate(rd->txt_query->sdRef);
+ g_free(rd->txt_query);
}
g_free(rd->name);
g_free(rd->type);
@@ -98,7 +100,16 @@ _mdns_handle_event(gpointer data, gint s
static void
_mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition) {
- DNSServiceProcessResult((DNSServiceRef) data);
+ DnsSDServiceRefHandlerData *srh = data;
+ DNSServiceErrorType errorCode = DNSServiceProcessResult(srh->sdRef);
+ if (errorCode != kDNSServiceErr_NoError) {
+ purple_debug_error("bonjour", "Error (%d) handling mDNS response.\n", errorCode);
+ /* This happens when the mDNSResponder goes down, I haven't seen it happen any other time (in my limited testing) */
+ if (errorCode == kDNSServiceErr_Unknown) {
+ purple_connection_error_reason(srh->account->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+ _("Error communicating with local mDNSResponder."));
+ }
+ }
}
static void
@@ -142,9 +153,9 @@ _mdns_record_query_callback(DNSServiceRe
bonjour_buddy_got_buddy_icon(bb, rdata, rdlen);
/* We've got what we need; stop listening */
- purple_input_remove(idata->null_query_handler);
- idata->null_query_handler = 0;
- DNSServiceRefDeallocate(idata->null_query);
+ purple_input_remove(idata->null_query->input_handler);
+ DNSServiceRefDeallocate(idata->null_query->sdRef);
+ g_free(idata->null_query);
idata->null_query = NULL;
}
}
@@ -153,7 +164,7 @@ _mdns_resolve_host_callback(GSList *host
static void
_mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message)
{
- ResolveCallbackArgs* args = (ResolveCallbackArgs*) data;
+ ResolveCallbackArgs *args = (ResolveCallbackArgs*) data;
Win32BuddyImplData *idata = args->bb->mdns_impl_data;
gboolean delete_buddy = FALSE;
PurpleBuddy *pb;
@@ -169,10 +180,10 @@ _mdns_resolve_host_callback(GSList *host
} else {
struct sockaddr_in *addr = g_slist_nth_data(hosts, 1);
DNSServiceErrorType errorCode;
+ DNSServiceRef txt_query_sr;
/* finally, set up the continuous txt record watcher, and add the buddy to purple */
-
- errorCode = DNSServiceQueryRecord(&args->res_data->txt_query, kDNSServiceFlagsLongLivedQuery,
+ errorCode = DNSServiceQueryRecord(&txt_query_sr, kDNSServiceFlagsLongLivedQuery,
kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT,
kDNSServiceClass_IN, _mdns_record_query_callback, args->bb);
if (errorCode == kDNSServiceErr_NoError) {
@@ -180,11 +191,14 @@ _mdns_resolve_host_callback(GSList *host
purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", args->bb->name, ip, args->bb->port_p2pj);
-
args->bb->ips = g_slist_prepend(args->bb->ips, g_strdup(ip));
args->res_data->ip = args->bb->ips->data;
- args->res_data->txt_query_handler = purple_input_add(DNSServiceRefSockFD(args->res_data->txt_query),
+ args->res_data->txt_query = g_new(DnsSDServiceRefHandlerData, 1);
+ args->res_data->txt_query->sdRef = txt_query_sr;
+ args->res_data->txt_query->account = args->account;
+
+ args->res_data->txt_query->input_handler = purple_input_add(DNSServiceRefSockFD(txt_query_sr),
PURPLE_INPUT_READ, _mdns_handle_event, args->res_data->txt_query);
bonjour_buddy_add_to_purple(args->bb, NULL);
@@ -231,21 +245,21 @@ _mdns_service_resolve_callback(DNSServic
_mdns_service_resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const char *txtRecord, void *context)
{
- ResolveCallbackArgs *args = (ResolveCallbackArgs*)context;
+ ResolveCallbackArgs *args = (ResolveCallbackArgs*) context;
Win32BuddyImplData *idata = args->bb->mdns_impl_data;
/* remove the input fd and destroy the service ref */
- purple_input_remove(args->resolver_handler);
- args->resolver_handler = 0;
- DNSServiceRefDeallocate(args->resolver);
- args->resolver = NULL;
+ purple_input_remove(args->resolver_query->input_handler);
+ DNSServiceRefDeallocate(args->resolver_query->sdRef);
+ g_free(args->resolver_query);
+ args->resolver_query = NULL;
if (errorCode != kDNSServiceErr_NoError)
purple_debug_error("bonjour", "service resolver - callback error.\n");
else {
/* set more arguments, and start the host resolver */
- if ((args->query =
+ if ((args->dns_query =
purple_dnsquery_a(hosttarget, port, _mdns_resolve_host_callback, args)) != NULL) {
args->full_service_name = g_strdup(fullname);
@@ -307,12 +321,13 @@ _mdns_service_browse_callback(DNSService
DNSServiceErrorType resErrorCode;
/* OK, lets go ahead and resolve it to add to the buddy list */
ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1);
+ DNSServiceRef resolver_sr;
purple_debug_info("bonjour", "Received new record for '%s' on iface %u (%s, %s)\n",
serviceName, interfaceIndex, regtype ? regtype : "",
replyDomain ? replyDomain : "");
- resErrorCode = DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype,
+ resErrorCode = DNSServiceResolve(&resolver_sr, 0, 0, serviceName, regtype,
replyDomain, _mdns_service_resolve_callback, args);
if (resErrorCode == kDNSServiceErr_NoError) {
GSList *tmp = pending_buddies;
@@ -320,7 +335,6 @@ _mdns_service_browse_callback(DNSService
BonjourBuddy* bb = NULL;
Win32SvcResolverData *rd;
Win32BuddyImplData *idata;
- gint fd;
/* Is there an existing buddy? */
if ((pb = purple_find_buddy(account, serviceName)))
@@ -347,7 +361,6 @@ _mdns_service_browse_callback(DNSService
pb->proto_data = bb;
}
-
rd = g_new0(Win32SvcResolverData, 1);
rd->if_idx = interfaceIndex;
rd->name = g_strdup(serviceName);
@@ -361,9 +374,12 @@ _mdns_service_browse_callback(DNSService
args->res_data = rd;
args->account = account;
+ args->resolver_query = g_new(DnsSDServiceRefHandlerData, 1);
+ args->resolver_query->sdRef = resolver_sr;
+ args->resolver_query->account = account;
/* get a file descriptor for this service ref, and add it to the input list */
- fd = DNSServiceRefSockFD(args->resolver);
- args->resolver_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, args->resolver);
+ args->resolver_query->input_handler = purple_input_add(DNSServiceRefSockFD(resolver_sr),
+ PURPLE_INPUT_READ, _mdns_handle_event, args->resolver_query);
} else {
purple_debug_error("bonjour", "service browser - failed to resolve service. (%d)\n", resErrorCode);
g_free(args);
@@ -455,18 +471,19 @@ gboolean _mdns_publish(BonjourDnsSd *dat
ret = FALSE;
} else {
/* OK, we're done constructing the text record, (re)publish the service */
+ DNSServiceRef presence_sr;
switch (type) {
case PUBLISH_START:
purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj);
- errorCode = DNSServiceRegister(&idata->presence_svc, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE,
+ errorCode = DNSServiceRegister(&presence_sr, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE,
NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data),
_mdns_service_register_callback, NULL);
break;
case PUBLISH_UPDATE:
purple_debug_info("bonjour", "Updating presence.\n");
- errorCode = DNSServiceUpdateRecord(idata->presence_svc, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
+ errorCode = DNSServiceUpdateRecord(idata->presence_query->sdRef, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
break;
}
@@ -478,8 +495,11 @@ gboolean _mdns_publish(BonjourDnsSd *dat
* "the client is responsible for ensuring that DNSServiceProcessResult() is called
* whenever there is a reply from the daemon - the daemon may terminate its connection
* with a client that does not process the daemon's responses */
- idata->presence_handler = purple_input_add(DNSServiceRefSockFD(idata->presence_svc),
- PURPLE_INPUT_READ, _mdns_handle_event, idata->presence_svc);
+ idata->presence_query = g_new(DnsSDServiceRefHandlerData, 1);
+ idata->presence_query->sdRef = presence_sr;
+ idata->presence_query->account = data->account;
+ idata->presence_query->input_handler = purple_input_add(DNSServiceRefSockFD(presence_sr),
+ PURPLE_INPUT_READ, _mdns_handle_event, idata->presence_query);
}
}
@@ -491,14 +511,18 @@ gboolean _mdns_browse(BonjourDnsSd *data
gboolean _mdns_browse(BonjourDnsSd *data) {
DNSServiceErrorType errorCode;
Win32SessionImplData *idata = data->mdns_impl_data;
+ DNSServiceRef browser_sr;
g_return_val_if_fail(idata != NULL, FALSE);
- errorCode = DNSServiceBrowse(&idata->browser_svc, 0, 0, ICHAT_SERVICE, NULL,
- _mdns_service_browse_callback, data->account);
+ errorCode = DNSServiceBrowse(&browser_sr, 0, 0, ICHAT_SERVICE, NULL,
+ _mdns_service_browse_callback, data->account);
if (errorCode == kDNSServiceErr_NoError) {
- idata->browser_handler = purple_input_add(DNSServiceRefSockFD(idata->browser_svc),
- PURPLE_INPUT_READ, _mdns_handle_event, idata->browser_svc);
+ idata->browser_query = g_new(DnsSDServiceRefHandlerData, 1);
+ idata->browser_query->sdRef = browser_sr;
+ idata->browser_query->account = data->account;
+ idata->browser_query->input_handler = purple_input_add(DNSServiceRefSockFD(browser_sr),
+ PURPLE_INPUT_READ, _mdns_handle_event, idata->browser_query);
return TRUE;
} else
purple_debug_error("bonjour", "Error registering Local Link presence browser. (%d)\n", errorCode);
@@ -513,14 +537,16 @@ void _mdns_stop(BonjourDnsSd *data) {
if (idata == NULL)
return;
- if (idata->presence_svc != NULL) {
- purple_input_remove(idata->presence_handler);
- DNSServiceRefDeallocate(idata->presence_svc);
+ if (idata->presence_query != NULL) {
+ purple_input_remove(idata->presence_query->input_handler);
+ DNSServiceRefDeallocate(idata->presence_query->sdRef);
+ g_free(idata->presence_query);
}
- if (idata->browser_svc != NULL) {
- purple_input_remove(idata->browser_handler);
- DNSServiceRefDeallocate(idata->browser_svc);
+ if (idata->browser_query != NULL) {
+ purple_input_remove(idata->browser_query->input_handler);
+ DNSServiceRefDeallocate(idata->browser_query->sdRef);
+ g_free(idata->browser_query);
}
g_free(idata);
@@ -536,15 +562,15 @@ gboolean _mdns_set_buddy_icon_data(Bonjo
if (avatar_data != NULL && idata->buddy_icon_rec == NULL) {
purple_debug_info("bonjour", "Setting new buddy icon.\n");
- errorCode = DNSServiceAddRecord(idata->presence_svc, &idata->buddy_icon_rec,
+ errorCode = DNSServiceAddRecord(idata->presence_query->sdRef, &idata->buddy_icon_rec,
0, kDNSServiceType_NULL, avatar_len, avatar_data, 0);
} else if (avatar_data != NULL) {
purple_debug_info("bonjour", "Updating existing buddy icon.\n");
- errorCode = DNSServiceUpdateRecord(idata->presence_svc, idata->buddy_icon_rec,
+ errorCode = DNSServiceUpdateRecord(idata->presence_query->sdRef, idata->buddy_icon_rec,
0, avatar_len, avatar_data, 0);
} else if (idata->buddy_icon_rec != NULL) {
purple_debug_info("bonjour", "Removing existing buddy icon.\n");
- errorCode = DNSServiceRemoveRecord(idata->presence_svc, idata->buddy_icon_rec, 0);
+ errorCode = DNSServiceRemoveRecord(idata->presence_query->sdRef, idata->buddy_icon_rec, 0);
idata->buddy_icon_rec = NULL;
}
@@ -572,8 +598,9 @@ void _mdns_delete_buddy(BonjourBuddy *bu
}
if (idata->null_query != NULL) {
- purple_input_remove(idata->null_query_handler);
- DNSServiceRefDeallocate(idata->null_query);
+ purple_input_remove(idata->null_query->input_handler);
+ DNSServiceRefDeallocate(idata->null_query->sdRef);
+ g_free(idata->null_query);
}
g_free(idata);
@@ -589,21 +616,29 @@ void _mdns_retrieve_buddy_icon(BonjourBu
/* Cancel any existing query */
if (idata->null_query != NULL) {
- purple_input_remove(idata->null_query_handler);
- idata->null_query_handler = 0;
- DNSServiceRefDeallocate(idata->null_query);
+ purple_input_remove(idata->null_query->input_handler);
+ DNSServiceRefDeallocate(idata->null_query->sdRef);
+ g_free(idata->null_query);
idata->null_query = NULL;
}
if (DNSServiceConstructFullName(svc_name, buddy->name, ICHAT_SERVICE, "local") != 0)
purple_debug_error("bonjour", "Unable to construct full name to retrieve buddy icon for %s.\n", buddy->name);
else {
- DNSServiceErrorType errorCode = DNSServiceQueryRecord(&idata->null_query, 0, kDNSServiceInterfaceIndexAny,
+ DNSServiceRef null_query_sr;
+
+ DNSServiceErrorType errorCode = DNSServiceQueryRecord(&null_query_sr, 0, kDNSServiceInterfaceIndexAny,
svc_name, kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_record_query_callback, buddy);
- if (errorCode == kDNSServiceErr_NoError)
- idata->null_query_handler = purple_input_add(DNSServiceRefSockFD(idata->null_query),
+
+ if (errorCode == kDNSServiceErr_NoError) {
+ idata->null_query = g_new(DnsSDServiceRefHandlerData, 1);
+
+ idata->null_query->sdRef = null_query_sr;
+ idata->null_query->account = buddy->account;
+
+ idata->null_query->input_handler = purple_input_add(DNSServiceRefSockFD(null_query_sr),
PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query);
- else
+ } else
purple_debug_error("bonjour", "Unable to query buddy icon record for %s. (%d)\n", buddy->name, errorCode);
}
More information about the Commits
mailing list