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.
     1 //
     2 //  MYAddressLookup.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 "MYAddressLookup.h"
    10 #import "IPAddress.h"
    11 #import "ExceptionUtils.h"
    12 #import "Test.h"
    13 #import "Logging.h"
    14 #import <dns_sd.h>
    15 
    16 
    17 @implementation MYAddressLookup
    18 
    19 - (id) initWithHostname: (NSString*)hostname
    20 {
    21     self = [super init];
    22     if (self != nil) {
    23         if (!hostname) {
    24             [self release];
    25             return nil;
    26         }
    27         _hostname = [hostname copy];
    28         _addresses = [[NSMutableSet alloc] init];
    29     }
    30     return self;
    31 }
    32 
    33 - (void) dealloc
    34 {
    35     [_hostname release];
    36     [_addresses release];
    37     [super dealloc];
    38 }
    39 
    40 
    41 - (NSString*) description
    42 {
    43     return $sprintf(@"%@[%@]", self.class,_hostname);
    44 }
    45 
    46 
    47 @synthesize port=_port, interfaceIndex=_interfaceIndex, addresses=_addresses;
    48 
    49 
    50 - (NSTimeInterval) timeToLive {
    51     return MAX(0.0, _expires - CFAbsoluteTimeGetCurrent());
    52 }
    53 
    54 
    55 - (void) priv_resolvedAddress: (const struct sockaddr*)sockaddr
    56                           ttl: (uint32_t)ttl
    57                         flags: (DNSServiceFlags)flags
    58 {
    59     HostAddress *address = [[HostAddress alloc] initWithHostname: _hostname 
    60                                                         sockaddr: sockaddr
    61                                                             port: _port];
    62     if (address) {
    63         if (flags & kDNSServiceFlagsAdd) {
    64             LogTo(DNS,@"%@ got %@ [TTL = %u]", self, address, ttl);
    65 			NSSet *changedObjects = [NSSet setWithObject:address];
    66 			[self willChangeValueForKey:@"addresses" 
    67 						withSetMutation:NSKeyValueUnionSetMutation 
    68 						   usingObjects:changedObjects]; 
    69             [_addresses addObject: address];
    70 			[self didChangeValueForKey:@"addresses" 
    71 					   withSetMutation:NSKeyValueUnionSetMutation 
    72 						  usingObjects:changedObjects]; 
    73         } else {
    74             LogTo(DNS,@"%@ lost %@ [TTL = %u]", self, address, ttl);
    75 			NSSet *changedObjects = [NSSet setWithObject:address];
    76 			[self willChangeValueForKey:@"addresses" 
    77 						withSetMutation:NSKeyValueMinusSetMutation 
    78 						   usingObjects:changedObjects]; 
    79             [_addresses removeObject: address];
    80 			[self didChangeValueForKey:@"addresses" 
    81 					   withSetMutation:NSKeyValueMinusSetMutation 
    82 						  usingObjects:changedObjects]; 
    83         }
    84         [address release];
    85     }
    86     
    87     _expires = CFAbsoluteTimeGetCurrent() + ttl;
    88 }
    89 
    90 
    91 static void lookupCallback(DNSServiceRef                    sdRef,
    92                            DNSServiceFlags                  flags,
    93                            uint32_t                         interfaceIndex,
    94                            DNSServiceErrorType              errorCode,
    95                            const char                       *hostname,
    96                            const struct sockaddr            *address,
    97                            uint32_t                         ttl,
    98                            void                             *context)
    99 {
   100     MYAddressLookup *lookup = context;
   101     @try{
   102         //LogTo(Bonjour, @"lookupCallback for %s (err=%i)", hostname,errorCode);
   103         if (errorCode)
   104             [lookup setError: errorCode];
   105         else
   106             [lookup priv_resolvedAddress: address ttl: ttl flags: flags];
   107     }catchAndReport(@"MYDNSLookup query callback");
   108     [lookup gotResponse: errorCode];
   109 }
   110 
   111 
   112 - (DNSServiceErrorType) createServiceRef: (DNSServiceRef*)sdRefPtr {
   113 	if ([_addresses count] > 0) {
   114 		NSSet *changedObjects = [NSSet setWithSet:_addresses];
   115 		[self willChangeValueForKey:@"addresses" 
   116 					withSetMutation:NSKeyValueMinusSetMutation 
   117 					   usingObjects:changedObjects]; 
   118 		[_addresses removeAllObjects];
   119 		[self didChangeValueForKey:@"addresses" 
   120 				   withSetMutation:NSKeyValueMinusSetMutation 
   121 					  usingObjects:changedObjects]; 
   122 	}
   123     return DNSServiceGetAddrInfo(sdRefPtr,
   124                                  kDNSServiceFlagsShareConnection,
   125                                  _interfaceIndex, 0,
   126                                  _hostname.UTF8String,
   127                                  &lookupCallback, self);
   128 }
   129 
   130 
   131 @end
   132 
   133 
   134 
   135 TestCase(MYDNSLookup) {
   136     EnableLogTo(Bonjour,YES);
   137     EnableLogTo(DNS,YES);
   138     [NSRunLoop currentRunLoop]; // create runloop
   139 
   140     MYAddressLookup *lookup = [[MYAddressLookup alloc] initWithHostname: @"www.apple.com" port: 80];
   141     [lookup start];
   142     
   143     [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 10]];
   144     [lookup release];
   145 }    
   146 
   147 
   148 /*
   149  Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   150  
   151  Redistribution and use in source and binary forms, with or without modification, are permitted
   152  provided that the following conditions are met:
   153  
   154  * Redistributions of source code must retain the above copyright notice, this list of conditions
   155  and the following disclaimer.
   156  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   157  and the following disclaimer in the documentation and/or other materials provided with the
   158  distribution.
   159  
   160  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   161  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   162  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   163  BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   164  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   165   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   166  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   167  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   168  */