PortMapper/MYPortMapper.m
changeset 30 096cf03b65d4
parent 26 cb9cdf247239
child 28 732576fa8a0d
     1.1 --- a/PortMapper/MYPortMapper.m	Wed Apr 22 16:45:39 2009 -0700
     1.2 +++ b/PortMapper/MYPortMapper.m	Sun Apr 26 18:12:44 2009 -0700
     1.3 @@ -13,24 +13,14 @@
     1.4  #import "ExceptionUtils.h"
     1.5  
     1.6  #import <dns_sd.h>
     1.7 -#import <sys/types.h>
     1.8 -#import <sys/socket.h>
     1.9 -#import <net/if.h>
    1.10 -#import <netinet/in.h>
    1.11 -#import <ifaddrs.h>
    1.12  
    1.13  
    1.14  NSString* const MYPortMapperChangedNotification = @"MYPortMapperChanged";
    1.15  
    1.16  
    1.17  @interface MYPortMapper ()
    1.18 -// Redeclare these properties as settable, internally:
    1.19 -@property (readwrite) SInt32 error;
    1.20 -@property (retain) IPAddress* publicAddress, *localAddress;
    1.21 -// Private getter:
    1.22 -@property (readonly) void* _service;
    1.23 +@property (retain) IPAddress* publicAddress, *localAddress; // redeclare as settable
    1.24  - (void) priv_updateLocalAddress;
    1.25 -- (void) priv_disconnect;
    1.26  @end
    1.27  
    1.28  
    1.29 @@ -61,23 +51,13 @@
    1.30  
    1.31  - (void) dealloc
    1.32  {
    1.33 -    if( _service )
    1.34 -        [self priv_disconnect];
    1.35      [_publicAddress release];
    1.36      [_localAddress release];
    1.37      [super dealloc];
    1.38  }
    1.39  
    1.40 -- (void) finalize
    1.41 -{
    1.42 -    if( _service )
    1.43 -        [self priv_disconnect];
    1.44 -    [super finalize];
    1.45 -}
    1.46 -
    1.47  
    1.48  @synthesize localAddress=_localAddress, publicAddress=_publicAddress,
    1.49 -            error=_error, _service=_service,
    1.50              mapTCP=_mapTCP, mapUDP=_mapUDP,
    1.51              desiredPublicPort=_desiredPublicPort;
    1.52  
    1.53 @@ -158,110 +138,44 @@
    1.54  }
    1.55  
    1.56  
    1.57 -/** CFSocket callback, informing us that _socket has data available, which means
    1.58 -    that the DNS service has an incoming result to be processed. This will end up invoking
    1.59 -    the portMapCallback. */
    1.60 -static void serviceCallback(CFSocketRef s, 
    1.61 -                            CFSocketCallBackType type,
    1.62 -                            CFDataRef address, const void *data, void *clientCallBackInfo)
    1.63 +- (DNSServiceRef) createServiceRef
    1.64  {
    1.65 -    MYPortMapper *mapper = (MYPortMapper*)clientCallBackInfo;
    1.66 -    DNSServiceRef service = mapper._service;
    1.67 -    DNSServiceErrorType err = DNSServiceProcessResult(service);
    1.68 -    if( err ) {
    1.69 -        // An error here means the socket has failed and should be closed.
    1.70 -        [mapper priv_portMapStatus: err publicAddress: 0 publicPort: 0];
    1.71 -        [mapper priv_disconnect];
    1.72 -    }
    1.73 -}
    1.74 -
    1.75 -
    1.76 -
    1.77 -- (BOOL) open
    1.78 -{
    1.79 -    NSAssert(!_service,@"Already open");
    1.80 -    // Create the DNSService:
    1.81      DNSServiceProtocol protocols = 0;
    1.82      if( _mapTCP ) protocols |= kDNSServiceProtocol_TCP;
    1.83      if( _mapUDP ) protocols |= kDNSServiceProtocol_UDP;
    1.84 -    self.error = DNSServiceNATPortMappingCreate((DNSServiceRef*)&_service, 
    1.85 -                                         0 /*flags*/, 
    1.86 -                                         0 /*interfaceIndex*/, 
    1.87 -                                         protocols,
    1.88 -                                         htons(_localPort),
    1.89 -                                         htons(_desiredPublicPort),
    1.90 -                                         0 /*ttl*/,
    1.91 -                                         &portMapCallback, 
    1.92 -                                         self);
    1.93 -    if( _error ) {
    1.94 -        LogTo(PortMapper,@"Error %i creating port mapping",_error);
    1.95 -        return NO;
    1.96 -    }
    1.97 -    
    1.98 -    // Wrap a CFSocket around the service's socket:
    1.99 -    CFSocketContext ctxt = { 0, self, CFRetain, CFRelease, NULL };
   1.100 -    _socket = CFSocketCreateWithNative(NULL, 
   1.101 -                                       DNSServiceRefSockFD(_service), 
   1.102 -                                       kCFSocketReadCallBack, 
   1.103 -                                       &serviceCallback, &ctxt);
   1.104 -    if( _socket ) {
   1.105 -        CFSocketSetSocketFlags(_socket, CFSocketGetSocketFlags(_socket) & ~kCFSocketCloseOnInvalidate);
   1.106 -        // Attach the socket to the runloop so the serviceCallback will be invoked:
   1.107 -        _socketSource = CFSocketCreateRunLoopSource(NULL, _socket, 0);
   1.108 -        if( _socketSource )
   1.109 -            CFRunLoopAddSource(CFRunLoopGetCurrent(), _socketSource, kCFRunLoopCommonModes);
   1.110 -    }
   1.111 -    if( _socketSource ) {
   1.112 -        LogTo(PortMapper,@"Opening");
   1.113 -        return YES;
   1.114 -    } else {
   1.115 -        Warn(@"Failed to open PortMapper");
   1.116 -        [self close];
   1.117 -        _error = kDNSServiceErr_Unknown;
   1.118 -        return NO;
   1.119 -    }
   1.120 +    DNSServiceRef serviceRef = NULL;
   1.121 +    self.error = DNSServiceNATPortMappingCreate(&serviceRef, 
   1.122 +                                                0 /*flags*/, 
   1.123 +                                                0 /*interfaceIndex*/, 
   1.124 +                                                protocols,
   1.125 +                                                htons(_localPort),
   1.126 +                                                htons(_desiredPublicPort),
   1.127 +                                                0 /*ttl*/,
   1.128 +                                                &portMapCallback, 
   1.129 +                                                self);
   1.130 +    return serviceRef;
   1.131 +}
   1.132 +
   1.133 +
   1.134 +- (void) stopService
   1.135 +{
   1.136 +    [super stopService];
   1.137 +    if (_publicAddress)
   1.138 +        self.publicAddress = nil;
   1.139  }
   1.140  
   1.141  
   1.142  - (BOOL) waitTillOpened
   1.143  {
   1.144 -    if( ! _socketSource )
   1.145 +    if( ! self.serviceRef )
   1.146          if( ! [self open] )
   1.147              return NO;
   1.148      // Run the runloop until there's either an error or a result:
   1.149 -    while( _error==0 && _publicAddress==nil )
   1.150 +    while( self.error==0 && _publicAddress==nil )
   1.151          if( ! [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
   1.152                                         beforeDate: [NSDate distantFuture]] )
   1.153              break;
   1.154 -    return (_error==0);
   1.155 -}
   1.156 -
   1.157 -
   1.158 -// Close down, but _without_ clearing the 'error' property
   1.159 -- (void) priv_disconnect
   1.160 -{
   1.161 -    if( _socketSource ) {
   1.162 -        CFRunLoopSourceInvalidate(_socketSource);
   1.163 -        CFRelease(_socketSource);
   1.164 -        _socketSource = NULL;
   1.165 -    }
   1.166 -    if( _socket ) {
   1.167 -        CFSocketInvalidate(_socket);
   1.168 -        CFRelease(_socket);
   1.169 -        _socket = NULL;
   1.170 -    }
   1.171 -    if( _service ) {
   1.172 -        LogTo(PortMapper,@"Deleting port mapping");
   1.173 -        DNSServiceRefDeallocate(_service);
   1.174 -        _service = NULL;
   1.175 -        self.publicAddress = nil;
   1.176 -    }
   1.177 -}
   1.178 -
   1.179 -- (void) close
   1.180 -{
   1.181 -    [self priv_disconnect];
   1.182 -    self.error = 0;
   1.183 +    return (self.error==0);
   1.184  }
   1.185  
   1.186