/// <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!"); } }
/// <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); }
/// <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 } }
/// <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); }
/// <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; } } } }