PortMapper/MYDNSService.m
changeset 28 732576fa8a0d
parent 27 92581f26073e
child 31 1d6924779df7
     1.1 --- a/PortMapper/MYDNSService.m	Fri Apr 24 10:10:32 2009 -0700
     1.2 +++ b/PortMapper/MYDNSService.m	Mon Apr 27 09:03:56 2009 -0700
     1.3 @@ -27,20 +27,32 @@
     1.4  
     1.5  - (void) dealloc
     1.6  {
     1.7 +    Log(@"DEALLOC %@ %p", self.class,self);
     1.8      if( _serviceRef )
     1.9 -        [self stopService];
    1.10 +        [self cancel];
    1.11      [super dealloc];
    1.12  }
    1.13  
    1.14  - (void) finalize
    1.15  {
    1.16      if( _serviceRef )
    1.17 -        [self stopService];
    1.18 +        [self cancel];
    1.19      [super finalize];
    1.20  }
    1.21  
    1.22  
    1.23 -@synthesize serviceRef=_serviceRef, error=_error;
    1.24 +- (DNSServiceErrorType) error {
    1.25 +    return _error;
    1.26 +}
    1.27 +
    1.28 +- (void) setError: (DNSServiceErrorType)error {
    1.29 +    if (error)
    1.30 +        Warn(@"%@ error := %i", self,error);
    1.31 +    _error = error;
    1.32 +}
    1.33 +
    1.34 +
    1.35 +@synthesize continuous=_continuous, serviceRef=_serviceRef;
    1.36  
    1.37  
    1.38  - (DNSServiceRef) createServiceRef {
    1.39 @@ -48,11 +60,17 @@
    1.40  }
    1.41  
    1.42  
    1.43 -- (BOOL) open
    1.44 +- (BOOL) start
    1.45  {
    1.46      if (_serviceRef)
    1.47 -        return YES;
    1.48 +        return YES;     // already started
    1.49 +
    1.50 +    if (_error)
    1.51 +        self.error = 0;
    1.52 +
    1.53 +    // Ask the subclass to create a DNSServiceRef:
    1.54      _serviceRef = [self createServiceRef];
    1.55 +    
    1.56      if (_serviceRef) {
    1.57          // Wrap a CFSocket around the service's socket:
    1.58          CFSocketContext ctxt = { 0, self, CFRetain, CFRelease, NULL };
    1.59 @@ -66,7 +84,7 @@
    1.60              _socketSource = CFSocketCreateRunLoopSource(NULL, _socket, 0);
    1.61              if( _socketSource ) {
    1.62                  CFRunLoopAddSource(CFRunLoopGetCurrent(), _socketSource, kCFRunLoopCommonModes);
    1.63 -                LogTo(DNS,@"Opening %@",self);
    1.64 +                LogTo(DNS,@"Opening %@ -- service=%p",self,_serviceRef);
    1.65                  return YES; // success
    1.66              }
    1.67          }
    1.68 @@ -74,13 +92,14 @@
    1.69      if (!_error)
    1.70          self.error = kDNSServiceErr_Unknown;
    1.71      LogTo(DNS,@"Failed to open %@ -- err=%i",self,_error);
    1.72 -    [self stopService];
    1.73 +    [self cancel];
    1.74      return NO;
    1.75  }
    1.76  
    1.77  
    1.78 -- (void) stopService
    1.79 +- (void) cancel
    1.80  {
    1.81 +    [self retain];            // Prevents _socket's dealloc from releasing & deallocing me!
    1.82      if( _socketSource ) {
    1.83          CFRunLoopSourceInvalidate(_socketSource);
    1.84          CFRelease(_socketSource);
    1.85 @@ -96,17 +115,45 @@
    1.86          DNSServiceRefDeallocate(_serviceRef);
    1.87          _serviceRef = NULL;
    1.88      }
    1.89 +    [self release];
    1.90  }
    1.91  
    1.92  
    1.93 -- (void) close
    1.94 +- (void) stop
    1.95  {
    1.96 -    [self stopService];
    1.97 +    [self cancel];
    1.98      if (_error)
    1.99          self.error = 0;
   1.100  }
   1.101  
   1.102  
   1.103 +- (BOOL) priv_processResult
   1.104 +{
   1.105 +    Assert(_serviceRef);
   1.106 +    DNSServiceErrorType err = DNSServiceProcessResult(_serviceRef);
   1.107 +    if (err) {
   1.108 +        // An error here means the socket has failed and should be closed.
   1.109 +        self.error = err;
   1.110 +        [self cancel];
   1.111 +        return NO;
   1.112 +    } else {
   1.113 +        if (!_continuous)
   1.114 +            [self cancel];
   1.115 +        return YES;
   1.116 +    }
   1.117 +}
   1.118 +
   1.119 +- (BOOL) waitForReply
   1.120 +{
   1.121 +    if (!_serviceRef)
   1.122 +        return NO;
   1.123 +    LogTo(DNS,@"Waiting for %@ ...", self);
   1.124 +    BOOL ok = [self priv_processResult];
   1.125 +    LogTo(DNS,@"    ...done waiting");
   1.126 +    return ok;
   1.127 +}    
   1.128 +
   1.129 +
   1.130  /** CFSocket callback, informing us that _socket has data available, which means
   1.131      that the DNS service has an incoming result to be processed. This will end up invoking
   1.132      the service's specific callback. */
   1.133 @@ -114,14 +161,11 @@
   1.134                              CFSocketCallBackType type,
   1.135                              CFDataRef address, const void *data, void *clientCallBackInfo)
   1.136  {
   1.137 -    MYDNSService *serviceObj = (MYDNSService*)clientCallBackInfo;
   1.138 -    DNSServiceRef service = serviceObj.serviceRef;
   1.139 -    DNSServiceErrorType err = DNSServiceProcessResult(service);
   1.140 -    if( err ) {
   1.141 -        // An error here means the socket has failed and should be closed.
   1.142 -        serviceObj.error = err;
   1.143 -        [serviceObj stopService];
   1.144 -    }
   1.145 +    NSAutoreleasePool *pool = [NSAutoreleasePool new];
   1.146 +    @try{
   1.147 +        [(MYDNSService*)clientCallBackInfo priv_processResult];
   1.148 +    }catchAndReport(@"PortMapper serviceCallback");
   1.149 +    [pool drain];
   1.150  }
   1.151  
   1.152