Bonjour/MYBonjourQuery.m
author Jens Alfke <jens@mooseyard.com>
Tue Jul 21 10:04:10 2009 -0700 (2009-07-21)
changeset 61 981f9d604c88
parent 31 1d6924779df7
permissions -rw-r--r--
Prevent crash if MYBonjourQuery is released during response handling
jens@28
     1
//
jens@28
     2
//  MYBonjourQuery.m
jens@28
     3
//  MYNetwork
jens@28
     4
//
jens@28
     5
//  Created by Jens Alfke on 4/24/09.
jens@28
     6
//  Copyright 2009 Jens Alfke. All rights reserved.
jens@28
     7
//
jens@28
     8
jens@28
     9
#import "MYBonjourQuery.h"
jens@28
    10
#import "MYBonjourService.h"
jens@28
    11
#import "Test.h"
jens@28
    12
#import "Logging.h"
jens@28
    13
#import "ExceptionUtils.h"
jens@28
    14
#import <dns_sd.h>
jens@28
    15
jens@28
    16
jens@28
    17
static NSString* kRecordTypeNames[] = {
jens@28
    18
    @"0",
jens@28
    19
    @"A", //         = 1,      /* Host address. */
jens@28
    20
    @"NS", //        = 2,      /* Authoritative server. */
jens@28
    21
    @"MD", //        = 3,      /* Mail destination. */
jens@28
    22
    @"MF", //        = 4,      /* Mail forwarder. */
jens@28
    23
    @"CNAME", //     = 5,      /* Canonical name. */
jens@28
    24
    @"SOA", //       = 6,      /* Start of authority zone. */
jens@28
    25
    @"MB", //        = 7,      /* Mailbox domain name. */
jens@28
    26
    @"MG", //        = 8,      /* Mail group member. */
jens@28
    27
    @"MR", //        = 9,      /* Mail rename name. */
jens@28
    28
    @"NULL", //      = 10,     /* Null resource record. */
jens@28
    29
    @"WKS", //       = 11,     /* Well known service. */
jens@28
    30
    @"PTR", //       = 12,     /* Domain name pointer. */
jens@28
    31
    @"HINFO", //     = 13,     /* Host information. */
jens@28
    32
    @"MINFO", //     = 14,     /* Mailbox information. */
jens@28
    33
    @"MX", //        = 15,     /* Mail routing information. */
jens@28
    34
    @"TXT" //       = 16,     /* One or more text strings (NOT "zero or more..."). */
jens@28
    35
    // this isn't a complete list; it just includes the most common ones.
jens@28
    36
    // For the full list, see the "kDNSServiceType_..." constants in <dns_sd.h>.
jens@28
    37
};
jens@28
    38
jens@28
    39
@interface MYBonjourQuery ()
jens@28
    40
@property (copy) NSData *recordData;
jens@28
    41
@end
jens@28
    42
jens@28
    43
jens@28
    44
@implementation MYBonjourQuery
jens@28
    45
jens@28
    46
jens@28
    47
- (id) initWithBonjourService: (MYBonjourService*)service recordType: (uint16_t)recordType;
jens@28
    48
{
jens@28
    49
    self = [super init];
jens@28
    50
    if (self) {
jens@28
    51
        _bonjourService = service;
jens@28
    52
        _recordType = recordType;
jens@28
    53
    }
jens@28
    54
    return self;
jens@28
    55
}
jens@28
    56
jens@28
    57
- (void) dealloc
jens@28
    58
{
jens@28
    59
    [_recordData release];
jens@28
    60
    [super dealloc];
jens@28
    61
}
jens@28
    62
jens@28
    63
jens@28
    64
- (NSString*) description
jens@28
    65
{
jens@28
    66
    NSString *typeName;
jens@28
    67
    if (_recordType <= 16)
jens@28
    68
        typeName = kRecordTypeNames[_recordType];
jens@28
    69
    else
jens@28
    70
        typeName = $sprintf(@"%u", _recordType);
jens@28
    71
    return $sprintf(@"%@[%@ /%@]", self.class, _bonjourService.name, typeName);
jens@28
    72
}
jens@28
    73
jens@28
    74
jens@28
    75
@synthesize recordData=_recordData;
jens@28
    76
jens@28
    77
jens@28
    78
- (void) priv_gotRecordBytes: (const void *)rdata
jens@28
    79
                      length: (uint16_t)rdlen
jens@28
    80
                        type: (uint16_t)rrtype
jens@28
    81
                         ttl: (uint32_t)ttl
jens@28
    82
                       flags: (DNSServiceFlags)flags
jens@28
    83
{
jens@28
    84
    NSData *data = [NSData dataWithBytes: rdata length: rdlen];
jens@28
    85
    if (!$equal(data,_recordData)) {
jens@28
    86
        if (data.length <= 16)
jens@28
    87
            LogTo(Bonjour,@"%@ = %@", self, data);
jens@28
    88
        else
jens@28
    89
            LogTo(Bonjour,@"%@ = %@...", self, [data subdataWithRange: NSMakeRange(0,16)]);
jens@28
    90
        self.recordData = data;
jens@28
    91
    }
jens@28
    92
    [_bonjourService queryDidUpdate: self];
jens@28
    93
}
jens@28
    94
jens@28
    95
jens@28
    96
static void queryCallback( DNSServiceRef                       DNSServiceRef,
jens@28
    97
                           DNSServiceFlags                     flags,
jens@28
    98
                           uint32_t                            interfaceIndex,
jens@28
    99
                           DNSServiceErrorType                 errorCode,
jens@28
   100
                           const char                          *fullname,
jens@28
   101
                           uint16_t                            rrtype,
jens@28
   102
                           uint16_t                            rrclass,
jens@28
   103
                           uint16_t                            rdlen,
jens@28
   104
                           const void                          *rdata,
jens@28
   105
                           uint32_t                            ttl,
jens@28
   106
                           void                                *context)
jens@28
   107
{
jens@31
   108
    MYBonjourQuery *query = context;
jens@61
   109
    [query retain];
jens@28
   110
    @try{
jens@28
   111
        //LogTo(Bonjour, @"queryCallback for %@ (err=%i)", context,errorCode);
jens@31
   112
        if (!errorCode)
jens@31
   113
            [query priv_gotRecordBytes: rdata
jens@31
   114
                                length: rdlen
jens@31
   115
                                  type: rrtype
jens@31
   116
                                   ttl: ttl
jens@31
   117
                                 flags: flags];
jens@28
   118
    }catchAndReport(@"MYBonjourResolver query callback");
jens@31
   119
    [query gotResponse: errorCode];
jens@61
   120
    [query release];
jens@28
   121
}
jens@28
   122
jens@28
   123
jens@31
   124
- (DNSServiceErrorType) createServiceRef: (DNSServiceRef*)sdRefPtr {
jens@28
   125
    const char *fullName = _bonjourService.fullName.UTF8String;
jens@28
   126
    if (fullName)
jens@31
   127
        return DNSServiceQueryRecord(sdRefPtr,
jens@31
   128
                                     kDNSServiceFlagsShareConnection, 
jens@31
   129
                                     _bonjourService.interfaceIndex, 
jens@31
   130
                                     fullName,
jens@31
   131
                                     _recordType, kDNSServiceClass_IN, 
jens@31
   132
                                     &queryCallback, self);
jens@31
   133
    else
jens@31
   134
        return kDNSServiceErr_NoSuchName;
jens@28
   135
}
jens@28
   136
jens@28
   137
jens@28
   138
@end
jens@31
   139
jens@31
   140
jens@31
   141
/*
jens@31
   142
 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
jens@31
   143
 
jens@31
   144
 Redistribution and use in source and binary forms, with or without modification, are permitted
jens@31
   145
 provided that the following conditions are met:
jens@31
   146
 
jens@31
   147
 * Redistributions of source code must retain the above copyright notice, this list of conditions
jens@31
   148
 and the following disclaimer.
jens@31
   149
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
jens@31
   150
 and the following disclaimer in the documentation and/or other materials provided with the
jens@31
   151
 distribution.
jens@31
   152
 
jens@31
   153
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
jens@31
   154
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
jens@31
   155
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
jens@31
   156
 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
jens@31
   157
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
jens@31
   158
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
jens@31
   159
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
jens@31
   160
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@31
   161
 */