예제 #1
0
        /// <summary>
        /// Constructs a DssSimulationMgr object.
        /// </summary>
        /// <param name="root">The root object.</param>
        public DssSimulationMgr(DssRoot root)
        {
            if (root == null)
            {
                throw new ArgumentNullException("root");
            }

            this.initialized = false;
            this.hostLeft    = false;

            this.root           = root;
            this.aftCalculator  = null;
            this.aptCalculators = null;

            this.currentRound      = null;
            this.nextRound         = null;
            this.nextNextRound     = null;
            this.nextNextNextRound = null;
            this.waitingForCommit  = false;

            this.commitTimeoutClock   = null;
            this.simulationFrameClock = null;

            this.commitAwMonitors = null;
            this.commitAwTimeouts = null;

            this.operatorFlags = null;
        }
예제 #2
0
        /// <see cref="IDisposable.Dispose"/>
        public void Dispose()
        {
            Dispose_i();

            this.simulationMgr.Dispose();
            this.alarmClockMgr.Dispose();
            this.eventQueue.Dispose();
            instance = null;
        }
예제 #3
0
        /// <summary>
        /// Call this function if a list of commands has been arrived from the given operator in the given frame.
        /// </summary>
        /// <param name="theCommands">List of the arrived commands.</param>
        /// <param name="opIdx">The index of the sender operator.</param>
        /// <param name="frameIdx">The index of the frame of the commands.</param>
        /// <returns>True in case of success, false otherwise.</returns>
        public bool Command(RCPackage[] theCommands, int opIdx, int frameIdx)
        {
            if (theCommands == null || theCommands.Length == 0)
            {
                throw new ArgumentNullException("theCommands");
            }
            if (opIdx < 0 || opIdx >= this.commitFlags.Length)
            {
                throw new ArgumentOutOfRangeException("opIdx");
            }
            if (frameIdx < 0 || frameIdx >= this.simulatorCommands.Length)
            {
                throw new ArgumentOutOfRangeException("frameNum");
            }

            for (int i = 0; i < theCommands.Length; i++)
            {
                if (theCommands[i] == null || !theCommands[i].IsCommitted ||
                    theCommands[i].PackageType != RCPackageType.CUSTOM_DATA_PACKAGE ||
                    DssRoot.IsInternalFormat(theCommands[i].PackageFormat))
                {
                    return(false);
                }
            }

            if (this.initialized)
            {
                if (!this.commitFlags[opIdx])
                {
                    if (this.simulatorCommands[frameIdx][opIdx] == null)
                    {
                        this.simulatorCommands[frameIdx][opIdx] = theCommands;
                        return(true);
                    }
                    else
                    {
                        /// Command list has been already sent by the given operator for the given frame.
                        return(false);
                    }
                }
                else
                {
                    /// The round has been already committed by the sender operator --> error.
                    return(false);
                }
            }
            else
            {
                throw new DssException("Uninitialized SimulationRound!");
            }
        }
예제 #4
0
        /// <summary>
        /// Creates an answer to the current setup step at guest side.
        /// </summary>
        /// <param name="outgoingPackages">The outgoing packages sent by the client module.</param>
        /// <returns>List of the packages of the outgoing setup step answer.</returns>
        /// <remarks>This function must be called at guest side.</remarks>
        public RCPackage[] CreateAnswer(RCPackage[] outgoingPackages)
        {
            if (this.mode != DssMode.GUEST_SIDE)
            {
                throw new DssException("This call is only allowed at guest side!");
            }
            if (this.state != SetupStepState.READY)
            {
                throw new DssException("You can only create answer in READY state!");
            }
            if (outgoingPackages == null)
            {
                throw new ArgumentNullException("outgoingPackages");
            }

            int numPackages = outgoingPackages.Length + 2; /// BEGIN, END

            RCPackage[] retList = new RCPackage[numPackages];
            for (int i = 0; i < numPackages; i++)
            {
                if (i == 0)         /// BEGIN
                {
                    retList[i] = RCPackage.CreateNetworkControlPackage(DssRoot.DSS_CTRL_SETUP_STEP_AW_BEGIN);
                    retList[i].WriteInt(0, this.stepID);
                }
                else if (i == numPackages - 1)  /// END
                {
                    retList[i] = RCPackage.CreateNetworkControlPackage(DssRoot.DSS_CTRL_SETUP_STEP_MSG_END);
                    retList[i].WriteInt(0, this.stepID);
                }
                else    /// Package from the client module
                {
                    if (outgoingPackages[i - 1] != null && outgoingPackages[i - 1].IsCommitted &&
                        outgoingPackages[i - 1].PackageType == RCPackageType.NETWORK_CONTROL_PACKAGE &&
                        !DssRoot.IsInternalFormat(outgoingPackages[i - 1].PackageFormat))
                    {
                        retList[i] = outgoingPackages[i - 1];
                    }
                    else
                    {
                        throw new DssException("Outgoing setup package format error!");
                    }
                }
            } /// end-for

            return(retList);
        }
예제 #5
0
        /// <summary>
        /// Internal function to timestamp and send the given commands to the lobby.
        /// </summary>
        /// <param name="cmds">The list of the commands to send.</param>
        private void SendCommandsToLobby(RCPackage[] cmds)
        {
            if (!this.initialized)
            {
                throw new DssException("DssSimulationMgr is uninitialized!");
            }
            if (cmds != null && cmds.Length != 0)
            {
                /// Compute the length of the buffer needed for sending the commands as a byte sequence
                int bufferLength = 0;
                for (int i = 0; i < cmds.Length; i++)
                {
                    if (cmds[i] != null && cmds[i].IsCommitted && cmds[i].PackageType == RCPackageType.CUSTOM_DATA_PACKAGE &&
                        !DssRoot.IsInternalFormat(cmds[i].PackageFormat))
                    {
                        bufferLength += cmds[i].PackageLength;
                    }
                    else
                    {
                        throw new DssException("Unexpected command from the client module!");
                    }
                }

                /// Create the buffer and write the commands into this buffer
                byte[] cmdBuffer = new byte[bufferLength];
                int    offset    = 0;
                for (int i = 0; i < cmds.Length; i++)
                {
                    offset += cmds[i].WritePackageToBuffer(cmdBuffer, offset);
                }

                /// Create the DSS_COMMAND package and send it to the lobby
                RCPackage cmdPackage = RCPackage.CreateNetworkCustomPackage(DssRoot.DSS_COMMAND);
                cmdPackage.WriteInt(0, this.nextNextRound.RoundIndex);       /// Round index of the command
                cmdPackage.WriteInt(1, this.currentRound.CurrentFrameIndex); /// Frame index of the command
                cmdPackage.WriteByteArray(2, cmdBuffer);                     /// The command list

                this.root.LobbyIface.SendPackage(cmdPackage);                /// Send the command package to the lobby
            }
        }
예제 #6
0
        /// <summary>
        /// Constructs a DssRoot object.
        /// </summary>
        /// <param name="simulatorIface">Interface of the simulator in the client module.</param>
        /// <exception cref="DssException">If another instance of this class exists.</exception>
        public DssRoot(ISimulator simulatorIface)
        {
            if (instance != null)
            {
                throw new DssException("Another instance of DssRoot already exists!");
            }

            this.simulatorIface = simulatorIface;
            this.eventQueue     = new DssEventQueue();
            this.alarmClockMgr  = new AlarmClockManager(this.eventQueue);
            this.idOfThisPeer   = -1;
            this.opCount        = -1;
            this.lobbyIface     = null;
            this.simulationMgr  = new DssSimulationMgr(this);

            this.lifeTimer = new Stopwatch();
            this.lifeTimer.Start();

            instance = this;

            TraceManager.WriteAllTrace("DssRoot successfully created.", DssTraceFilters.SETUP_STAGE_INFO);
        }
예제 #7
0
 /// <summary>
 /// Constructs a DssEventHandler object.
 /// </summary>
 public DssEventHandler(DssRoot root)
 {
     this.root = root;
 }
예제 #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;
     }
 }
예제 #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;
            }
        }
예제 #10
0
        /// <summary>
        /// Starts a new setup step at host side.
        /// </summary>
        /// <param name="outgoingPackages">The outgoing packages sent by the client module.</param>
        /// <param name="leftList">List of the guests that left or were dropped from the DSS.</param>
        /// <param name="lostList">List of the guests that the host left connection with.</param>
        /// <param name="channelStates">The current state of the channels.</param>
        /// <returns>List of the packages of the outgoing setup step request.</returns>
        /// <remarks>This function must be called at host side.</remarks>
        public RCPackage[] CreateRequest(RCPackage[] outgoingPackages,
                                         int[] leftList,
                                         int[] lostList,
                                         DssChannelState[] channelStates)
        {
            if (this.mode != DssMode.HOST_SIDE)
            {
                throw new DssException("This call is only allowed at host side!");
            }
            if (this.state != SetupStepState.NOT_FINISHED)
            {
                throw new DssException("Invalid setup step state!");
            }
            if (channelStates == null || channelStates.Length < 1)
            {
                throw new ArgumentNullException("channelStates");
            }
            if (outgoingPackages == null)
            {
                throw new ArgumentNullException("outgoingPackages");
            }

            int numPackages = outgoingPackages.Length + 2; /// BEGIN, END

            RCPackage[] retList = new RCPackage[numPackages];
            for (int i = 0; i < numPackages; i++)
            {
                if (i == 0)         /// BEGIN
                {
                    retList[i] = RCPackage.CreateNetworkControlPackage(DssRoot.DSS_CTRL_SETUP_STEP_RQ_BEGIN);
                    retList[i].WriteInt(0, this.stepID);
                    retList[i].WriteIntArray(1, leftList != null ? leftList : new int[0] {
                    });
                    retList[i].WriteIntArray(2, lostList != null ? lostList : new int[0] {
                    });
                    byte[] stateBytes = new byte[channelStates.Length];
                    for (int j = 0; j < channelStates.Length; j++)
                    {
                        stateBytes[j] = (byte)channelStates[j];
                    }
                    retList[i].WriteByteArray(3, stateBytes);
                }
                else if (i == numPackages - 1)  /// END
                {
                    retList[i] = RCPackage.CreateNetworkControlPackage(DssRoot.DSS_CTRL_SETUP_STEP_MSG_END);
                    retList[i].WriteInt(0, this.stepID);
                }
                else    /// Package from the client module
                {
                    if (outgoingPackages[i - 1] != null && outgoingPackages[i - 1].IsCommitted &&
                        outgoingPackages[i - 1].PackageType == RCPackageType.NETWORK_CONTROL_PACKAGE &&
                        !DssRoot.IsInternalFormat(outgoingPackages[i - 1].PackageFormat))
                    {
                        retList[i] = outgoingPackages[i - 1];
                    }
                    else
                    {
                        throw new DssException("Outgoing setup package format error!");
                    }
                }
            } /// end-for

            return(retList);
        }
예제 #11
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;
                    }
                }
            }
        }