6.7. Basic Features - Changing the Session Invitation State

Depending on the settings when a session is created, it can be either open (an open invitation to participants to join) or closed.

The API for changing the session invitation state works automatically to synchronize processes between host and client. (There is also a way for the application to directly manage synchronization between the host and client. This is discussed below.)

Changing the Session Invitation State

To change the state, all stations call either OpenSessionAsync() or CloseSessionAsync(). The process continues automatically and all stations reflect the changed invitation state, even if new stations join or leave the session or host migration occurs during the asynchronous process.

To change the state to an open invitation, call OpenSessionAsync(). To close the session and stop inviting participants, call CloseSesssionAsync(). PiaSession automatically performs the appropriate process subsequent to the state change, and the asynchronous process ends after this is completed. The application only needs to wait for the asynchronous process to end after it has called the API.

If the calling station was the host, it follows through with the process to open or close the matchmaking session to invitations. If the calling station was a client, it does nothing for the matchmaking session. The asynchronous process then continues until the following conditions are met.

  • When CloseSessionAsync() has been called, the number of participants in the matchmaking session matches the number of stations in the mesh.
  • All stations participating in the session have called the API to change the invitation state.

Make sure that the host and the clients all call the same API. If the host calls OpenSessionAsync() and the clients call CloseSessionAsync() (or vice versa), ResultSessionInvalidState is returned either when the API is called or as the result of the asynchronous process.

Make sure that all stations call the API within a set period of time (60 seconds). If clients call the API more than 60 seconds after the host has called the API, synchronization fails and ResultSessionInvaidState is returned.

ResultSessionInconsistentState is returned if the asynchronous process stalls for a long time due to the communications environment after all participants in the session have called the API to change the invitation state.

 

Code 6-18. Session Invitation State Synchronous Process by the Application (Closed Invitation)
// The number of participants must align, and the same API must be called among all stations with the same timing, like during the sequence before the game starts.
result = nn::pia::session::Session::GetInstance()->CloseSessionAsync();
if (result == nn::pia::ResultSessionInconsistentState())
{
    // The host has called OpenSessionAsync() already. This causes implementation problems, so correct it.
}
else 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::Session::GetInstance()->IsCompletedCloseSession() == false )
{
    if ( networkType == INTERNET )
    {
        // When using Internet communications, you must call the Scheduler::Dispatch function of NEX for keep-alive communication with the server.
        nn::nex::Scheduler::GetInstance()->DispatchAll();
    }
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
}
 
// Check the results of the asynchronous process.
result = nn::pia::session::Session::GetInstance()->GetCloseSessionResult();
if (result == nn::pia::ResultSessionInvalidState())
{
    // An error is returned for any of these reasons. This causes implementation problems, so correct it.
    // - The host has called OpenSessionAsync().
    // - Not all stations called CloseSessionAsync() within a specific period of time.
}
else if (result == nn::pia::ResultSessionInconsistentState())
{
    // The asynchronous process takes a long time after all stations have called CloseSessionAsync().
}
else if ( result.IsFailure() )
{
    // Error handling.
}

Session Invitation State Synchronous Process by the Application

When the application directly performs the synchronous process for the session invitation state, the host calls the APIs for changing the state (OpenParticipationAsync() and CloseParticipationAsync()).

The clients cannot perceive the session invitation state. When host migration occurs, the invitation state becomes unknown. If any station is connecting at the time, it joins the session after the asynchronous processing of these APIs has completed. To deal with this situation, the application must perform a synchronous communications process. Note that this makes the program more complicated.

To change the state to open invitation, call OpenParticipationAsync() and start the asynchronous process. To learn when the asynchronous process has completed, use IsCompletedOpenParticipation(). If the state has been successfully changed, GetOpenParticipationResult() returns the result that IsSuccess()is true.

Code 6-17. Session Invitation State Synchronous Process by the Application (Open Invitation)
result = nn::pia::session::Session::GetInstance()->OpenParticipationAsync();
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::Session::GetInstance()->IsCompletedOpenParticipation() == false )
{
    if ( networkType == INTERNET )
    {
        // When using Internet communications, you must call the Scheduler::Dispatch function of NEX for keep-alive communication with the server.
        nn::nex::Scheduler::GetInstance()->DispatchAll();
    }
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
}
 
// Check the results of the asynchronous process.
result = nn::pia::session::Session::GetInstance()->GetOpenParticipationResult();
if ( result.IsFailure() )
{
    // Error handling.
}

 

To change the state to close the session to invitations, call CloseParticipationAsync() and start the asynchronous process. To learn when the asynchronous process has completed, use IsCompletedCloseParticipation(). If the state has been successfully changed, GetCloseParticipationResult() returns the result that IsSuccess()is true.

The process of closing the session to invitations proceeds as follows.

  1. Ends the matchmaking session in which the host is participating. (The nex::MatchmakeExtensionClient::CloseParticipation function is called when using Internet communication.)
  2. A check is performed to determine whether the number of matchmaking session participants matches those of the mesh. If they match, the session ends without issue, and asynchronous processes are ended.
  3. When the number of participants does not match, there are either new participants or some who left at or around the start of an asynchronous process. When this occurs, wait a while (approximately fifteen seconds) until the number of participants matches.
  4. If they match within that time, the session ends without issue, and asynchronous processes are terminated.
  5. If the number of participants does not match even after the time has elapsed, time out and terminate the asynchronous processes. (This means that a new participation process or a leave process is taking too much time.)

If the process times out, GetCloseParticipationResult() returns ResultNegligibleFault. At this point, the matchmaking session has been closed successfully, but there is a possibility that new participants will join the mesh after the end of the asynchronous process. Handle this appropriately in the application. For example:

  • Call CloseParticipationAsync() again and wait until the process of closing the session is successful.
  • Have the application perform appropriate processes so that no issues arise from new participations after asynchronous processes finish.
  • Register a callback to determine session join-in approval and deny new participants from joining.
Code 6-18. Session Invitation State Synchronous Process by the Application (Closed Invitation)
result = nn::pia::session::Session::GetInstance()->CloseParticipationAsync();
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::Session::GetInstance()->IsCompletedCloseParticipation() == false)
{
    if (networkType == INTERNET)
    {
        // When using Internet communications, you must call the Scheduler::Dispatch function of NEX for keep-alive communication with the server.
        nn::nex::Scheduler::GetInstance()->DispatchAll();
    }
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
}
 
// Check the results of the asynchronous process.
result = nn::pia::session::Session::GetInstance()->GetCloseParticipationResult();
if (result.IsFailure())
{
    if (result == ResultNegligibleFault())
    {
        // The asynchronous process timed out.
        // The matchmaking session is closed, but there may be newly joining participants.
        // Implement the application to correctly handle the situation in one of the following ways: continue the process, call CloseParticipationAsync()
        // again, or deny the join session request and return an error to the newly joining participant.
    }
    else
    {
        // Error handling.
    }
}