/// <summary> /// Internal function to reset the SetupStep objects of all channels. /// </summary> private void ResetSteps() { for (int i = 0; i < this.sessions.Length; i++) { SetupStep currStep = this.hostRoot.GetStep(i); if (currStep.State == SetupStepState.READY || currStep.State == SetupStepState.ERROR) { currStep.Reset(); } } }
/// <summary> /// Sends the setup step answer to the host. /// </summary> private void ContinueSetup() { /// Send the answer packages. SetupStep currStep = this.guestRoot.Step; RCPackage[] packagesToSend = currStep.CreateAnswer(this.channelProxy.OutgoingPackages != null ? this.channelProxy.OutgoingPackages : new RCPackage[0] { }); currStep.Reset(); foreach (RCPackage pckg in packagesToSend) { this.guestRoot.Lobby.SendControlPackage(pckg); } /// Trigger the session state machine. this.SendingSetupStepAW_WaitingSetupStepRQ.Fire(); }
/// <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; } }
/// <summary> /// Sends the setup step requests to the guests, perform the tasks initiated by the client module and /// send the SMC to waiting state. /// </summary> private void ContinueSetup() { this.SetupStepTimerInactive_Running.Fire(); this.SendingSetupStepRQs_WaitingSetupStepAWs.Fire(); /// First handle the channels where drop happened. for (int i = 0; i < this.channelProxies.Length; i++) { if (this.channelProxies[i].TaskToPerform == DssChannelTask.DROP_AND_OPEN || this.channelProxies[i].TaskToPerform == DssChannelTask.DROP_AND_CLOSE) { /// Drop guest and close channel if necessary. this.channels[i].DropGuest(this.channelProxies[i].TaskToPerform == DssChannelTask.DROP_AND_OPEN); this.hostRoot.GuestLeftDss(i); } } /// Then handle any other channels. for (int i = 0; i < this.sessions.Length; i++) { if (this.channelProxies[i].TaskToPerform == DssChannelTask.CLOSE) { /// Close the channel. this.channels[i].CloseChannel(); } else if (this.channelProxies[i].TaskToPerform == DssChannelTask.OPEN) { /// Open the channel. this.channels[i].OpenChannel(); } else if (this.channelProxies[i].TaskToPerform != DssChannelTask.DROP_AND_OPEN && this.channelProxies[i].TaskToPerform != DssChannelTask.DROP_AND_CLOSE) { /// No task to perform on the channel just send the setup step request. if (this.channels[i].CurrentState == this.channels[i].Engaged) { SetupStep currStep = this.hostRoot.GetStep(i); if (currStep.State == SetupStepState.READY || currStep.State == SetupStepState.ERROR) { currStep.Reset(); } DssChannelState[] chStates = new DssChannelState[this.channels.Length]; for (int j = 0; j < channels.Length; j++) { if (this.channelProxies[j].TaskToPerform == DssChannelTask.OPEN || this.channelProxies[j].TaskToPerform == DssChannelTask.DROP_AND_OPEN) { chStates[j] = DssChannelState.CHANNEL_OPENED; } else if (this.channelProxies[j].TaskToPerform == DssChannelTask.CLOSE || this.channelProxies[j].TaskToPerform == DssChannelTask.DROP_AND_CLOSE) { chStates[j] = DssChannelState.CHANNEL_CLOSED; } else { if (this.channels[j].CurrentState == this.channels[j].Opened) { chStates[j] = DssChannelState.CHANNEL_OPENED; } else if (this.channels[j].CurrentState == this.channels[j].Closed) { chStates[j] = DssChannelState.CHANNEL_CLOSED; } else if (this.channels[j].CurrentState == this.channels[j].Engaged) { chStates[j] = DssChannelState.GUEST_CONNECTED; } else { throw new DssException("Unexpected channel state!"); } } } int[] leftList = null; int[] lostList = null; this.hostRoot.GetGuestEvents(out leftList, out lostList); RCPackage[] packagesToSend = currStep.CreateRequest(this.channelProxies[i].OutgoingPackages != null ? this.channelProxies[i].OutgoingPackages : new RCPackage[0] { }, leftList, lostList, chStates); foreach (RCPackage pckg in packagesToSend) { this.hostRoot.Lobby.SendControlPackage(pckg, i + 1); } this.sessions[i].SetupStepRequestSent(); } } } /// end-for (int i = 0; i < this.channelProxies.Length; i++) }
/// <summary> /// This function is called by the SMC framework when the DSS-manager has to call the setup interface /// of the client module. /// </summary> /// <param name="state"></param> private void CallClientModuleSetupIface(ISMState state) { if (state == this.SendingSetupStepRQs) { TraceManager.WriteAllTrace("Calling IDssHostSetup.ExecuteNextStep on client module.", DssTraceFilters.SETUP_STAGE_INFO); /// Unlock the channel interfaces for the client module. IDssGuestChannel[] channelIfaces = this.DssChannelIfaces; for (int i = 0; i < this.channels.Length; i++) { if (this.channels[i].CurrentState == this.channels[i].Opened) { this.channelProxies[i].UnlockForClient(null, DssChannelState.CHANNEL_OPENED); } else if (this.channels[i].CurrentState == this.channels[i].Closed) { this.channelProxies[i].UnlockForClient(null, DssChannelState.CHANNEL_CLOSED); } else if (this.channels[i].CurrentState == this.channels[i].Engaged) { SetupStep currStep = this.hostRoot.GetStep(i); this.channelProxies[i].UnlockForClient(currStep.StepPackageList, DssChannelState.GUEST_CONNECTED); } else { throw new DssException("Unexpected channel state!"); } } /// Calling the client module for setup step execution. DssSetupResult result = this.hostRoot.SetupIface.ExecuteNextStep(channelIfaces); /// Lock the channel interfaces. for (int i = 0; i < this.channels.Length; i++) { this.channelProxies[i].Lock(); } /// Evaluate the result of the setup step execution. if (result == DssSetupResult.CONTINUE_SETUP) { ContinueSetup(); } else if (result == DssSetupResult.LEAVE_DSS) { LeaveDss(); } else if (result == DssSetupResult.START_SIMULATION) { StartSimulation(); } else { throw new DssException("Unexpected answer from client module!"); } } else { throw new DssException("Unexpected state!"); } }