8. Peer-to-Peer Communication

The following steps show the overall flow of P2P communication.

  1. Initialization
  2. Creating a session (the host) or joining a session (all other clients)
  3. P2P communication
  4. Finalization

This chapter only explains initialization, session management, and shutdown for P2P communication over the Internet. For more information about NEX peer-to-peer communication, see the NEX P2P Programming Manual.

8.1. Initialization and Finalization

To start Internet peer-to-peer (P2P) communication, use the ConnectivityManager::StartNATSession function to automatically select the ports for P2P communication and initialize the NAT traversal feature, and then generate a NetZ class object to manage P2P communication. (For more information, see Code 8.1.)

Configure the P2P communication settings as needed after creating the NetZ class object. The following settings are required.

Code 8.1 Initializing NetZ

void InitializeNetZ(const nn::nex::qVector<qByte>& sessionKey)
{
    if (pNetZ)
    {
        return;
    }
    nn::nex::CallContext oContext;
    if(!nn::nex::ConnectivityManager::GetInstance()->StartNATSession(&oContext))
    {
        return;
    }
    oContext.Wait(); // Actually, the Dispatch process is repeated periodically.
    if(!oContext.GetOutcome())
    {
        return;
    }
    NetZ pNetZ = qNew NetZ();

    // Configure P2P communication settings as necessary.
    Station::SetLocalPlayerName(_T("PLAYER NAME"), 0);
    Network::GetInstance()->SetP2PDataPacketSessionSignatureKey(sessionKey);
}

With the StartNATSession function, the names of NAT type detection server addresses are resolved. If the cable on the WAN side of the router is unplugged before name resolution, we recommend calling asynchronously because it takes up to 30 seconds to wait for the address resolution process to timeout. Also, because name resolution cannot be canceled, it takes up to 30 seconds if terminating NEX with address resolution in a state of non-completion after the StartNATSession function.

When finalizing P2P communication, call NetZ::Terminate to terminate the session, and then destroy the NetZ class object. After that, use the ConnectivityManager::StopNATSession function to release ports. If you attempt to delete the NetZ object before terminating a session, processing blocks until an internal call to the NetZ::Terminate function has completed, as seen in the following code example.

Code 8.2. Finalizing NetZ

void FinalizeNetZ(nn::nex::NetZ pNetZ)
{
    if (!pNetZ)
    {
        return;
    }
    // If Terminate is not called, processing blocks until the NetZ object is deleted.
    nn::nex::CallContext oContext;
    pNetZ->Terminate(&oContext);
    oContext.Wait();

    qDelete pNetZ;
    nn::nex::ConnectivityManager::GetInstance()->StopNATSession();
}

8.2. Creating a Peer-to-Peer Session

A P2P session must be created by a matchmaking session host. Use the Session::CreateSession function to create a P2P session. You can optionally pass a session name in as one of this function's arguments. Specify the default value of true as the second argument.

Code 8.3. Session Creation Function

static qBool CreateSession(const qChar *szSessionName=NULL,
                           qBool bNetworked=true);

8.3. Joining a Peer-to-Peer Session

Use the MatchMakingClient::GetSessionURLs function to get the URL of the matchmaking session host, and then use the Session::JoinSession function to join the P2P session. Leave the matchmaking session if you fail to join the P2P session.

Code 8.4. Joining a P2P Session

// Join a peer-to-peer session.
qBool JoinMachmakeSession(
          NetZ* pNetZ,
          MatchmakeExtensionClient *pMatchMakingClient,
          GatheringID sessionGid)
{
    qList<StationURL> lstURLs;
    ProtocolCallContext oContext;

    // Get the host URL.
    if (!pMatchMakingClient->GetSessionURLs(&oContext, sessionGid, &lstURLs))
    {
        return false;
    }
    oContext.Wait();
    // Confirm that at least one URL has been saved.
    if(!oContext.GetOutcome() || lstURLs.empty())
    {
        return false;
    }

    if(!pNetZ->JoinSession(&oContext, lstURLs))
    {
        return false;
    }

    oContext.Wait();
    return oContext.GetOutcome();
}

Warning

All URLs in the list obtained with the MatchMakingClient::GetSessionURLs function are required. Pass to the Session::JoinSession function without processing.

8.4. NAT Traversal Features of NEX

NAT traversal is a feature for establishing P2P communication in an environment that uses network address translation (NAT). Although NEX supports NAT traversal by combining all NAT types, NAT traversal is not supported under some network configurations. Although application developers do not need to be aware of this when implementing code, this chapter describes how to solve problems that may arise during development and debugging.

8.4.1. Port Number of the Socket Used in Peer-to-Peer Communication

NEX uses separate UDP sockets for server communication and P2P communication. When several devices are connected on the same LAN, the port numbers used for both server communication and P2P communication are selected randomly to avoid port number conflicts.

If port numbers conflict, NAT assigns different port numbers. How port numbers are assigned is also dependent on the implementation of NAT. Although standard server communication does not have this problem, it must be avoided for P2P communication because it is important to predict which port the peer is sending packets from.

The socket used for server communication is re-created every time the local user logs in, while the socket used for P2P communication is re-created every time a NAT session starts (every time matchmaking is performed). In both cases, the sockets are then bound to a random port number. The same range of port numbers, 49,152 through 65,535, can be assigned for both server communication and P2P communication.

Note

The UDP-9103 port is used for communication with the friend server (fixed).

Note

Although http or https communication is performed when using NEX, TCP sockets are not used directly.

8.4.2. Classification of NAT Types

With NEX, NAT types are classified according to two mapping types and two filtering types. A total of four NAT types are possible by combining mapping types and filtering types. This example assumes a client IP address of 192.168.0.1, an IP address of 10.10.10.1 assigned to the global side of NAT, and two peer addresses of 10.10.10.10:10000 and 10.10.10.11:10000.

  • Mapping types

    The mapping type is determined based on changes in the source port assignment when packets are sent in order to two addresses.

    • Endpoint-Independent Mapping (EIM)

      If packets are sent to different addresses from the same local source port, mapping is performed so that the global source port after overwriting is the same.

      [192.168.0.1:10000:10.10.10.10:10000]→[10.10.10.1:10000:10.10.10.10:10000]

      [192.168.0.1:10000:10.10.10.11:10000]→[10.10.10.1:10000:10.10.10.11:10000]

    • Endpoint-Dependent Mapping (EDM)

      If packets are sent to different addresses from the same local source pot, mapping is performed so that the global source port after overwriting is different.

      [192.168.0.1:10000:10.10.10.10:10000]→[10.10.10.1:10000:10.10.10.10:10000]

      [192.168.0.1:10000:10.10.10.11:10000]→[10.10.10.1:10001:10.10.10.11:10000]

  • Filtering types

    After a packet is sent to an address, the filtering type determines whether packets received at other ports at that address are filtered by NAT. The following example assumes that a particular type of server program is running at 10.10.10.10:10000, and that when a packet is received responses are returned from the two ports 10000 and 10100. If the terminal sends a packet to 10.10.10.10:10000 under these conditions, the following packets can be observed on the LAN side of the terminal.

    • Port-Independent Filtering (PIF)

      [192.168.0.1:10000:10.10.10.10:10000] // Send from the terminal.

      [10.10.10.10:10000:192.168.0.1:10000] // First response from the server.

      [10.10.10.10:10100:192.168.0.1:10000] // Second response from the server.

    • Port-Dependent Filtering (PDF)

      [192.168.0.1:10000:10.10.10.10:10000] // Send from the terminal.

      [10.10.10.10:10000:192.168.0.1:10000] // First response from the server.

      // Second response from the server was not received.

Generally, even though using PIF provides higher NAT traversal performance than EIM and PDF, which is better than EDM, all NAT type combinations are supported.

8.4.3. Checking the NAT Type

You can get the network NAT type during connection by executing a connection test for Internet settings from the 3DS System Settings. The upper 2 digits of the support code (the value shown in the lower right of the upper screen) that is acquired with the connection test is associated with the NAT type. The correspondence is shown in Figure 8.1. For example, when the support code is 110, the type is EIM-PIF.

_images/Fig_NATType_CTR.png

Figure 8.1. Correspondence Between Support Codes and NAT Types

Also, the Wii U connection test performs NAT type determination twice, and determines whether port prediction is possible for EDM. The lower two digits of the support code indicate the results.

  • 00: The NAT type determination process completed normally. For EDM, the external port was allocated regularly. However, it cannot be determined if allocation was incremental.
  • 01: For EDM, the external port was allocated randomly.
  • 02: The NAT type differs with each determination. The upper two digits indicate the results from the first test.
  • 99: Failed to communicate with the NAT type determination server, so the NAT type could not be determined. In this case, the upper two digits of the support code are always 00.

 

8.4.4. Network Configurations Not Supported by NEX

NEX does not support the following network configurations. Although clients with these network configurations can log in to the game server, attempts to join P2P sessions fail.

  • Port assignment rules are random EDM: Because the port assignment rules are random, it is not possible to predict the port to which future packets will be mapped.
  • Port assignment rules result in decremental EDM: NEX does not support this type of assignment rule to avoid failed determinations with decremental EDM because of packet switching, and because there are far fewer cases of decremental EDM than incremental EDM.
  • Multiple terminals running under EDM: This configuration is not supported because port predictions may fail if the send timing of packets matches exactly. Problems can easily arise if two clients connected to the same EDM router attempt to join the same session.
  • Multi-level NAT with three or more levels: If the client being connected to has a multi-level NAT configuration with three or more levels, packets with a TTL value of 3 that are sent to the client being connected to first do not reach the outermost NAT. Communication fails because the outermost router bounces packets arriving from connected clients.
  • NAT traversal to a router with SPI (neighboring nodes only): To deal with stateful packet inspection (SPI) under NEX, the client being connected to sends packets with a TTL value of 3 first. Such packets are sent only to update the NAT table for the client being connected to. Communication may fail if this packet reaches a connected client with a router that has the SPI feature. Note that the SPI feature has different functionality depending on the router type. Even if the router has the SPI feature, problem occurrence is not limited to communication between the routers that are closest, in terms of the network.

Because the implementation of the application does not change this functionality, the developer does not need to be aware of these limitations during implementation. However, in some cases problems are emphasized if debugging is performed during development with a large number of clients connected to a small number of routers. Be sure to check the network configuration if there are problems with clients joining P2P sessions.


CONFIDENTIAL