Microsoft DirectX 9.0 SDK Update (Summer 2003)

Advanced NAT Techniques for Peer Clients


Microsoft® DirectPlay® cannot provide 100 percent connectivity for peer clients behind Network Address Translation (NAT) devices that do not support Universal Plug and Play (UPnP). However, your application might be able to improve support for some of these cases using more elaborate methods. The techniques described here require additional development effort as well as external server resources.

NAT Resolver

NAT devices create an implicit port mapping when an internal computer sends a packet to an external computer. Some NAT devices allow any external computer to use this port mapping to send to the internal computer, instead of only forwarding replies sent by the original external target. These are sometimes referred to as "loose NATs." DirectPlay automatically takes advantage of this behavior when the peer host is outside of the NAT. Your application can use the IDirectPlay8NATResolver interface and address components to also allow peer clients behind a loose NAT to join a session hosted behind the same NAT device with external peer clients already connected to the same session.

You must start by implementing an IDirectPlay8NATResolver server that will be accessible from the Internet. Then your game application can add the DPNA_KEY_NAT_RESOLVER component to the device address passed to IDirectPlay8Peer::EnumHosts or IDirectPlay8Peer::Connect. The component data is a string containing the Internet Protocol (IP) address and port for the NAT resolver to use, separated by a colon. For example, the following code specifies to use a server located on port 5678 at the address 123.123.123.123.

						
WCHAR * wszNATResolver = L"123.123.123.123:5678";						
DWORD dwNATResolverSize = (wcslen(wszNATResolver) + 1) * sizeof(WCHAR);						
						
hr = pDP8DeviceAddress->AddComponent(DPNA_KEY_NAT_RESOLVER,						
                        wszNATResolver,
                        dwNATResolverSize,
                        DPNA_DATATYPE_STRING);
						

You can also specify a hostname instead of a numerical IP address as shown in the following example.

						
WCHAR * wszNATResolver = L"resolver.mydomain.com:5678";						
DWORD dwNATResolverSize = (wcslen(wszNATResolver) + 1) * sizeof(WCHAR);						
						
hr = pDP8DeviceAddress->AddComponent(DPNA_KEY_NAT_RESOLVER,						
                        wszNATResolver,
                        dwNATResolverSize,
                        DPNA_DATATYPE_STRING);
						

For robustness, you might want to have more than one resolving servers to try. You can specify multiple addresses separated by commas as shown in the following example.

						
WCHAR * wszNATResolvers = L"123.123.123.123:5678,backupresolver.mydomain.com:6789";						
DWORD dwNATResolverSize = (wcslen(wszNATResolvers) + 1) * sizeof(WCHAR);						
						
hr = pDP8DeviceAddress->AddComponent(DPNA_KEY_NAT_RESOLVER,						
                        wszNATResolvers,
                        dwNATResolverSize,
                        DPNA_DATATYPE_STRING);
						

Each resolver is tried simultaneously for speed, and the first response is used. If no server responds, the IDirectPlay8Peer::EnumHosts or IDirectPlay8Peer::Connect call still succeeds.

Because hosting these resolving servers requires resources, you might want to prevent arbitrary players from using the resolver. This can be achieved with the DPNA_KEY_NAT_RESOLVER_USER_STRING address component. This value is passed directly to the resolver for verification in the DPN_MSGID_NAT_RESOLVER_QUERY message, and it can choose to respond or ignore as appropriate. The following example shows how to do this.

						
WCHAR * wszPassword = L"MyPassword";						
DWORD dwPasswordSize = (wcslen(wszPassword) + 1) * sizeof(WCHAR);						
						
hr = pDP8DeviceAddress->AddComponent(DPNA_KEY_NAT_RESOLVER_USER_STRING,						
                        wszPassword,
                        dwPasswordSize,
                        DPNA_DATATYPE_STRING);
						

Note  The user string is passed in clear text over the network, so if the text could contain sensitive information, you should encrypt it in some fashion.

The peer client's NAT device generates a port mapping for the NAT resolver query. If the NAT resolver elects to respond to the query, DirectPlay will send the mapping's public address back to the querying peer client. The address will then be reported to the host when connecting to the session so external peer clients can contact this joining internal client.

An example usage of NAT resolver address components can be found in the NATPeer sample.



© 2003 Microsoft Corporation. All rights reserved.