PortMapper/MYDNSService.m
changeset 27 92581f26073e
child 28 732576fa8a0d
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/PortMapper/MYDNSService.m	Fri Apr 24 10:10:32 2009 -0700
     1.3 @@ -0,0 +1,151 @@
     1.4 +//
     1.5 +//  MYDNSService.m
     1.6 +//  MYNetwork
     1.7 +//
     1.8 +//  Created by Jens Alfke on 4/23/09.
     1.9 +//  Copyright 2009 Jens Alfke. All rights reserved.
    1.10 +//
    1.11 +
    1.12 +#import "MYDNSService.h"
    1.13 +#import "CollectionUtils.h"
    1.14 +#import "Logging.h"
    1.15 +#import "Test.h"
    1.16 +#import "ExceptionUtils.h"
    1.17 +
    1.18 +#import <dns_sd.h>
    1.19 +
    1.20 +
    1.21 +static void serviceCallback(CFSocketRef s, 
    1.22 +                            CFSocketCallBackType type,
    1.23 +                            CFDataRef address,
    1.24 +                            const void *data,
    1.25 +                            void *clientCallBackInfo);
    1.26 +
    1.27 +
    1.28 +@implementation MYDNSService
    1.29 +
    1.30 +
    1.31 +- (void) dealloc
    1.32 +{
    1.33 +    if( _serviceRef )
    1.34 +        [self stopService];
    1.35 +    [super dealloc];
    1.36 +}
    1.37 +
    1.38 +- (void) finalize
    1.39 +{
    1.40 +    if( _serviceRef )
    1.41 +        [self stopService];
    1.42 +    [super finalize];
    1.43 +}
    1.44 +
    1.45 +
    1.46 +@synthesize serviceRef=_serviceRef, error=_error;
    1.47 +
    1.48 +
    1.49 +- (DNSServiceRef) createServiceRef {
    1.50 +    AssertAbstractMethod();
    1.51 +}
    1.52 +
    1.53 +
    1.54 +- (BOOL) open
    1.55 +{
    1.56 +    if (_serviceRef)
    1.57 +        return YES;
    1.58 +    _serviceRef = [self createServiceRef];
    1.59 +    if (_serviceRef) {
    1.60 +        // Wrap a CFSocket around the service's socket:
    1.61 +        CFSocketContext ctxt = { 0, self, CFRetain, CFRelease, NULL };
    1.62 +        _socket = CFSocketCreateWithNative(NULL, 
    1.63 +                                           DNSServiceRefSockFD(_serviceRef), 
    1.64 +                                           kCFSocketReadCallBack, 
    1.65 +                                           &serviceCallback, &ctxt);
    1.66 +        if( _socket ) {
    1.67 +            CFSocketSetSocketFlags(_socket, CFSocketGetSocketFlags(_socket) & ~kCFSocketCloseOnInvalidate);
    1.68 +            // Attach the socket to the runloop so the serviceCallback will be invoked:
    1.69 +            _socketSource = CFSocketCreateRunLoopSource(NULL, _socket, 0);
    1.70 +            if( _socketSource ) {
    1.71 +                CFRunLoopAddSource(CFRunLoopGetCurrent(), _socketSource, kCFRunLoopCommonModes);
    1.72 +                LogTo(DNS,@"Opening %@",self);
    1.73 +                return YES; // success
    1.74 +            }
    1.75 +        }
    1.76 +    }
    1.77 +    if (!_error)
    1.78 +        self.error = kDNSServiceErr_Unknown;
    1.79 +    LogTo(DNS,@"Failed to open %@ -- err=%i",self,_error);
    1.80 +    [self stopService];
    1.81 +    return NO;
    1.82 +}
    1.83 +
    1.84 +
    1.85 +- (void) stopService
    1.86 +{
    1.87 +    if( _socketSource ) {
    1.88 +        CFRunLoopSourceInvalidate(_socketSource);
    1.89 +        CFRelease(_socketSource);
    1.90 +        _socketSource = NULL;
    1.91 +    }
    1.92 +    if( _socket ) {
    1.93 +        CFSocketInvalidate(_socket);
    1.94 +        CFRelease(_socket);
    1.95 +        _socket = NULL;
    1.96 +    }
    1.97 +    if( _serviceRef ) {
    1.98 +        LogTo(DNS,@"Stopped %@",self);
    1.99 +        DNSServiceRefDeallocate(_serviceRef);
   1.100 +        _serviceRef = NULL;
   1.101 +    }
   1.102 +}
   1.103 +
   1.104 +
   1.105 +- (void) close
   1.106 +{
   1.107 +    [self stopService];
   1.108 +    if (_error)
   1.109 +        self.error = 0;
   1.110 +}
   1.111 +
   1.112 +
   1.113 +/** CFSocket callback, informing us that _socket has data available, which means
   1.114 +    that the DNS service has an incoming result to be processed. This will end up invoking
   1.115 +    the service's specific callback. */
   1.116 +static void serviceCallback(CFSocketRef s, 
   1.117 +                            CFSocketCallBackType type,
   1.118 +                            CFDataRef address, const void *data, void *clientCallBackInfo)
   1.119 +{
   1.120 +    MYDNSService *serviceObj = (MYDNSService*)clientCallBackInfo;
   1.121 +    DNSServiceRef service = serviceObj.serviceRef;
   1.122 +    DNSServiceErrorType err = DNSServiceProcessResult(service);
   1.123 +    if( err ) {
   1.124 +        // An error here means the socket has failed and should be closed.
   1.125 +        serviceObj.error = err;
   1.126 +        [serviceObj stopService];
   1.127 +    }
   1.128 +}
   1.129 +
   1.130 +
   1.131 +@end
   1.132 +
   1.133 +
   1.134 +/*
   1.135 + Copyright (c) 2008-2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   1.136 + 
   1.137 + Redistribution and use in source and binary forms, with or without modification, are permitted
   1.138 + provided that the following conditions are met:
   1.139 + 
   1.140 + * Redistributions of source code must retain the above copyright notice, this list of conditions
   1.141 + and the following disclaimer.
   1.142 + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   1.143 + and the following disclaimer in the documentation and/or other materials provided with the
   1.144 + distribution.
   1.145 + 
   1.146 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   1.147 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   1.148 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   1.149 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   1.150 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   1.151 +  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   1.152 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   1.153 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1.154 + */