6.19.2. Advanced Mesh Network Features

Keep-Alive Settings

Configuring keep-alive settings can enhance the stability of your mesh network and reduce the frequency of disconnections. Keep-alive settings include the maximum permissible quiet time and the interval at which to send keep-alive packets. To change the settings, specify the values you want to set in the maxSilenceTime and keepAliveSendingInterval members of the StartupSetting structure used when starting the mesh network. This works exactly the same as with sessions. For more information, see 6.13. Advanced Features - Adjusting Session Behavior.

Code 6-59. Mesh Network Keep-Alive Settings
// Configure when starting the mesh.
 
// Example of changing setting values:
const u32 APP_MAX_SILENCE_TIME = 15000; // Maximum silence time (milliseconds).
const u32 APP_KEEP_ALIVE_SENDING_INTERVAL = 3000; // Interval for sending a keep-alive (milliseconds).

bool bEnableHostMigration = false; // Set to use the host migration feature.

// Set the name associated with the local station (the name that appears in the game).
nn::pia::transport::Station::PlayerName playerName;

// Set a name, up to 16 characters, and a language code.
// In the sample demo, the name of the Mii is set as an example.
GetLocalPlayerName(&playerName);

// Packet encryption settings.
// Use an encryption key that is difficult to guess.
char sampleCryptoKeyData[] = "session crypto key";
nn::pia::common::CryptoSetting sampleCryptoSetting;
sampleCryptoSetting.m_Mode = nn::pia::common::CryptoSetting::MODE_AES_128;
::std::memcpy(sampleCryptoSetting.m_Key, sampleCryptoKeyData, sampleCryptoSetting.KEY_SIZE);
// In this example the part of sampleCryptoKeyData that is longer than sampleCryptoSetting.KEY_SIZE is ignored.

// Startup settings.
nn::pia::session::Mesh::StartupSetting startupSetting;
startupSetting.bUsingHostMigration = bEnableHostMigration; // Host migration setting.
startupSetting.pPlayerName = &playerName; // Player name to use for communication.
startupSetting.pCryptoMode = &sampleCryptoSetting; // Encryption settings.
startupSetting.maxSilenceTime = APP_MAX_SILENCE_TIME; // Maximum allowed silence time.
startupSetting.keepAliveSendingInterval = APP_KEEP_ALIVE_SENDING_INTERVAL; // Keep-alive send interval.
 
// Startup.
result = nn::pia::session::Mesh::GetInstance()->Startup(startupSetting);
if (result.IsFailure())
{
    // Error handling.
}
 
/* Processes for creating the mesh or joining the mesh. */

Determining Approval for Join Requests

The mesh host can determine whether a request to join a mesh is approved or denied. To make this determination, prepare a determination callback function and register it in the instance of the Mesh class. This works exactly the same as with sessions. For more information, see 6.15. Advanced Features - Approval for Joining a Session.

Code 6-60. Callback Function for Determining Whether to Approve a Join Request
// Example of a join-in request approval determination callback function.
bool sampleJoinApprovalCallback(const nn::pia::transport::Station::IdentificationToken* pRequesterToken)
{
    bool judgment;
    // Write the code for determining approval of a join-in request.
    // The pRequesterToken parameter is the pointer to the identification token for the station requesting approval to join.
    // Do not include code that blocks for a long period of time because that might reduce system performance.
    if (judgment)
    {
        return true; // Approve if true is returned.
    }
    else
    {
        return false; // Deny if false is returned.
    }
}
Code 6-61. Registering and Unregistering a Determination Callback Function
// Register the determination callback function.
nn::pia::session::Mesh::GetInstance()->RegisterJoiningMeshApprovalCallback(sampleJoinApprovalCallback);
 
// From the time it is registered until the time it is unregistered, this callback function is called when the mesh host receives a join request.
 
// Unregister the determination callback function.
nn::pia::session::Mesh::GetInstance()->UnregisterJoiningMeshApprovalCallback();

Station Identification Tokens

Stations can be identified using station identification tokens. To use station identification tokens, specify the local station's identification token in the pToken member of the StartupSetting structure passed as an argument when calling the Mesh::Startup function. This works exactly the same as with sessions. For more information, see 6.14. Advanced Features - Station Identification Tokens.

Code 6-62. Configuring the Station Identification Token for the Local Station
// Configure when starting the mesh.

// Set a name to associate with the local station (the name that appears in the game).
nn::pia::transport::Station::PlayerName playerName;

// Set a name, up to 16 characters, and a language code.
// In the sample demo, the name of the Mii is set as an example.
GetLocalPlayerName(&playerName);
 
// Details of encryption settings (sampleCryptoSetting) and signature settings (sampleSignatureSetting) are omitted here.
 
// Configure the identification token for the local station.
nn::pia::transport::Station::IdentificationToken localToken;
// LOCAL_TOKEN_DATA is the leading address for a data array for the identification token of IDENTIFICATION_TOKEN_MAX_DATA_SIZE (in bytes).
::std::memcpy(localToken.data, LOCAL_TOKEN_DATA, nn::pia::transport::Station::IDENTIFICATION_TOKEN_MAX_DATA_SIZE);

// Startup settings.
nn::pia::session::Mesh::StartupSetting startupSetting;
startupSetting.pPlayerName = &playerName; // Player name to use for communication.
startupSetting.signatureSetting = sampleSignatureSetting; // Settings for the packet signature feature.
startupSetting.pCryptoMode = &sampleCryptoSetting; // Encryption settings.
startupSetting.pToken = &localToken; // Identification token.
 
// Startup.
result = nn::pia::session::Mesh::GetInstance()->Startup(startupSetting);
if (result.IsFailure())
{
    // Error processing.
}
 
/* Processes for creating or joining the mesh. */
Code 6-63. Getting a Station Identification Token
// Can be run while participating in a mesh.
 
nn::pia::StationId targetId; // Assume that this is the StationId of the target station.
nn::pia::transport::Station* pTargetStation = nn::pia::transport::StationManager::GetInstance()->GetStation(targetId);
if (pTargetStation != NULL)
{
    nn::pia::transport::Station::IdentificationToken tokenBuf;
    // Get the identification token for the station.
    result = pTargetStation->GetIdentificationToken(&tokenBuf);
    if (result.IsFailure())
    {
        // Error handling.
    }
} 
/* The identification token for pTargetStation is stored in tokenBuf if it is obtained successfully. */

The Sync Clock

The sync clock measures the time that has elapsed since a mesh was created (in milliseconds). Mesh clients can access the sync clock at any time.

Mesh clients periodically send synchronization pulses to the mesh host and receive its responses to synchronize the sync clock for the mesh network. The interval at which to send synchronization pulses can be changed to any time (in milliseconds).

Code 6-64. Getting the Synchronization Clock
// Can be run while participating in a mesh.
// Get the time that has elapsed since the mesh was created.
s64 sessionTime = nn::pia::session::Mesh::GetInstance()->GetSyncClockTime();
Code 6-65. Confirming and Changing the Send Interval for the Synchronization Pulse
// Can be run while participating in a mesh.
 
// Confirm the send interval for the synchronization pulse.
s32 currentPulseInterval = nn::pia::session::Mesh::GetInstance()->GetSyncClockPulseInterval();
 
// Change the send interval for the synchronization pulse.
s32 pulseInterval; // Assume this variable is set to the send interval (in milliseconds) that you want to change.
nn::pia::session::Mesh::GetInstance()->SetSyncClockPulseInterval(pulseInterval);

Host Migration

The host migration feature allows a mesh network to continue when the mesh host leaves by transferring the mesh host privilege to one of the other clients still in the mesh. You can specify whether to enable host migration when starting up the mesh network. This works exactly the same as with sessions. For more information, see 6.9. Basic Features - Host Migration.

Code 6-66. Configuring the Use of Host Migration
// Startup settings.
nn::pia::session::Mesh::StartupSetting startupSetting;
startupSetting.bUsingHostMigration = true; // Host migration settings.

result = nn::pia::session::Mesh::GetInstance()->Startup(startupSetting);
/* These settings enable host migration. */

Required Settings and Processing for Each Communication Method

You must configure host migration settings that conform to the communication method you are using. For more information about the settings method, see the programming manual for each module and the API reference.

Internet Communication
  • Set the NEX matchmaking host migration flag (nn::nex::GatheringFlags::MigrateOwner) to true using the nn::nex::Gathering::SetFlag function.
  • When establishing GatheringID in the participating matchmaking session, call the NexFacade::UpdateGatheringID function and update the information managed by NexFacade. Mesh::Startup checks whether the appropriate settings have been made and returns an error if there is a problem.
UDS Communication
  • Always enable host migration when using PiaLocal for local communication. Mesh::Startup checks whether the appropriate settings have been made and returns an error if there is a problem.

Removing the Mesh Host From the Mesh When Using Host Migration

The mesh host can only leave the mesh without destroying it if host migration is enabled. Mesh hosts leave a mesh using an asynchronous process. This works exactly the same as host migration in sessions. For more information, see 6.9. Basic Features - Host Migration.

Code 6-67. Mesh Host Leaving the Mesh
// Leave the mesh (starts an asynchronous process).
// This process can only be started by the mesh host when host migration is enabled.
result = nn::pia::session::Mesh::GetInstance()->LeaveSessionWithHostMigrationAsync();
if (result.IsFailure())
{
    // Error handling.
}
// When the asynchronous process starts successfully, you must periodically call the dispatch function to wait on the progress of the asynchronous process.
while (nn::pia::session::Mesh::GetInstance()->IsCompletedLeaveMeshWithHostMigration() == false)
{
    if (NetworkType == INTERNET)
    {
        // When using Internet communications, you must call the NEX scheduler dispatch function for keep-alive communication with the server.
        nn::nex::Scheduler::GetInstance()->DispatchAll();
    }
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
    // We recommend periodically checking the state of the network connection even while waiting on an asynchronous process.
    result = nn::pia::transport::Transport::GetInstance()->CheckConnectionError();
    if (result.IsFailure())
    {
        // Error handling.
    }
}
// Check the results of the asynchronous process.
if (nn::pia::session::Mesh::GetInstance()->GetLeaveSessionWithHostMigrationResult().IsSuccess() == false)
{
    // Error handling.
    // If the asynchronous leave mesh process starts successfully, it never fails.
}

Host Migration State Change Events

When using host migration, mesh events are issued to notify other stations in the mesh about the results of the host migration process. Notifications are issued when the host migration is successful and when host migration fails.

Code 6-68. Callback Function for the Mesh State Change Event
// Example of the mesh state change event callback function (for host migration).
void sampleSessionEventCallback(nn::pia::session::Mesh::EventType eventType, nn::pia::StationId id)
{
    // The eventType argument is an enumerated type that indicates the content of the state change that occurs.
    // The id argument is the StationId that indicates the target of the state change that occurred.
    switch (eventType)
    {
    case nn::pia::session::Mesh::EVENT_JOIN:
        {
            // StationId: When the station assigned the id joined the mesh.
        }break;
    case nn::pia::session::Mesh::EVENT_LEAVE:
        {
            // StationId: When the station assigned the id left the mesh.
        }break;
    case nn::pia::session::Mesh::EVENT_HOST_CHANGED: // Note: Event only used for host migration.
        {
            // When, due to host migration, the station with StationId:id becomes the new mesh host.
        }break;
    case nn::pia::session::Mesh::EVENT_MIGRATION_FAIL: // Note: Event only used for host migration.
        {
            // When host migration fails.
            // For this event, the id argument becomes STATION_ID_INVALID.
        }break;
    }
}