Bonjour/MYAddressLookup.m
author Jens Alfke <jens@mooseyard.com>
Mon Apr 27 09:03:56 2009 -0700 (2009-04-27)
changeset 28 732576fa8a0d
child 31 1d6924779df7
permissions -rw-r--r--
Rewrote the Bonjour classes, using the low-level <dns_sd.h> API. They're now subclasses of MYDNSService.
     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 = [[NSMutableArray 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             [_addresses addObject: address];
    65         else
    66             [_addresses removeObject: address];
    67         [address release];
    68     }
    69     
    70     _expires = CFAbsoluteTimeGetCurrent() + ttl;
    71 
    72     if (!(flags & kDNSServiceFlagsMoreComing))
    73         LogTo(DNS,@"Got addresses of %@: %@ [TTL = %u]", self, _addresses, ttl);
    74 }
    75 
    76 
    77 static void lookupCallback(DNSServiceRef                    sdRef,
    78                            DNSServiceFlags                  flags,
    79                            uint32_t                         interfaceIndex,
    80                            DNSServiceErrorType              errorCode,
    81                            const char                       *hostname,
    82                            const struct sockaddr            *address,
    83                            uint32_t                         ttl,
    84                            void                             *context)
    85 {
    86     MYAddressLookup *lookup = context;
    87     @try{
    88         //LogTo(Bonjour, @"lookupCallback for %s (err=%i)", hostname,errorCode);
    89         if (errorCode)
    90             [lookup setError: errorCode];
    91         else
    92             [lookup priv_resolvedAddress: address ttl: ttl flags: flags];
    93     }catchAndReport(@"MYDNSLookup query callback");
    94 }
    95 
    96 
    97 - (DNSServiceRef) createServiceRef {
    98     [_addresses removeAllObjects];
    99     DNSServiceRef serviceRef = NULL;
   100     self.error = DNSServiceGetAddrInfo(&serviceRef, 0,
   101                                        _interfaceIndex, 0,
   102                                        _hostname.UTF8String,
   103                                        &lookupCallback, self);
   104     return serviceRef;
   105 }
   106 
   107 
   108 @end
   109 
   110 
   111 
   112 TestCase(MYDNSLookup) {
   113     EnableLogTo(Bonjour,YES);
   114     EnableLogTo(DNS,YES);
   115     [NSRunLoop currentRunLoop]; // create runloop
   116 
   117     MYAddressLookup *lookup = [[MYAddressLookup alloc] initWithHostname: @"www.apple.com" port: 80];
   118     [lookup start];
   119     
   120     [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 10]];
   121     [lookup release];
   122 }