Microsoft DirectX 9.0 SDK Update (Summer 2003) |
Using the IDirectPlay8NATResolver Interface
The IDirectPlay8NATResolver interface can be used in conjunction with the DPNA_KEY_NAT_RESOLVER and DPNA_KEY_NAT_RESOLVER_USER_STRING address components to improve automated Network Address Translation (NAT) support in some cases. This section describes how to implement a NAT resolver application that is deployed on the Internet. Hosts and clients use this server to identify their public address as described in Advanced NAT Techniques for Peer Hosts, Advanced NAT Techniques for Peer Clients, and Advanced NAT Techniques for Servers.
Creating an IDirectPlay8NATResolver Interface
To prepare the NAT resolver you must first create the interface object and call IDirectPlay8NATResolver::Initialize to specify a callback function. This is shown in the following example.hr = CoCreateInstance(CLSID_DirectPlay8NATResolver, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay8NATResolver, (LPVOID*) &g_pDPNATResolver); . . . hr = g_pDPNATResolver->Initialize(NULL, DirectPlayMessageHandler, 0);
The IDirectPlay8ThreadPool interface can be used to control threading for the IDirectPlay8NATResolver interface. If you choose to use IDirectPlay8ThreadPool, that interface should be initialized and configured first.
Starting a NAT Resolver
Once the IDirectPlay8NATResolver interface has been initialized, you should call IDirectPlay8NATResolver::Start to begin listening for NAT resolver queries. The device addresses passed to IDirectPlay8NATResolver::Start are similar to those passed to IDirectPlay8Peer::Host or IDirectPlay8Server::Host, except that they must only be for the Transmission Control Protocol/Internet Protocol (TCP/IP) service provider, and Internet Protocol, version 6 (IPv6) device globally unique identifiers (GUIDs) are not accepted. You can leave the device GUID unspecified and listen using all devices. You might also choose to not specify an address object at all, and Microsoft® DirectPlay® will automatically select a port for listening on all TCP/IP protocol devices. The following example shows how to optionally start listening on a particular port specified by the user.if (g_dwPort > 0) { hr = pDP8AddrLocal->AddComponent(DPNA_KEY_PORT, &g_dwPort, sizeof(DWORD), DPNA_DATATYPE_DWORD); } hr = g_pDPNATResolver->Start(&pDP8AddrLocal, 1, 0);
Handling queries
The IDirectPlay8NATResolver interface only generates one callback to the application's message handler, DPN_MSGID_NAT_RESOLVER_QUERY. The message contains the address of the query sender and the device on which it was received. The application can allow DirectPlay to respond to the query by returning DPN_OK from its message handler, or ignore it by returning a failure code. This is shown in the following example.
case DPN_MSGID_NAT_RESOLVER_QUERY: { DPNMSG_NAT_RESOLVER_QUERY *pMsgNATResolverQuery = (DPNMSG_NAT_RESOLVER_QUERY*) pMsgBuffer; . . . if (bIgnoreQuery) { // Return failure to ignore the query. return DPNERR_GENERIC; } // Return OK so that DirectPlay will reply. . . . }
The DPNMSG_NAT_RESOLVER_QUERY structure also contains a pointer to the user string, or NULL if the string was not specified. This string is the same as the DPNA_NAT_RESOLVER_USER_STRING component included in the querying application's device address specified to IDirectPlay8Peer::Host, IDirectPlay8Peer::EnumHosts, IDirectPlay8Peer::Connect, IDirectPlay8Server::Host, IDirectPlay8Client::EnumHosts, or IDirectPlay8Client::Connect. The user string is sent in clear text, so you should encrypt the string if it contains sensitive data.
See NATResolver for an example usage of this interface.