Main Page | File List | Globals

PortMapper.h File Reference

#include <CoreFoundation/CoreFoundation.h>

Go to the source code of this file.

Typedefs

typedef enum PMProtocol PMProtocol
typedef enum PMResult PMResult
typedef enum PMRouterType PMRouterType
typedef void(* PMInitializeCallback )(PMResult result, void *context)
typedef void(* PMGetPublicIPCallback )(CFStringRef ipAddress, void *context)
typedef void(* PMAddPortMapCallback )(PMResult result, int publicPort, int privatePort, PMProtocol protocol, void *context)
typedef void(* PMRemovePortMapCallback )(PMResult result, int publicPort, int privatePort, PMProtocol protocol, void *context)

Enumerations

enum  PMProtocol { kPMUDP_Protocol, kPMTCP_Protocol }
enum  PMResult {
  kPMSuccessful = 0, kPMInitializationError, kPMNotInitializedError, kPMNoRouterFoundError,
  kPMPortMappingError, kPMPortMappingInUseError, kPMNoSuchPortMappingError, kPMUnexpectedResult,
  kPMPortMappingDisabledError, kPMSamePortValuesRequired
}
enum  PMRouterType { kPMUnknownRouter, kPMUPnPRouterType, kPMNAT_PMPRouterType }

Functions

PMResult PMInitialize ()
 Initializes this port mapping library.

void PMInitializeAsync (PMInitializeCallback callback, CFRunLoopRef runLoop, void *context)
 Initializes this port mapping library asynchronously.

PMResult PMAddPortMapping (int publicPort, int privatePort, PMProtocol protocol)
 Asks the router to forward a port.

void PMAddPortMappingAsync (int publicPort, int privatePort, PMProtocol protocol, PMAddPortMapCallback callback, CFRunLoopRef runLoop, void *context)
 Asks the router to forward a port asynchronously.

PMResult PMRemovePortMapping (int publicPort, int privatePort, PMProtocol protocol)
 Asks the router to remove a port mapping.

void PMRemovePortMappingAsync (int publicPort, int privatePort, PMProtocol protocol, PMRemovePortMapCallback callback, CFRunLoopRef runLoop, void *context)
 Asks the router to remove a port mapping asynchronously.

CFStringRef PMGetPublicIPAddress ()
 Asks the router for its Public IP.

void PMGetPublicIPAddressAsync (PMGetPublicIPCallback callback, CFRunLoopRef runLoop, void *context)
 Asks the router for its Public IP asynchronously.

CFStringRef PMGetRouterName ()
 Returns the name of the router.

PMRouterType PMGetRouterType ()
 Returns the router type.

void PMSetRemoveAtExit (int flag)
 Sets the remove at exit flag.


Detailed Description

This library provides an abstraction to the remote port mapping facilities on "modern" consumer grade routers. Currently there are two APIs for doing this, UPnP from MS and Intel, and NAT-PMP from Apple. UPnP has been around for awhile, while NAT-PMP is the new kid on the block (July 20005).

UPnP is Microsoft's and Intel's attempt to bring automatic plug-in play to network devices. Under their system network devices would broadcast, respond to searches, and through a http, XML, and SOAP a network application is suppose to interrogate the device to figure out what it does, and how to configure it. It works, but is rather complex and most implementations are rather flaky...

Apple looked at UPnP and thought MS and Intel are insane and never even looked back at UPnP, and have just recently made up their own protocol called NAT-PMP (http://files.dns-sd.org/draft-nat-port-mapping.txt ). It is a much simpler protocol, and is faster since it doesn't have the multiple back and forths, and the overhead of a SOAP call. The downside is that it is only supported in the Airport Express, and Airport Extreme base stations whose firmware has been updated to V6.2 (Which came with the Airport 4.2 update). By default the port mapping is disabled, and the user must enable it for this library to work properly (although it can still get the public IP address).

In general usage pattern is this:

  1. Initialize the Library with a call to PMInitialize(). This is needed so that we can figure out what type of router the user has, and to set up some globals, and to spawn a thread we use to refresh the ports.
  2. Add port mappings using the PMAddPortMapping() or PMAddPortMappingAsync()
  3. Start doing network things that makes your App great.
  4. Remove port mappings, or allow the lib to remove the automatically when your program quits.

All of the operations that require some network access have async versions that will execute the operation on a background thread, and then optionally notify the caller, either on their run loop, or the thread that we used to execute the operation. All of the async operations will be executed on the same background thread, so issuing two add port maps at the same time will cause the second add operation to be run after the first one completes. This way you can issue an add, and immediately a remove, and the remove will not start until the add has finished.

The only tricky part is with initializing the library. We haven't set up the locks yet, so it is not safe to call the initialization functions from two different threads at the same time. So make sure you either call PMInitialize() or PMInitializeAsync() from a single thread, before sending any more add or remove messages. It is perfectly safe to call the async initialize, and the async add function, before the async initialization has completed. The async add will be queued and executed after the initialization has completed. If the initialization failed, then the add will also fail with a kPMNotInitializedError. If you try to call a synchronous function while the async initializer is running it will fail and you will get a kPMNotInitializedError result.

The port maps that are inserted are set to expire after an hour. The library runs a refresh thread, that will update the expiration times every half hour. This way, if your program unexpectedly quits, the port map will eventually go away. While all NAT-PMP devices support expiration times (they don't actually allow you to use an infinite timeout), not all UPnP devices support expiration times, and those routers should default to inserting an infinite port mapping.

By default the Port Mapping lib will automatically remove any port mappings you added when your application exists. If you do not want this to happen you can disable it by calling PMSetRemoveAtExit() and pass in a 0.

If the user switches their default interface, or switches from wired to wireless, or their IP address, all of the port mappings you added have become invalid. Currently you have to detect this change and reinitialize the library by calling PMInitialize().


Typedef Documentation

typedef void(* PMAddPortMapCallback)(PMResult result, int publicPort, int privatePort, PMProtocol protocol, void *context)
 

Callback is invoked when the PMAddPortMapAsync function finishes.

Parameters:
result The result of the add port map function.
publicPort The requested public port.
privatePort The requested private port.
protocol The requested protocol
context The user defined context object.

typedef void(* PMGetPublicIPCallback)(CFStringRef ipAddress, void *context)
 

Callback is invoked when the PMGetPublicIPAsync function finishes.

Parameters:
ipAddress The public IP address of the router. NULL if the library hasn't been initialized.
context The user defined context object.

typedef void(* PMInitializeCallback)(PMResult result, void *context)
 

Callback is invoked when the PMInitializeAsync function finishes.

Parameters:
result The result of the initialization function.
context The user defined context object.

typedef enum PMProtocol PMProtocol
 

The different networking protocols.

typedef void(* PMRemovePortMapCallback)(PMResult result, int publicPort, int privatePort, PMProtocol protocol, void *context)
 

Callback is invoked when the PMRemovePortMapAsync function finishes.

Parameters:
result The result of the remove port map function.
publicPort The requested public port.
privatePort The requested private port.
protocol The requested protocol
context The user defined context object.

typedef enum PMResult PMResult
 

Result codes

typedef enum PMRouterType PMRouterType
 

This library will support multiple port mapping types and these enums can be used to identify what type the router is.


Enumeration Type Documentation

enum PMProtocol
 

The different networking protocols.

Enumeration values:
kPMUDP_Protocol  Signals the UDP protocol
kPMTCP_Protocol  Signals the TCP protocol

enum PMResult
 

Result codes

Enumeration values:
kPMSuccessful  Operation completed successfully.
kPMInitializationError  We encountered an error initializing the library
kPMNotInitializedError  A port mapping attempt was made before the library was initialized.
kPMNoRouterFoundError  A compatible router was not found.
kPMPortMappingError  There was an error adding the port map.
kPMPortMappingInUseError  The requested port is already in use by another computer.
kPMNoSuchPortMappingError  The requested port map to delete doesn't exist.
kPMUnexpectedResult  A weird error happened.
kPMPortMappingDisabledError  The user has disabled the port mapping features of their router.
kPMSamePortValuesRequired  If the router doesn't support mapping a public port to a different private port

enum PMRouterType
 

This library will support multiple port mapping types and these enums can be used to identify what type the router is.

Enumeration values:
kPMUnknownRouter  The router type is unknown. Only before we have been initialized.
kPMUPnPRouterType  The router is a UPnP compatible router.
kPMNAT_PMPRouterType  The router is a NAT-PMP compatible router.


Function Documentation

PMResult PMAddPortMapping int  publicPort,
int  privatePort,
PMProtocol  protocol
 

Asks the router to forward a port.

Sends a request to the router to map the given public port to the given private port on this computer. Not all routers support having a different public and private port, in which case this should return a kPMPortMappingInUseError;

Parameters:
publicPort The requested public port
privatePort The requested private port
protocol The requested protocol
Returns:
One of the PMResult values.

void PMAddPortMappingAsync int  publicPort,
int  privatePort,
PMProtocol  protocol,
PMAddPortMapCallback  callback,
CFRunLoopRef  runLoop,
void *  context
 

Asks the router to forward a port asynchronously.

Sends a request to the router to map the given public port to the given private port on this computer on a background thread and notifies the callback when it has completed.

Parameters:
publicPort The requested public port
privatePort The requested private port
protocol The requested protocol
callback The function to notify when we are finished. This can be NULL and no notification will be sent.
runLoop The CFRunLoop to preform the callback on. If this is NULL then the callback is preformed on the background thread.
context A user defined object that is passed to the callback function.

CFStringRef PMGetPublicIPAddress  ) 
 

Asks the router for its Public IP.

Asks the router to return its public or external IP address. The IP address is cached after the first call.

Returns:
A CFString containing the IP address. You do NOT need to release the result since it is cached.

void PMGetPublicIPAddressAsync PMGetPublicIPCallback  callback,
CFRunLoopRef  runLoop,
void *  context
 

Asks the router for its Public IP asynchronously.

Asks the router to return its public or external IP address. The IP address is cached after the first call. The work is done on a background thread and the callback is notified when we are finished.

Parameters:
callback The function to notify when we are finished. This can be NULL and no notification will be sent.
runLoop The CFRunLoop to preform the callback on. If this is NULL then the callback is preformed on the background thread.
context A user defined object that is passed to the callback function.

CFStringRef PMGetRouterName  ) 
 

Returns the name of the router.

Returns the name of the router. This really only works with the UPnP routers.

Returns:
The router's name, or NULL if we haven't been initialized yet.

PMRouterType PMGetRouterType  ) 
 

Returns the router type.

Returns:
One of the PMRouterType values

PMResult PMInitialize  ) 
 

Initializes this port mapping library.

This function will try to find a compatible router and sets up some globals. Currently only UPnP routers and NAT-PMP routers are supported.

This function sets some global variables so it is NOT fully thread safe. It can be called by any thread, but two threads should not call this function at the same time.

If the network configuration changes, you need to recall this method so that we can figure out how to talk to the new router. This will also clear any history we have about the port mappings that you have added.

Return values:
kPMSuccessful There was no error and the library is ready for use.
kPMNoRouterFoundError A compatible router was not found.
kPMPortMappingDisabledError If the user has disabled their router's port mapping abilities.
kPMInitializationError We found a router, but failed to properly communicate with it.

void PMInitializeAsync PMInitializeCallback  callback,
CFRunLoopRef  runLoop,
void *  context
 

Initializes this port mapping library asynchronously.

This function executes the PMInitialize() function on a background thread and notifies the callback when it has completed.

Parameters:
callback The function to notify when we are finished. This can be NULL and no notification will be sent.
runLoop The CFRunLoop to preform the callback on. If this is NULL then the callback is preformed on the background thread.
context A user defined object that is passed to the callback function.

PMResult PMRemovePortMapping int  publicPort,
int  privatePort,
PMProtocol  protocol
 

Asks the router to remove a port mapping.

Sends a request to the router to remove the port mapping identified by the given public port and the given private port. A call to remove the port mapping should match what was used when calling PMAddPortMapping().

Parameters:
publicPort The public port
privatePort The private port
protocol The protocol
Returns:
One of the PMResult values.

void PMRemovePortMappingAsync int  publicPort,
int  privatePort,
PMProtocol  protocol,
PMRemovePortMapCallback  callback,
CFRunLoopRef  runLoop,
void *  context
 

Asks the router to remove a port mapping asynchronously.

Sends a request to the router to remove the port mapping identified by the given public port and the given private port. A call to remove the port mapping should match what was used when calling PMAddPortMapping(). The actual work of this function will be executed on a background thread and the callback will be notified when it is finished.

Parameters:
publicPort The public port
privatePort The private port
protocol The protocol
callback The function to notify when we are finished. This can be NULL and no notification will be sent.
runLoop The CFRunLoop to preform the callback on. If this is NULL then the callback is preformed on the background thread.
context A user defined object that is passed to the callback function.

void PMSetRemoveAtExit int  flag  ) 
 

Sets the remove at exit flag.

If this flag is set then we will try to remove any port mappings added when the program exits. If you want the port mapping to last longer, then set this to 0.

Parameters:
flag Set this to 1 to remove the port mappings on exit, or 0 to leave the port mappings active.


Generated on Fri Sep 2 00:17:57 2005 for PortMapper by doxygen 1.3.4