jens@28: // jens@28: // MYAddressLookup.m jens@28: // MYNetwork jens@28: // jens@28: // Created by Jens Alfke on 4/24/09. jens@28: // Copyright 2009 Jens Alfke. All rights reserved. jens@28: // jens@28: jens@28: #import "MYAddressLookup.h" jens@28: #import "IPAddress.h" jens@28: #import "ExceptionUtils.h" jens@28: #import "Test.h" jens@28: #import "Logging.h" jens@28: #import jens@28: jens@28: jens@28: @implementation MYAddressLookup jens@28: jens@28: - (id) initWithHostname: (NSString*)hostname jens@28: { jens@28: self = [super init]; jens@28: if (self != nil) { jens@28: if (!hostname) { jens@28: [self release]; jens@28: return nil; jens@28: } jens@28: _hostname = [hostname copy]; jens@28: _addresses = [[NSMutableArray alloc] init]; jens@28: } jens@28: return self; jens@28: } jens@28: jens@28: - (void) dealloc jens@28: { jens@28: [_hostname release]; jens@28: [_addresses release]; jens@28: [super dealloc]; jens@28: } jens@28: jens@28: jens@28: - (NSString*) description jens@28: { jens@28: return $sprintf(@"%@[%@]", self.class,_hostname); jens@28: } jens@28: jens@28: jens@28: @synthesize port=_port, interfaceIndex=_interfaceIndex, addresses=_addresses; jens@28: jens@28: jens@28: - (NSTimeInterval) timeToLive { jens@28: return MAX(0.0, _expires - CFAbsoluteTimeGetCurrent()); jens@28: } jens@28: jens@28: jens@28: - (void) priv_resolvedAddress: (const struct sockaddr*)sockaddr jens@28: ttl: (uint32_t)ttl jens@28: flags: (DNSServiceFlags)flags jens@28: { jens@28: HostAddress *address = [[HostAddress alloc] initWithHostname: _hostname jens@28: sockaddr: sockaddr jens@28: port: _port]; jens@28: if (address) { jens@28: if (flags & kDNSServiceFlagsAdd) jens@28: [_addresses addObject: address]; jens@28: else jens@28: [_addresses removeObject: address]; jens@28: [address release]; jens@28: } jens@28: jens@28: _expires = CFAbsoluteTimeGetCurrent() + ttl; jens@28: jens@28: if (!(flags & kDNSServiceFlagsMoreComing)) jens@28: LogTo(DNS,@"Got addresses of %@: %@ [TTL = %u]", self, _addresses, ttl); jens@28: } jens@28: jens@28: jens@28: static void lookupCallback(DNSServiceRef sdRef, jens@28: DNSServiceFlags flags, jens@28: uint32_t interfaceIndex, jens@28: DNSServiceErrorType errorCode, jens@28: const char *hostname, jens@28: const struct sockaddr *address, jens@28: uint32_t ttl, jens@28: void *context) jens@28: { jens@28: MYAddressLookup *lookup = context; jens@28: @try{ jens@28: //LogTo(Bonjour, @"lookupCallback for %s (err=%i)", hostname,errorCode); jens@28: if (errorCode) jens@28: [lookup setError: errorCode]; jens@28: else jens@28: [lookup priv_resolvedAddress: address ttl: ttl flags: flags]; jens@28: }catchAndReport(@"MYDNSLookup query callback"); jens@28: } jens@28: jens@28: jens@28: - (DNSServiceRef) createServiceRef { jens@28: [_addresses removeAllObjects]; jens@28: DNSServiceRef serviceRef = NULL; jens@28: self.error = DNSServiceGetAddrInfo(&serviceRef, 0, jens@28: _interfaceIndex, 0, jens@28: _hostname.UTF8String, jens@28: &lookupCallback, self); jens@28: return serviceRef; jens@28: } jens@28: jens@28: jens@28: @end jens@28: jens@28: jens@28: jens@28: TestCase(MYDNSLookup) { jens@28: EnableLogTo(Bonjour,YES); jens@28: EnableLogTo(DNS,YES); jens@28: [NSRunLoop currentRunLoop]; // create runloop jens@28: jens@28: MYAddressLookup *lookup = [[MYAddressLookup alloc] initWithHostname: @"www.apple.com" port: 80]; jens@28: [lookup start]; jens@28: jens@28: [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 10]]; jens@28: [lookup release]; jens@28: }