Bonjour/MYAddressLookup.m
author Jens Alfke <jens@mooseyard.com>
Wed May 06 09:21:57 2009 -0700 (2009-05-06)
changeset 44 d8a559a39284
parent 31 1d6924779df7
child 46 50dc5502ef46
permissions -rw-r--r--
* Merged part of Jim Roepke's changes -- the MYAddressLookup fixes and updated iPhone project.
* Changed API of Jim Roepke's TCPListener improvement (made it a settable property, not a method to override.)
* Added more types to .hgignore.
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);
jim@43
    65
			NSSet *changedObjects = [NSSet setWithObject:address];
jim@43
    66
			[self willChangeValueForKey:@"addresses" 
jim@43
    67
						withSetMutation:NSKeyValueUnionSetMutation 
jim@43
    68
						   usingObjects:changedObjects]; 
jens@28
    69
            [_addresses addObject: address];
jim@43
    70
			[self didChangeValueForKey:@"addresses" 
jim@43
    71
					   withSetMutation:NSKeyValueUnionSetMutation 
jim@43
    72
						  usingObjects:changedObjects]; 
jens@31
    73
        } else {
jens@31
    74
            LogTo(DNS,@"%@ lost %@ [TTL = %u]", self, address, ttl);
jim@43
    75
			NSSet *changedObjects = [NSSet setWithObject:address];
jim@43
    76
			[self willChangeValueForKey:@"addresses" 
jim@43
    77
						withSetMutation:NSKeyValueMinusSetMutation 
jim@43
    78
						   usingObjects:changedObjects]; 
jens@28
    79
            [_addresses removeObject: address];
jim@43
    80
			[self didChangeValueForKey:@"addresses" 
jim@43
    81
					   withSetMutation:NSKeyValueMinusSetMutation 
jim@43
    82
						  usingObjects:changedObjects]; 
jens@31
    83
        }
jens@28
    84
        [address release];
jens@28
    85
    }
jens@28
    86
    
jens@28
    87
    _expires = CFAbsoluteTimeGetCurrent() + ttl;
jens@28
    88
}
jens@28
    89
jens@28
    90
jens@28
    91
static void lookupCallback(DNSServiceRef                    sdRef,
jens@28
    92
                           DNSServiceFlags                  flags,
jens@28
    93
                           uint32_t                         interfaceIndex,
jens@28
    94
                           DNSServiceErrorType              errorCode,
jens@28
    95
                           const char                       *hostname,
jens@28
    96
                           const struct sockaddr            *address,
jens@28
    97
                           uint32_t                         ttl,
jens@28
    98
                           void                             *context)
jens@28
    99
{
jens@28
   100
    MYAddressLookup *lookup = context;
jens@28
   101
    @try{
jens@28
   102
        //LogTo(Bonjour, @"lookupCallback for %s (err=%i)", hostname,errorCode);
jens@28
   103
        if (errorCode)
jens@28
   104
            [lookup setError: errorCode];
jens@28
   105
        else
jens@28
   106
            [lookup priv_resolvedAddress: address ttl: ttl flags: flags];
jens@28
   107
    }catchAndReport(@"MYDNSLookup query callback");
jens@31
   108
    [lookup gotResponse: errorCode];
jens@28
   109
}
jens@28
   110
jens@28
   111
jens@31
   112
- (DNSServiceErrorType) createServiceRef: (DNSServiceRef*)sdRefPtr {
jim@43
   113
	if ([_addresses count] > 0) {
jim@43
   114
		NSSet *changedObjects = [NSSet setWithSet:_addresses];
jim@43
   115
		[self willChangeValueForKey:@"addresses" 
jim@43
   116
					withSetMutation:NSKeyValueMinusSetMutation 
jim@43
   117
					   usingObjects:changedObjects]; 
jim@43
   118
		[_addresses removeAllObjects];
jim@43
   119
		[self didChangeValueForKey:@"addresses" 
jim@43
   120
				   withSetMutation:NSKeyValueMinusSetMutation 
jim@43
   121
					  usingObjects:changedObjects]; 
jim@43
   122
	}
jens@31
   123
    return DNSServiceGetAddrInfo(sdRefPtr,
jens@31
   124
                                 kDNSServiceFlagsShareConnection,
jens@31
   125
                                 _interfaceIndex, 0,
jens@31
   126
                                 _hostname.UTF8String,
jens@31
   127
                                 &lookupCallback, self);
jens@28
   128
}
jens@28
   129
jens@28
   130
jens@28
   131
@end
jens@28
   132
jens@28
   133
jens@28
   134
jens@28
   135
TestCase(MYDNSLookup) {
jens@28
   136
    EnableLogTo(Bonjour,YES);
jens@28
   137
    EnableLogTo(DNS,YES);
jens@28
   138
    [NSRunLoop currentRunLoop]; // create runloop
jens@28
   139
jens@28
   140
    MYAddressLookup *lookup = [[MYAddressLookup alloc] initWithHostname: @"www.apple.com" port: 80];
jens@28
   141
    [lookup start];
jens@28
   142
    
jens@28
   143
    [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 10]];
jens@28
   144
    [lookup release];
jens@28
   145
}    
jens@31
   146
jens@31
   147
jens@31
   148
/*
jens@31
   149
 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
jens@31
   150
 
jens@31
   151
 Redistribution and use in source and binary forms, with or without modification, are permitted
jens@31
   152
 provided that the following conditions are met:
jens@31
   153
 
jens@31
   154
 * Redistributions of source code must retain the above copyright notice, this list of conditions
jens@31
   155
 and the following disclaimer.
jens@31
   156
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
jens@31
   157
 and the following disclaimer in the documentation and/or other materials provided with the
jens@31
   158
 distribution.
jens@31
   159
 
jens@31
   160
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
jens@31
   161
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
jens@31
   162
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
jens@31
   163
 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
jens@31
   164
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
jens@31
   165
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
jens@31
   166
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
jens@31
   167
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@31
   168
 */