Beispiel #1
0
        /// <summary>
        /// Initializes the isometric tiles of the map structure.
        /// </summary>
        /// <param name="isotileListPackage">The package that contains the isometric tile informations.</param>
        private void LoadIsoTiles(RCPackage isotileListPackage)
        {
            string[] terrainIndexTable = isotileListPackage.ReadStringArray(0);
            byte[]   isotileInfoBytes  = isotileListPackage.ReadByteArray(1);

            int offset = 0;

            while (offset < isotileInfoBytes.Length)
            {
                int       parsedBytes;
                RCPackage package = RCPackage.Parse(isotileInfoBytes, offset, isotileInfoBytes.Length - offset, out parsedBytes);
                if (package == null || !package.IsCommitted)
                {
                    throw new MapException("Syntax error!");
                }
                offset += parsedBytes;
                if (package.PackageFormat.ID == MapFileFormat.ISOTILE)
                {
                    RCIntVector        quadCoords   = new RCIntVector(package.ReadShort(0), package.ReadShort(1));
                    TerrainCombination terrainCombo = (TerrainCombination)package.ReadByte(4);
                    string             terrainA     = terrainIndexTable[package.ReadByte(2)];
                    string             terrainB     = terrainCombo != TerrainCombination.Simple ? terrainIndexTable[package.ReadByte(3)] : null;
                    int variantIdx = package.ReadByte(5);

                    this.mapStructure.InitIsoTile(quadCoords,
                                                  terrainCombo == TerrainCombination.Simple ?
                                                  this.mapStructure.Tileset.GetIsoTileType(terrainA) :
                                                  this.mapStructure.Tileset.GetIsoTileType(terrainA, terrainB, terrainCombo),
                                                  variantIdx);
                }
            }
        }
Beispiel #2
0
 /// <summary>
 /// Called when a NETWORK_CUSTOM_PACKAGE has arrived from the lobby.
 /// </summary>
 /// <remarks>Must be implemented at both server and client side.</remarks>
 public virtual void PackageArrivedHdl(int timestamp, RCPackage package, int senderID)
 {
     if (IsSimulationRunning_i())
     {
         /// Package arrived during simulation stage must be handled.
         if (package.PackageFormat.ID == DssRoot.DSS_COMMAND)
         {
             if (!CommandPackageArrived(package, senderID))
             {
                 this.root.SimulationMgr.SimulationStageError(string.Format("Processing incoming DSS_COMMAND package failed. Sender: {0}. Package: {1}", senderID, package.ToString()),
                                                              new byte[] { });
             }
         }
         else if (package.PackageFormat.ID == DssRoot.DSS_COMMIT)
         {
             if (!this.root.SimulationMgr.RegisterCommit(package, senderID))
             {
                 this.root.SimulationMgr.SimulationStageError(string.Format("Processing incoming DSS_COMMIT package failed. Sender: {0}. Package: {1}", senderID, package.ToString()),
                                                              new byte[] { });
             }
         }
         else if (package.PackageFormat.ID == DssRoot.DSS_COMMIT_ANSWER)
         {
             if (!this.root.SimulationMgr.RegisterCommitAnswer(package, senderID))
             {
                 this.root.SimulationMgr.SimulationStageError(string.Format("Processing incoming DSS_COMMIT_ANSWER package failed. Sender: {0}. Package: {1}", senderID, package.ToString()),
                                                              new byte[] { });
             }
         }
         else if (package.PackageFormat.ID == DssRoot.DSS_LEAVE)
         {
             if (this.root.SimulationMgr.RegisterLeaveMessage(package, senderID))
             {
                 this.root.OperatorLeftSimulationStage(senderID);
             }
             else
             {
                 this.root.SimulationMgr.SimulationStageError(string.Format("Processing incoming DSS_LEAVE package failed. Sender: {0}. Package: {1}", senderID, package.ToString()),
                                                              new byte[] { });
             }
         }
         else if (package.PackageFormat.ID == DssRoot.DSS_SIM_ERROR)
         {
             string errorDescr = package.ReadString(0);
             byte[] customData = package.ReadByteArray(1);
             this.root.SimulationMgr.SimulationStageErrorReceived(string.Format("DSS_SIM_ERROR received from operator-{0}: {1}", senderID, errorDescr), customData);
         }
         else
         {
             this.root.SimulationMgr.SimulationStageError(string.Format("Unexpected package arrived from operator-{0}: {1}", senderID, package.ToString()),
                                                          new byte[] { });
         }
     }
     else
     {
         /// Package arrived during setup stage is not allowed.
         PackageArrivedDuringSetupStage_i(package, senderID);
     }
 }
Beispiel #3
0
        /// <summary>
        /// Initializes the terrain objects of the map.
        /// </summary>
        /// <param name="terrainObjListPackage">The package that contains the terrain object informations.</param>
        /// <param name="map">Reference to the map.</param>
        private void LoadTerrainObjects(RCPackage terrainObjListPackage, IMapAccess map)
        {
            /// TODO: Avoid this downcast!
            MapAccess mapObj = map as MapAccess;

            if (mapObj == null)
            {
                throw new ArgumentException("The given map cannot be handled by the MapEditor!", "map");
            }

            string[] terrainObjIndexTable = terrainObjListPackage.ReadStringArray(0);
            byte[]   terrainObjInfoBytes  = terrainObjListPackage.ReadByteArray(1);

            int offset = 0;

            while (offset < terrainObjInfoBytes.Length)
            {
                int       parsedBytes;
                RCPackage package = RCPackage.Parse(terrainObjInfoBytes, offset, terrainObjInfoBytes.Length - offset, out parsedBytes);
                if (package == null || !package.IsCommitted)
                {
                    throw new MapException("Syntax error!");
                }
                offset += parsedBytes;
                if (package.PackageFormat.ID == MapFileFormat.TERRAINOBJ)
                {
                    RCIntVector        quadCoords     = new RCIntVector(package.ReadShort(0), package.ReadShort(1));
                    ITerrainObjectType terrainObjType = this.mapStructure.Tileset.GetTerrainObjectType(terrainObjIndexTable[package.ReadByte(2)]);

                    /// TODO: Might be better to create the TerrainObject with a factory?
                    ITerrainObject newObj = new TerrainObject(map, terrainObjType, quadCoords);
                    foreach (ICellDataChangeSet changeset in newObj.Type.CellDataChangesets)
                    {
                        changeset.Apply(newObj);
                    }
                    mapObj.AttachTerrainObject(newObj);
                }
            }

            /// Check the constraints of the terrain objects.
            List <ITerrainObject> terrainObjects = new List <ITerrainObject>(map.TerrainObjects);

            foreach (ITerrainObject terrainObj in terrainObjects)
            {
                mapObj.DetachTerrainObject(terrainObj);
                if (terrainObj.Type.CheckConstraints(map, terrainObj.MapCoords).Count != 0)
                {
                    throw new MapException(string.Format("Terrain object at {0} is voilating the tileset constraints!", terrainObj.MapCoords));
                }
                if (terrainObj.Type.CheckTerrainObjectIntersections(map, terrainObj.MapCoords).Count != 0)
                {
                    throw new MapException(string.Format("Terrain object at {0} intersects other terrain objects!", terrainObj.MapCoords));
                }
                mapObj.AttachTerrainObject(terrainObj);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Internal function to handle command packages and send them to the simulation manager.
        /// </summary>
        /// <param name="commandPackage">The package that contains the commands.</param>
        /// <param name="senderID">The ID of the sender peer.</param>
        /// <returns>True in case of success, false otherwise.</returns>
        private bool CommandPackageArrived(RCPackage commandPackage, int senderID)
        {
            if (commandPackage == null)
            {
                throw new ArgumentNullException("commandPackage");
            }
            if (!commandPackage.IsCommitted ||
                DssRoot.DSS_COMMAND != commandPackage.PackageFormat.ID)
            {
                throw new ArgumentException("commandPackage");
            }
            if (senderID < 0 || senderID >= this.root.OpCount)
            {
                throw new ArgumentException("senderID");
            }
            if (senderID == this.root.IdOfThisPeer)
            {
                throw new ArgumentException("senderID");
            }

            int roundIdx = commandPackage.ReadInt(0);
            int frameIdx = commandPackage.ReadInt(1);

            byte[] cmdBuffer = commandPackage.ReadByteArray(2);
            if (cmdBuffer.Length == 0)
            {
                return(false);
            }

            List <RCPackage> cmds = new List <RCPackage>();

            int offset         = 0;
            int remainingBytes = cmdBuffer.Length;

            while (offset < cmdBuffer.Length)
            {
                /// Parse and check the next command package.
                int       parsedBytes = 0;
                RCPackage currPackage = RCPackage.Parse(cmdBuffer, offset, remainingBytes, out parsedBytes);
                if (currPackage != null && currPackage.IsCommitted)
                {
                    cmds.Add(currPackage);
                    offset         += parsedBytes;
                    remainingBytes -= parsedBytes;
                }
                else
                {
                    /// Uncommitted command package.
                    return(false);
                }
            }

            return(this.root.SimulationMgr.RegisterCommands(cmds.ToArray(), roundIdx, frameIdx, senderID));
        }
Beispiel #5
0
        /// <summary>
        /// Constructs a LobbyInfo object from an RCPackage.
        /// </summary>
        /// <param name="source">The package that contains the LobbyInfo data.</param>
        /// <returns>The contructed LobbyInfo or null if no LobbyInfo can be constructed from the given RCPackage.</returns>
        public static LobbyInfo FromRCPackage(RCPackage source)
        {
            if (null != source && source.IsCommitted && source.PackageFormat.ID == Network.FORMAT_LOBBY_INFO)
            {
                string idStr = source.ReadString(0);
                Guid   id;
                if (!Guid.TryParse(idStr, out id))
                {
                    TraceManager.WriteAllTrace(string.Format("Unable to parse {0} as a GUID!", idStr), NetworkingSystemTraceFilters.INFO);
                    return(null);
                }

                byte[]    customDataBytes = source.ReadByteArray(3);
                int       parsedBytes     = 0;
                RCPackage customData      = null;

                if (customDataBytes.Length > 0)
                {
                    RCPackage.Parse(customDataBytes, 0, customDataBytes.Length, out parsedBytes);
                }
                if (customDataBytes.Length == 0 ||
                    (null != customData && customData.IsCommitted && parsedBytes == customDataBytes.Length))
                {
                    LobbyInfo retInfo = new LobbyInfo(id,                                               /// ID
                                                      source.ReadString(1),                             /// IPAddress
                                                      source.ReadInt(2),                                /// PortNumber
                                                      (customDataBytes.Length != 0) ? customData : null /// Custom infos about the lobby
                                                      );
                    return(retInfo);
                }
                else
                {
                    TraceManager.WriteAllTrace("LobbyInfo.FromRCPackage failed: unexpected CustomData package format!", NetworkingSystemTraceFilters.INFO);
                    return(null);
                }
            }
            else
            {
                TraceManager.WriteAllTrace("LobbyInfo.FromRCPackage failed: unexpected package format!", NetworkingSystemTraceFilters.INFO);
                return(null);
            }
        }
        /// <summary>
        /// Registers the given DSS_LEAVE message arrived from the given operator.
        /// </summary>
        /// <param name="leaveMsg">The arrived DSS_LEAVE message.</param>
        /// <param name="senderID">The sender operator.</param>
        /// <returns>True in case of success, false otherwise.</returns>
        public bool RegisterLeaveMessage(RCPackage leaveMsg, int senderID)
        {
            if (!this.initialized)
            {
                throw new DssException("DssSimulationMgr is uninitialized!");
            }

            /// If we are currently finishing the simulation --> do nothing
            if (this.hostLeft)
            {
                return(true);
            }

            if (leaveMsg == null || !leaveMsg.IsCommitted)
            {
                throw new ArgumentException("leaveMsg");
            }
            if (senderID == this.root.IdOfThisPeer)
            {
                throw new DssException("Unexpected DSS_LEAVE sender!");
            }
            if (senderID < 0 || senderID >= this.root.OpCount)
            {
                throw new ArgumentException("senderID");
            }

            if (leaveMsg.PackageFormat.ID != DssRoot.DSS_LEAVE)
            {
                /// Package format error.
                return(false);
            }

            string reason = leaveMsg.ReadString(0);

            byte[] customData = leaveMsg.ReadByteArray(1);
            TraceManager.WriteAllTrace(string.Format("DSS_LEAVE: sender={0}, reason= {1}", senderID, reason), DssTraceFilters.SIMULATION_INFO);

            /// Set the corresponding operator flag to false.
            this.operatorFlags[senderID] = false;

            if (senderID > 0)
            {
                /// GUEST-leave
                /// Unregister all CommitMonitors that became unnecessary.
                List <int> commitAwTicketsToUnreg = new List <int>();
                foreach (KeyValuePair <int, CommitMonitor> monitor in this.commitAwMonitors)
                {
                    monitor.Value.Refresh();
                    if (monitor.Value.IsCommitAnswered)
                    {
                        commitAwTicketsToUnreg.Add(monitor.Value.Ticket);
                    }
                }
                foreach (int ticket in commitAwTicketsToUnreg)
                {
                    UnregisterCommitMonitor(ticket);
                }

                /// Try to register the leave of operator to the nextRound.
                if (!this.nextRound.Leave(senderID))
                {
                    /// If failed, try to register to the nextNextRound.
                    if (!this.nextNextRound.Leave(senderID))
                    {
                        /// If failed, try to register to the nextNextNextRound.
                        if (!this.nextNextNextRound.Leave(senderID))
                        {
                            /// Error: unable to register
                            TraceManager.WriteAllTrace(string.Format("Unable to register the leave of operator-{0}.", senderID), DssTraceFilters.SIMULATION_ERROR);
                            return(false);
                        }
                    }
                }

                /// Now check whether the next round has become committed with this leave message.
                if (this.waitingForCommit && this.nextRound.IsCommitted)
                {
                    TraceManager.WriteAllTrace("WAITING FOR COMMIT END (guest left)", DssTraceFilters.SIMULATION_INFO);
                    /// The missing commit has arrived, so we can continue the simulation
                    this.waitingForCommit = false;
                    /// Compute the scheduled time for the next frame
                    int nextFrameStartTime = this.currentRound.BaseTime
                                             + (this.currentRound.CurrentFrameIndex + 1) * this.currentRound.TargetFrameTime;
                    SendCommit();
                    SwapRounds();
                    /// Schedule the next frame.
                    SetNextFrameExecutionTime(Math.Max(nextFrameStartTime, DssRoot.Time));
                }
            }
            else
            {
                /// HOST-leave
                /// Stop the timers
                UnregisterAllCommitMonitors();
                StopCommitTimeoutClock();

                if (this.waitingForCommit && this.nextRound.IsCommitted)
                {
                    /// Can continue with the next round

                    TraceManager.WriteAllTrace("WAITING FOR COMMIT END (host left)", DssTraceFilters.SIMULATION_INFO);
                    /// The missing commit has arrived, so we can continue the simulation
                    this.waitingForCommit = false;
                    /// Compute the scheduled time for the next frame
                    int nextFrameStartTime = this.currentRound.BaseTime
                                             + (this.currentRound.CurrentFrameIndex + 1) * this.currentRound.TargetFrameTime;
                    SendCommit();
                    SwapRounds();
                    /// Schedule the next frame.
                    SetNextFrameExecutionTime(Math.Max(nextFrameStartTime, DssRoot.Time));
                }
                else if (this.waitingForCommit && !this.nextRound.IsCommitted)
                {
                    /// Cannot continue with the next round --> notify the client module and exit the event loop
                    NotifyClientAboutLeavingGuests(this.nextRound);
                    NotifyClientAboutLeavingGuests(this.nextNextRound);
                    NotifyClientAboutLeavingGuests(this.nextNextNextRound);
                    this.root.SimulatorIface.HostLeftDssDuringSim();
                    this.root.EventQueue.ExitEventLoop();
                }
                this.hostLeft = true;
            }

            return(true);
        }
        /// <summary>
        /// Registers the given commit arrived from the given operator.
        /// </summary>
        /// <param name="commit">The arrived commit package.</param>
        /// <param name="senderID">The sender operator.</param>
        /// <returns>True in case of success, false otherwise.</returns>
        public bool RegisterCommit(RCPackage commit, int senderID)
        {
            if (!this.initialized)
            {
                throw new DssException("DssSimulationMgr is uninitialized!");
            }

            /// If we are currently finishing the simulation --> do nothing
            if (this.hostLeft)
            {
                return(true);
            }

            if (commit == null || !commit.IsCommitted)
            {
                throw new ArgumentException("commit");
            }
            if (senderID == this.root.IdOfThisPeer)
            {
                throw new DssException("Unexpected commit sender!");
            }
            if (senderID < 0 || senderID >= this.root.OpCount)
            {
                throw new ArgumentException("senderID");
            }

            if (commit.PackageFormat.ID != DssRoot.DSS_COMMIT)
            {
                /// Package format error.
                return(false);
            }

            short senderAFT = commit.ReadShort(0);
            short senderAPT = commit.ReadShort(1);
            int   roundIdx  = commit.ReadInt(2);
            int   ticket    = commit.ReadInt(3);

            byte[] stateHash = commit.ReadByteArray(4);

            if (senderAFT < 0)
            {
                return(false);
            }
            if (senderAPT < 0)
            {
                return(false);
            }
            if (stateHash == null)
            {
                return(false);
            }

            bool success = false;

            if (roundIdx == this.nextRound.RoundIndex)
            {
                success = this.nextRound.Commit(senderID, senderAFT, senderAPT, stateHash);
                if (this.waitingForCommit && this.nextRound.IsCommitted)
                {
                    TraceManager.WriteAllTrace("WAITING FOR COMMIT END", DssTraceFilters.SIMULATION_INFO);
                    /// The missing commit has arrived, so we can continue the simulation
                    this.waitingForCommit = false;
                    /// Compute the scheduled time for the next frame
                    int nextFrameStartTime = this.currentRound.BaseTime
                                             + (this.currentRound.CurrentFrameIndex + 1) * this.currentRound.TargetFrameTime;
                    SendCommit();
                    SwapRounds();
                    /// Schedule the next frame.
                    SetNextFrameExecutionTime(Math.Max(nextFrameStartTime, DssRoot.Time));
                }
            }
            else if (roundIdx == this.nextNextRound.RoundIndex)
            {
                success = this.nextNextRound.Commit(senderID, senderAFT, senderAPT, stateHash);
            }
            else
            {
                TraceManager.WriteAllTrace(string.Format("RoundIdx mismatch! RoundIdx: {0}", roundIdx), DssTraceFilters.SIMULATION_ERROR);
            }

            if (success)
            {
                /// Create the answer for the commit and send it back to the sender.
                RCPackage commitAw = RCPackage.CreateNetworkCustomPackage(DssRoot.DSS_COMMIT_ANSWER);
                commitAw.WriteInt(0, ticket);
                this.root.LobbyIface.SendPackage(commitAw, new int[1] {
                    senderID
                });
            }
            return(success);
        }
Beispiel #8
0
        /// <summary>
        /// Continues the connection procedure to the server.
        /// </summary>
        /// <returns>
        /// In case of error this function automatically shuts down the connection, notifies the listener and
        /// returns false. Otherwise it returns true. If the line state report arrives from the server, this
        /// function automatically notifies the listener.
        /// </returns>
        private bool ContinueConnectToTheServer()
        {
            RCPackage lineStateReport = null;

            if (this.connection.ContinueConnectToTheServer(out lineStateReport))
            {
                if (lineStateReport != null)
                {
                    short            clientID       = lineStateReport.ReadShort(0);
                    byte[]           lineStateBytes = lineStateReport.ReadByteArray(1);
                    LobbyLineState[] lineStates     = new LobbyLineState[lineStateBytes.Length];
                    bool             lineStatesOK   = true;
                    for (int i = 0; i < lineStateBytes.Length; i++)
                    {
                        if (lineStateBytes[i] == (byte)LobbyLineState.Closed ||
                            lineStateBytes[i] == (byte)LobbyLineState.Engaged ||
                            lineStateBytes[i] == (byte)LobbyLineState.Opened)
                        {
                            lineStates[i] = (LobbyLineState)lineStateBytes[i];
                        }
                        else
                        {
                            lineStatesOK = false;
                        }
                    }
                    lineStatesOK = lineStatesOK && clientID > 0 && clientID < lineStateBytes.Length;
                    if (!lineStatesOK)
                    {
                        /// Line state report error --> shutdown.
                        this.connection.Shutdown();
                        if (this.Disposed != null)
                        {
                            this.Disposed(this);
                        }
                        this.listener.LobbyLost();
                        return(false);
                    }
                    else
                    {
                        /// Connection procedure finished --> send a line state report to the listener.
                        this.clientID    = clientID;
                        this.memberCount = lineStates.Length;
                        this.listener.LineStateReport(clientID, lineStates);
                        return(true);
                    }
                }
                /// No error but connection procedure not finished.
                return(true);
            }
            else
            {
                /// Connection rejected by the server or an error occured --> shutdown.
                this.connection.Shutdown();
                if (this.Disposed != null)
                {
                    this.Disposed(this);
                }
                this.listener.LobbyLost();
                return(false);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Internal function for parsing a DSS_CTRL_START_SIMULATION package.
        /// </summary>
        /// <param name="package">The package to parse.</param>
        /// <returns>True if the package has been successfully parsed, false otherwise.</returns>
        private bool ParseStartSimPackage(RCPackage package, out int[] leftList, out int[] lostList, out bool[] opFlags)
        {
            /// Read the left-list
            leftList = package.ReadIntArray(0);
            for (int i = 0; i < leftList.Length; ++i)
            {
                if (leftList[i] < 0)
                {
                    leftList = null;
                    lostList = null;
                    opFlags  = null;
                    return(false);
                }
            }

            /// Read the lost-list
            lostList = package.ReadIntArray(1);
            for (int i = 0; i < lostList.Length; ++i)
            {
                if (lostList[i] < 0)
                {
                    leftList = null;
                    lostList = null;
                    opFlags  = null;
                    return(false);
                }
            }

            /// Read the channel-state-list
            byte[] chStateBytes = package.ReadByteArray(2);
            if (chStateBytes.Length == this.guestRoot.OpCount - 1)
            {
                opFlags    = new bool[this.guestRoot.OpCount];
                opFlags[0] = true;
                for (int i = 0; i < chStateBytes.Length; ++i)
                {
                    if (chStateBytes[i] == (byte)DssChannelState.CHANNEL_CLOSED ||
                        chStateBytes[i] == (byte)DssChannelState.CHANNEL_OPENED ||
                        chStateBytes[i] == (byte)DssChannelState.GUEST_CONNECTED)
                    {
                        opFlags[i + 1] = (chStateBytes[i] == (byte)DssChannelState.GUEST_CONNECTED);
                    }
                    else
                    {
                        /// Error
                        leftList = null;
                        lostList = null;
                        opFlags  = null;
                        return(false);
                    }
                }
            } /// end-if (chStateBytes != null && chStateBytes.Length != this.guestRoot.OpCount - 1)
            else
            {
                /// Error
                leftList = null;
                lostList = null;
                opFlags  = null;
                return(false);
            }

            /// Everything is OK, the start simulation message arrived successfully.
            return(true);
        }
Beispiel #10
0
        /// <summary>
        /// Call this function if a control package has arrived from the network and you are waiting for a setup step
        /// answer or request. This class will parse it for you automatically.
        /// </summary>
        /// <param name="package">The incoming control package.</param>
        public void IncomingPackage(RCPackage package)
        {
            if (package == null)
            {
                throw new ArgumentNullException("package");
            }
            if (!package.IsCommitted)
            {
                throw new ArgumentException("Uncommitted package!", "package");
            }
            if (package.PackageType != RCPackageType.NETWORK_CONTROL_PACKAGE)
            {
                throw new ArgumentException("Unexpected package type!", "package");
            }
            if (this.state != SetupStepState.NOT_FINISHED)
            {
                throw new DssException("This call is only allowed in NOT_FINISHED state!");
            }

            if (this.mode == DssMode.HOST_SIDE)
            {
                /// Host side parsing
                if (this.beginArrived)
                {
                    if (!DssRoot.IsInternalFormat(package.PackageFormat))
                    {
                        this.packageListTmp.Add(package);
                    }
                    else
                    {
                        if (package.PackageFormat.ID == DssRoot.DSS_CTRL_SETUP_STEP_MSG_END &&
                            package.ReadInt(0) == this.stepID)
                        {
                            /// Finished
                            this.packageList = this.packageListTmp.ToArray();
                            this.state       = SetupStepState.READY;
                        }
                        else
                        {
                            /// Error
                            this.state = SetupStepState.ERROR;
                        }
                    }
                }
                else /// end-if (this.beginArrived)
                {
                    if (package.PackageFormat.ID == DssRoot.DSS_CTRL_SETUP_STEP_AW_BEGIN &&
                        package.ReadInt(0) == this.stepID)
                    {
                        this.beginArrived = true;
                    }
                    else
                    {
                        /// Error
                        this.state = SetupStepState.ERROR;
                    }
                }
            }
            else /// end-if (this.mode == SetupStepMode.HOST_SIDE)
            {
                /// Guest side parsing
                if (this.beginArrived)
                {
                    if (!DssRoot.IsInternalFormat(package.PackageFormat))
                    {
                        this.packageListTmp.Add(package);
                    }
                    else
                    {
                        if (package.PackageFormat.ID == DssRoot.DSS_CTRL_SETUP_STEP_MSG_END &&
                            package.ReadInt(0) == this.stepID)
                        {
                            /// Finished
                            this.packageList = this.packageListTmp.ToArray();
                            this.state       = SetupStepState.READY;
                        }
                        else
                        {
                            /// Error
                            this.state = SetupStepState.ERROR;
                        }
                    }
                }
                else /// end-if (this.beginArrived)
                {
                    if (package.PackageFormat.ID == DssRoot.DSS_CTRL_SETUP_STEP_RQ_BEGIN)
                    {
                        /// Read the step ID
                        this.stepID = package.ReadInt(0);

                        /// Read the left-list
                        int[] leftList = package.ReadIntArray(1);
                        bool  err      = false;
                        for (int i = 0; i < leftList.Length; ++i)
                        {
                            if (leftList[i] < 0)
                            {
                                err = true;
                                break;
                            }
                        }
                        if (!err)
                        {
                            /// OK, save the list
                            this.leftList = leftList;
                        }
                        else
                        {
                            /// Error
                            this.state = SetupStepState.ERROR;
                            return;
                        }

                        /// Read the lost-list
                        int[] lostList = package.ReadIntArray(2);
                        err = false;
                        for (int i = 0; i < lostList.Length; ++i)
                        {
                            if (lostList[i] < 0)
                            {
                                err = true;
                                break;
                            }
                        }
                        if (!err)
                        {
                            /// OK, save the list
                            this.lostList = lostList;
                        }
                        else
                        {
                            /// Error
                            this.state = SetupStepState.ERROR;
                            return;
                        }

                        /// Read the channel-state-list
                        byte[] chStateBytes = package.ReadByteArray(3);
                        if (chStateBytes.Length != 0)
                        {
                            this.channelStateList = new DssChannelState[chStateBytes.Length];
                            for (int i = 0; i < chStateBytes.Length; ++i)
                            {
                                if (chStateBytes[i] == (byte)DssChannelState.CHANNEL_CLOSED ||
                                    chStateBytes[i] == (byte)DssChannelState.CHANNEL_OPENED ||
                                    chStateBytes[i] == (byte)DssChannelState.GUEST_CONNECTED)
                                {
                                    this.channelStateList[i] = (DssChannelState)chStateBytes[i];
                                }
                                else
                                {
                                    /// Error
                                    this.state = SetupStepState.ERROR;
                                    return;
                                }
                            }
                        } /// end-if (chStateBytes != null && chStateBytes.Length != 0)
                        else
                        {
                            /// Error
                            this.state = SetupStepState.ERROR;
                            return;
                        }

                        /// Everything is OK, the begin message arrived successfully.
                        this.beginArrived = true;
                    }
                    else /// end-if (package.PackageFormat.ID == DssRoot.DSS_CTRL_SETUP_STEP_RQ_BEGIN)
                    {
                        /// Error
                        this.state = SetupStepState.ERROR;
                    }
                }
            }
        }