Beispiel #1
0
        /// <summary>
        /// Creates an RCCommand object from the given RCPackage.
        /// </summary>
        /// <param name="cmdPackage">The RCPackage to be deserialized.</param>
        /// <returns>The created RCCommand.</returns>
        public static RCCommand FromPackage(RCPackage cmdPackage)
        {
            if (cmdPackage == null)
            {
                throw new ArgumentNullException("cmdPackage");
            }
            if (!cmdPackage.IsCommitted)
            {
                throw new ArgumentException("The incoming package is not committed!", "cmdPackage");
            }
            if (cmdPackage.PackageFormat.ID != RCCommand.COMMAND_PACKAGEFORMAT)
            {
                throw new ArgumentException("The incoming package is not a command package!", "cmdPackage");
            }

            RCNumVector targetPosition  = RCNumVector.Undefined;
            int         targetPositionX = cmdPackage.ReadInt(2);
            int         targetPositionY = cmdPackage.ReadInt(3);

            if (targetPositionX != -1 && targetPositionY != -1)
            {
                targetPosition = new RCNumVector(new RCNumber(targetPositionX), new RCNumber(targetPositionY));
            }

            return(new RCCommand(
                       cmdPackage.ReadString(0),
                       cmdPackage.ReadIntArray(1),
                       targetPosition,
                       cmdPackage.ReadInt(4),
                       cmdPackage.ReadString(5)));
        }
Beispiel #2
0
        /// <see cref="IScenarioLoader.LoadScenario"/>
        public Scenario LoadScenario(IMapAccess map, byte[] data)
        {
            if (map == null)
            {
                throw new ArgumentNullException("map");
            }
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            /// Load the packages from the byte array.
            int      offset   = 0;
            Scenario scenario = new Scenario(map);

            while (offset < data.Length)
            {
                int       parsedBytes;
                RCPackage package = RCPackage.Parse(data, offset, data.Length - offset, out parsedBytes);
                if (package == null || !package.IsCommitted)
                {
                    throw new SimulatorException("Syntax error!");
                }
                offset += parsedBytes;
                if (package.PackageFormat.ID == ScenarioFileFormat.MINERAL_FIELD)
                {
                    IQuadTile    quadTile     = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1)));
                    MineralField mineralField = new MineralField();
                    mineralField.ResourceAmount.Write(package.ReadInt(2));
                    scenario.AddElementToScenario(mineralField);
                    mineralField.AttachToMap(quadTile);
                }
                else if (package.PackageFormat.ID == ScenarioFileFormat.VESPENE_GEYSER)
                {
                    IQuadTile     quadTile      = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1)));
                    VespeneGeyser vespeneGeyser = new VespeneGeyser();
                    vespeneGeyser.ResourceAmount.Write(package.ReadInt(2));
                    scenario.AddElementToScenario(vespeneGeyser);
                    vespeneGeyser.AttachToMap(quadTile);
                }
                else if (package.PackageFormat.ID == ScenarioFileFormat.START_LOCATION)
                {
                    IQuadTile     quadTile      = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1)));
                    StartLocation startLocation = new StartLocation(package.ReadByte(2));
                    scenario.AddElementToScenario(startLocation);
                    startLocation.AttachToMap(quadTile);
                }
            }

            /// Check the constraints of the visible entities.
            foreach (Entity entity in scenario.GetElementsOnMap <Entity>(MapObjectLayerEnum.GroundObjects, MapObjectLayerEnum.AirObjects))
            {
                if (entity.CheckPlacementConstraints(entity.MapObject.QuadraticPosition.Location, new RCSet <Entity>()).Count != 0)
                {
                    throw new MapException(string.Format("Entity at {0} is voilating its placement constraints!", entity.MapObject.QuadraticPosition.Location));
                }
            }
            return(scenario);
        }
Beispiel #3
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 #4
0
        /// <summary>
        /// Creates a MapHeader structure from the given RCPackage.
        /// </summary>
        /// <param name="package">The RCPackage that contains the map header informations.</param>
        /// <returns>The created MapHeader structure.</returns>
        public static MapHeader FromPackage(RCPackage package)
        {
            if (package == null)
            {
                throw new ArgumentNullException("package");
            }
            if (!package.IsCommitted)
            {
                throw new ArgumentException("The header package is not committed!", "package");
            }
            if (package.PackageType != RCPackageType.CUSTOM_DATA_PACKAGE)
            {
                throw new ArgumentException("Invalid package type!", "package");
            }
            if (package.PackageFormat.ID != MapFileFormat.MAP_HEADER)
            {
                throw new ArgumentException("Invalid package format!", "package");
            }

            MapHeader header = new MapHeader();

            header.appVersion   = new Version(package.ReadInt(0), package.ReadInt(1), package.ReadInt(2), package.ReadInt(3));
            header.mapName      = package.ReadString(4);
            header.tilesetName  = package.ReadString(5);
            header.mapSize      = new RCIntVector(package.ReadShort(6), package.ReadShort(7));
            header.maxPlayers   = package.ReadByte(8);
            header.checksumList = new List <int>(package.ReadIntArray(9));

            if (header.mapName == null)
            {
                throw new MapException("Map name information is missing!");
            }
            if (header.tilesetName == null)
            {
                throw new MapException("Tileset name information is missing!");
            }
            if (header.mapSize.X <= 0 || header.mapSize.Y <= 0)
            {
                throw new MapException("Map size cannot be negative or 0!");
            }
            if (header.maxPlayers <= 0)
            {
                throw new MapException("Maximum number of players cannot be negative or 0!");
            }
            return(header);
        }
        /// <summary>
        /// Registers the given commit answer arrived from the given operator.
        /// </summary>
        /// <param name="commit">The arrived commit answer package.</param>
        /// <param name="senderID">The sender operator.</param>
        /// <returns>True in case of success, false otherwise.</returns>
        public bool RegisterCommitAnswer(RCPackage commitAw, 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 (commitAw == null || !commitAw.IsCommitted)
            {
                throw new ArgumentException("commitAw");
            }
            if (senderID == this.root.IdOfThisPeer)
            {
                throw new DssException("Unexpected commit answer sender!");
            }
            if (senderID < 0 || senderID >= this.root.OpCount)
            {
                throw new ArgumentException("senderID");
            }

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

            int ticket = commitAw.ReadInt(0);

            if (!this.commitAwMonitors.ContainsKey(ticket))
            {
                /// Unexpected ticket.
                return(false);
            }

            CommitMonitor monitor  = this.commitAwMonitors[ticket];
            int           pingTime = -1;

            if (monitor.AnswerArrived(senderID, out pingTime))
            {
                this.aptCalculators[senderID].NewItem(pingTime);
                if (monitor.IsCommitAnswered)
                {
                    UnregisterCommitMonitor(ticket);
                }
                return(true);
            }
            else
            {
                /// Ping already answered by the sender.
                return(false);
            }
        }
Beispiel #6
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 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>
 /// Called when a control packages arrived from the host during setup stage.
 /// </summary>
 /// <param name="package">The arrived control package.</param>
 public void SetupStageCtrlPackage(RCPackage package)
 {
     if (this.sm.CurrentState == this.WaitingConnectionACK)
     {
         if (package.PackageFormat.ID == DssRoot.DSS_CTRL_CONN_ACK)
         {
             int otherMajor    = package.ReadInt(0);
             int otherMinor    = package.ReadInt(1);
             int otherBuild    = package.ReadInt(2);
             int otherRevision = package.ReadInt(3);
             if (otherMajor >= 0 && otherMinor >= 0 && otherBuild >= 0 && otherRevision >= 0)
             {
                 Version otherVer = new Version(otherMajor, otherMinor, otherBuild, otherRevision);
                 if (DssRoot.IsCompatibleVersion(otherVer))
                 {
                     this.WaitingConnectionACK_WaitingSetupStepRQ.Fire();
                     this.controller.ExecuteFirings();
                     return;
                 }
                 else
                 {
                     TraceManager.WriteAllTrace(string.Format("Incompatible with host version: {0} (RC.DssServices)", otherVer), DssTraceFilters.SETUP_STAGE_ERROR);
                     SetupStageError();
                     return;
                 }
             }
             else
             {
                 TraceManager.WriteAllTrace("Unable to parse version information!", DssTraceFilters.SETUP_STAGE_ERROR);
                 SetupStageError();
                 return;
             }
         } /// end-if (package.PackageFormat.ID == DssRoot.DSS_CTRL_CONN_ACK)
         else if (package.PackageFormat.ID == DssRoot.DSS_CTRL_CONN_REJECT)
         {
             TraceManager.WriteAllTrace(string.Format("Connection request rejected by the host! Reason: {0}", package.ReadString(0)), DssTraceFilters.SETUP_STAGE_ERROR);
             SetupStageError();
             return;
         }
         else
         {
             TraceManager.WriteAllTrace("Unexpected answer from host to connection request!", DssTraceFilters.SETUP_STAGE_ERROR);
             SetupStageError();
             return;
         }
     }
     else if (this.sm.CurrentState == this.WaitingSetupStepRQ)
     {
         if (package.PackageFormat.ID == DssRoot.DSS_LEAVE)
         {
             /// The host left the DSS
             this.guestRoot.SetupIface.HostLeftDss();
             StopTimeouts();
             this.guestRoot.EventQueue.ExitEventLoop();
             return;
         } /// end-if (package.PackageFormat.ID == DssRoot.DSS_LEAVE)
         else if (package.PackageFormat.ID == DssRoot.DSS_CTRL_DROP_GUEST)
         {
             /// The current guest has been dropped out of the DSS by the host.
             this.guestRoot.SetupIface.DroppedByHost();
             StopTimeouts();
             this.guestRoot.EventQueue.ExitEventLoop();
             return;
         } /// end-if (package.PackageFormat.ID == DssRoot.DSS_CTRL_DROP_GUEST)
         else if (package.PackageFormat.ID == DssRoot.DSS_CTRL_START_SIMULATION)
         {
             int[]  leftList = null;
             int[]  lostList = null;
             bool[] opFlags  = null;
             if (ParseStartSimPackage(package, out leftList, out lostList, out opFlags))
             {
                 StopTimeouts();
                 CallNotificationMethods(leftList, lostList);
                 this.guestRoot.SetupIface.SimulationStarted();
                 this.opFlagsTmp = opFlags;
                 this.WaitingSetupStepRQ_Simulating.Fire();
                 this.controller.ExecuteFirings();
                 return;
             }
             else
             {
                 SetupStageError();
                 return;
             }
         } /// end-if (package.PackageFormat.ID == DssRoot.DSS_CTRL_START_SIMULATION)
         else
         {
             this.guestRoot.Step.IncomingPackage(package);
             if (this.guestRoot.Step.State == SetupStepState.READY)
             {
                 /// Setup step request arrived.
                 this.WaitingSetupStepRQ_SendingSetupStepAW.Fire();
                 this.controller.ExecuteFirings();
                 return;
             }
             else if (this.guestRoot.Step.State == SetupStepState.ERROR)
             {
                 /// Setup step request error.
                 SetupStageError();
                 return;
             }
             else
             {
                 /// Setup step request not finished yet, more packages to wait.
                 return;
             }
         }
     } /// end-if (this.sm.CurrentState == this.WaitingSetupStepRQ)
     else
     {
         /// Go to error state if the package cannot be handled until now.
         SetupStageError();
         return;
     }
 }
Beispiel #9
0
        /// <summary>
        /// This function is called when a control package arrives at setup stage.
        /// </summary>
        /// <param name="package">The arrived control package.</param>
        public void SetupStageCtrlPackage(RCPackage package)
        {
            bool error = false;

            if (this.sm.CurrentState == this.WaitingConnectionRQ)
            {
                if (package.PackageFormat.ID == DssRoot.DSS_CTRL_CONN_REQUEST)
                {
                    RCPackage rejPackage    = null;
                    int       otherMajor    = package.ReadInt(0);
                    int       otherMinor    = package.ReadInt(1);
                    int       otherBuild    = package.ReadInt(2);
                    int       otherRevision = package.ReadInt(3);
                    if (otherMajor >= 0 && otherMinor >= 0 && otherBuild >= 0 && otherRevision >= 0)
                    {
                        Version otherVer = new Version(otherMajor, otherMinor, otherBuild, otherRevision);
                        if (DssRoot.IsCompatibleVersion(otherVer))
                        {
                            /// We send back a DSS_CTRL_CONN_ACK package.
                            RCPackage ackPackage = RCPackage.CreateNetworkControlPackage(DssRoot.DSS_CTRL_CONN_ACK);
                            ackPackage.WriteInt(0, DssRoot.APPLICATION_VERSION.Major);
                            ackPackage.WriteInt(1, DssRoot.APPLICATION_VERSION.Minor);
                            ackPackage.WriteInt(2, DssRoot.APPLICATION_VERSION.Build);
                            ackPackage.WriteInt(3, DssRoot.APPLICATION_VERSION.Revision);

                            this.manager.HostRoot.Lobby.SendControlPackage(ackPackage, this.channel.Index + 1);
                            this.WaitingConnectionRQ_SendingSetupStepRQ.Fire();
                        }
                        else
                        {
                            /// We send back a DSS_CTRL_CONN_REJECT package
                            rejPackage = RCPackage.CreateNetworkControlPackage(DssRoot.DSS_CTRL_CONN_REJECT);
                            string reason = string.Format("Incompatible with host version: {0} (RC.DssServices)",
                                                          DssRoot.APPLICATION_VERSION.ToString());
                            rejPackage.WriteString(0, reason);
                            rejPackage.WriteByteArray(1, new byte[0]);
                        }
                    }
                    else
                    {
                        /// We create a DSS_CTRL_CONN_REJECT package
                        rejPackage = RCPackage.CreateNetworkControlPackage(DssRoot.DSS_CTRL_CONN_REJECT);
                        rejPackage.WriteString(0, "Unable to parse version information!");
                        rejPackage.WriteByteArray(1, new byte[0]);
                    }


                    /// We send back a DSS_CTRL_CONN_REJECT package if necessary.
                    if (rejPackage != null && rejPackage.IsCommitted)
                    {
                        this.manager.HostRoot.Lobby.SendControlPackage(rejPackage, this.channel.Index + 1);

                        error = true;
                    }
                } /// end-if (package.PackageFormat.ID == DssRoot.DSS_CTRL_CONN_REQUEST)
            }     /// end-if (this.sm.CurrentState == this.WaitingConnectionRQ)
            else if (this.sm.CurrentState == this.WaitingSetupStepAW)
            {
                if (package.PackageFormat.ID == DssRoot.DSS_LEAVE)
                {
                    string leaveReason = package.ReadString(0);
                    string trcMsg      = string.Format("Guest-{0} has left the DSS. Reason: {1}",
                                                       this.channel.Index,
                                                       leaveReason.Length != 0 ? leaveReason : "-");
                    TraceManager.WriteAllTrace(trcMsg, DssTraceFilters.SETUP_STAGE_INFO);
                    this.WaitingSetupStepAW_Inactive.Fire();
                    this.channel.GuestLeaveSetupStage();
                } /// end-if (package.PackageFormat.ID == DssRoot.DSS_LEAVE)
                else
                {
                    SetupStep currentStep = this.manager.HostRoot.GetStep(this.channel.Index);
                    currentStep.IncomingPackage(package);
                    if (currentStep.State == SetupStepState.READY)
                    {
                        /// Setup step answer arrived.
                        this.WaitingSetupStepAW_SendingSetupStepRQ.Fire();
                    }
                    else if (currentStep.State == SetupStepState.ERROR)
                    {
                        /// Setup step answer error.
                        error = true;
                    }
                    else
                    {
                        /// Setup step answer not finished yet, more packages to wait.
                    }
                }
            } /// end-if (this.sm.CurrentState == this.WaitingSetupStepAW)

            if (error)
            {
                /// Go to error state if the package cannot be handled until now.
                SetupStageError();
                this.channel.SetupStageError();
                return;
            }
        }
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;
                    }
                }
            }
        }