Merged Jens' latest changes.
1.1 --- a/BLIP/BLIPMessage.m Thu Jul 02 19:58:11 2009 -0700
1.2 +++ b/BLIP/BLIPMessage.m Thu Jul 02 20:45:11 2009 -0700
1.3 @@ -39,6 +39,7 @@
1.4 _body = body.copy;
1.5 _properties = [[BLIPMutableProperties alloc] init];
1.6 _propertiesAvailable = YES;
1.7 + _complete = YES;
1.8 } else {
1.9 _encodedBody = body.mutableCopy;
1.10 }
2.1 --- a/BLIP/BLIPRequest.m Thu Jul 02 19:58:11 2009 -0700
2.2 +++ b/BLIP/BLIPRequest.m Thu Jul 02 20:45:11 2009 -0700
2.3 @@ -262,7 +262,7 @@
2.4 if( complete && _onComplete ) {
2.5 @try{
2.6 [_onComplete invokeWithSender: self];
2.7 - }catchAndReport(@"BLIPResponse onComplete target");
2.8 + }catchAndReport(@"BLIPRequest onComplete target");
2.9 }
2.10 }
2.11
3.1 --- a/Bonjour/MYAddressLookup.h Thu Jul 02 19:58:11 2009 -0700
3.2 +++ b/Bonjour/MYAddressLookup.h Thu Jul 02 20:45:11 2009 -0700
3.3 @@ -7,11 +7,13 @@
3.4 //
3.5
3.6 #import "MYDNSService.h"
3.7 +@class MYBonjourService;
3.8
3.9
3.10 /** An asynchronous DNS address lookup. Supports both Bonjour services and traditional hostnames. */
3.11 @interface MYAddressLookup : MYDNSService
3.12 {
3.13 + MYBonjourService *_service;
3.14 NSString *_hostname;
3.15 UInt16 _interfaceIndex;
3.16 NSMutableSet *_addresses;
3.17 @@ -24,6 +26,8 @@
3.18 to access its addressLookup property instead of creating your own instance.) */
3.19 - (id) initWithHostname: (NSString*)hostname;
3.20
3.21 +@property (readonly, copy) NSString *hostname;
3.22 +
3.23 /** The port number; this will be copied into the resulting IPAddress objects.
3.24 Defaults to zero, but you can set it before calling -start. */
3.25 @property UInt16 port;
3.26 @@ -42,4 +46,9 @@
3.27 query will continue to update them. */
3.28 @property (readonly) NSTimeInterval timeToLive;
3.29
3.30 +
3.31 +//internal:
3.32 +- (id) _initWithBonjourService: (MYBonjourService*)service;
3.33 +- (void) _serviceGotResponse;
3.34 +
3.35 @end
4.1 --- a/Bonjour/MYAddressLookup.m Thu Jul 02 19:58:11 2009 -0700
4.2 +++ b/Bonjour/MYAddressLookup.m Thu Jul 02 20:45:11 2009 -0700
4.3 @@ -7,6 +7,7 @@
4.4 //
4.5
4.6 #import "MYAddressLookup.h"
4.7 +#import "MYBonjourService.h"
4.8 #import "IPAddress.h"
4.9 #import "ExceptionUtils.h"
4.10 #import "Test.h"
4.11 @@ -14,6 +15,11 @@
4.12 #import <dns_sd.h>
4.13
4.14
4.15 +@interface MYAddressLookup ()
4.16 +@property (copy) NSString *hostname;
4.17 +@end
4.18 +
4.19 +
4.20 @implementation MYAddressLookup
4.21
4.22 - (id) initWithHostname: (NSString*)hostname
4.23 @@ -30,10 +36,21 @@
4.24 return self;
4.25 }
4.26
4.27 +
4.28 +- (id) _initWithBonjourService: (MYBonjourService*)service {
4.29 + self = [super init];
4.30 + if (self) {
4.31 + _service = [service retain];
4.32 + _addresses = [[NSMutableSet alloc] init];
4.33 + }
4.34 + return self;
4.35 +}
4.36 +
4.37 - (void) dealloc
4.38 {
4.39 [_hostname release];
4.40 [_addresses release];
4.41 + [_service release];
4.42 [super dealloc];
4.43 }
4.44
4.45 @@ -44,7 +61,7 @@
4.46 }
4.47
4.48
4.49 -@synthesize port=_port, interfaceIndex=_interfaceIndex, addresses=_addresses;
4.50 +@synthesize hostname=_hostname, port=_port, interfaceIndex=_interfaceIndex, addresses=_addresses;
4.51
4.52
4.53 - (NSTimeInterval) timeToLive {
4.54 @@ -52,6 +69,38 @@
4.55 }
4.56
4.57
4.58 +- (BOOL) start {
4.59 + if (_hostname) {
4.60 + return [super start];
4.61 + } else {
4.62 + // Service doesn't know its hostname yet; wait till it does:
4.63 + LogTo(DNS,@"MYAddressLookup requesting hostname of %@ ...", _service);
4.64 + Assert(_service);
4.65 + return [_service start];
4.66 + }
4.67 +}
4.68 +
4.69 +
4.70 +// Called by my _service's gotResponse method:
4.71 +- (void) _serviceGotResponse {
4.72 + Assert(_service);
4.73 + DNSServiceErrorType err = _service.error;
4.74 + if (err) {
4.75 + [self cancel];
4.76 + self.error = err;
4.77 + } else {
4.78 + NSString *hostname = _service.hostname;
4.79 + UInt16 port = _service.port;
4.80 + if (port!=_port || !$equal(hostname,_hostname)) {
4.81 + self.hostname = hostname;
4.82 + self.port = port;
4.83 + if (_hostname)
4.84 + [self start];
4.85 + }
4.86 + }
4.87 +}
4.88 +
4.89 +
4.90 - (void) priv_resolvedAddress: (const struct sockaddr*)sockaddr
4.91 ttl: (uint32_t)ttl
4.92 flags: (DNSServiceFlags)flags
4.93 @@ -85,7 +134,7 @@
4.94 {
4.95 MYAddressLookup *lookup = context;
4.96 @try{
4.97 - //LogTo(Bonjour, @"lookupCallback for %s (err=%i)", hostname,errorCode);
4.98 + LogTo(DNS, @"lookupCallback for %s (err=%i)", hostname,errorCode);
4.99 if (errorCode)
4.100 [lookup setError: errorCode];
4.101 else
4.102 @@ -96,10 +145,12 @@
4.103
4.104
4.105 - (DNSServiceErrorType) createServiceRef: (DNSServiceRef*)sdRefPtr {
4.106 + Assert(_hostname);
4.107 kvSetSet(self, @"addresses", _addresses, nil);
4.108 return DNSServiceGetAddrInfo(sdRefPtr,
4.109 kDNSServiceFlagsShareConnection,
4.110 - _interfaceIndex, 0,
4.111 + _interfaceIndex,
4.112 + kDNSServiceProtocol_IPv4,
4.113 _hostname.UTF8String,
4.114 &lookupCallback, self);
4.115 }
5.1 --- a/Bonjour/MYBonjourBrowser.h Thu Jul 02 19:58:11 2009 -0700
5.2 +++ b/Bonjour/MYBonjourBrowser.h Thu Jul 02 20:45:11 2009 -0700
5.3 @@ -22,7 +22,7 @@
5.4 MYBonjourRegistration *_myRegistration;
5.5 }
5.6
5.7 -/** Initializes a new BonjourBrowser.
5.8 +/** Initializes a new MYBonjourBrowser.
5.9 Call -start to begin browsing.
5.10 @param serviceType The name of the service type to look for, e.g. "_http._tcp". */
5.11 - (id) initWithServiceType: (NSString*)serviceType;
5.12 @@ -31,12 +31,12 @@
5.13 @property (readonly) BOOL browsing;
5.14
5.15 /** The set of currently found services. These are instances of the serviceClass,
5.16 - which is BonjourService by default.
5.17 + which is MYBonjourService by default.
5.18 This is KV-observable. */
5.19 @property (readonly) NSSet *services;
5.20
5.21 /** The class of objects to create to represent services.
5.22 - The default value is [BonjourService class]; you can change this, but only
5.23 + The default value is [MYBonjourService class]; you can change this, but only
5.24 to a subclass of that. */
5.25 @property Class serviceClass;
5.26
6.1 --- a/Bonjour/MYBonjourBrowser.m Thu Jul 02 19:58:11 2009 -0700
6.2 +++ b/Bonjour/MYBonjourBrowser.m Thu Jul 02 20:45:11 2009 -0700
6.3 @@ -51,7 +51,7 @@
6.4
6.5 - (void) dealloc
6.6 {
6.7 - LogTo(Bonjour,@"DEALLOC BonjourBrowser");
6.8 + LogTo(Bonjour,@"DEALLOC MYBonjourBrowser");
6.9 [_myRegistration cancel];
6.10 [_myRegistration release];
6.11 [_serviceType release];
6.12 @@ -160,18 +160,18 @@
6.13 }
6.14
6.15
6.16 -static void browseCallback (DNSServiceRef sdRef,
6.17 - DNSServiceFlags flags,
6.18 - uint32_t interfaceIndex,
6.19 - DNSServiceErrorType errorCode,
6.20 - const char *serviceName,
6.21 - const char *regtype,
6.22 - const char *replyDomain,
6.23 - void *context)
6.24 +static void browseCallback (DNSServiceRef sdRef,
6.25 + DNSServiceFlags flags,
6.26 + uint32_t interfaceIndex,
6.27 + DNSServiceErrorType errorCode,
6.28 + const char *serviceName,
6.29 + const char *regtype,
6.30 + const char *replyDomain,
6.31 + void *context)
6.32 {
6.33 MYBonjourBrowser *browser = context;
6.34 @try{
6.35 - //LogTo(Bonjour,@"browseCallback (error=%i, name='%s')", errorCode,serviceName);
6.36 + LogTo(Bonjour,@"browseCallback (error=%i, name='%s', intf=%u)", errorCode,serviceName,interfaceIndex);
6.37 if (!errorCode)
6.38 [browser priv_gotServiceName: [NSString stringWithUTF8String: serviceName]
6.39 type: [NSString stringWithUTF8String: regtype]
6.40 @@ -253,9 +253,8 @@
6.41 if( [[change objectForKey: NSKeyValueChangeKindKey] intValue]==NSKeyValueChangeInsertion ) {
6.42 NSSet *newServices = [change objectForKey: NSKeyValueChangeNewKey];
6.43 for( MYBonjourService *service in newServices ) {
6.44 - NSString *hostname = service.hostname; // block till it's resolved
6.45 Log(@"##### %@ : at %@:%hu, TXT=%@",
6.46 - service, hostname, service.port, service.txtRecord);
6.47 + service, service.hostname, service.port, service.txtRecord);
6.48 service.addressLookup.continuous = YES;
6.49 [service.addressLookup addObserver: self
6.50 forKeyPath: @"addresses"
7.1 --- a/Bonjour/MYBonjourRegistration.m Thu Jul 02 19:58:11 2009 -0700
7.2 +++ b/Bonjour/MYBonjourRegistration.m Thu Jul 02 20:45:11 2009 -0700
7.3 @@ -60,6 +60,7 @@
7.4 [_name release];
7.5 [_type release];
7.6 [_domain release];
7.7 + [_txtRecord release];
7.8 [super dealloc];
7.9 }
7.10
7.11 @@ -149,6 +150,8 @@
7.12
7.13
7.14 + (NSData*) dataFromTXTRecordDictionary: (NSDictionary*)txtDict {
7.15 + if (!txtDict)
7.16 + return nil;
7.17 // First translate any non-NSData values into UTF-8 formatted description data:
7.18 NSMutableDictionary *encodedDict = $mdict();
7.19 for (NSString *key in txtDict) {
7.20 @@ -166,7 +169,7 @@
7.21 [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(updateTxtRecord) object: nil];
7.22 if (self.serviceRef) {
7.23 NSData *data = [[self class] dataFromTXTRecordDictionary: _txtRecord];
7.24 - Assert(data!=nil, @"Can't convert dictionary to TXT record");
7.25 + Assert(data!=nil || _txtRecord==nil, @"Can't convert dictionary to TXT record: %@", _txtRecord);
7.26 DNSServiceErrorType err = DNSServiceUpdateRecord(self.serviceRef,
7.27 NULL,
7.28 0,
7.29 @@ -187,10 +190,7 @@
7.30
7.31 - (void) setTxtRecord: (NSDictionary*)txtDict {
7.32 if (!$equal(_txtRecord,txtDict)) {
7.33 - if (txtDict)
7.34 - [_txtRecord setDictionary: txtDict];
7.35 - else
7.36 - setObj(&_txtRecord,nil);
7.37 + setObjCopy(&_txtRecord, txtDict);
7.38 [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(updateTxtRecord) object: nil];
7.39 [self performSelector: @selector(updateTxtRecord) withObject: nil afterDelay: 0.1];
7.40 }
7.41 @@ -235,6 +235,7 @@
7.42 - (void) updateTXT {
7.43 NSDictionary *txt = $dict({@"time", $sprintf(@"%.3lf", CFAbsoluteTimeGetCurrent())});
7.44 _reg.txtRecord = txt;
7.45 + CAssertEqual(_reg.txtRecord, txt);
7.46 [self performSelector: @selector(updateTXT) withObject: nil afterDelay: 3.0];
7.47 }
7.48
8.1 --- a/Bonjour/MYBonjourService.h Thu Jul 02 19:58:11 2009 -0700
8.2 +++ b/Bonjour/MYBonjourService.h Thu Jul 02 20:45:11 2009 -0700
8.3 @@ -10,7 +10,7 @@
8.4 @class MYBonjourQuery, MYAddressLookup;
8.5
8.6
8.7 -/** Represents a Bonjour service discovered by a BonjourBrowser. */
8.8 +/** Represents a Bonjour service discovered by a MYBonjourBrowser. */
8.9 @interface MYBonjourService : MYDNSService
8.10 {
8.11 @private
9.1 --- a/Bonjour/MYBonjourService.m Thu Jul 02 19:58:11 2009 -0700
9.2 +++ b/Bonjour/MYBonjourService.m Thu Jul 02 20:45:11 2009 -0700
9.3 @@ -21,6 +21,8 @@
9.4
9.5
9.6 @interface MYBonjourService ()
9.7 +@property (copy) NSString *hostname;
9.8 +@property UInt16 port;
9.9 @end
9.10
9.11
9.12 @@ -60,7 +62,8 @@
9.13 }
9.14
9.15
9.16 -@synthesize name=_name, type=_type, domain=_domain, fullName=_fullName, interfaceIndex=_interfaceIndex;
9.17 +@synthesize name=_name, type=_type, domain=_domain, fullName=_fullName,
9.18 + hostname=_hostname, port=_port, interfaceIndex=_interfaceIndex;
9.19
9.20
9.21 - (NSString*) description {
9.22 @@ -105,21 +108,15 @@
9.23 }
9.24
9.25
9.26 -- (void) priv_finishResolve {
9.27 - // If I haven't finished my resolve yet, run it *synchronously* now so I can return a valid value:
9.28 +- (NSString*) hostname {
9.29 if (!_startedResolve )
9.30 [self start];
9.31 - if (self.serviceRef)
9.32 - [self waitForReply];
9.33 -}
9.34 -
9.35 -- (NSString*) hostname {
9.36 - if (!_hostname) [self priv_finishResolve];
9.37 return _hostname;
9.38 }
9.39
9.40 - (UInt16) port {
9.41 - if (!_port) [self priv_finishResolve];
9.42 + if (!_startedResolve )
9.43 + [self start];
9.44 return _port;
9.45 }
9.46
9.47 @@ -185,16 +182,19 @@
9.48 LogTo(Bonjour, @"%@: hostname=%@, port=%u, txt=%u bytes",
9.49 self, hostname, port, txtData.length);
9.50
9.51 - // Don't call a setter method to set these properties: the getters are synchronous, so
9.52 - // I might already be blocked in a call to one of them, in which case creating a KV
9.53 - // notification could cause trouble...
9.54 - _hostname = hostname.copy;
9.55 - _port = port;
9.56 + if (port!=_port || !$equal(hostname,_hostname)) {
9.57 + self.hostname = hostname;
9.58 + self.port = port;
9.59 + }
9.60
9.61 - // TXT getter is async, though, so I can use a setter to announce the data's availability:
9.62 [self setTxtData: txtData];
9.63 }
9.64
9.65 +- (void) gotResponse: (DNSServiceErrorType)errorCode {
9.66 + [super gotResponse: errorCode];
9.67 + [_addressLookup _serviceGotResponse];
9.68 +}
9.69 +
9.70
9.71 static void resolveCallback(DNSServiceRef sdRef,
9.72 DNSServiceFlags flags,
9.73 @@ -236,8 +236,7 @@
9.74 - (MYAddressLookup*) addressLookup {
9.75 if (!_addressLookup) {
9.76 // Create the lookup the first time this is called:
9.77 - _addressLookup = [[MYAddressLookup alloc] initWithHostname: self.hostname];
9.78 - _addressLookup.port = _port;
9.79 + _addressLookup = [[MYAddressLookup alloc] _initWithBonjourService: self];
9.80 _addressLookup.interfaceIndex = _interfaceIndex;
9.81 }
9.82 // (Re)start the lookup if it's expired:
10.1 --- a/PortMapper/MYDNSService.h Thu Jul 02 19:58:11 2009 -0700
10.2 +++ b/PortMapper/MYDNSService.h Thu Jul 02 20:45:11 2009 -0700
10.3 @@ -38,6 +38,9 @@
10.4 /** Stops the service. */
10.5 - (void) stop;
10.6
10.7 +/** Has the service started up? */
10.8 +@property (readonly) BOOL isRunning;
10.9 +
10.10
10.11 /** The error status, a DNSServiceErrorType enum; nonzero if something went wrong.
10.12 This property is KV observable. */
11.1 --- a/PortMapper/MYDNSService.m Thu Jul 02 19:58:11 2009 -0700
11.2 +++ b/PortMapper/MYDNSService.m Thu Jul 02 20:45:11 2009 -0700
11.3 @@ -143,6 +143,11 @@
11.4 }
11.5
11.6
11.7 +- (BOOL) isRunning {
11.8 + return _serviceRef != NULL;
11.9 +}
11.10 +
11.11 +
11.12 + (NSString*) fullNameOfService: (NSString*)serviceName
11.13 ofType: (NSString*)type
11.14 inDomain: (NSString*)domain
11.15 @@ -291,8 +296,12 @@
11.16 NSAutoreleasePool *pool = [NSAutoreleasePool new];
11.17 LogTo(DNS,@"---serviceCallback----");
11.18 DNSServiceErrorType err = DNSServiceProcessResult(_connectionRef);
11.19 - if (err)
11.20 + if (err) {
11.21 Warn(@"%@: DNSServiceProcessResult failed, err=%i !!!", self,err);
11.22 + //FIX: Are errors here fatal, meaning I should close the connection?
11.23 + // I've run into infinite loops constantly getting kDNSServiceErr_ServiceNotRunning
11.24 + // or kDNSServiceErr_BadReference ...
11.25 + }
11.26 [pool drain];
11.27 return !err;
11.28 }