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