comparison libpurple/protocols/bonjour/mdns_win32.c @ 21979:26648115261c

Improve error handling, particularly the debug output. I was hoping that this would provide some debug output that could be used to figure out how to detect and disconnect when the mdnsResponder crashes, but that doesn't appear to be the case.
author Daniel Atallah <daniel.atallah@gmail.com>
date Fri, 04 Jan 2008 01:09:13 +0000
parents 41959f031322
children 71d18f5adbba
comparison
equal deleted inserted replaced
21978:4795260eb0bd 21979:26648115261c
121 uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, 121 uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname,
122 uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, 122 uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata,
123 uint32_t ttl, void *context) 123 uint32_t ttl, void *context)
124 { 124 {
125 125
126 if (kDNSServiceErr_NoError != errorCode) { 126 if (errorCode != kDNSServiceErr_NoError) {
127 purple_debug_error("bonjour", "record query - callback error.\n"); 127 purple_debug_error("bonjour", "record query - callback error.\n");
128 /* TODO: Probably should remove the buddy when this happens */ 128 /* TODO: Probably should remove the buddy when this happens */
129 } else if (flags & kDNSServiceFlagsAdd) { 129 } else if (flags & kDNSServiceFlagsAdd) {
130 if (rrtype == kDNSServiceType_TXT) { 130 if (rrtype == kDNSServiceType_TXT) {
131 /* New Buddy */ 131 /* New Buddy */
166 if (!hosts || !hosts->data) { 166 if (!hosts || !hosts->data) {
167 purple_debug_error("bonjour", "host resolution - callback error.\n"); 167 purple_debug_error("bonjour", "host resolution - callback error.\n");
168 delete_buddy = TRUE; 168 delete_buddy = TRUE;
169 } else { 169 } else {
170 struct sockaddr_in *addr = g_slist_nth_data(hosts, 1); 170 struct sockaddr_in *addr = g_slist_nth_data(hosts, 1);
171 DNSServiceErrorType errorCode;
171 172
172 /* finally, set up the continuous txt record watcher, and add the buddy to purple */ 173 /* finally, set up the continuous txt record watcher, and add the buddy to purple */
173 174
174 if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&args->res_data->txt_query, kDNSServiceFlagsLongLivedQuery, 175 errorCode = DNSServiceQueryRecord(&args->res_data->txt_query, kDNSServiceFlagsLongLivedQuery,
175 kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT, 176 kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT,
176 kDNSServiceClass_IN, _mdns_record_query_callback, args->bb)) { 177 kDNSServiceClass_IN, _mdns_record_query_callback, args->bb);
177 178 if (errorCode == kDNSServiceErr_NoError) {
178 const char *ip = inet_ntoa(addr->sin_addr); 179 const char *ip = inet_ntoa(addr->sin_addr);
179 180
180 purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", args->bb->name, ip, args->bb->port_p2pj); 181 purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", args->bb->name, ip, args->bb->port_p2pj);
181 182
182 183
186 args->res_data->txt_query_handler = purple_input_add(DNSServiceRefSockFD(args->res_data->txt_query), 187 args->res_data->txt_query_handler = purple_input_add(DNSServiceRefSockFD(args->res_data->txt_query),
187 PURPLE_INPUT_READ, _mdns_handle_event, args->res_data->txt_query); 188 PURPLE_INPUT_READ, _mdns_handle_event, args->res_data->txt_query);
188 189
189 bonjour_buddy_add_to_purple(args->bb, NULL); 190 bonjour_buddy_add_to_purple(args->bb, NULL);
190 } else { 191 } else {
191 purple_debug_error("bonjour", "Unable to set up record watcher for buddy %s\n", args->bb->name); 192 purple_debug_error("bonjour", "Unable to set up record watcher for buddy %s (%d)\n", args->bb->name, errorCode);
192 delete_buddy = TRUE; 193 delete_buddy = TRUE;
193 } 194 }
194 195
195 } 196 }
196 197
237 purple_input_remove(args->resolver_handler); 238 purple_input_remove(args->resolver_handler);
238 args->resolver_handler = 0; 239 args->resolver_handler = 0;
239 DNSServiceRefDeallocate(args->resolver); 240 DNSServiceRefDeallocate(args->resolver);
240 args->resolver = NULL; 241 args->resolver = NULL;
241 242
242 if (kDNSServiceErr_NoError != errorCode) 243 if (errorCode != kDNSServiceErr_NoError)
243 purple_debug_error("bonjour", "service resolver - callback error.\n"); 244 purple_debug_error("bonjour", "service resolver - callback error.\n");
244 else { 245 else {
245 /* set more arguments, and start the host resolver */ 246 /* set more arguments, and start the host resolver */
246 247
247 if ((args->query = 248 if ((args->query =
284 static void DNSSD_API 285 static void DNSSD_API
285 _mdns_service_register_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, 286 _mdns_service_register_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
286 const char *name, const char *regtype, const char *domain, void *context) { 287 const char *name, const char *regtype, const char *domain, void *context) {
287 288
288 /* TODO: deal with collision */ 289 /* TODO: deal with collision */
289 if (kDNSServiceErr_NoError != errorCode) 290 if (errorCode != kDNSServiceErr_NoError)
290 purple_debug_error("bonjour", "service advertisement - callback error (%d).\n", errorCode); 291 purple_debug_error("bonjour", "service advertisement - callback error (%d).\n", errorCode);
291 else 292 else
292 purple_debug_info("bonjour", "service advertisement - callback.\n"); 293 purple_debug_info("bonjour", "service advertisement - callback.\n");
293 } 294 }
294 295
296 _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, 297 _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
297 DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) 298 DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context)
298 { 299 {
299 PurpleAccount *account = (PurpleAccount*)context; 300 PurpleAccount *account = (PurpleAccount*)context;
300 301
301 if (kDNSServiceErr_NoError != errorCode) 302 if (errorCode != kDNSServiceErr_NoError)
302 purple_debug_error("bonjour", "service browser - callback error\n"); 303 purple_debug_error("bonjour", "service browser - callback error (%d)\n", errorCode);
303 else if (flags & kDNSServiceFlagsAdd) { 304 else if (flags & kDNSServiceFlagsAdd) {
304 /* A presence service instance has been discovered... check it isn't us! */ 305 /* A presence service instance has been discovered... check it isn't us! */
305 if (purple_utf8_strcasecmp(serviceName, account->username) != 0) { 306 if (purple_utf8_strcasecmp(serviceName, account->username) != 0) {
307 DNSServiceErrorType resErrorCode;
306 /* OK, lets go ahead and resolve it to add to the buddy list */ 308 /* OK, lets go ahead and resolve it to add to the buddy list */
307 ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1); 309 ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1);
308 310
309 purple_debug_info("bonjour", "Received new record for '%s' on iface %u (%s, %s)\n", 311 purple_debug_info("bonjour", "Received new record for '%s' on iface %u (%s, %s)\n",
310 serviceName, interfaceIndex, regtype ? regtype : "", 312 serviceName, interfaceIndex, regtype ? regtype : "",
311 replyDomain ? replyDomain : ""); 313 replyDomain ? replyDomain : "");
312 314
313 if (kDNSServiceErr_NoError == DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, 315 resErrorCode = DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype,
314 replyDomain, _mdns_service_resolve_callback, args)) { 316 replyDomain, _mdns_service_resolve_callback, args);
317 if (resErrorCode == kDNSServiceErr_NoError) {
315 GSList *tmp = pending_buddies; 318 GSList *tmp = pending_buddies;
316 PurpleBuddy *pb; 319 PurpleBuddy *pb;
317 BonjourBuddy* bb = NULL; 320 BonjourBuddy* bb = NULL;
318 Win32SvcResolverData *rd; 321 Win32SvcResolverData *rd;
319 Win32BuddyImplData *idata; 322 Win32BuddyImplData *idata;
360 363
361 /* get a file descriptor for this service ref, and add it to the input list */ 364 /* get a file descriptor for this service ref, and add it to the input list */
362 fd = DNSServiceRefSockFD(args->resolver); 365 fd = DNSServiceRefSockFD(args->resolver);
363 args->resolver_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, args->resolver); 366 args->resolver_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, args->resolver);
364 } else { 367 } else {
365 purple_debug_error("bonjour", "service browser - failed to resolve service.\n"); 368 purple_debug_error("bonjour", "service browser - failed to resolve service. (%d)\n", resErrorCode);
366 g_free(args); 369 g_free(args);
367 } 370 }
368 } 371 }
369 } else { 372 } else {
370 PurpleBuddy *pb = NULL; 373 PurpleBuddy *pb = NULL;
430 } 433 }
431 434
432 gboolean _mdns_publish(BonjourDnsSd *data, PublishType type, GSList *records) { 435 gboolean _mdns_publish(BonjourDnsSd *data, PublishType type, GSList *records) {
433 TXTRecordRef dns_data; 436 TXTRecordRef dns_data;
434 gboolean ret = TRUE; 437 gboolean ret = TRUE;
435 DNSServiceErrorType set_ret = kDNSServiceErr_NoError; 438 DNSServiceErrorType errorCode = kDNSServiceErr_NoError;
436 Win32SessionImplData *idata = data->mdns_impl_data; 439 Win32SessionImplData *idata = data->mdns_impl_data;
437 440
438 g_return_val_if_fail(idata != NULL, FALSE); 441 g_return_val_if_fail(idata != NULL, FALSE);
439 442
440 TXTRecordCreate(&dns_data, 256, NULL); 443 TXTRecordCreate(&dns_data, 256, NULL);
441 444
442 while (records) { 445 while (records) {
443 PurpleKeyValuePair *kvp = records->data; 446 PurpleKeyValuePair *kvp = records->data;
444 set_ret = TXTRecordSetValue(&dns_data, kvp->key, strlen(kvp->value), kvp->value); 447 errorCode = TXTRecordSetValue(&dns_data, kvp->key, strlen(kvp->value), kvp->value);
445 if (set_ret != kDNSServiceErr_NoError) 448 if (errorCode != kDNSServiceErr_NoError)
446 break; 449 break;
447 records = records->next; 450 records = records->next;
448 } 451 }
449 452
450 if (set_ret != kDNSServiceErr_NoError) { 453 if (errorCode != kDNSServiceErr_NoError) {
451 purple_debug_error("bonjour", "Unable to allocate memory for text record.\n"); 454 purple_debug_error("bonjour", "Unable to allocate memory for text record.(%d)\n", errorCode);
452 ret = FALSE; 455 ret = FALSE;
453 } else { 456 } else {
454 DNSServiceErrorType err = kDNSServiceErr_NoError;
455
456 /* OK, we're done constructing the text record, (re)publish the service */ 457 /* OK, we're done constructing the text record, (re)publish the service */
457 458
458 switch (type) { 459 switch (type) {
459 case PUBLISH_START: 460 case PUBLISH_START:
460 purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj); 461 purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj);
461 err = DNSServiceRegister(&idata->presence_svc, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE, 462 errorCode = DNSServiceRegister(&idata->presence_svc, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE,
462 NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 463 NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data),
463 _mdns_service_register_callback, NULL); 464 _mdns_service_register_callback, NULL);
464 break; 465 break;
465 466
466 case PUBLISH_UPDATE: 467 case PUBLISH_UPDATE:
467 purple_debug_info("bonjour", "Updating presence.\n"); 468 purple_debug_info("bonjour", "Updating presence.\n");
468 err = DNSServiceUpdateRecord(idata->presence_svc, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0); 469 errorCode = DNSServiceUpdateRecord(idata->presence_svc, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
469 break; 470 break;
470 } 471 }
471 472
472 if (err != kDNSServiceErr_NoError) { 473 if (errorCode != kDNSServiceErr_NoError) {
473 purple_debug_error("bonjour", "Failed to publish presence service.\n"); 474 purple_debug_error("bonjour", "Failed to publish presence service.(%d)\n", errorCode);
474 ret = FALSE; 475 ret = FALSE;
475 } else if (type == PUBLISH_START) { 476 } else if (type == PUBLISH_START) {
476 /* We need to do this because according to the Apple docs: 477 /* We need to do this because according to the Apple docs:
477 * "the client is responsible for ensuring that DNSServiceProcessResult() is called 478 * "the client is responsible for ensuring that DNSServiceProcessResult() is called
478 * whenever there is a reply from the daemon - the daemon may terminate its connection 479 * whenever there is a reply from the daemon - the daemon may terminate its connection
486 TXTRecordDeallocate(&dns_data); 487 TXTRecordDeallocate(&dns_data);
487 return ret; 488 return ret;
488 } 489 }
489 490
490 gboolean _mdns_browse(BonjourDnsSd *data) { 491 gboolean _mdns_browse(BonjourDnsSd *data) {
492 DNSServiceErrorType errorCode;
491 Win32SessionImplData *idata = data->mdns_impl_data; 493 Win32SessionImplData *idata = data->mdns_impl_data;
492 494
493 g_return_val_if_fail(idata != NULL, FALSE); 495 g_return_val_if_fail(idata != NULL, FALSE);
494 496
495 if (DNSServiceBrowse(&idata->browser_svc, 0, 0, ICHAT_SERVICE, NULL, 497 errorCode = DNSServiceBrowse(&idata->browser_svc, 0, 0, ICHAT_SERVICE, NULL,
496 _mdns_service_browse_callback, data->account) 498 _mdns_service_browse_callback, data->account);
497 == kDNSServiceErr_NoError) { 499 if (errorCode == kDNSServiceErr_NoError) {
498 idata->browser_handler = purple_input_add(DNSServiceRefSockFD(idata->browser_svc), 500 idata->browser_handler = purple_input_add(DNSServiceRefSockFD(idata->browser_svc),
499 PURPLE_INPUT_READ, _mdns_handle_event, idata->browser_svc); 501 PURPLE_INPUT_READ, _mdns_handle_event, idata->browser_svc);
500 return TRUE; 502 return TRUE;
501 } 503 } else
504 purple_debug_error("bonjour", "Error registering Local Link presence browser. (%d)\n", errorCode);
505
502 506
503 return FALSE; 507 return FALSE;
504 } 508 }
505 509
506 void _mdns_stop(BonjourDnsSd *data) { 510 void _mdns_stop(BonjourDnsSd *data) {
524 data->mdns_impl_data = NULL; 528 data->mdns_impl_data = NULL;
525 } 529 }
526 530
527 gboolean _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) { 531 gboolean _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
528 Win32SessionImplData *idata = data->mdns_impl_data; 532 Win32SessionImplData *idata = data->mdns_impl_data;
529 DNSServiceErrorType err = kDNSServiceErr_NoError; 533 DNSServiceErrorType errorCode = kDNSServiceErr_NoError;
530 534
531 g_return_val_if_fail(idata != NULL, FALSE); 535 g_return_val_if_fail(idata != NULL, FALSE);
532 536
533 if (avatar_data != NULL && idata->buddy_icon_rec == NULL) { 537 if (avatar_data != NULL && idata->buddy_icon_rec == NULL) {
534 purple_debug_info("bonjour", "Setting new buddy icon.\n"); 538 purple_debug_info("bonjour", "Setting new buddy icon.\n");
535 err = DNSServiceAddRecord(idata->presence_svc, &idata->buddy_icon_rec, 539 errorCode = DNSServiceAddRecord(idata->presence_svc, &idata->buddy_icon_rec,
536 0, kDNSServiceType_NULL, avatar_len, avatar_data, 0); 540 0, kDNSServiceType_NULL, avatar_len, avatar_data, 0);
537 } else if (avatar_data != NULL) { 541 } else if (avatar_data != NULL) {
538 purple_debug_info("bonjour", "Updating existing buddy icon.\n"); 542 purple_debug_info("bonjour", "Updating existing buddy icon.\n");
539 err = DNSServiceUpdateRecord(idata->presence_svc, idata->buddy_icon_rec, 543 errorCode = DNSServiceUpdateRecord(idata->presence_svc, idata->buddy_icon_rec,
540 0, avatar_len, avatar_data, 0); 544 0, avatar_len, avatar_data, 0);
541 } else if (idata->buddy_icon_rec != NULL) { 545 } else if (idata->buddy_icon_rec != NULL) {
542 purple_debug_info("bonjour", "Removing existing buddy icon.\n"); 546 purple_debug_info("bonjour", "Removing existing buddy icon.\n");
543 DNSServiceRemoveRecord(idata->presence_svc, idata->buddy_icon_rec, 0); 547 errorCode = DNSServiceRemoveRecord(idata->presence_svc, idata->buddy_icon_rec, 0);
544 idata->buddy_icon_rec = NULL; 548 idata->buddy_icon_rec = NULL;
545 } 549 }
546 550
547 if (err != kDNSServiceErr_NoError) 551 if (errorCode != kDNSServiceErr_NoError) {
548 purple_debug_error("bonjour", "Error (%d) setting buddy icon record.\n", err); 552 purple_debug_error("bonjour", "Error (%d) setting buddy icon record.\n", errorCode);
549 553 return FALSE;
550 return (err == kDNSServiceErr_NoError); 554 }
555
556 return TRUE;
551 } 557 }
552 558
553 void _mdns_init_buddy(BonjourBuddy *buddy) { 559 void _mdns_init_buddy(BonjourBuddy *buddy) {
554 buddy->mdns_impl_data = g_new0(Win32BuddyImplData, 1); 560 buddy->mdns_impl_data = g_new0(Win32BuddyImplData, 1);
555 } 561 }
587 idata->null_query_handler = 0; 593 idata->null_query_handler = 0;
588 DNSServiceRefDeallocate(idata->null_query); 594 DNSServiceRefDeallocate(idata->null_query);
589 idata->null_query = NULL; 595 idata->null_query = NULL;
590 } 596 }
591 597
592 DNSServiceConstructFullName(svc_name, buddy->name, ICHAT_SERVICE, "local"); 598 if (DNSServiceConstructFullName(svc_name, buddy->name, ICHAT_SERVICE, "local") != 0)
593 if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->null_query, 0, kDNSServiceInterfaceIndexAny, svc_name, 599 purple_debug_error("bonjour", "Unable to construct full name to retrieve buddy icon for %s.\n", buddy->name);
594 kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_record_query_callback, buddy)) { 600 else {
595 idata->null_query_handler = purple_input_add(DNSServiceRefSockFD(idata->null_query), 601 DNSServiceErrorType errorCode = DNSServiceQueryRecord(&idata->null_query, 0, kDNSServiceInterfaceIndexAny,
596 PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query); 602 svc_name, kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_record_query_callback, buddy);
597 } 603 if (errorCode == kDNSServiceErr_NoError)
598 604 idata->null_query_handler = purple_input_add(DNSServiceRefSockFD(idata->null_query),
599 } 605 PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query);
600 606 else
607 purple_debug_error("bonjour", "Unable to query buddy icon record for %s. (%d)\n", buddy->name, errorCode);
608 }
609
610 }
611