Moved _handleCloseRequest to a new method. Added warning messages.
     5 //  Created by Jens Alfke on 1/4/08.
 
     6 //  Copyright 2008 Jens Alfke. All rights reserved.
 
     9 #import "MYPortMapper.h"
 
    11 #import "CollectionUtils.h"
 
    13 #import "ExceptionUtils.h"
 
    18 NSString* const MYPortMapperChangedNotification = @"MYPortMapperChanged";
 
    21 @interface MYPortMapper ()
 
    22 @property (retain) IPAddress* publicAddress, *localAddress; // redeclare as settable
 
    23 - (void) priv_updateLocalAddress;
 
    27 @implementation MYPortMapper
 
    30 - (id) initWithLocalPort: (UInt16)localPort
 
    34         _localPort = localPort;
 
    36         self.continuous = YES;
 
    37         [self priv_updateLocalAddress];
 
    42 - (id) initWithNullMapping
 
    44     // A PortMapper with no port or protocols will cause the DNSService to look up 
 
    45     // our public address without creating a mapping.
 
    46     if ([self initWithLocalPort: 0]) {
 
    47         _mapTCP = _mapUDP = NO;
 
    55     [_publicAddress release];
 
    56     [_localAddress release];
 
    61 @synthesize localAddress=_localAddress, publicAddress=_publicAddress,
 
    62             mapTCP=_mapTCP, mapUDP=_mapUDP,
 
    63             desiredPublicPort=_desiredPublicPort;
 
    68     return ! $equal(_publicAddress,_localAddress);
 
    71 - (void) priv_updateLocalAddress 
 
    73     IPAddress *localAddress = [IPAddress localAddressWithPort: _localPort];
 
    74     if (!$equal(localAddress,_localAddress))
 
    75         self.localAddress = localAddress;
 
    79 static IPAddress* makeIPAddr( UInt32 rawAddr, UInt16 port ) {
 
    81         return [[[IPAddress alloc] initWithIPv4: rawAddr port: port] autorelease];
 
    86 /** Called whenever the port mapping changes (see comment for callback, below.) */
 
    87 - (void) priv_portMapStatus: (DNSServiceErrorType)errorCode 
 
    88               publicAddress: (UInt32)rawPublicAddress
 
    89                  publicPort: (UInt16)publicPort
 
    91     if( errorCode==kDNSServiceErr_NoError ) {
 
    92         if( rawPublicAddress==0 || (publicPort==0 && (_mapTCP || _mapUDP)) ) {
 
    93             LogTo(PortMapper,@"%@: No port-map available", self);
 
    94             errorCode = kDNSServiceErr_NATPortMappingUnsupported;
 
    98     [self priv_updateLocalAddress];
 
    99     IPAddress *publicAddress = makeIPAddr(rawPublicAddress,publicPort);
 
   100     if (!$equal(publicAddress,_publicAddress))
 
   101         self.publicAddress = publicAddress;
 
   104         LogTo(PortMapper,@"%@: Public addr is %@ (mapped=%i)",
 
   105               self, self.publicAddress, self.isMapped);
 
   108     [self gotResponse: errorCode];
 
   109     [[NSNotificationCenter defaultCenter] postNotificationName: MYPortMapperChangedNotification
 
   114 /** Asynchronous callback from DNSServiceNATPortMappingCreate.
 
   115     This is invoked whenever the status of the port mapping changes.
 
   116     All it does is dispatch to the object's priv_portMapStatus:publicAddress:publicPort: method. */
 
   117 static void portMapCallback (
 
   119                       DNSServiceFlags                  flags,
 
   120                       uint32_t                         interfaceIndex,
 
   121                       DNSServiceErrorType              errorCode,
 
   122                       uint32_t                         publicAddress,    /* four byte IPv4 address in network byte order */
 
   123                       DNSServiceProtocol               protocol,
 
   124                       uint16_t                         privatePort,
 
   125                       uint16_t                         publicPort,       /* may be different than the requested port */
 
   126                       uint32_t                         ttl,              /* may be different than the requested ttl */
 
   131         [(MYPortMapper*)context priv_portMapStatus: errorCode 
 
   132                                      publicAddress: publicAddress
 
   133                                         publicPort: ntohs(publicPort)];  // port #s in network byte order!
 
   134     }catchAndReport(@"PortMapper");
 
   138 - (DNSServiceErrorType) createServiceRef: (DNSServiceRef*)sdRefPtr {
 
   139     DNSServiceProtocol protocols = 0;
 
   140     if( _mapTCP ) protocols |= kDNSServiceProtocol_TCP;
 
   141     if( _mapUDP ) protocols |= kDNSServiceProtocol_UDP;
 
   142     return DNSServiceNATPortMappingCreate(sdRefPtr, 
 
   143                                           kDNSServiceFlagsShareConnection, 
 
   144                                           0 /*interfaceIndex*/, 
 
   147                                           htons(_desiredPublicPort),
 
   154 - (BOOL) waitTillOpened
 
   156     if( ! self.serviceRef )
 
   160     return (self.error==0);
 
   164 + (IPAddress*) findPublicAddress
 
   166     IPAddress *addr = nil;
 
   167     MYPortMapper *mapper = [[self alloc] initWithNullMapping];
 
   168     mapper.continuous = NO;
 
   169     if( [mapper waitTillOpened] )
 
   170         addr = [mapper.publicAddress retain];
 
   173     return [addr autorelease];
 
   181  Copyright (c) 2008-2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
 
   183  Redistribution and use in source and binary forms, with or without modification, are permitted
 
   184  provided that the following conditions are met:
 
   186  * Redistributions of source code must retain the above copyright notice, this list of conditions
 
   187  and the following disclaimer.
 
   188  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
 
   189  and the following disclaimer in the documentation and/or other materials provided with the
 
   192  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 
   193  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
 
   194  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
 
   195  BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
   196  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 
   197   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 
   198  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
 
   199  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.