Bonjour/MYBonjourQuery.m
author Jens Alfke <jens@mooseyard.com>
Tue Apr 28 10:36:28 2009 -0700 (2009-04-28)
changeset 29 59689fbdcf77
child 31 1d6924779df7
permissions -rw-r--r--
Fixed two CF memory leaks. (Fixes issue #5)
     1 //
     2 //  MYBonjourQuery.m
     3 //  MYNetwork
     4 //
     5 //  Created by Jens Alfke on 4/24/09.
     6 //  Copyright 2009 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import "MYBonjourQuery.h"
    10 #import "MYBonjourService.h"
    11 #import "Test.h"
    12 #import "Logging.h"
    13 #import "ExceptionUtils.h"
    14 #import <dns_sd.h>
    15 
    16 
    17 static NSString* kRecordTypeNames[] = {
    18     @"0",
    19     @"A", //         = 1,      /* Host address. */
    20     @"NS", //        = 2,      /* Authoritative server. */
    21     @"MD", //        = 3,      /* Mail destination. */
    22     @"MF", //        = 4,      /* Mail forwarder. */
    23     @"CNAME", //     = 5,      /* Canonical name. */
    24     @"SOA", //       = 6,      /* Start of authority zone. */
    25     @"MB", //        = 7,      /* Mailbox domain name. */
    26     @"MG", //        = 8,      /* Mail group member. */
    27     @"MR", //        = 9,      /* Mail rename name. */
    28     @"NULL", //      = 10,     /* Null resource record. */
    29     @"WKS", //       = 11,     /* Well known service. */
    30     @"PTR", //       = 12,     /* Domain name pointer. */
    31     @"HINFO", //     = 13,     /* Host information. */
    32     @"MINFO", //     = 14,     /* Mailbox information. */
    33     @"MX", //        = 15,     /* Mail routing information. */
    34     @"TXT" //       = 16,     /* One or more text strings (NOT "zero or more..."). */
    35     // this isn't a complete list; it just includes the most common ones.
    36     // For the full list, see the "kDNSServiceType_..." constants in <dns_sd.h>.
    37 };
    38 
    39 @interface MYBonjourQuery ()
    40 @property (copy) NSData *recordData;
    41 @end
    42 
    43 
    44 @implementation MYBonjourQuery
    45 
    46 
    47 - (id) initWithBonjourService: (MYBonjourService*)service recordType: (uint16_t)recordType;
    48 {
    49     self = [super init];
    50     if (self) {
    51         _bonjourService = service;
    52         _recordType = recordType;
    53     }
    54     return self;
    55 }
    56 
    57 - (void) dealloc
    58 {
    59     [_recordData release];
    60     [super dealloc];
    61 }
    62 
    63 
    64 - (NSString*) description
    65 {
    66     NSString *typeName;
    67     if (_recordType <= 16)
    68         typeName = kRecordTypeNames[_recordType];
    69     else
    70         typeName = $sprintf(@"%u", _recordType);
    71     return $sprintf(@"%@[%@ /%@]", self.class, _bonjourService.name, typeName);
    72 }
    73 
    74 
    75 @synthesize recordData=_recordData;
    76 
    77 
    78 - (void) priv_gotRecordBytes: (const void *)rdata
    79                       length: (uint16_t)rdlen
    80                         type: (uint16_t)rrtype
    81                          ttl: (uint32_t)ttl
    82                        flags: (DNSServiceFlags)flags
    83 {
    84     NSData *data = [NSData dataWithBytes: rdata length: rdlen];
    85     if (!$equal(data,_recordData)) {
    86         if (data.length <= 16)
    87             LogTo(Bonjour,@"%@ = %@", self, data);
    88         else
    89             LogTo(Bonjour,@"%@ = %@...", self, [data subdataWithRange: NSMakeRange(0,16)]);
    90         self.recordData = data;
    91     }
    92     [_bonjourService queryDidUpdate: self];
    93 }
    94 
    95 
    96 static void queryCallback( DNSServiceRef                       DNSServiceRef,
    97                            DNSServiceFlags                     flags,
    98                            uint32_t                            interfaceIndex,
    99                            DNSServiceErrorType                 errorCode,
   100                            const char                          *fullname,
   101                            uint16_t                            rrtype,
   102                            uint16_t                            rrclass,
   103                            uint16_t                            rdlen,
   104                            const void                          *rdata,
   105                            uint32_t                            ttl,
   106                            void                                *context)
   107 {
   108     @try{
   109         //LogTo(Bonjour, @"queryCallback for %@ (err=%i)", context,errorCode);
   110         if (errorCode)
   111             [(MYBonjourQuery*)context setError: errorCode];
   112         else
   113             [(MYBonjourQuery*)context priv_gotRecordBytes: rdata
   114                                                       length: rdlen
   115                                                         type: rrtype
   116                                                          ttl: ttl
   117                                                        flags: flags];
   118     }catchAndReport(@"MYBonjourResolver query callback");
   119 }
   120 
   121 
   122 - (DNSServiceRef) createServiceRef {
   123     DNSServiceRef serviceRef = NULL;
   124     const char *fullName = _bonjourService.fullName.UTF8String;
   125     if (fullName)
   126         self.error = DNSServiceQueryRecord(&serviceRef, 0, 
   127                                            _bonjourService.interfaceIndex, 
   128                                            fullName,
   129                                            _recordType, kDNSServiceClass_IN, 
   130                                            &queryCallback, self);
   131     return serviceRef;
   132 }
   133 
   134 
   135 @end