5. Sessions and Stations

A group of stations is called a "P2P session." For the rest of this document, it is called a "session." The manager of a session is called the "session master." This terminal acts as the host for P2P communication. The terminals that participate in a session are called "stations." A terminal refers to itself as the "local station."

When using Internet communication, you must automatically select the ports for P2P communication and initialize the NAT traversal feature before initializing NetZ. For more information, see P2P Communications in Server Services.

5.1. Session Management

5.1.1. Role of the Session Master

The session master manages the information of the entire session, receives requests to join the session, manages the session clock that is synchronized in the session, and creates duplicated objects that are shared in the session. You can check whether a station is the session master by using Session::GetRole.

The initial session master is the station that created the session by calling Session::CreateSession. If this station leaves the session, the second station on the station list is chosen as the new session master.

The session master manages and can make changes to the session information. You can get session information for the local station using Session::GetLocalSessionDescription. Session information is managed in the SessionDescription class, and includes information such as the application title, the session name, the session ID, user-defined attributes, and the session's library version and build number.

5.1.2. Creating a Session

A session is created by the session master using Session::CreateSession.

The status of a session is controlled by the Session class. This class is a singleton, meaning that it has only one instance, which has a global point of access. In other words, only one Session may be created for each NetZ instance. The main function of the Session class is to enable a session to be created and joined and also specific information about the session to be set and retrieved. After a station is part of a session, specific information about that station may be retrieved with the Station class.

To create a session for local communication, the UDS network master must call Session::CreateSession.

5.1.3. Joining a Session

To join an existing session, call the Session::JoinSession function using one of the following syntaxes.

Code 5.1 Joining a Session

qBool Session::JoinSession(CallContext* pCallContext,
                           const StationURL& refStationURL); // Asynchronous, for local communication.
qBool Session::JoinSession(const StationURL& refStationURL); // Synchronous, for local communication.

qBool Session::JoinSession(CallContext* pCallContext,
                           const qList< StationURL > & lstURLs); // Asynchronous, for Internet communication.
qBool Session::JoinSession(const qList< StationURL > & lstURLs); // Synchronous, for Internet communication.

In this code, refStationURL and lstURLs are references to the station URLs that are used to join sessions that you can get with nn::pia::local::UdsNetwork::GetMasterUrl or MatchMakingClient::GetSessionURLs. The URL list contains both the global and the local IP of the session being joined. The program will not run properly if you retrieve only one. If you use a member function for local communication during Internet communication, the application forcibly terminates on assert, or the Join fails.

pCallContext is a pointer to the CallContext of the call. If defined, the call is made asynchronously. Otherwise it is made synchronously. If a call is synchronous, the system waits for the call to return a value or an error before performing the next task. If asynchronous, you may perform other tasks while waiting for the call to complete.

Before the Session::JoinSession function terminates, all WellKnownDO objects and all IDGenerator core objects are guaranteed not only to be discovered but also to be discovered before any user duplicated objects. It is also guaranteed that UserDO is not discovered inside the Session::JoinSession function. The first UserDO is only discovered when you call the Scheduler::Dispatch function after calling the Session::JoinSession function.

For more information about the threading model for Net-Z, see the section about the initialization settings for general features.

5.1.4. Leaving a Session

The only way to delete a Session object is to delete the NetZ instance. To leave a session, you must delete the NetZ instance.

When the NetZ instance is destroyed, all duplicated objects, including those on the local station, are deleted.

5.1.5. Searching for and Joining Sessions on a LAN (for Debugging)

To allow the joining of P2P sessions on a LAN, NetZ provides the LANSessionDiscovery class. The LANSessionDiscovery class can be used to search for P2P sessions that exist on the same LAN. This class can only be used on the session master and on terminals that are running on the same LAN. It cannot be used for non-debugging purposes and does not need to be configured when using local communication. When you call LANSessionDiscovery::Enable, other sessions that were created on the LAN can be referenced using Session::QuerySession.

Session::QuerySession must be called before calling Session::CreateSession or Session::JoinSession.

For example, you could use the following code to search for P2P sessions on the LAN and output information from the session descriptions.

Code 5.2 Searching for P2P Sessions on LAN

LANSessionDiscovery::Enable();

.....

std::list<SessionDescription> lstResult;
if (Session::QuerySessions(&lstResult,false)==0)
{
    QLOG(EventLog::Error, _T("No session found."));
}
else
{
    std::list<SessionDescription>::iterator it=lstResult.begin();
    while (it!=lstResult.end())
    {
        // Display relevant information from SessionDescription
        QLOG(EventLog::Info, _T("Session ID    : ") << it->GetSessionID());
    }
}

As another example, the following code would search for P2P sessions on the LAN and join the first session in the list.

Code 5.3 Searching for and Joining P2P Sessions on LAN

LANSessionDiscovery::Enable();

.....

std::list<SessionDescription> lstResult;
if ( Session::QuerySessions(&lstResult,false) == 0 )
{
    QLOG(EventLog::Error, _T("No session found."));
}
else
{
    if (! Session::JoinSession(&lstResult.begin()) )
    {
        QLOG(EventLog::Error, _T("Join Failed."));
    }
}

5.2. Stations

There are two kinds of stations: local stations that exist as long as the session exists, and peer stations that are generated upon searching and deleted upon leaving. A unique Station object is generated for each one.

A Station object includes information such as the station status, the DOHandle, and the StationID that is a unique global station identifier within the session. You can determine whether a Station object is a local station or a peer station by using the Station::IsLocal and Station::IsAPeer member functions. You can also use Station::IsConnected to check whether you can communicate with a different station.

5.2.1. Station State Transitions

Use Station::GetState to get the current state of a station. Figure 5.1 shows the transitions between the different states: Station::Unknown, Station::JoiningSession, Station::CreatingSession, Station::Participating, Station::Leaving, and Station::LeavingOnFault.

_images/Fig_Station_StateChart.png

Figure 5.1 Station State Transitions

5.2.2. Detecting Stations Joining and Leaving Sessions

You can use the following functions to know when stations join and leave the session.

Table 5.1 API for Handling Stations Joining and Leaving Sessions
API Description
Station::RegisterOperationBeginCallback() Sets a callback that is called when a station starts to join or starts to leave.
Station::RegisterOperationEndCallback() Sets a callback that is called when a station is finished joining or finished leaving.

This section describes the main uses for these APIs.

To view sample code, see the AutoMatch sample.

5.2.3. Detecting Lost Stations

NEX uses keep-alive packets to monitor the existence of stations to detect the abnormal loss of stations (for example, due to network faults, peer stations powered off, or Wi-Fi turned off).

The library behaves in the following way to monitor the existence of stations.

  • If a station has not sent any normal packets for a certain duration (the default is 1000 msec, and the value is obtained using the StreamSettings::GetKeepAliveTimeout function), keep-alive packets are sent to that station at intervals of StreamSettings::GetKeepAliveTimeout.
  • If a station receives a keep-alive packet, it sends back a keep-alive response.
  • If no packets are received during a certain duration (the default is 10,000 msec, and the value is obtained using the StreamSettings::GetMaxSilenceTime function), it is assumed that the station is not connected.

When loss of a station is detected, the state change can be detected with the callback registered by the Station::RegisterOperationBeginCallback function and the Station::GetState function because the lost station takes the value Station::LeavingOnFault.

5.2.4. Station Protocol Information

The NEX protocol statistical information can get the statistical operation object with the Station::GetEndPointInfoInterface function. Get statistical information after communication starts or after executing the EndPointInfoInterface::ResetEndPointInfo function with the EndPointInfoInterface::GetEndPointInfo function. Refer to the EndPointInfo structure for the available information. These statistics are the statistical information after duplicated object message handling with the BundlingPolicy class and before packet handling with the StreamBundling class settings. The data actually output might be grouped together by packet handling.

Get the packet count for the send buffer for reliable communication with the EndPointInfoInterface::GetReliableBufferPacketCount or EndPointInfoInterface::GetReliableBufferPacketCounts function.

Regarding RTT, use the Station::GetRTT and Station::GetRTTAverage functions to directly get the round trip delay for a specified message and the average round trip delay of messages sent between the local station and another station.

5.2.5. Station Version and User-Defined Information

You can set the version of the application using the Station::SetLocalApplicationVersion() function. The value set with this function can be obtained by using Station::GetApplicationVersion.

In addition, a user-defined string can be associated with a particular station by using the Station::SetLocalIdentificationToken function . One way to use an identification token is to use it to pass a password or other identifying tag when a station attempts to join a session to determine whether the station has the right to join the session. In this case, the information is passed to the connection point station so that that station can make a decision about the join request. The identification token is set on the joining station object, and is then accessible with the Station::GetIdentificationToken function. An example of how to use an identification token is detailed in Chapter 13 Extended Duplicated Object Features.


CONFIDENTIAL