Microsoft DirectX 9.0 SDK Update (Summer 2003)

Basic NAT Issues for Clients


The IDirectPlay8Client interface has very few Network Address Translation (NAT) concerns and works in almost all scenarios. Clients should however keep enumerations active and avoid relying on DPNSVR to ensure NAT compatibility.

Keeping EnumHosts Active While Connecting

Most NAT devices create virtual connections each time an internal client starts sending packets to a new external address and port, such as a new IDirectPlay8Client::EnumHosts operation. These virtual connections will sometimes be destroyed as soon as the IDirectPlay8Client::EnumHosts operation completes. If your client application enumerates hosts before connecting, you should neither cancel the IDirectPlay8Client::EnumHosts operation nor allow it to time out so that the call to IDirectPlay8Client::Connect can reuse the virtual connection. This requirement can be met by specifying INFINITE for the dwEnumCount parameter as shown in the following example.
hr = pDP8Client->EnumHosts(&dpnad,
                           pDP8AddressHost,
                           pDP8AddressDevice,
                           NULL,
                           0,
                           INFINITE,
                           0,
                           0,
                           NULL,
                           &dpnhEnumHosts,
                           0);

Microsoft® DirectPlay® will automatically cancel all outstanding IDirectPlay8Client::EnumHosts operations for you when the connect operation completes successfully. If the connect fails, the enumerations will continue running. You can then cancel them using the IDirectPlay8Client::CancelAsyncOperation method.

To ensure that the connect operation uses the same virtual connection as the enumeration, the host and device address objects specified to IDirectPlay8Client::Connect should be the same as those included in the corresponding DPN_MSGID_ENUM_HOSTS_RESPONSE message. For examples of how to add a reference or duplicate these addresses, see the DirectPlay C++ Samples.

DPNSVR

The application sends enumeration queries to the DPNSVR port when the DPNA_KEY_PORT component is not specified in the IDirectPlay8Address host object passed to IDirectPlay8Client::EnumHosts. However the hosts reply from their respective game ports. Some NAT devices expect replies to come from the port to which the client originally sent, and might therefore drop the enumeration response. If your application uses DPNSVR to help with session discovery, it should also attempt to enumerate the game port directly.

Enumerating the Host's Game Port Directly

The host can retrieve its addresses using IDirectPlay8Server::GetLocalHostAddresses and pass it in string format to the client using IDirectPlay8Address::GetURLA through a match-making service. The client can then convert the string back into an address using the IDirectPlay8Address::BuildFromURLA method as shown in the following example.

IDirectPlay8Address *pDP8AddressHost = NULL;

hr = CoCreateInstance(CLSID_DirectPlay8Address, CLSCTX_INPROC_SERVER, IID_IDirectPlay8Address, NULL, (PVOID*) (&pDP8AddressHost));

hr = pDP8AddressHost->BuildFromURLA(szHostAddress);

This address object can then be passed to IDirectPlay8Client::EnumHosts or IDirectPlay8Client::Connect.

Enumerating or Connecting from a Particular Port

Applications should almost always let DirectPlay choose the local port or ports when enumerating or connecting. However, you might want to allow the user to select a local port. This can be added to a device address using the DPNA_KEY_PORT component as shown in the following example.

DWORD dwUserSelectedPort; // value retrieved from user input

if (dwUserSelectedPort != 0)
{
    // User specified a port value; use it.
    hr = pDP8AddressDevice->AddComponent(DPNA_KEY_PORT, &dwUserSelectedPort, sizeof(dwUserSelectedPort), DPNA_DATATYPE_DWORD);
}
else
{
    // Let DirectPlay select; don't add port component.
}

This address object is then passed to IDirectPlay8Client::EnumHosts or IDirectPlay8Client::Connect for the device address parameter.

Disabling Automatic Traversal

When the client has Microsoft Windows® Internet Connection Firewall enabled or is behind a Universal Plug and Play (UPnP) NAT device, DirectPlay will attempt to enable port forwarding for your application automatically. This asks the device to accept all packets received from the Internet on a particular port and forward them to a particular address and port inside the private network. In many cases, this is unnecessary, particularly when the server is known to be on the open Internet. You can decrease the time required by IDirectPlay8Client::EnumHosts or IDirectPlay8Client::Connect and prevent automated traversal by setting the DPNA_KEY_TRAVERSALMODE component to DPNA_TRAVERSALMODE_NONE as shown in the following example.

DWORD dwTraversalMode = DPNA_TRAVERSALMODE_NONE;

hr = pDP8AddressDevice->AddComponent(DPNA_KEY_TRAVERSALMODE, &dwTraversalMode, sizeof(dwTraversalMode), DPNA_DATATYPE_DWORD);



© 2003 Microsoft Corporation. All rights reserved.