Merged Jens' latest changes.
authormorrowa
Thu Jul 02 20:45:11 2009 -0700 (2009-07-02)
changeset 57998dcacd4983
parent 56 6c3b5372a307
parent 50 63baa74c903f
child 58 6577813acf12
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  }