server | v5 switch to v4  

4.x to 5.0 RC1 Upgrade Guide

This guide is for migrating from v4 to v5 versions equal or higher than v5.0 RC1 (not v5 BETA).

Overview Of Major Changes

As on the Photon Cloud, v5 will now run a Name Server. Clients should connect it to authenticate and get a Master Server address. This affects the authentication configuration. If you did not have a license before (using the 20 free CCU bootstrap mode), you need to get one now to be able to use the new server version. CounterPublisher (App, Project and DLLs) was deprecated and removed from SDK. Other than that, some configuration changes need to be reviewed.

Back To Top
 

License Updates And Upgrades

When upgrading to a new major version of the Photon SDK or when using an older SDK version with a newly purchased license file, you should make sure ahead of time before going into production, that your Photon SDK runs with that license.

The easiest way to do this is to put the license file in question into the Photon SDK folder you plan to use and start Photon via the Photon Control application. You should then check the license information shown in the tray app and additionally check the logs for licensing errors.

Back To Top
 

Code Changes

Here we list the possible changes needed to your custom classes that extend some commonly used types.

ApplicationBase

If you are extending ApplicationBase class:

  • One of the constructors need to pass IConfiguration parameter to base contructor. In order to do this you need to import NuGet package "Microsoft.Extensions.Configuration.Abstractions". Then load the configuration (from XML or JSON or elsewhere) then pass it to base class constructor. You can take a look at how we do it in MasterApplication or GameApplication or PhotonApp classes. Common pattern we use:

        using Photon.SocketServer;
      using Microsoft.Extensions.Configuration;
    
      public class CustomPhotonApplication : ApplicationBase
      {
          public CustomPhotonApplication() : base(LoadConfiguration())
          {
          }
    
          private static IConfiguration LoadConfiguration()
          {
  • (optional) New methods to override:

    • object DecryptAuthToken(InitRequest initRequest, byte[] authToken, int offset, int length, out Dictionary<byte, object> encryptionData, out string errorMsg)
    • void OnWebRTCChannelDestroyed(IPhotonWebRTCPeer peer, object userData, byte channelId)

Back To Top
 

ClientPeer

If you are extending ClientPeer class:

  • void OnUnexpectedDataReceived(byte[] data, string debugMessage) is gone and is replaced with void OnDeserializationError(byte[] data, RtsMessageType msgType, string debugMessage, short errorCode = -12, byte code = 0, Exception exception = null)
  • First parameter of OnDisconnected has changed from DisconnectReason or int: before: void OnDisconnect(DisconnectReason reasonCode, string reasonDetail) after: void OnDisconnect(int reasonCode, string reasonDetail)
  • (optional) New methods to override:
    • string GetHistograms()
    • void OnEncryptionQueueOverload(EncryptionQueueFailureParams failureParams)

Back To Top
 

S2SPeerBase

Same as when extending ClientPeer plus new extra optional method to override: void OnDisconnectMessage(DisconnectMessage message).

Back To Top
 

InboundS2SPeer

Same as when extending S2SPeerBase.

Back To Top
 

OutboundS2SPeer

Same as when extending S2SPeerBase plus new extra optional method to override void OnConnectionEstablished(InitV3Response initResponse).

Back To Top
 

PhotonServer.config Changes

  • We now support a new syntax for defining server application instances: Instead of:

      <Configuration>
      <InstanceName>
      </InstanceName>
    </Configuration>

    Do:

      <Configuration>
      <Instance Name="InstanceName">
      </Instance>
    </Configuration>
  • For the LoadBalancing instance, the default application is now NameServer and no longer Master as it used to be in v4.

  • Remove CounterPublisher application node from LoadBalancing instance.

  • Remove MMO instance.

Back To Top
 

Obsolete Settings

There are some settings removed in v5 and due to the newly introduced schema validation, the server will fail to start if these are still present.

Applications

  • Shared Directory logic is old and not used. Remove related setting:
    • SharedDirIsExeDir

Back To Top
 

Application

  • Shared Directory logic is old and not used. Remove related settings:
    • SharedDirIsExeDir
    • SharedDirectory
  • Automatic restarting of applications on change is now disabled. Remove related settings:
    • RestartDelayMilliseconds
    • WatchFiles
    • ExcludeFiles
    • EnableShadowCopy
    • EnableAutoRestart
    • ForceAutoRestart
  • Resolver
  • EnableOutboundENet

Back To Top
 

TCPListener

  • Certificate setup has changed read more here. Old certificate setup settings are gone:
    • StoreName
    • UseMachineStore
    • CertificateName
  • DisconnectTimeout
  • MaxQueuedBuffers
  • MaxPendingWrites
  • FlowControlNotificationStepSize
  • PolicyApplication

Back To Top
 

HTTPListener

  • Access-Control-Allow-Origin

Back To Top
 

Instance

  • AttachConsole
  • TCPUsePageAllocator
  • UseStandardAllocator
  • UseLockFreeAllocator
  • UseTLSAllocator
  • ENETUseLowContentionBufferAllocator
  • ENETNumAllocators
  • ENETUsePageAllocator
  • ValidateCRCifPresent

Back To Top
 

IOPool / ENetIOPool / ENetThreadPool

"Priority" setting as been removed from all three pools.

Back To Top
 

Runtime

  • OptimiseBroadcast removed
  • UnhandledExceptionPolicy: Replace value "ReloadDomain" with "Ignore" or "TerminateProcess". "ReloadDomain" is no longer supported.

Back To Top
 

HTTP WebSocket Listeners

WebSocketListeners have changed syntax.

Before (v4):

    <WebSocketListeners>
      <WebSocketListener
        IPAddress="0.0.0.0"
        Port="9090"
        DisableNagle="true"
        InactivityTimeout="10000"
        OverrideApplication="Master">
      </WebSocketListener>
      <WebSocketListener
        IPAddress="0.0.0.0"
        Port="9091"
        DisableNagle="true"
        InactivityTimeout="10000"
        OverrideApplication="Game">
      </WebSocketListener>
    </WebSocketListeners>

After (v5):

    <HTTPListeners>
      <HTTPListener
        Name="*:[PORT]::Master"
        IPAddress="0.0.0.0"
        Port="9090"
        DisableNagle="true"
        InactivityTimeout="10000">
        <Routing>
          <Route 
            Url="/+" 
            OverrideApplication="Master"
            PeerType="WebSocket"
            Counters="false" />
          <Route Url="/photon/m" Ping="true" Counters="false"/>
        </Routing>
      </HTTPListener>
      <HTTPListener
        Name="*:[PORT]::Game"
        IPAddress="0.0.0.0"
        Port="9091"
        DisableNagle="true"
        InactivityTimeout="10000"
        AppDataInactivityTimeout="15000">
        <Routing>
          <Route 
            Url="/+" 
            OverrideApplication="Game"
            PingEvery="2000" 
            PeerType="WebSocket"
            Counters="false" />
          <Route Url="/photon/g" Ping="true" Counters="false"/>
        </Routing>
      </HTTPListener>
      <HTTPListener
        Name="*:[PORT]::NameServer"
        IPAddress="0.0.0.0"
        Port="9093"
        DisableNagle="true"
        InactivityTimeout="10000"
        AppDataInactivityTimeout="15000">
        <Routing>
          <Route 
            Url="/+" 
            OverrideApplication="NameServer"
            PeerType="WebSocket"
            Counters="false" />
          <Route Url="/photon/n" Ping="true" Counters="false"/>
        </Routing>
      </HTTPListener>
    </HTTPListeners>

Back To Top
 

Secure Listeners Setup

Since we have moved from Secure Channel (Schannel) to OpenSSL, certificate format and configuration for secure listeners have changed.

  • Remove the obsolete attributes:
    • StoreName
    • UseMachineStore
    • CertificateName

Replace with the new settings for certificates setup. Read more on certificate setup.

Back To Top
 

LoadBalancing Configuration Changes

File Name Changes

First, the most noticebale difference is that now each server application has its own configuration file that has the following name format: "{application_name}.xml.config". This is important especially for Master and GameServer applications that used to share the same file name and content by default: "Photon.LoadBalancing.dll.config". The content of that file is now split into two files:

  • "deploy\LoadBalancing\Master\bin\Master.xml.config"
  • "deploy\LoadBalancing\GameServer\bin\GameServer.xml.config"

Here is the list of the configuration files:

Back To Top
 

Master

Before (v4):

"deploy\Loadbalancing\Master\bin\Photon.LoadBalancing.dll.config"

After (v5):

"deploy\LoadBalancing\Master\bin\Master.xml.config"

Back To Top
 

GameServer

Before (v4):

"deploy\Loadbalancing\GameServer\bin\Photon.LoadBalancing.dll.config"

After (v5):

"deploy\LoadBalancing\GameServer\bin\GameServer.xml.config"

Back To Top
 

Plugins

Game Server Plugins configuration is no longer part of the GameSever configuration file, it's now done in its own file "deploy\LoadBalancing\GameServer\bin\plugin.config". In v4 it used to be inside "deploy\LoadBalancing\GameServer\bin\Photon.LoadBalancing.dll.config" so you need to move the plugins configuration from there.

Before (v4):

"deploy\Loadbalancing\GameServer\bin\Photon.LoadBalancing.dll.config"

After (v5):

"deploy\LoadBalancing\GameServer\bin\plugin.config"

Back To Top
 

Structure Change

The second important change is that configuration files have a new structure.

Old file structure:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <!-- sections defined here -->
  </configSections>
  <applicationSettings>
     <!-- app settings -->
  </applicationSettings>
  <!-- other settings -->
  <Photon>
    <CounterPublisher>
    </CounterPublisher>
  </Photon>
  <startup>
  </startup>
</configuration>

New file structure:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <Photon>
    <!-- all settings here -->
  </Photon>
</configuration>

Notice the root <Photon> element.

Some of the old configuration sections (XML elements) are no longer needed:

  • <configSections>
  • <applicationSettings>
  • <startup>
  • <CounterPublisher>

Some elements have been renamed.

  • <Photon.LoadBalancing.Common.CommonSettings> is now <LoadBalacing>
  • <Photon.Common.Authentication.Settings> is now <Authentication>
  • <Photon.LoadBalancing.MasterServer.MasterServerSettings> is now <Master>
  • <Photon.LoadBalancing.GameServer.GameServerSettings> is now <GameServer>
  • <WebRpcSettings> is now <WebRpc>
  • <AuthSettings> is now <CustomAuth>

Also now each setting node has a custom name matching the setting instead of the old generic format. This applies to all elements except <WebRPC> (previously <WebRpcSettings>) and <CustomAuth> (previously <AuthSettings) which did not change.

Old setting node format:

<setting name="SettingName" serializeAs="String">
    <value>SettingValue</value>
</setting>

New setting node format:

<SettingName>SettingValue</SettingName>

Here is a more detailed breakdown of the changes per file:

Back To Top
 

Master

<CustomAuth> (previously <AuthSettings) is no longer part of the MasterServer configuration and is instead done in NameServer ("deploy\NameServer\bin\NameServer.xml.config").

Old file structure:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <!-- sections defined here -->
  </configSections>
  <applicationSettings>
    <Photon.LoadBalancing.Common.CommonSettings>
    </Photon.LoadBalancing.Common.CommonSettings>
    <Photon.Common.Authentication.Settings>
    </Photon.Common.Authentication.Settings>
    <Photon.LoadBalancing.MasterServer.MasterServerSettings>
    </Photon.LoadBalancing.MasterServer.MasterServerSettings>
  </applicationSettings>
  <Photon>
    <CounterPublisher>
    </CounterPublisher>
  </Photon>
  <WebRpcSettings>
  </WebRpcSettings>
  <startup>
  </startup>
</configuration>

New file structure:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <Photon>
    <LoadBalancing>
    </LoadBalancing>
    <Authentication>
    </Authentication>
    <Master>
      <S2S>
      </S2S>
      <GS>
      </GS>
      <Limits>
        <Inbound>
        </Inbound>
        <Lobby>
        </Lobby>
      </Limits>
    </Master>
    <WebRpc>
      <HttpQueueSetting>
      </HttpQueueSettings>
    </WebRpc>
    <SocketServer>
      <S2S>
      </S2S>
    </SocketServer>
  </Photon>
</configuration>

Back To Top
 

GameServer

Old file structure:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <!-- sections defined here -->
  </configSections>
  <applicationSettings>
    <Photon.LoadBalancing.Common.CommonSettings>
    </Photon.LoadBalancing.Common.CommonSettings>
    <Photon.Common.Authentication.Settings>
    </Photon.Common.Authentication.Settings>
    <Photon.LoadBalancing.MasterServer.GameServerSettings>
    </Photon.LoadBalancing.MasterServer.GameServerSettings>
  </applicationSettings>
  <Photon>
    <CounterPublisher>
    </CounterPublisher>
  </Photon>
  <WebRpcSettings>
  </WebRpcSettings>
  <startup>
  </startup>
</configuration>

New file structure:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <Photon>
    <LoadBalancing>
    </LoadBalancing>
    <Authentication>
    </Authentication>
    <GameServer>
      <S2S>
      </S2S>
      <Master>
      </Master>
      <Limits>
        <Inbound>
          <EventCache>
          </EventCache>
          <Properties>
          </Properties>
          <Operations>
          </Operations>
        </Inbound>
      </Limits>
      <HttpQueueSetting>
      </HttpQueueSettings>
    </GameServer>
    <WebRpc>
      <HttpQueueSetting>
      </HttpQueueSettings>
    </WebRpc>
    <SocketServer>
      <S2S>
      </S2S>
    </SocketServer>
  </Photon>
</configuration>

Back To Top
 

Plugins

Add a <Configuration></Configuration> enclosing wrapper element as follows:

<Configuration>
  <PluginSettings Enabled="True">
    <Plugins>
      <!-- custom plugin settings here -->
    </Plugins>
  </PluginSettings>
</Configuration>

Back To Top
 

HttpQueueSettings

HttpQueue is used for everything HTTP (outbound). So it made sense to group the queue's related settings into one group. This group of settings is used in GameServer, WebRPC and CustomAuth settings (as a subgroup). Most of the settings were already available in v4 but now it's more organized (new structure), clean and consistent (naming).

  • HttpRequestTimeout: How long (in milliseconds) the queue can wait for a HTTP response.
  • LimitHttpResponseMaxSize: Maximum size of HTTP response payload.
  • MaxBackoffTime: Backoff threshold when retrying to send a HTTP request.
  • MaxConcurrentRequests: Maximum concurrent HTTP requests allowed.
  • MaxErrorRequests: Maximum number of errors that can occur while processing queued requests. If reached the HttpQueue will disconnect (clear all queued requests and reject incoming) and then resume after ReconnectInterval.
  • MaxQueuedRequests: Maximum number of requests that can be queued.
  • MaxTimedOutRequests: Maximum number of requests that timeout in the queue waiting to be processed. If reached the HttpQueue will disconnect (clear all queued requests and reject incoming) and then resume after ReconnectInterval.
  • QueueTimeout: If a request stays in the HttpQueue for QueueTimeout milliseconds it will be removed automatically.
  • ReconnectInterval: How long (in milliseconds) the queue needs to wait before resuming process of HTTP requests.

Settings with same or similar names from GameServer, WebRPC or CustomAuth nodes need to be removed or moved under a <HttpQueueSettings> element.

Back To Top
 

NameServer (NEW)

In v5 we added the NameServer application which was available in Photon Cloud only before. Its configuration is done using two files:

  • one file for the actual application. Custom authentication is now done on the NameServer and not on the MasterServer anymore. So move any previously configured custom authentication settings from the MasterServer's configuration file (section used to be named <AuthSettings>) to the NameServer's configuration file (section renamed to <CustomAuth>): "deploy\NameServer\bin\NameServer.xml.config".

  • one file for the list of regions (MasterServer) to be associated with that NameServer. The file can be changed in 'NameServerConfig' setting in "deploy\NameServer\bin\NameServer.xml.config". Default is: "deploy\Nameserver.json"

'NameServer' is now the default application for the LoadBalancing instance in PhotonServer.config replacing 'Master' as it used to be in v4.

Back To Top
 

LoadBalancer And Workload Configuration Changes

Level Name Update

In v4 only 5 levels existed. Those level names were 'Lowest', 'Low', 'Middle', 'High' and 'Highest'.

Now we use 'Level0', 'Level1', 'Level2', ..., 'Level9'. 'Lowest' is replaced with 'Level0'. 'Highest' is replaced with 'Level9'.

Back To Top
 

Workload Configuration Change

The GameServer setting "WorkloadConfigFile" sets the path for the LoadBalancer configuration file. By default in v5 it's "deploy\Workload.1Gbps.config" (used to be "Workload.config"). Another example file is available in the SDK as well: "Workload.config".

Back To Top
 

Controller Setup Update

Old controller setup:

<add Name="{ControllerName}" InitialInput="0" InitialLevel="Lowest">
  <FeedbackLevels>
    <add Level="Lowest" Value="{LowestValue}"/>
    <add Level="Low" Value="{LowValue}"/>
    <add Level="Normal" Value="{NormalValue}"/>
    <add Level="High" Value="{HighValue}"/>
    <add Level="Highest" Value="{HighestValue}"/>
  </FeedbackLevels>
</add>

New controller setup:

<Controller Name="{ContollerName}" InitialInput="0" InitialLevel="Lowest">
  <FeedbackLevels>
    <Level name="0" Level="Level0" Value="{Value0}" ValueDown="{ValueDown0}"/>
    <Level name="1" Level="Level1" Value="{Value1}" ValueDown="{ValueDown1}"/>
    <Level name="2" Level="Level2" Value="{Value2}" ValueDown="{ValueDown2}"/>
    <Level name="3" Level="Level3" Value="{Value3}" ValueDown="{ValueDown3}"/>
    <Level name="4" Level="Level4" Value="{Value4}" ValueDown="{ValueDown4}"/>
    <Level name="5" Level="Level5" Value="{Value5}" ValueDown="{ValueDown5}"/>
    <Level name="6" Level="Level6" Value="{Value6}" ValueDown="{ValueDown6}"/>
    <Level name="7" Level="Level7" Value="{Value7}" ValueDown="{ValueDown7}"/>
    <Level name="8" Level="Level8" Value="{Value8}" ValueDown="{ValueDown8}"/>
    <Level name="9" Level="Level9" Value="{Value9}" ValueDown="{ValueDown9}"/>
  </FeedbackLevels>
</Controller>

Back To Top
 

File Structure Update

Old structure:

<?xml version="1.0" encoding="utf-8" ?>
<FeedbackControlSystem>
  <FeedbackControllers>
      <!-- one or more controllers setup -->
  </FeedbackControllers>
</FeedbackControlSystem>

New structure (wrapper <Configuration></Configuration> element/node added):

<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
  <FeedbackControlSystem>
    <FeedbackControllers>
      <!-- one or more controllers setup -->
    </FeedbackControllers>
  </FeedbackControlSystem>
</Configuration>

Back To Top
 

LoadBalancer Configuration Change

The LoadBalancer configuration file is "deploy\LoadBalancer.config".

<?xml version="1.0" encoding="utf-8" ?>
<LoadBalancer>
  <LoadBalancerWeights>
    <add Level="Lowest" Value="{LowestValue}"/>
    <add Level="Low" Value="{LowValue}"/>
    <add Level="Normal" Value="{NormalValue}"/>
    <add Level="High" Value="{HighValue}"/>
    <add Level="Highest" Value="{HighestValue}"/>
  </LoadBalancerWeights>
</LoadBalancer>

New structure (wrapper <Configuration></Configuration> element/node added):

<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
  <LoadBalancer ReserveRatio="{ReserveRatio}" ValueUp="{ValueUp}">
    <LoadBalancerWeights>
      <Level name="0" Level="Level0" Value="{Value0}" />
      <Level name="1" Level="Level1" Value="{Value1}"/>
      <Level name="2" Level="Level2" Value="{Value2}"/>
      <Level name="3" Level="Level3" Value="{Value3}"/>
      <Level name="4" Level="Level4" Value="{Value4}"/>
      <Level name="5" Level="Level5" Value="{Value5}"/>
      <Level name="6" Level="Level6" Value="{Value6}"/>
      <Level name="7" Level="Level7" Value="{Value7}"/>
      <Level name="8" Level="Level8" Value="{Value8}"/>
      <Level name="9" Level="Level9" Value="{Value9}"/>
    </LoadBalancerWeights>
  </LoadBalancer>
</Configuration>

To Document Top