Bonjour/MYAddressLookup.m
author Jens Alfke <jens@mooseyard.com>
Sun May 24 15:03:39 2009 -0700 (2009-05-24)
changeset 49 20cccc7c26ee
parent 45 8efb48eabd08
parent 43 aab592ac36fc
child 50 63baa74c903f
permissions -rw-r--r--
Misc. tweaks made while porting Chatty to use MYNetwork.
* Allow -[BLIPConnection sendRequest:] to re-send an already-sent or received request.
* Allow use of the basic -init method for BLIPConnection.
* Some new convenience factory methods.
* Broke dependencies on Security.framework out into new TCPEndpoint+Certs.m source file, so client apps aren't forced to link against Security.
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];
jim@43
    28
        _addresses = [[NSMutableSet 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@31
    63
        if (flags & kDNSServiceFlagsAdd) {
jens@31
    64
            LogTo(DNS,@"%@ got %@ [TTL = %u]", self, address, ttl);
jens@45
    65
            kvAddToSet(self, @"addresses", _addresses, address);
jens@31
    66
        } else {
jens@31
    67
            LogTo(DNS,@"%@ lost %@ [TTL = %u]", self, address, ttl);
jens@45
    68
            kvRemoveFromSet(self, @"addresses", _addresses, address);
jens@31
    69
        }
jens@28
    70
        [address release];
jens@28
    71
    }
jens@28
    72
    
jens@28
    73
    _expires = CFAbsoluteTimeGetCurrent() + 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@31
    94
    [lookup gotResponse: errorCode];
jens@28
    95
}
jens@28
    96
jens@28
    97
jens@31
    98
- (DNSServiceErrorType) createServiceRef: (DNSServiceRef*)sdRefPtr {
jens@45
    99
    kvSetSet(self, @"addresses", _addresses, nil);
jens@31
   100
    return DNSServiceGetAddrInfo(sdRefPtr,
jens@31
   101
                                 kDNSServiceFlagsShareConnection,
jens@31
   102
                                 _interfaceIndex, 0,
jens@31
   103
                                 _hostname.UTF8String,
jens@31
   104
                                 &lookupCallback, self);
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
}    
jens@31
   123
jens@31
   124
jens@31
   125
/*
jens@31
   126
 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
jens@31
   127
 
jens@31
   128
 Redistribution and use in source and binary forms, with or without modification, are permitted
jens@31
   129
 provided that the following conditions are met:
jens@31
   130
 
jens@31
   131
 * Redistributions of source code must retain the above copyright notice, this list of conditions
jens@31
   132
 and the following disclaimer.
jens@31
   133
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
jens@31
   134
 and the following disclaimer in the documentation and/or other materials provided with the
jens@31
   135
 distribution.
jens@31
   136
 
jens@31
   137
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
jens@31
   138
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
jens@31
   139
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
jens@31
   140
 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
jens@31
   141
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
jens@31
   142
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
jens@31
   143
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
jens@31
   144
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@31
   145
 */