PortMapper/MYPortMapper.h
author Dan Preston <danpreston@codechemistry.com>
Tue May 05 15:10:15 2009 -0700 (2009-05-05)
changeset 37 7c7d5a0cb4d6
parent 26 cb9cdf247239
permissions -rw-r--r--
Fixed the leak of SecIdentityRef objects in a while loop.
jens@26
     1
//
jens@26
     2
//  MYPortMapper.m
jens@26
     3
//  MYNetwork
jens@26
     4
//
jens@26
     5
//  Created by Jens Alfke on 1/4/08.
jens@26
     6
//  Copyright 2008 Jens Alfke. All rights reserved.
jens@26
     7
//
jens@26
     8
jens@27
     9
#import "MYDNSService.h"
jens@26
    10
@class IPAddress;
jens@26
    11
jens@26
    12
jens@26
    13
/*  MYPortMapper attempts to make a particular network port on this computer publicly reachable
jens@26
    14
    for incoming connections, by "opening a hole" through a Network Address Translator 
jens@26
    15
    (NAT) or firewall that may be in between the computer and the public Internet.
jens@26
    16
 
jens@26
    17
    The port mapping may fail if:
jens@26
    18
    * the NAT/router/firewall does not support either the UPnP or NAT-PMP protocols;
jens@26
    19
    * the device doesn't implement the protocols correctly (this happens);
jens@26
    20
    * the network administrator has disabled port-mapping;
jens@26
    21
    * there is a second layer of NAT/firewall (this happens in some ISP networks.)
jens@26
    22
 
jens@26
    23
    The PortMapper is asynchronous. It will take a nonzero amount of time to set up the
jens@26
    24
    mapping, and the mapping may change in the future as the network configuration changes.
jens@26
    25
    To be informed of changes, either use key-value observing to watch the "error" and
jens@26
    26
    "publicAddress" properties, or observe the MYPortMapperChangedNotification.
jens@26
    27
 
jens@26
    28
    Typical usage is to:
jens@26
    29
    * Start a network service that listens for incoming connections on a port
jens@26
    30
    * Open a MYPortMapper
jens@26
    31
    * When the MYPortMapper reports the public address and port of the mapping, you somehow
jens@26
    32
      notify other peers of that address and port, so they can connect to you.
jens@26
    33
    * When the MYPortMapper reports changes, you (somehow) notify peers of the changes.
jens@26
    34
    * When closing the network service, close the MYPortMapper object too.
jens@26
    35
*/ 
jens@27
    36
@interface MYPortMapper : MYDNSService
jens@26
    37
{
jens@27
    38
    @private
jens@26
    39
    UInt16 _localPort, _desiredPublicPort;
jens@26
    40
    BOOL _mapTCP, _mapUDP;
jens@26
    41
    IPAddress *_publicAddress, *_localAddress;
jens@26
    42
}
jens@26
    43
jens@26
    44
/** Initializes a PortMapper that will map the given local (private) port.
jens@26
    45
    By default it will map TCP and not UDP, and will not suggest a desired public port,
jens@26
    46
    but this can be configured by setting properties before opening the PortMapper. */
jens@26
    47
- (id) initWithLocalPort: (UInt16)localPort;
jens@26
    48
jens@26
    49
/** Initializes a PortMapper that will not map any ports.
jens@26
    50
    This is useful if you just want to find out your public IP address.
jens@26
    51
    (For a simplified, but synchronous, convenience method for this, see
jens@26
    52
    +findPublicAddress.) */
jens@26
    53
- (id) initWithNullMapping;
jens@26
    54
jens@26
    55
/** Should the TCP or UDP port, or both, be mapped? By default, TCP only.
jens@26
    56
    These properties have no effect if changed while the PortMapper is open. */
jens@26
    57
@property BOOL mapTCP, mapUDP;
jens@26
    58
jens@26
    59
/** You can set this to the public port number you'd like to get.
jens@26
    60
    It defaults to 0, which means "no preference".
jens@26
    61
    This property has no effect if changed while the PortMapper is open. */
jens@26
    62
@property UInt16 desiredPublicPort;
jens@26
    63
jens@26
    64
/** Blocks till the PortMapper finishes opening. Returns YES if it opened, NO on error.
jens@26
    65
    It's not usually a good idea to use this, as it will lock up your application
jens@26
    66
    until a response arrives from the NAT. Listen for asynchronous notifications instead.
jens@26
    67
    If called when the PortMapper is closed, it will call -open for you.
jens@26
    68
    If called when it's already open, it just returns YES. */
jens@26
    69
- (BOOL) waitTillOpened;
jens@26
    70
jens@26
    71
/** The known public IPv4 address/port, once it's been determined.
jens@26
    72
    This property is KV observable. */
jens@26
    73
@property (readonly,retain) IPAddress* publicAddress;
jens@26
    74
jens@26
    75
/** The current local address/port, as of the time the port mapping was last updated.
jens@26
    76
    The address part is of the main interface; the port is the specified local port.
jens@26
    77
    This property is KV observable. */
jens@26
    78
@property (readonly,retain) IPAddress* localAddress;
jens@26
    79
jens@26
    80
/** Returns YES if a non-null port mapping is in effect: 
jens@26
    81
    that is, if the public address differs from the local one. */
jens@26
    82
@property (readonly) BOOL isMapped;
jens@26
    83
jens@26
    84
jens@26
    85
// UTILITY CLASS METHOD:
jens@26
    86
jens@26
    87
/** Determine the main interface's public IP address, without mapping any ports.
jens@26
    88
    This method internally calls -waitTillOpened, so it may take a nontrivial amount
jens@26
    89
    of time (and will crank the runloop while it waits.)
jens@26
    90
    If you want to do this asynchronously, you should instead create a new
jens@26
    91
    MYPortMapper instance using -initWithNullMapping. */
jens@26
    92
+ (IPAddress*) findPublicAddress;
jens@26
    93
jens@26
    94
@end
jens@26
    95
jens@26
    96
jens@26
    97
/** This notification is posted asynchronously when the status of a PortMapper
jens@26
    98
    (its error, publicAddress or publicPort) changes. */
jens@26
    99
extern NSString* const MYPortMapperChangedNotification;