Bonjour/MYAddressLookup.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)
jens@28
     1
//
jens@28
     2
//  MYAddressLookup.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 "MYAddressLookup.h"
jens@28
    10
#import "IPAddress.h"
jens@28
    11
#import "ExceptionUtils.h"
jens@28
    12
#import "Test.h"
jens@28
    13
#import "Logging.h"
jens@28
    14
#import <dns_sd.h>
jens@28
    15
jens@28
    16
jens@28
    17
@implementation MYAddressLookup
jens@28
    18
jens@28
    19
- (id) initWithHostname: (NSString*)hostname
jens@28
    20
{
jens@28
    21
    self = [super init];
jens@28
    22
    if (self != nil) {
jens@28
    23
        if (!hostname) {
jens@28
    24
            [self release];
jens@28
    25
            return nil;
jens@28
    26
        }
jens@28
    27
        _hostname = [hostname copy];
jens@28
    28
        _addresses = [[NSMutableArray alloc] init];
jens@28
    29
    }
jens@28
    30
    return self;
jens@28
    31
}
jens@28
    32
jens@28
    33
- (void) dealloc
jens@28
    34
{
jens@28
    35
    [_hostname release];
jens@28
    36
    [_addresses release];
jens@28
    37
    [super dealloc];
jens@28
    38
}
jens@28
    39
jens@28
    40
jens@28
    41
- (NSString*) description
jens@28
    42
{
jens@28
    43
    return $sprintf(@"%@[%@]", self.class,_hostname);
jens@28
    44
}
jens@28
    45
jens@28
    46
jens@28
    47
@synthesize port=_port, interfaceIndex=_interfaceIndex, addresses=_addresses;
jens@28
    48
jens@28
    49
jens@28
    50
- (NSTimeInterval) timeToLive {
jens@28
    51
    return MAX(0.0, _expires - CFAbsoluteTimeGetCurrent());
jens@28
    52
}
jens@28
    53
jens@28
    54
jens@28
    55
- (void) priv_resolvedAddress: (const struct sockaddr*)sockaddr
jens@28
    56
                          ttl: (uint32_t)ttl
jens@28
    57
                        flags: (DNSServiceFlags)flags
jens@28
    58
{
jens@28
    59
    HostAddress *address = [[HostAddress alloc] initWithHostname: _hostname 
jens@28
    60
                                                        sockaddr: sockaddr
jens@28
    61
                                                            port: _port];
jens@28
    62
    if (address) {
jens@28
    63
        if (flags & kDNSServiceFlagsAdd)
jens@28
    64
            [_addresses addObject: address];
jens@28
    65
        else
jens@28
    66
            [_addresses removeObject: address];
jens@28
    67
        [address release];
jens@28
    68
    }
jens@28
    69
    
jens@28
    70
    _expires = CFAbsoluteTimeGetCurrent() + ttl;
jens@28
    71
jens@28
    72
    if (!(flags & kDNSServiceFlagsMoreComing))
jens@28
    73
        LogTo(DNS,@"Got addresses of %@: %@ [TTL = %u]", self, _addresses, ttl);
jens@28
    74
}
jens@28
    75
jens@28
    76
jens@28
    77
static void lookupCallback(DNSServiceRef                    sdRef,
jens@28
    78
                           DNSServiceFlags                  flags,
jens@28
    79
                           uint32_t                         interfaceIndex,
jens@28
    80
                           DNSServiceErrorType              errorCode,
jens@28
    81
                           const char                       *hostname,
jens@28
    82
                           const struct sockaddr            *address,
jens@28
    83
                           uint32_t                         ttl,
jens@28
    84
                           void                             *context)
jens@28
    85
{
jens@28
    86
    MYAddressLookup *lookup = context;
jens@28
    87
    @try{
jens@28
    88
        //LogTo(Bonjour, @"lookupCallback for %s (err=%i)", hostname,errorCode);
jens@28
    89
        if (errorCode)
jens@28
    90
            [lookup setError: errorCode];
jens@28
    91
        else
jens@28
    92
            [lookup priv_resolvedAddress: address ttl: ttl flags: flags];
jens@28
    93
    }catchAndReport(@"MYDNSLookup query callback");
jens@28
    94
}
jens@28
    95
jens@28
    96
jens@28
    97
- (DNSServiceRef) createServiceRef {
jens@28
    98
    [_addresses removeAllObjects];
jens@28
    99
    DNSServiceRef serviceRef = NULL;
jens@28
   100
    self.error = DNSServiceGetAddrInfo(&serviceRef, 0,
jens@28
   101
                                       _interfaceIndex, 0,
jens@28
   102
                                       _hostname.UTF8String,
jens@28
   103
                                       &lookupCallback, self);
jens@28
   104
    return serviceRef;
jens@28
   105
}
jens@28
   106
jens@28
   107
jens@28
   108
@end
jens@28
   109
jens@28
   110
jens@28
   111
jens@28
   112
TestCase(MYDNSLookup) {
jens@28
   113
    EnableLogTo(Bonjour,YES);
jens@28
   114
    EnableLogTo(DNS,YES);
jens@28
   115
    [NSRunLoop currentRunLoop]; // create runloop
jens@28
   116
jens@28
   117
    MYAddressLookup *lookup = [[MYAddressLookup alloc] initWithHostname: @"www.apple.com" port: 80];
jens@28
   118
    [lookup start];
jens@28
   119
    
jens@28
   120
    [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 10]];
jens@28
   121
    [lookup release];
jens@28
   122
}