Mercurial > pidgin
comparison libpurple/protocols/bonjour/mdns_win32.c @ 21987:71d18f5adbba
Detect the mdnsresponder crashing in the DnsSD implementation and disconnect the account instead of pegging the CPU.
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Fri, 04 Jan 2008 20:41:08 +0000 |
parents | 26648115261c |
children | 1be0d49532a1 |
comparison
equal
deleted
inserted
replaced
21985:035cfd9080a6 | 21987:71d18f5adbba |
---|---|
28 #include "dnsquery.h" | 28 #include "dnsquery.h" |
29 #include "mdns_common.h" | 29 #include "mdns_common.h" |
30 | 30 |
31 static GSList *pending_buddies = NULL; | 31 static GSList *pending_buddies = NULL; |
32 | 32 |
33 typedef struct _dnssd_service_ref_handler { | |
34 DNSServiceRef sdRef; | |
35 PurpleAccount *account; | |
36 guint input_handler; | |
37 } DnsSDServiceRefHandlerData; | |
38 | |
33 /* data used by win32 bonjour implementation */ | 39 /* data used by win32 bonjour implementation */ |
34 typedef struct _win32_session_impl_data { | 40 typedef struct _win32_session_impl_data { |
35 DNSServiceRef presence_svc; | 41 DnsSDServiceRefHandlerData *presence_query; |
36 DNSServiceRef browser_svc; | 42 DnsSDServiceRefHandlerData *browser_query; |
37 DNSRecordRef buddy_icon_rec; | 43 DNSRecordRef buddy_icon_rec; |
38 | |
39 guint presence_handler; | |
40 guint browser_handler; | |
41 } Win32SessionImplData; | 44 } Win32SessionImplData; |
42 | 45 |
43 typedef struct _win32_buddy_service_resolver_data { | 46 typedef struct _win32_buddy_service_resolver_data { |
44 DNSServiceRef txt_query; | 47 DnsSDServiceRefHandlerData *txt_query; |
45 guint txt_query_handler; | |
46 uint32_t if_idx; | 48 uint32_t if_idx; |
47 gchar *name; | 49 gchar *name; |
48 gchar *type; | 50 gchar *type; |
49 gchar *domain; | 51 gchar *domain; |
50 /* This is a reference to the entry in BonjourBuddy->ips */ | 52 /* This is a reference to the entry in BonjourBuddy->ips */ |
51 const char *ip; | 53 const char *ip; |
52 } Win32SvcResolverData; | 54 } Win32SvcResolverData; |
53 | 55 |
54 typedef struct _win32_buddy_impl_data { | 56 typedef struct _win32_buddy_impl_data { |
55 GSList *resolvers; | 57 GSList *resolvers; |
56 DNSServiceRef null_query; | 58 DnsSDServiceRefHandlerData *null_query; |
57 guint null_query_handler; | |
58 } Win32BuddyImplData; | 59 } Win32BuddyImplData; |
59 | 60 |
60 /* data structure for the resolve callback */ | 61 /* data structure for the resolve callback */ |
61 typedef struct _ResolveCallbackArgs { | 62 typedef struct _ResolveCallbackArgs { |
62 DNSServiceRef resolver; | 63 DnsSDServiceRefHandlerData *resolver_query; |
63 guint resolver_handler; | |
64 PurpleAccount *account; | 64 PurpleAccount *account; |
65 BonjourBuddy *bb; | 65 BonjourBuddy *bb; |
66 Win32SvcResolverData *res_data; | 66 Win32SvcResolverData *res_data; |
67 gchar *full_service_name; | 67 gchar *full_service_name; |
68 PurpleDnsQueryData *query; | 68 PurpleDnsQueryData *dns_query; |
69 } ResolveCallbackArgs; | 69 } ResolveCallbackArgs; |
70 | |
70 | 71 |
71 static gint | 72 static gint |
72 _find_resolver_data(gconstpointer a, gconstpointer b) { | 73 _find_resolver_data(gconstpointer a, gconstpointer b) { |
73 const Win32SvcResolverData *rd_a = a; | 74 const Win32SvcResolverData *rd_a = a; |
74 const Win32SvcResolverData *rd_b = b; | 75 const Win32SvcResolverData *rd_b = b; |
85 } | 86 } |
86 | 87 |
87 static void | 88 static void |
88 _cleanup_resolver_data(Win32SvcResolverData *rd) { | 89 _cleanup_resolver_data(Win32SvcResolverData *rd) { |
89 if (rd->txt_query != NULL) { | 90 if (rd->txt_query != NULL) { |
90 purple_input_remove(rd->txt_query_handler); | 91 purple_input_remove(rd->txt_query->input_handler); |
91 DNSServiceRefDeallocate(rd->txt_query); | 92 DNSServiceRefDeallocate(rd->txt_query->sdRef); |
93 g_free(rd->txt_query); | |
92 } | 94 } |
93 g_free(rd->name); | 95 g_free(rd->name); |
94 g_free(rd->type); | 96 g_free(rd->type); |
95 g_free(rd->domain); | 97 g_free(rd->domain); |
96 g_free(rd); | 98 g_free(rd); |
97 } | 99 } |
98 | 100 |
99 static void | 101 static void |
100 _mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition) { | 102 _mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition) { |
101 DNSServiceProcessResult((DNSServiceRef) data); | 103 DnsSDServiceRefHandlerData *srh = data; |
104 DNSServiceErrorType errorCode = DNSServiceProcessResult(srh->sdRef); | |
105 if (errorCode != kDNSServiceErr_NoError) { | |
106 purple_debug_error("bonjour", "Error (%d) handling mDNS response.\n", errorCode); | |
107 /* This happens when the mDNSResponder goes down, I haven't seen it happen any other time (in my limited testing) */ | |
108 if (errorCode == kDNSServiceErr_Unknown) { | |
109 purple_connection_error_reason(srh->account->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
110 _("Error communicating with local mDNSResponder.")); | |
111 } | |
112 } | |
102 } | 113 } |
103 | 114 |
104 static void | 115 static void |
105 _mdns_parse_text_record(BonjourBuddy *buddy, const char *record, uint16_t record_len) | 116 _mdns_parse_text_record(BonjourBuddy *buddy, const char *record, uint16_t record_len) |
106 { | 117 { |
140 g_return_if_fail(idata != NULL); | 151 g_return_if_fail(idata != NULL); |
141 | 152 |
142 bonjour_buddy_got_buddy_icon(bb, rdata, rdlen); | 153 bonjour_buddy_got_buddy_icon(bb, rdata, rdlen); |
143 | 154 |
144 /* We've got what we need; stop listening */ | 155 /* We've got what we need; stop listening */ |
145 purple_input_remove(idata->null_query_handler); | 156 purple_input_remove(idata->null_query->input_handler); |
146 idata->null_query_handler = 0; | 157 DNSServiceRefDeallocate(idata->null_query->sdRef); |
147 DNSServiceRefDeallocate(idata->null_query); | 158 g_free(idata->null_query); |
148 idata->null_query = NULL; | 159 idata->null_query = NULL; |
149 } | 160 } |
150 } | 161 } |
151 } | 162 } |
152 | 163 |
153 static void | 164 static void |
154 _mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message) | 165 _mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message) |
155 { | 166 { |
156 ResolveCallbackArgs* args = (ResolveCallbackArgs*) data; | 167 ResolveCallbackArgs *args = (ResolveCallbackArgs*) data; |
157 Win32BuddyImplData *idata = args->bb->mdns_impl_data; | 168 Win32BuddyImplData *idata = args->bb->mdns_impl_data; |
158 gboolean delete_buddy = FALSE; | 169 gboolean delete_buddy = FALSE; |
159 PurpleBuddy *pb; | 170 PurpleBuddy *pb; |
160 | 171 |
161 if ((pb = purple_find_buddy(args->account, args->bb->name))) | 172 if ((pb = purple_find_buddy(args->account, args->bb->name))) |
167 purple_debug_error("bonjour", "host resolution - callback error.\n"); | 178 purple_debug_error("bonjour", "host resolution - callback error.\n"); |
168 delete_buddy = TRUE; | 179 delete_buddy = TRUE; |
169 } else { | 180 } else { |
170 struct sockaddr_in *addr = g_slist_nth_data(hosts, 1); | 181 struct sockaddr_in *addr = g_slist_nth_data(hosts, 1); |
171 DNSServiceErrorType errorCode; | 182 DNSServiceErrorType errorCode; |
183 DNSServiceRef txt_query_sr; | |
172 | 184 |
173 /* finally, set up the continuous txt record watcher, and add the buddy to purple */ | 185 /* finally, set up the continuous txt record watcher, and add the buddy to purple */ |
174 | 186 errorCode = DNSServiceQueryRecord(&txt_query_sr, kDNSServiceFlagsLongLivedQuery, |
175 errorCode = DNSServiceQueryRecord(&args->res_data->txt_query, kDNSServiceFlagsLongLivedQuery, | |
176 kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT, | 187 kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT, |
177 kDNSServiceClass_IN, _mdns_record_query_callback, args->bb); | 188 kDNSServiceClass_IN, _mdns_record_query_callback, args->bb); |
178 if (errorCode == kDNSServiceErr_NoError) { | 189 if (errorCode == kDNSServiceErr_NoError) { |
179 const char *ip = inet_ntoa(addr->sin_addr); | 190 const char *ip = inet_ntoa(addr->sin_addr); |
180 | 191 |
181 purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", args->bb->name, ip, args->bb->port_p2pj); | 192 purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", args->bb->name, ip, args->bb->port_p2pj); |
182 | 193 |
183 | |
184 args->bb->ips = g_slist_prepend(args->bb->ips, g_strdup(ip)); | 194 args->bb->ips = g_slist_prepend(args->bb->ips, g_strdup(ip)); |
185 args->res_data->ip = args->bb->ips->data; | 195 args->res_data->ip = args->bb->ips->data; |
186 | 196 |
187 args->res_data->txt_query_handler = purple_input_add(DNSServiceRefSockFD(args->res_data->txt_query), | 197 args->res_data->txt_query = g_new(DnsSDServiceRefHandlerData, 1); |
198 args->res_data->txt_query->sdRef = txt_query_sr; | |
199 args->res_data->txt_query->account = args->account; | |
200 | |
201 args->res_data->txt_query->input_handler = purple_input_add(DNSServiceRefSockFD(txt_query_sr), | |
188 PURPLE_INPUT_READ, _mdns_handle_event, args->res_data->txt_query); | 202 PURPLE_INPUT_READ, _mdns_handle_event, args->res_data->txt_query); |
189 | 203 |
190 bonjour_buddy_add_to_purple(args->bb, NULL); | 204 bonjour_buddy_add_to_purple(args->bb, NULL); |
191 } else { | 205 } else { |
192 purple_debug_error("bonjour", "Unable to set up record watcher for buddy %s (%d)\n", args->bb->name, errorCode); | 206 purple_debug_error("bonjour", "Unable to set up record watcher for buddy %s (%d)\n", args->bb->name, errorCode); |
229 | 243 |
230 static void DNSSD_API | 244 static void DNSSD_API |
231 _mdns_service_resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, | 245 _mdns_service_resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, |
232 const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const char *txtRecord, void *context) | 246 const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const char *txtRecord, void *context) |
233 { | 247 { |
234 ResolveCallbackArgs *args = (ResolveCallbackArgs*)context; | 248 ResolveCallbackArgs *args = (ResolveCallbackArgs*) context; |
235 Win32BuddyImplData *idata = args->bb->mdns_impl_data; | 249 Win32BuddyImplData *idata = args->bb->mdns_impl_data; |
236 | 250 |
237 /* remove the input fd and destroy the service ref */ | 251 /* remove the input fd and destroy the service ref */ |
238 purple_input_remove(args->resolver_handler); | 252 purple_input_remove(args->resolver_query->input_handler); |
239 args->resolver_handler = 0; | 253 DNSServiceRefDeallocate(args->resolver_query->sdRef); |
240 DNSServiceRefDeallocate(args->resolver); | 254 g_free(args->resolver_query); |
241 args->resolver = NULL; | 255 args->resolver_query = NULL; |
242 | 256 |
243 if (errorCode != kDNSServiceErr_NoError) | 257 if (errorCode != kDNSServiceErr_NoError) |
244 purple_debug_error("bonjour", "service resolver - callback error.\n"); | 258 purple_debug_error("bonjour", "service resolver - callback error.\n"); |
245 else { | 259 else { |
246 /* set more arguments, and start the host resolver */ | 260 /* set more arguments, and start the host resolver */ |
247 | 261 |
248 if ((args->query = | 262 if ((args->dns_query = |
249 purple_dnsquery_a(hosttarget, port, _mdns_resolve_host_callback, args)) != NULL) { | 263 purple_dnsquery_a(hosttarget, port, _mdns_resolve_host_callback, args)) != NULL) { |
250 | 264 |
251 args->full_service_name = g_strdup(fullname); | 265 args->full_service_name = g_strdup(fullname); |
252 | 266 |
253 /* TODO: Should this be per resolver? */ | 267 /* TODO: Should this be per resolver? */ |
305 /* A presence service instance has been discovered... check it isn't us! */ | 319 /* A presence service instance has been discovered... check it isn't us! */ |
306 if (purple_utf8_strcasecmp(serviceName, account->username) != 0) { | 320 if (purple_utf8_strcasecmp(serviceName, account->username) != 0) { |
307 DNSServiceErrorType resErrorCode; | 321 DNSServiceErrorType resErrorCode; |
308 /* OK, lets go ahead and resolve it to add to the buddy list */ | 322 /* OK, lets go ahead and resolve it to add to the buddy list */ |
309 ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1); | 323 ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1); |
324 DNSServiceRef resolver_sr; | |
310 | 325 |
311 purple_debug_info("bonjour", "Received new record for '%s' on iface %u (%s, %s)\n", | 326 purple_debug_info("bonjour", "Received new record for '%s' on iface %u (%s, %s)\n", |
312 serviceName, interfaceIndex, regtype ? regtype : "", | 327 serviceName, interfaceIndex, regtype ? regtype : "", |
313 replyDomain ? replyDomain : ""); | 328 replyDomain ? replyDomain : ""); |
314 | 329 |
315 resErrorCode = DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, | 330 resErrorCode = DNSServiceResolve(&resolver_sr, 0, 0, serviceName, regtype, |
316 replyDomain, _mdns_service_resolve_callback, args); | 331 replyDomain, _mdns_service_resolve_callback, args); |
317 if (resErrorCode == kDNSServiceErr_NoError) { | 332 if (resErrorCode == kDNSServiceErr_NoError) { |
318 GSList *tmp = pending_buddies; | 333 GSList *tmp = pending_buddies; |
319 PurpleBuddy *pb; | 334 PurpleBuddy *pb; |
320 BonjourBuddy* bb = NULL; | 335 BonjourBuddy* bb = NULL; |
321 Win32SvcResolverData *rd; | 336 Win32SvcResolverData *rd; |
322 Win32BuddyImplData *idata; | 337 Win32BuddyImplData *idata; |
323 gint fd; | |
324 | 338 |
325 /* Is there an existing buddy? */ | 339 /* Is there an existing buddy? */ |
326 if ((pb = purple_find_buddy(account, serviceName))) | 340 if ((pb = purple_find_buddy(account, serviceName))) |
327 bb = pb->proto_data; | 341 bb = pb->proto_data; |
328 /* Is there a pending buddy? */ | 342 /* Is there a pending buddy? */ |
345 pending_buddies = g_slist_prepend(pending_buddies, bb); | 359 pending_buddies = g_slist_prepend(pending_buddies, bb); |
346 else | 360 else |
347 pb->proto_data = bb; | 361 pb->proto_data = bb; |
348 } | 362 } |
349 | 363 |
350 | |
351 rd = g_new0(Win32SvcResolverData, 1); | 364 rd = g_new0(Win32SvcResolverData, 1); |
352 rd->if_idx = interfaceIndex; | 365 rd->if_idx = interfaceIndex; |
353 rd->name = g_strdup(serviceName); | 366 rd->name = g_strdup(serviceName); |
354 rd->type = g_strdup(regtype); | 367 rd->type = g_strdup(regtype); |
355 rd->domain = g_strdup(replyDomain); | 368 rd->domain = g_strdup(replyDomain); |
359 | 372 |
360 args->bb = bb; | 373 args->bb = bb; |
361 args->res_data = rd; | 374 args->res_data = rd; |
362 args->account = account; | 375 args->account = account; |
363 | 376 |
377 args->resolver_query = g_new(DnsSDServiceRefHandlerData, 1); | |
378 args->resolver_query->sdRef = resolver_sr; | |
379 args->resolver_query->account = account; | |
364 /* get a file descriptor for this service ref, and add it to the input list */ | 380 /* get a file descriptor for this service ref, and add it to the input list */ |
365 fd = DNSServiceRefSockFD(args->resolver); | 381 args->resolver_query->input_handler = purple_input_add(DNSServiceRefSockFD(resolver_sr), |
366 args->resolver_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, args->resolver); | 382 PURPLE_INPUT_READ, _mdns_handle_event, args->resolver_query); |
367 } else { | 383 } else { |
368 purple_debug_error("bonjour", "service browser - failed to resolve service. (%d)\n", resErrorCode); | 384 purple_debug_error("bonjour", "service browser - failed to resolve service. (%d)\n", resErrorCode); |
369 g_free(args); | 385 g_free(args); |
370 } | 386 } |
371 } | 387 } |
453 if (errorCode != kDNSServiceErr_NoError) { | 469 if (errorCode != kDNSServiceErr_NoError) { |
454 purple_debug_error("bonjour", "Unable to allocate memory for text record.(%d)\n", errorCode); | 470 purple_debug_error("bonjour", "Unable to allocate memory for text record.(%d)\n", errorCode); |
455 ret = FALSE; | 471 ret = FALSE; |
456 } else { | 472 } else { |
457 /* OK, we're done constructing the text record, (re)publish the service */ | 473 /* OK, we're done constructing the text record, (re)publish the service */ |
474 DNSServiceRef presence_sr; | |
458 | 475 |
459 switch (type) { | 476 switch (type) { |
460 case PUBLISH_START: | 477 case PUBLISH_START: |
461 purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj); | 478 purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj); |
462 errorCode = DNSServiceRegister(&idata->presence_svc, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE, | 479 errorCode = DNSServiceRegister(&presence_sr, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE, |
463 NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), | 480 NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), |
464 _mdns_service_register_callback, NULL); | 481 _mdns_service_register_callback, NULL); |
465 break; | 482 break; |
466 | 483 |
467 case PUBLISH_UPDATE: | 484 case PUBLISH_UPDATE: |
468 purple_debug_info("bonjour", "Updating presence.\n"); | 485 purple_debug_info("bonjour", "Updating presence.\n"); |
469 errorCode = DNSServiceUpdateRecord(idata->presence_svc, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0); | 486 errorCode = DNSServiceUpdateRecord(idata->presence_query->sdRef, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0); |
470 break; | 487 break; |
471 } | 488 } |
472 | 489 |
473 if (errorCode != kDNSServiceErr_NoError) { | 490 if (errorCode != kDNSServiceErr_NoError) { |
474 purple_debug_error("bonjour", "Failed to publish presence service.(%d)\n", errorCode); | 491 purple_debug_error("bonjour", "Failed to publish presence service.(%d)\n", errorCode); |
476 } else if (type == PUBLISH_START) { | 493 } else if (type == PUBLISH_START) { |
477 /* We need to do this because according to the Apple docs: | 494 /* We need to do this because according to the Apple docs: |
478 * "the client is responsible for ensuring that DNSServiceProcessResult() is called | 495 * "the client is responsible for ensuring that DNSServiceProcessResult() is called |
479 * whenever there is a reply from the daemon - the daemon may terminate its connection | 496 * whenever there is a reply from the daemon - the daemon may terminate its connection |
480 * with a client that does not process the daemon's responses */ | 497 * with a client that does not process the daemon's responses */ |
481 idata->presence_handler = purple_input_add(DNSServiceRefSockFD(idata->presence_svc), | 498 idata->presence_query = g_new(DnsSDServiceRefHandlerData, 1); |
482 PURPLE_INPUT_READ, _mdns_handle_event, idata->presence_svc); | 499 idata->presence_query->sdRef = presence_sr; |
500 idata->presence_query->account = data->account; | |
501 idata->presence_query->input_handler = purple_input_add(DNSServiceRefSockFD(presence_sr), | |
502 PURPLE_INPUT_READ, _mdns_handle_event, idata->presence_query); | |
483 } | 503 } |
484 } | 504 } |
485 | 505 |
486 /* Free the memory used by temp data */ | 506 /* Free the memory used by temp data */ |
487 TXTRecordDeallocate(&dns_data); | 507 TXTRecordDeallocate(&dns_data); |
489 } | 509 } |
490 | 510 |
491 gboolean _mdns_browse(BonjourDnsSd *data) { | 511 gboolean _mdns_browse(BonjourDnsSd *data) { |
492 DNSServiceErrorType errorCode; | 512 DNSServiceErrorType errorCode; |
493 Win32SessionImplData *idata = data->mdns_impl_data; | 513 Win32SessionImplData *idata = data->mdns_impl_data; |
514 DNSServiceRef browser_sr; | |
494 | 515 |
495 g_return_val_if_fail(idata != NULL, FALSE); | 516 g_return_val_if_fail(idata != NULL, FALSE); |
496 | 517 |
497 errorCode = DNSServiceBrowse(&idata->browser_svc, 0, 0, ICHAT_SERVICE, NULL, | 518 errorCode = DNSServiceBrowse(&browser_sr, 0, 0, ICHAT_SERVICE, NULL, |
498 _mdns_service_browse_callback, data->account); | 519 _mdns_service_browse_callback, data->account); |
499 if (errorCode == kDNSServiceErr_NoError) { | 520 if (errorCode == kDNSServiceErr_NoError) { |
500 idata->browser_handler = purple_input_add(DNSServiceRefSockFD(idata->browser_svc), | 521 idata->browser_query = g_new(DnsSDServiceRefHandlerData, 1); |
501 PURPLE_INPUT_READ, _mdns_handle_event, idata->browser_svc); | 522 idata->browser_query->sdRef = browser_sr; |
523 idata->browser_query->account = data->account; | |
524 idata->browser_query->input_handler = purple_input_add(DNSServiceRefSockFD(browser_sr), | |
525 PURPLE_INPUT_READ, _mdns_handle_event, idata->browser_query); | |
502 return TRUE; | 526 return TRUE; |
503 } else | 527 } else |
504 purple_debug_error("bonjour", "Error registering Local Link presence browser. (%d)\n", errorCode); | 528 purple_debug_error("bonjour", "Error registering Local Link presence browser. (%d)\n", errorCode); |
505 | 529 |
506 | 530 |
511 Win32SessionImplData *idata = data->mdns_impl_data; | 535 Win32SessionImplData *idata = data->mdns_impl_data; |
512 | 536 |
513 if (idata == NULL) | 537 if (idata == NULL) |
514 return; | 538 return; |
515 | 539 |
516 if (idata->presence_svc != NULL) { | 540 if (idata->presence_query != NULL) { |
517 purple_input_remove(idata->presence_handler); | 541 purple_input_remove(idata->presence_query->input_handler); |
518 DNSServiceRefDeallocate(idata->presence_svc); | 542 DNSServiceRefDeallocate(idata->presence_query->sdRef); |
519 } | 543 g_free(idata->presence_query); |
520 | 544 } |
521 if (idata->browser_svc != NULL) { | 545 |
522 purple_input_remove(idata->browser_handler); | 546 if (idata->browser_query != NULL) { |
523 DNSServiceRefDeallocate(idata->browser_svc); | 547 purple_input_remove(idata->browser_query->input_handler); |
548 DNSServiceRefDeallocate(idata->browser_query->sdRef); | |
549 g_free(idata->browser_query); | |
524 } | 550 } |
525 | 551 |
526 g_free(idata); | 552 g_free(idata); |
527 | 553 |
528 data->mdns_impl_data = NULL; | 554 data->mdns_impl_data = NULL; |
534 | 560 |
535 g_return_val_if_fail(idata != NULL, FALSE); | 561 g_return_val_if_fail(idata != NULL, FALSE); |
536 | 562 |
537 if (avatar_data != NULL && idata->buddy_icon_rec == NULL) { | 563 if (avatar_data != NULL && idata->buddy_icon_rec == NULL) { |
538 purple_debug_info("bonjour", "Setting new buddy icon.\n"); | 564 purple_debug_info("bonjour", "Setting new buddy icon.\n"); |
539 errorCode = DNSServiceAddRecord(idata->presence_svc, &idata->buddy_icon_rec, | 565 errorCode = DNSServiceAddRecord(idata->presence_query->sdRef, &idata->buddy_icon_rec, |
540 0, kDNSServiceType_NULL, avatar_len, avatar_data, 0); | 566 0, kDNSServiceType_NULL, avatar_len, avatar_data, 0); |
541 } else if (avatar_data != NULL) { | 567 } else if (avatar_data != NULL) { |
542 purple_debug_info("bonjour", "Updating existing buddy icon.\n"); | 568 purple_debug_info("bonjour", "Updating existing buddy icon.\n"); |
543 errorCode = DNSServiceUpdateRecord(idata->presence_svc, idata->buddy_icon_rec, | 569 errorCode = DNSServiceUpdateRecord(idata->presence_query->sdRef, idata->buddy_icon_rec, |
544 0, avatar_len, avatar_data, 0); | 570 0, avatar_len, avatar_data, 0); |
545 } else if (idata->buddy_icon_rec != NULL) { | 571 } else if (idata->buddy_icon_rec != NULL) { |
546 purple_debug_info("bonjour", "Removing existing buddy icon.\n"); | 572 purple_debug_info("bonjour", "Removing existing buddy icon.\n"); |
547 errorCode = DNSServiceRemoveRecord(idata->presence_svc, idata->buddy_icon_rec, 0); | 573 errorCode = DNSServiceRemoveRecord(idata->presence_query->sdRef, idata->buddy_icon_rec, 0); |
548 idata->buddy_icon_rec = NULL; | 574 idata->buddy_icon_rec = NULL; |
549 } | 575 } |
550 | 576 |
551 if (errorCode != kDNSServiceErr_NoError) { | 577 if (errorCode != kDNSServiceErr_NoError) { |
552 purple_debug_error("bonjour", "Error (%d) setting buddy icon record.\n", errorCode); | 578 purple_debug_error("bonjour", "Error (%d) setting buddy icon record.\n", errorCode); |
570 _cleanup_resolver_data(rd); | 596 _cleanup_resolver_data(rd); |
571 idata->resolvers = g_slist_delete_link(idata->resolvers, idata->resolvers); | 597 idata->resolvers = g_slist_delete_link(idata->resolvers, idata->resolvers); |
572 } | 598 } |
573 | 599 |
574 if (idata->null_query != NULL) { | 600 if (idata->null_query != NULL) { |
575 purple_input_remove(idata->null_query_handler); | 601 purple_input_remove(idata->null_query->input_handler); |
576 DNSServiceRefDeallocate(idata->null_query); | 602 DNSServiceRefDeallocate(idata->null_query->sdRef); |
603 g_free(idata->null_query); | |
577 } | 604 } |
578 | 605 |
579 g_free(idata); | 606 g_free(idata); |
580 | 607 |
581 buddy->mdns_impl_data = NULL; | 608 buddy->mdns_impl_data = NULL; |
587 | 614 |
588 g_return_if_fail(idata != NULL); | 615 g_return_if_fail(idata != NULL); |
589 | 616 |
590 /* Cancel any existing query */ | 617 /* Cancel any existing query */ |
591 if (idata->null_query != NULL) { | 618 if (idata->null_query != NULL) { |
592 purple_input_remove(idata->null_query_handler); | 619 purple_input_remove(idata->null_query->input_handler); |
593 idata->null_query_handler = 0; | 620 DNSServiceRefDeallocate(idata->null_query->sdRef); |
594 DNSServiceRefDeallocate(idata->null_query); | 621 g_free(idata->null_query); |
595 idata->null_query = NULL; | 622 idata->null_query = NULL; |
596 } | 623 } |
597 | 624 |
598 if (DNSServiceConstructFullName(svc_name, buddy->name, ICHAT_SERVICE, "local") != 0) | 625 if (DNSServiceConstructFullName(svc_name, buddy->name, ICHAT_SERVICE, "local") != 0) |
599 purple_debug_error("bonjour", "Unable to construct full name to retrieve buddy icon for %s.\n", buddy->name); | 626 purple_debug_error("bonjour", "Unable to construct full name to retrieve buddy icon for %s.\n", buddy->name); |
600 else { | 627 else { |
601 DNSServiceErrorType errorCode = DNSServiceQueryRecord(&idata->null_query, 0, kDNSServiceInterfaceIndexAny, | 628 DNSServiceRef null_query_sr; |
629 | |
630 DNSServiceErrorType errorCode = DNSServiceQueryRecord(&null_query_sr, 0, kDNSServiceInterfaceIndexAny, | |
602 svc_name, kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_record_query_callback, buddy); | 631 svc_name, kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_record_query_callback, buddy); |
603 if (errorCode == kDNSServiceErr_NoError) | 632 |
604 idata->null_query_handler = purple_input_add(DNSServiceRefSockFD(idata->null_query), | 633 if (errorCode == kDNSServiceErr_NoError) { |
634 idata->null_query = g_new(DnsSDServiceRefHandlerData, 1); | |
635 | |
636 idata->null_query->sdRef = null_query_sr; | |
637 idata->null_query->account = buddy->account; | |
638 | |
639 idata->null_query->input_handler = purple_input_add(DNSServiceRefSockFD(null_query_sr), | |
605 PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query); | 640 PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query); |
606 else | 641 } else |
607 purple_debug_error("bonjour", "Unable to query buddy icon record for %s. (%d)\n", buddy->name, errorCode); | 642 purple_debug_error("bonjour", "Unable to query buddy icon record for %s. (%d)\n", buddy->name, errorCode); |
608 } | 643 } |
609 | 644 |
610 } | 645 } |
611 | 646 |