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 + */