/// <summary>
        /// This method sends the server side capability negotiation packet to the client. 
        /// </summary>
        internal override void SendNegotiationAsync()
        {
            RemoteSessionCapability serverCapability = _session.Context.ServerCapability;
            RemoteDataObject data = RemotingEncoder.GenerateServerSessionCapability(serverCapability,
                Guid.Empty);

            RemoteSessionStateMachineEventArgs negotiationSendCompletedArg =
                new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationSendCompleted);
            _stateMachine.RaiseEvent(negotiationSendCompletedArg);

            RemoteDataObject<PSObject> dataToBeSent = RemoteDataObject<PSObject>.CreateFrom(
                data.Destination, data.DataType, data.RunspacePoolId, data.PowerShellId, (PSObject)data.Data);
            // send data to client..flush is not true as we expect to send state changed
            // information (from runspace creation)
            _transportManager.SendDataToClient<PSObject>(dataToBeSent, false);
        }
        /// <summary>
        /// Processes events in the queue. If there are no
        /// more events to process, then sets eventsInProcess
        /// variable to false. This will ensure that another
        /// thread which raises an event can then take control
        /// of processing the events.
        /// </summary>
        private void ProcessEvents()
        {
            RemoteSessionStateMachineEventArgs eventArgs = null;

            do
            {
                lock (_syncObject)
                {
                    if (_processPendingEventsQueue.Count == 0)
                    {
                        _eventsInProcess = false;
                        break;
                    }

                    eventArgs = _processPendingEventsQueue.Dequeue();
                }

                try
                {
                    RaiseEventPrivate(eventArgs);
                }
                catch (Exception ex)
                {
                    HandleFatalError(ex);
                }

                try
                {
                    RaiseStateMachineEvents();
                }
                catch (Exception ex)
                {
                    HandleFatalError(ex);
                }
            } while (_eventsInProcess);
        }
Пример #3
0
        /// <summary>
        /// This method is used by all classes to raise a FSM event.
        /// The method will queue the event. The event queue will be handled in
        /// a thread safe manner by a single dedicated thread.
        /// </summary>
        /// <param name="arg">
        /// This parameter contains the event to be raised.
        /// </param>
        /// <param name="clearQueuedEvents">
        /// optional bool indicating whether to clear currently queued events
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// If the parameter is null.
        /// </exception>
        internal void RaiseEvent(RemoteSessionStateMachineEventArgs arg, bool clearQueuedEvents = false)
        {
            lock (_syncObject)
            {
                s_trace.WriteLine("Event received : {0} for {1}", arg.StateEvent, _id);
                if (clearQueuedEvents)
                {
                    _processPendingEventsQueue.Clear();
                }

                _processPendingEventsQueue.Enqueue(arg);

                if (!_eventsInProcess)
                {
                    _eventsInProcess = true;
                }
                else
                {
                    return;
                }
            }

            ProcessEvents();
        }
        /// <summary>
        /// This is the handler for NegotiationPending event. 
        /// NegotiationPending state can be in reached in the following cases
        /// 1. From Idle to NegotiationPending (during startup)
        /// 2. From Negotiation(Response)Sent to NegotiationPending.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        private void DoNegotiationPending(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert((_state == RemoteSessionState.Idle) || (_state == RemoteSessionState.NegotiationSent),
                    "DoNegotiationPending can only occur when the state is Idle or NegotiationSent.");

                SetState(RemoteSessionState.NegotiationPending, null);
            }
        }
        /// <summary>
        /// Helper method used by dependents to figure out if the RaiseEvent
        /// method can be short-circuited. This will be useful in cases where
        /// the dependent code wants to take action immediately instead of
        /// going through state machine.
        /// </summary>
        /// <param name="arg"></param>
        internal bool CanByPassRaiseEvent(RemoteSessionStateMachineEventArgs arg)
        {
            if (arg.StateEvent == RemoteSessionEvent.MessageReceived)
            {
                if (_state == RemoteSessionState.Established ||
                    _state == RemoteSessionState.EstablishedAndKeySent || //server session will never be in this state.. TODO- remove this
                    _state == RemoteSessionState.EstablishedAndKeyReceived ||
                    _state == RemoteSessionState.EstablishedAndKeyExchanged)
                {
                    return true;
                }
            }

            return false;
        }
        /// <summary>
        /// This is the private version of raising a FSM event. 
        /// It can only be called by the dedicated thread that processes the event queue.
        /// It calls the event handler
        /// in the right position of the event handling matrix.
        /// </summary>
        /// <param name="fsmEventArg">
        /// The parameter contains the actual FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter is null.
        /// </exception>
        private void RaiseEventPrivate(RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            if (fsmEventArg == null)
            {
                throw PSTraceSource.NewArgumentNullException("fsmEventArg");
            }

            EventHandler<RemoteSessionStateMachineEventArgs> handler = _stateMachineHandle[(int)_state, (int)fsmEventArg.StateEvent];
            if (handler != null)
            {
                s_trace.WriteLine("Before calling state machine event handler: state = {0}, event = {1}", _state, fsmEventArg.StateEvent);

                handler(this, fsmEventArg);

                s_trace.WriteLine("After calling state machine event handler: state = {0}, event = {1}", _state, fsmEventArg.StateEvent);
            }
        }
Пример #7
0
        private void SetStateHandler(object sender, RemoteSessionStateMachineEventArgs eventArgs)
        {
            switch (eventArgs.StateEvent)
            {
            case RemoteSessionEvent.NegotiationSendCompleted:
                this.SetState(RemoteSessionState.NegotiationSent, null);
                return;

            case RemoteSessionEvent.NegotiationReceived:
                if (eventArgs.RemoteSessionCapability == null)
                {
                    throw PSTraceSource.NewArgumentException("eventArgs");
                }
                this.SetState(RemoteSessionState.NegotiationReceived, null);
                return;

            case RemoteSessionEvent.NegotiationCompleted:
                this.SetState(RemoteSessionState.Established, null);
                return;

            case RemoteSessionEvent.NegotiationPending:
            case RemoteSessionEvent.Close:
            case RemoteSessionEvent.KeySendFailed:
            case RemoteSessionEvent.KeyReceiveFailed:
            case RemoteSessionEvent.KeyRequestFailed:
            case RemoteSessionEvent.DisconnectStart:
            case RemoteSessionEvent.ReconnectStart:
                break;

            case RemoteSessionEvent.CloseCompleted:
                this.SetState(RemoteSessionState.Closed, eventArgs.Reason);
                return;

            case RemoteSessionEvent.CloseFailed:
                this.SetState(RemoteSessionState.Closed, eventArgs.Reason);
                return;

            case RemoteSessionEvent.ConnectFailed:
                this.SetState(RemoteSessionState.ClosingConnection, eventArgs.Reason);
                return;

            case RemoteSessionEvent.KeySent:
                if ((this._state != RemoteSessionState.Established) && (this._state != RemoteSessionState.EstablishedAndKeyRequested))
                {
                    break;
                }
                this.SetState(RemoteSessionState.EstablishedAndKeySent, eventArgs.Reason);
                this._keyExchangeTimer           = new System.Timers.Timer();
                this._keyExchangeTimer.AutoReset = false;
                this._keyExchangeTimer.Elapsed  += new ElapsedEventHandler(this.HandleKeyExchangeTimeout);
                this._keyExchangeTimer.Interval  = 180000.0;
                return;

            case RemoteSessionEvent.KeyReceived:
                if (this._state != RemoteSessionState.EstablishedAndKeySent)
                {
                    break;
                }
                if (this._keyExchangeTimer != null)
                {
                    this._keyExchangeTimer.Enabled = false;
                    this._keyExchangeTimer.Dispose();
                    this._keyExchangeTimer = null;
                }
                this.keyExchanged = true;
                this.SetState(RemoteSessionState.Established, eventArgs.Reason);
                if (!this.pendingDisconnect)
                {
                    break;
                }
                this.pendingDisconnect = false;
                this.DoDisconnect(sender, eventArgs);
                return;

            case RemoteSessionEvent.KeyRequested:
                if (this._state != RemoteSessionState.Established)
                {
                    break;
                }
                this.SetState(RemoteSessionState.EstablishedAndKeyRequested, eventArgs.Reason);
                return;

            case RemoteSessionEvent.DisconnectCompleted:
                if ((this._state != RemoteSessionState.Disconnecting) && (this._state != RemoteSessionState.RCDisconnecting))
                {
                    break;
                }
                this.SetState(RemoteSessionState.Disconnected, eventArgs.Reason);
                return;

            case RemoteSessionEvent.DisconnectFailed:
                if (this._state != RemoteSessionState.Disconnecting)
                {
                    break;
                }
                this.SetState(RemoteSessionState.Disconnected, eventArgs.Reason);
                return;

            case RemoteSessionEvent.ReconnectCompleted:
                if (this._state == RemoteSessionState.Reconnecting)
                {
                    this.SetState(RemoteSessionState.Established, eventArgs.Reason);
                }
                break;

            default:
                return;
            }
        }
Пример #8
0
 private void DoFatal(object sender, RemoteSessionStateMachineEventArgs eventArgs) => this.RaiseEvent(new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close, (Exception) new PSRemotingDataStructureException(eventArgs.Reason, PSRemotingErrorId.FatalErrorCausingClose, new object[0])));
        /// <summary>
        /// This is the handler for ConnectFailed event. In this implementation, this should never
        /// happen. This is because the IO channel is stdin/stdout/stderr redirection.
        /// Therefore, the connection is a dummy operation.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If the parameter <paramref name="fsmEventArg"/> does not contain ConnectFailed event.
        /// </exception>   
        private void DoConnectFailed(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.ConnectFailed, "StateEvent must be ConnectFailed");

                if (fsmEventArg.StateEvent != RemoteSessionEvent.ConnectFailed)
                {
                    throw PSTraceSource.NewArgumentException("fsmEventArg");
                }

                Dbg.Assert(_state == RemoteSessionState.Connecting, "session State must be Connecting");

                // This method should not be called in this implementation.
                throw PSTraceSource.NewInvalidOperationException();
            }
        }
        /// <summary>
        /// This is the handler for CloseFailed event.
        /// It simply force the new state to be Closed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        private void DoCloseFailed(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.CloseFailed, "StateEvent must be CloseFailed");

                RemoteSessionState stateBeforeTransition = _state;

                SetState(RemoteSessionState.Closed, fsmEventArg.Reason);

                // ignore
                CleanAll();
            }
        }
Пример #11
0
        public override void CreateAsync()
        {
            RemoteSessionStateMachineEventArgs arg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.CreateSession);

            base.SessionDataStructureHandler.StateMachine.RaiseEvent(arg, false);
        }
Пример #12
0
        public override void DisconnectAsync()
        {
            RemoteSessionStateMachineEventArgs arg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.DisconnectStart);

            base.SessionDataStructureHandler.StateMachine.RaiseEvent(arg, false);
        }
Пример #13
0
        /// <summary>
        /// This handler method runs the negotiation algorithm. It decides if the negotiation is succesful,
        /// or fails.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="negotiationEventArg">
        /// This parameter contains the client negotiation capability packet.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="negotiationEventArg"/> is null.
        /// </exception>
        private void HandleNegotiationReceived(object sender, RemoteSessionNegotiationEventArgs negotiationEventArg)
        {
            if (negotiationEventArg == null)
            {
                throw PSTraceSource.NewArgumentNullException("negotiationEventArg");
            }

            try
            {
                Context.ClientCapability = negotiationEventArg.RemoteSessionCapability;
                // This will throw if there is an error running the algorithm
                RunServerNegotiationAlgorithm(negotiationEventArg.RemoteSessionCapability, false);

                // Send server's capability to client.
                RemoteSessionStateMachineEventArgs sendingNegotiationArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationSending);
                SessionDataStructureHandler.StateMachine.RaiseEvent(sendingNegotiationArg);

                // if negotiation succeeded change the state to neg. completed.
                RemoteSessionStateMachineEventArgs negotiationCompletedArg =
                    new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationCompleted);
                SessionDataStructureHandler.StateMachine.RaiseEvent(negotiationCompletedArg);
            }
            catch (PSRemotingDataStructureException dse)
            {
                // Before setting to negotiation failed..send servers capability...that
                // way client can communicate differently if it wants to.
                RemoteSessionStateMachineEventArgs sendingNegotiationArg =
                    new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationSending);
                SessionDataStructureHandler.StateMachine.RaiseEvent(sendingNegotiationArg);

                RemoteSessionStateMachineEventArgs negotiationFailedArg =
                    new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationFailed,
                        dse);
                SessionDataStructureHandler.StateMachine.RaiseEvent(negotiationFailedArg);
            }
        }
Пример #14
0
 /// <summary>
 /// This handles closing of any resource used by this session.
 /// Resources used are RunspacePoolDriver, TransportManager.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="args"></param>
 private void HandleResourceClosing(object sender, EventArgs args)
 {
     RemoteSessionStateMachineEventArgs closeSessionArgs = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close);
     closeSessionArgs.RemoteData = null;
     SessionDataStructureHandler.StateMachine.RaiseEvent(closeSessionArgs);
 }
Пример #15
0
 private void DoDisconnect(object sender, RemoteSessionStateMachineEventArgs arg)
 {
     this.SetState(RemoteSessionState.Disconnecting, null);
 }
Пример #16
0
        internal void DispatchInputQueueData(object sender, RemoteDataEventArgs dataEventArg)
        {
            using (ServerRemoteSession._trace.TraceMethod())
            {
                RemoteDataObject <PSObject> remoteDataObject    = dataEventArg != null ? dataEventArg.ReceivedData : throw ServerRemoteSession._trace.NewArgumentNullException(nameof(dataEventArg));
                RemotingDestination         remotingDestination = remoteDataObject != null ? remoteDataObject.Destination : throw ServerRemoteSession._trace.NewArgumentException(nameof(dataEventArg));
                if ((remotingDestination & this.MySelf) != this.MySelf)
                {
                    throw new PSRemotingDataStructureException(PSRemotingErrorId.RemotingDestinationNotForMe, new object[2]
                    {
                        (object)this.MySelf,
                        (object)remotingDestination
                    });
                }
                RemotingTargetInterface targetInterface = remoteDataObject.TargetInterface;
                RemotingDataType        dataType        = remoteDataObject.DataType;
                switch (targetInterface)
                {
                case RemotingTargetInterface.Session:
                    switch (dataType)
                    {
                    case RemotingDataType.SessionCapability:
                        this._sessionDSHandler.RaiseDataReceivedEvent(dataEventArg);
                        return;

                    case RemotingDataType.CloseSession:
                        this._sessionDSHandler.RaiseDataReceivedEvent(dataEventArg);
                        return;

                    case RemotingDataType.CreateRunspacePool:
                        RemoteSessionStateMachineEventArgs fsmEventArg1 = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.MessageReceived);
                        if (this.SessionDataStructureHandler.StateMachine.CanByPassRaiseEvent(fsmEventArg1))
                        {
                            fsmEventArg1.RemoteData = remoteDataObject;
                            this.SessionDataStructureHandler.StateMachine.DoMessageReceived((object)this, fsmEventArg1);
                            return;
                        }
                        this.SessionDataStructureHandler.StateMachine.RaiseEvent(fsmEventArg1);
                        return;

                    case RemotingDataType.PublicKey:
                        this._sessionDSHandler.RaiseDataReceivedEvent(dataEventArg);
                        return;

                    default:
                        return;
                    }

                case RemotingTargetInterface.RunspacePool:
                case RemotingTargetInterface.PowerShell:
                    RemoteSessionStateMachineEventArgs fsmEventArg2 = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.MessageReceived);
                    if (this.SessionDataStructureHandler.StateMachine.CanByPassRaiseEvent(fsmEventArg2))
                    {
                        fsmEventArg2.RemoteData = remoteDataObject;
                        this.SessionDataStructureHandler.StateMachine.DoMessageReceived((object)this, fsmEventArg2);
                        break;
                    }
                    this.SessionDataStructureHandler.StateMachine.RaiseEvent(fsmEventArg2);
                    break;
                }
            }
        }
Пример #17
0
 /// <summary>
 /// Connects to a existing Remote Session Asynchronously by executing a Connect negotiation algorithm.
 /// </summary>
 public override void ConnectAsync()
 {
     // Raise the connectsession event in statemachine. This start the process of connection and negotiation to an existing remote session
     RemoteSessionStateMachineEventArgs startArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.ConnectSession);
     SessionDataStructureHandler.StateMachine.RaiseEvent(startArg);
 }
        /// <summary>
        /// This is the handler for NegotiationSending event.
        /// It sets the new state to be NegotiationSending, and sends the server side 
        /// negotiation packet by queuing it on the output queue.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>

        private void DoNegotiationSending(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            if (fsmEventArg == null)
            {
                throw PSTraceSource.NewArgumentNullException("fsmEventArg");
            }

            Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.NegotiationSending, "Event must be NegotiationSending");
            Dbg.Assert(_state == RemoteSessionState.NegotiationReceived, "State must be NegotiationReceived");

            SetState(RemoteSessionState.NegotiationSending, null);

            _session.SessionDataStructureHandler.SendNegotiationAsync();
        }
        /// <summary>
        /// This method contains all the logic for handling the state machine
        /// for key exchange. All the different scenarios are covered in this
        /// </summary>
        /// <param name="sender">sender of this event, unused</param>
        /// <param name="eventArgs">event args</param>
        private void DoKeyExchange(object sender, RemoteSessionStateMachineEventArgs eventArgs)
        {
            //There are corner cases with disconnect that can result in client receiving outdated key exchange packets
            //***TODO*** Deal with this on the client side. Key exchange packets should have additional information
            //that identify the context of negotiation. Just like callId in SetMax and SetMinRunspaces messages
            Dbg.Assert(_state >= RemoteSessionState.Established,
                "Key Receving can only be raised after reaching the Established state");

            switch (eventArgs.StateEvent)
            {
                case RemoteSessionEvent.KeyReceived:
                    {
                        //does the server ever start key exchange process??? This may not be required
                        if (_state == RemoteSessionState.EstablishedAndKeyRequested)
                        {
                            // reset the timer
                            Timer tmp = Interlocked.Exchange(ref _keyExchangeTimer, null);
                            if (tmp != null)
                            {
                                tmp.Dispose();
                            }
                        }

                        // the key import would have been done
                        // set state accordingly
                        SetState(RemoteSessionState.EstablishedAndKeyReceived, eventArgs.Reason);

                        // you need to send an encrypted session key to the client
                        _session.SendEncryptedSessionKey();
                    }
                    break;

                case RemoteSessionEvent.KeySent:
                    {
                        if (_state == RemoteSessionState.EstablishedAndKeyReceived)
                        {
                            // key exchange is now complete
                            SetState(RemoteSessionState.EstablishedAndKeyExchanged, eventArgs.Reason);
                        }
                    }
                    break;

                case RemoteSessionEvent.KeyRequested:
                    {
                        if ((_state == RemoteSessionState.Established) || (_state == RemoteSessionState.EstablishedAndKeyExchanged))
                        {
                            // the key has been sent set state accordingly
                            SetState(RemoteSessionState.EstablishedAndKeyRequested, eventArgs.Reason);

                            // start the timer
                            _keyExchangeTimer = new Timer(HandleKeyExchangeTimeout, null, BaseTransportManager.ServerDefaultKeepAliveTimeoutMs, Timeout.Infinite);
                        }
                    }
                    break;

                case RemoteSessionEvent.KeyReceiveFailed:
                    {
                        if ((_state == RemoteSessionState.Established) || (_state == RemoteSessionState.EstablishedAndKeyExchanged))
                        {
                            return;
                        }

                        DoClose(this, eventArgs);
                    }
                    break;

                case RemoteSessionEvent.KeySendFailed:
                    {
                        DoClose(this, eventArgs);
                    }
                    break;
            }
        }
        /// <summary>
        /// This is the handler for the NegotiationCompleted event.
        /// It sets the new state to be Established. It turns off the negotiation timeout timer.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>

        private void DoEstablished(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(_state == RemoteSessionState.NegotiationSent, "State must be NeogtiationReceived");
                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.NegotiationCompleted, "StateEvent must be NegotiationCompleted");

                if (fsmEventArg.StateEvent != RemoteSessionEvent.NegotiationCompleted)
                {
                    throw PSTraceSource.NewArgumentException("fsmEventArg");
                }

                if (_state != RemoteSessionState.NegotiationSent)
                {
                    throw PSTraceSource.NewInvalidOperationException();
                }

                SetState(RemoteSessionState.Established, null);
            }
        }
Пример #21
0
 private void DoDisconnectDuringKeyExchange(object sender, RemoteSessionStateMachineEventArgs arg)
 {
     // set flag to indicate Disconnect request queue up
     _pendingDisconnect = true;
 }
 /// <summary>
 /// Handle connect event - this is raised when a new client tries to connect to an existing session
 /// No changes to state. Calls into the session to handle any post connect operations
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="fsmEventArg"></param>
 private void DoConnect(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
 {
     Dbg.Assert(_state != RemoteSessionState.Idle, "session should not be in idle state when SessionConnect event is queued");
     if ((_state != RemoteSessionState.Closed) && (_state != RemoteSessionState.ClosingConnection))
     {
         _session.HandlePostConnect();
     }
 }
Пример #23
0
        internal void DispatchInputQueueData(object sender, RemoteDataEventArgs dataEventArg)
        {
            if (dataEventArg == null)
            {
                throw PSTraceSource.NewArgumentNullException("dataEventArg");
            }
            RemoteDataObject <PSObject> receivedData = dataEventArg.ReceivedData;

            if (receivedData == null)
            {
                throw PSTraceSource.NewArgumentException("dataEventArg");
            }
            RemotingDestination destination = receivedData.Destination;

            if ((destination & this.MySelf) != this.MySelf)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.RemotingDestinationNotForMe, new object[] { this.MySelf, destination });
            }
            RemotingTargetInterface            targetInterface = receivedData.TargetInterface;
            RemotingDataType                   dataType        = receivedData.DataType;
            RemoteSessionStateMachineEventArgs arg             = null;

            switch (targetInterface)
            {
            case RemotingTargetInterface.Session:
                switch (dataType)
                {
                case RemotingDataType.SessionCapability:
                    this._sessionDSHandler.RaiseDataReceivedEvent(dataEventArg);
                    return;

                case RemotingDataType.CloseSession:
                    this._sessionDSHandler.RaiseDataReceivedEvent(dataEventArg);
                    return;

                case RemotingDataType.CreateRunspacePool:
                    arg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.MessageReceived);
                    if (this.SessionDataStructureHandler.StateMachine.CanByPassRaiseEvent(arg))
                    {
                        arg.RemoteData = receivedData;
                        this.SessionDataStructureHandler.StateMachine.DoMessageReceived(this, arg);
                        return;
                    }
                    this.SessionDataStructureHandler.StateMachine.RaiseEvent(arg);
                    return;

                case RemotingDataType.PublicKey:
                    this._sessionDSHandler.RaiseDataReceivedEvent(dataEventArg);
                    return;
                }
                return;

            case RemotingTargetInterface.RunspacePool:
            case RemotingTargetInterface.PowerShell:
                arg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.MessageReceived);
                if (!this.SessionDataStructureHandler.StateMachine.CanByPassRaiseEvent(arg))
                {
                    this.SessionDataStructureHandler.StateMachine.RaiseEvent(arg);
                    return;
                }
                arg.RemoteData = receivedData;
                this.SessionDataStructureHandler.StateMachine.DoMessageReceived(this, arg);
                return;
            }
        }
        /// <summary>
        /// This is the handler for NegotiationTimeout event.
        /// If the connection is already Established, it ignores this event.
        /// Otherwise, it raises a Close event to trigger a close of the connection.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        private void DoNegotiationTimeout(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.NegotiationTimeout, "StateEvent must be NegotiationTimeout");

                if (_state == RemoteSessionState.Established)
                {
                    // ignore
                    return;
                }

                RemoteSessionStateMachineEventArgs closeArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close);

                RaiseEventPrivate(closeArg);
            }
        }
Пример #25
0
 private void DoDisconnectDuringKeyExchange(object sender, RemoteSessionStateMachineEventArgs arg)
 {
     this.pendingDisconnect = true;
 }
Пример #26
0
        /// <summary>
        /// Restores connection to a disconnected remote session. Negotiation has already been performed before
        /// </summary>
        public override void ReconnectAsync()
        {
            RemoteSessionStateMachineEventArgs startReconnectArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.ReconnectStart);

            SessionDataStructureHandler.StateMachine.RaiseEvent(startReconnectArg);
        }
Пример #27
0
 /// <summary>
 /// Connects to a existing Remote Session Asynchronously by executing a Connect negotiation algorithm
 /// </summary>
 public override void ConnectAsync()
 {
     //Raise the connectsession event in statemachine. This start the process of connection and negotiation to an existing remote session
     RemoteSessionStateMachineEventArgs startArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.ConnectSession);
     SessionDataStructureHandler.StateMachine.RaiseEvent(startArg);
 }
Пример #28
0
        /// <summary>
        /// This is the handler for MessageReceived event. It dispatches the data to various components
        /// that uses the data.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        ///
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If the parameter <paramref name="fsmEventArg"/> does not contain remote data.
        /// </exception>
        internal void DoMessageReceived(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                if (fsmEventArg.RemoteData == null)
                {
                    throw PSTraceSource.NewArgumentException("fsmEventArg");
                }

                Dbg.Assert(_state == RemoteSessionState.Established ||
                           _state == RemoteSessionState.EstablishedAndKeyExchanged ||
                           _state == RemoteSessionState.EstablishedAndKeyReceived ||
                           _state == RemoteSessionState.EstablishedAndKeySent,  //server session will never be in this state.. TODO- remove this
                           "State must be Established or EstablishedAndKeySent or EstablishedAndKeyReceived or EstablishedAndKeyExchanged");

                RemotingTargetInterface targetInterface = fsmEventArg.RemoteData.TargetInterface;
                RemotingDataType        dataType        = fsmEventArg.RemoteData.DataType;

                Guid clientRunspacePoolId;
                ServerRunspacePoolDriver runspacePoolDriver;
                //string errorMessage = null;

                RemoteDataEventArgs remoteDataForSessionArg = null;

                switch (targetInterface)
                {
                case RemotingTargetInterface.Session:
                {
                    switch (dataType)
                    {
                    // GETBACK
                    case RemotingDataType.CreateRunspacePool:
                        remoteDataForSessionArg = new RemoteDataEventArgs(fsmEventArg.RemoteData);
                        _session.SessionDataStructureHandler.RaiseDataReceivedEvent(remoteDataForSessionArg);
                        break;

                    default:
                        Dbg.Assert(false, "Should never reach here");
                        break;
                    }
                }
                break;

                case RemotingTargetInterface.RunspacePool:
                    // GETBACK
                    clientRunspacePoolId = fsmEventArg.RemoteData.RunspacePoolId;
                    runspacePoolDriver   = _session.GetRunspacePoolDriver(clientRunspacePoolId);

                    if (runspacePoolDriver != null)
                    {
                        runspacePoolDriver.DataStructureHandler.ProcessReceivedData(fsmEventArg.RemoteData);
                    }
                    else
                    {
                        s_trace.WriteLine(@"Server received data for Runspace (id: {0}),
                                but the Runspace cannot be found", clientRunspacePoolId);

                        PSRemotingDataStructureException reasonOfFailure = new
                                                                           PSRemotingDataStructureException(RemotingErrorIdStrings.RunspaceCannotBeFound,
                                                                                                            clientRunspacePoolId);
                        RemoteSessionStateMachineEventArgs runspaceNotFoundArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.FatalError, reasonOfFailure);
                        RaiseEvent(runspaceNotFoundArg);
                    }

                    break;

                case RemotingTargetInterface.PowerShell:
                    clientRunspacePoolId = fsmEventArg.RemoteData.RunspacePoolId;
                    runspacePoolDriver   = _session.GetRunspacePoolDriver(clientRunspacePoolId);

                    runspacePoolDriver.DataStructureHandler.DispatchMessageToPowerShell(fsmEventArg.RemoteData);
                    break;

                default:
                    s_trace.WriteLine("Server received data unknown targetInterface: {0}", targetInterface);

                    PSRemotingDataStructureException   reasonOfFailure2 = new PSRemotingDataStructureException(RemotingErrorIdStrings.ReceivedUnsupportedRemotingTargetInterfaceType, targetInterface);
                    RemoteSessionStateMachineEventArgs unknownTargetArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.FatalError, reasonOfFailure2);
                    RaiseEvent(unknownTargetArg);
                    break;
                }
            }
        }
Пример #29
0
 /// <summary>
 /// Closes Session Connection Asynchronously.
 /// </summary>
 /// <remarks>
 /// Caller should register for ConnectionClosed event to get notified
 /// </remarks>
 public override void CloseAsync()
 {
     RemoteSessionStateMachineEventArgs closeArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close);
     SessionDataStructureHandler.StateMachine.RaiseEvent(closeArg);
 }
Пример #30
0
 private void DoNegotiationSending(object sender, RemoteSessionStateMachineEventArgs arg)
 {
     using (ClientRemoteSessionDSHandlerStateMachine._trace.TraceMethod())
         this.SetState(RemoteSessionState.NegotiationSending, (Exception)null);
 }
Пример #31
0
 /// <summary>
 /// Restores connection to a disconnected remote session. Negotiation has already been performed before
 /// </summary>
 public override void ReconnectAsync()
 {
     RemoteSessionStateMachineEventArgs startReconnectArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.ReconnectStart);
     SessionDataStructureHandler.StateMachine.RaiseEvent(startReconnectArg);
 }
Пример #32
0
        private void SetStateHandler(object sender, RemoteSessionStateMachineEventArgs eventArgs)
        {
            using (ClientRemoteSessionDSHandlerStateMachine._trace.TraceMethod())
            {
                switch (eventArgs.StateEvent)
                {
                case RemoteSessionEvent.NegotiationSendCompleted:
                    this.SetState(RemoteSessionState.NegotiationSent, (Exception)null);
                    break;

                case RemoteSessionEvent.NegotiationReceived:
                    if (eventArgs.RemoteSessionCapability == null)
                    {
                        throw ClientRemoteSessionDSHandlerStateMachine._trace.NewArgumentException(nameof(eventArgs));
                    }
                    this.SetState(RemoteSessionState.NegotiationReceived, (Exception)null);
                    break;

                case RemoteSessionEvent.NegotiationCompleted:
                    this.SetState(RemoteSessionState.Established, (Exception)null);
                    break;

                case RemoteSessionEvent.CloseCompleted:
                    this.SetState(RemoteSessionState.Closed, eventArgs.Reason);
                    break;

                case RemoteSessionEvent.CloseFailed:
                    this.SetState(RemoteSessionState.Closed, eventArgs.Reason);
                    break;

                case RemoteSessionEvent.ConnectFailed:
                    this.SetState(RemoteSessionState.ClosingConnection, eventArgs.Reason);
                    break;

                case RemoteSessionEvent.KeySent:
                    if (this._state != RemoteSessionState.Established && this._state != RemoteSessionState.EstablishedAndKeyRequested)
                    {
                        break;
                    }
                    this.SetState(RemoteSessionState.EstablishedAndKeySent, eventArgs.Reason);
                    this._keyExchangeTimer           = new Timer();
                    this._keyExchangeTimer.AutoReset = false;
                    this._keyExchangeTimer.Elapsed  += new ElapsedEventHandler(this.HandleKeyExchangeTimeout);
                    this._keyExchangeTimer.Interval  = 180000.0;
                    break;

                case RemoteSessionEvent.KeyReceived:
                    if (this._state != RemoteSessionState.EstablishedAndKeySent)
                    {
                        break;
                    }
                    if (this._keyExchangeTimer != null)
                    {
                        this._keyExchangeTimer.Enabled = false;
                        this._keyExchangeTimer.Dispose();
                        this._keyExchangeTimer = (Timer)null;
                    }
                    this.SetState(RemoteSessionState.EstablishedAndKeyExchanged, eventArgs.Reason);
                    break;

                case RemoteSessionEvent.KeyRequested:
                    if (this._state != RemoteSessionState.Established)
                    {
                        break;
                    }
                    this.SetState(RemoteSessionState.EstablishedAndKeyRequested, eventArgs.Reason);
                    break;
                }
            }
        }
Пример #33
0
        /// <summary>
        /// Start the key exchange process
        /// </summary>
        internal override void StartKeyExchange()
        {
            if (SessionDataStructureHandler.StateMachine.State == RemoteSessionState.Established ||
                SessionDataStructureHandler.StateMachine.State == RemoteSessionState.EstablishedAndKeyRequested)
            {
                // Start the key sending process
                string localPublicKey = null;
                bool ret = false;
                RemoteSessionStateMachineEventArgs eventArgs = null;
                Exception exception = null;

                try
                {
                    ret = _cryptoHelper.ExportLocalPublicKey(out localPublicKey);
                }
                catch (PSCryptoException cryptoException)
                {
                    ret = false;
                    exception = cryptoException;
                }

                if (!ret)
                {
                    // we need to complete the key exchange 
                    // since the crypto helper will be waiting on it
                    CompleteKeyExchange();

                    // exporting local public key failed
                    // set state to Closed
                    eventArgs = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.KeySendFailed,
                                        exception);

                    SessionDataStructureHandler.StateMachine.RaiseEvent(eventArgs);
                }

                // send using data structure handler
                eventArgs = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.KeySent);
                SessionDataStructureHandler.StateMachine.RaiseEvent(eventArgs);

                SessionDataStructureHandler.SendPublicKeyAsync(localPublicKey);
            }
        }
        /// <summary>
        /// This method is used by all classes to raise a FSM event.
        /// The method will queue the event. The event queue will be handled in
        /// a thread safe manner by a single dedicated thread.
        /// </summary>
        /// <param name="fsmEventArg">
        /// This parameter contains the event to be raised.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// If the parameter is null.
        /// </exception>
        internal void RaiseEvent(RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            // make sure only one thread is processing events.
            lock (_syncObject)
            {
                s_trace.WriteLine("Event received : {0}", fsmEventArg.StateEvent);
                _processPendingEventsQueue.Enqueue(fsmEventArg);

                if (_eventsInProcess)
                {
                    return;
                }
                _eventsInProcess = true;
            }

            ProcessEvents();

            // currently server state machine doesn't raise events
            // this will allow server state machine to raise events.
            //RaiseStateMachineEvents();
        }
Пример #35
0
        /// <summary>
        /// Handles an encrypted session key received from the other side
        /// </summary>
        /// <param name="sender">sender of this event</param>
        /// <param name="eventArgs">arguments that contain the remote
        /// public key</param>
        private void HandleEncryptedSessionKeyReceived(object sender, RemoteDataEventArgs<string> eventArgs)
        {
            if (SessionDataStructureHandler.StateMachine.State == RemoteSessionState.EstablishedAndKeySent)
            {
                string encryptedSessionKey = eventArgs.Data;

                bool ret = _cryptoHelper.ImportEncryptedSessionKey(encryptedSessionKey);

                RemoteSessionStateMachineEventArgs args = null;
                if (!ret)
                {
                    // importing remote public key failed
                    // set state to closed
                    args = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.KeyReceiveFailed);

                    SessionDataStructureHandler.StateMachine.RaiseEvent(args);
                }

                // complete the key exchange process
                CompleteKeyExchange();

                args = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.KeyReceived);
                SessionDataStructureHandler.StateMachine.RaiseEvent(args);
            }
        }
        /// <summary>
        /// This is the handler for Start event of the FSM. This is the beginning of everything
        /// else. From this moment on, the FSM will proceeds step by step to eventually reach
        /// Established state or Closed state.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        private void DoCreateSession(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.CreateSession, "StateEvent must be CreateSession");
                Dbg.Assert(_state == RemoteSessionState.Idle, "DoCreateSession cannot only be called in Idle state");

                DoNegotiationPending(sender, fsmEventArg);
            }
        }
Пример #37
0
        /// <summary>
        /// Handles a request for public key from the server
        /// </summary>
        /// <param name="sender">send of this event, unused</param>
        /// <param name="eventArgs">arguments describing this event, unused</param>
        private void HandlePublicKeyRequestReceived(object sender, RemoteDataEventArgs<string> eventArgs)
        {
            if (SessionDataStructureHandler.StateMachine.State == RemoteSessionState.Established)
            {
                RemoteSessionStateMachineEventArgs args =
                    new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.KeyRequested);
                SessionDataStructureHandler.StateMachine.RaiseEvent(args);

                StartKeyExchange();
            }
        }
        /// <summary>
        /// This is the handler for the NegotiationReceived event.
        /// It sets the new state to be NegotiationReceived.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If the parameter <paramref name="fsmEventArg"/> is not NegotiationReceived event or it does not hold the
        /// client negotiation packet.
        /// </exception>

        private void DoNegotiationReceived(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.NegotiationReceived, "StateEvent must be NegotiationReceived");
                Dbg.Assert(fsmEventArg.RemoteSessionCapability != null, "RemoteSessioncapability must be non-null");
                Dbg.Assert(_state == RemoteSessionState.NegotiationPending, "state must be in NegotiationPending state");

                if (fsmEventArg.StateEvent != RemoteSessionEvent.NegotiationReceived)
                {
                    throw PSTraceSource.NewArgumentException("fsmEventArg");
                }

                if (fsmEventArg.RemoteSessionCapability == null)
                {
                    throw PSTraceSource.NewArgumentException("fsmEventArg");
                }

                SetState(RemoteSessionState.NegotiationReceived, null);
            }
        }
Пример #39
0
        /// <summary>
        /// Examines the negotiation packet received from the server
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="arg"></param>
        private void HandleNegotiationReceived(object sender, RemoteSessionNegotiationEventArgs arg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (arg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("arg");
                }

                if (arg.RemoteSessionCapability == null)
                {
                    throw PSTraceSource.NewArgumentException("arg");
                }

                Context.ServerCapability = arg.RemoteSessionCapability;

                try
                {
                    // This will throw if there is an error running the algorithm
                    RunClientNegotiationAlgorithm(Context.ServerCapability);

                    RemoteSessionStateMachineEventArgs negotiationCompletedArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationCompleted);
                    SessionDataStructureHandler.StateMachine.RaiseEvent(negotiationCompletedArg);
                }
                catch (PSRemotingDataStructureException dse)
                {
                    RemoteSessionStateMachineEventArgs negotiationFailedArg =
                        new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationFailed,
                            dse);
                    SessionDataStructureHandler.StateMachine.RaiseEvent(negotiationFailedArg);
                }
            }
        }
        /// <summary>
        /// This is the handler for NegotiationSendCompleted event.
        /// It sets the new state to be NegotiationSent.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>

        private void DoNegotiationCompleted(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(_state == RemoteSessionState.NegotiationSending, "State must be NegotiationSending");
                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.NegotiationSendCompleted, "StateEvent must be NegotiationSendCompleted");

                SetState(RemoteSessionState.NegotiationSent, null);
            }
        }
Пример #41
0
 private void HandleServerRemoteSessionClosed(
     Object sender,
     RemoteSessionStateMachineEventArgs eventArgs)
 {
     Exception reasonForClose = null;
     if (null != eventArgs)
     {
         reasonForClose = eventArgs.Reason;
     }
     Close(reasonForClose);
 }
        /// <summary>
        /// This is the handler for MessageReceived event. It dispatches the data to various components
        /// that uses the data.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If the parameter <paramref name="fsmEventArg"/> does not contain remote data.
        /// </exception>        
        internal void DoMessageReceived(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                if (fsmEventArg.RemoteData == null)
                {
                    throw PSTraceSource.NewArgumentException("fsmEventArg");
                }

                Dbg.Assert(_state == RemoteSessionState.Established ||
                           _state == RemoteSessionState.EstablishedAndKeyExchanged ||
                           _state == RemoteSessionState.EstablishedAndKeyReceived ||
                           _state == RemoteSessionState.EstablishedAndKeySent,  //server session will never be in this state.. TODO- remove this
                           "State must be Established or EstablishedAndKeySent or EstablishedAndKeyReceived or EstablishedAndKeyExchanged");

                RemotingTargetInterface targetInterface = fsmEventArg.RemoteData.TargetInterface;
                RemotingDataType dataType = fsmEventArg.RemoteData.DataType;

                Guid clientRunspacePoolId;
                ServerRunspacePoolDriver runspacePoolDriver;
                //string errorMessage = null;

                RemoteDataEventArgs remoteDataForSessionArg = null;

                switch (targetInterface)
                {
                    case RemotingTargetInterface.Session:
                        {
                            switch (dataType)
                            {
                                // GETBACK
                                case RemotingDataType.CreateRunspacePool:
                                    remoteDataForSessionArg = new RemoteDataEventArgs(fsmEventArg.RemoteData);
                                    _session.SessionDataStructureHandler.RaiseDataReceivedEvent(remoteDataForSessionArg);
                                    break;

                                default:
                                    Dbg.Assert(false, "Should never reach here");
                                    break;
                            }
                        }
                        break;

                    case RemotingTargetInterface.RunspacePool:
                        // GETBACK
                        clientRunspacePoolId = fsmEventArg.RemoteData.RunspacePoolId;
                        runspacePoolDriver = _session.GetRunspacePoolDriver(clientRunspacePoolId);

                        if (runspacePoolDriver != null)
                        {
                            runspacePoolDriver.DataStructureHandler.ProcessReceivedData(fsmEventArg.RemoteData);
                        }
                        else
                        {
                            s_trace.WriteLine(@"Server received data for Runspace (id: {0}), 
                                but the Runspace cannot be found", clientRunspacePoolId);

                            PSRemotingDataStructureException reasonOfFailure = new
                                PSRemotingDataStructureException(RemotingErrorIdStrings.RunspaceCannotBeFound,
                                    clientRunspacePoolId);
                            RemoteSessionStateMachineEventArgs runspaceNotFoundArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.FatalError, reasonOfFailure);
                            RaiseEvent(runspaceNotFoundArg);
                        }

                        break;

                    case RemotingTargetInterface.PowerShell:
                        clientRunspacePoolId = fsmEventArg.RemoteData.RunspacePoolId;
                        runspacePoolDriver = _session.GetRunspacePoolDriver(clientRunspacePoolId);

                        runspacePoolDriver.DataStructureHandler.DispatchMessageToPowerShell(fsmEventArg.RemoteData);
                        break;

                    default:
                        s_trace.WriteLine("Server received data unknown targetInterface: {0}", targetInterface);

                        PSRemotingDataStructureException reasonOfFailure2 = new PSRemotingDataStructureException(RemotingErrorIdStrings.ReceivedUnsupportedRemotingTargetInterfaceType, targetInterface);
                        RemoteSessionStateMachineEventArgs unknownTargetArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.FatalError, reasonOfFailure2);
                        RaiseEvent(unknownTargetArg);
                        break;
                }
            }
        }
Пример #43
0
        private void HandleReconnectComplete(object sender, EventArgs args)
        {
            RemoteSessionStateMachineEventArgs arg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.ReconnectCompleted);

            this.StateMachine.RaiseEvent(arg, false);
        }
        /// <summary>
        /// This is the handler for FatalError event. It directly calls the DoClose, which
        /// is the Close event handler.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> does not contains FatalError event.
        /// </exception>
        private void DoFatalError(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.FatalError, "StateEvent must be FatalError");

                if (fsmEventArg.StateEvent != RemoteSessionEvent.FatalError)
                {
                    throw PSTraceSource.NewArgumentException("fsmEventArg");
                }

                DoClose(this, fsmEventArg);
            }
        }
Пример #45
0
        internal void HandleTransportError(object sender, TransportErrorOccuredEventArgs e)
        {
            PSRemotingTransportRedirectException exception = e.Exception as PSRemotingTransportRedirectException;

            if ((exception != null) && (this.maxUriRedirectionCount > 0))
            {
                Exception exception2 = null;
                try
                {
                    this.maxUriRedirectionCount--;
                    this.PerformURIRedirection(exception.RedirectLocation);
                    return;
                }
                catch (ArgumentNullException exception3)
                {
                    exception2 = exception3;
                }
                catch (UriFormatException exception4)
                {
                    exception2 = exception4;
                }
                if (exception2 != null)
                {
                    PSRemotingTransportException exception5 = new PSRemotingTransportException(PSRemotingErrorId.RedirectedURINotWellFormatted, RemotingErrorIdStrings.RedirectedURINotWellFormatted, new object[] { this._session.Context.RemoteAddress.OriginalString, exception.RedirectLocation })
                    {
                        TransportMessage = e.Exception.TransportMessage
                    };
                    e.Exception = exception5;
                }
            }
            RemoteSessionEvent connectFailed = RemoteSessionEvent.ConnectFailed;

            switch (e.ReportingTransportMethod)
            {
            case TransportMethodEnum.CreateShellEx:
                connectFailed = RemoteSessionEvent.ConnectFailed;
                break;

            case TransportMethodEnum.SendShellInputEx:
            case TransportMethodEnum.CommandInputEx:
                connectFailed = RemoteSessionEvent.SendFailed;
                break;

            case TransportMethodEnum.ReceiveShellOutputEx:
            case TransportMethodEnum.ReceiveCommandOutputEx:
                connectFailed = RemoteSessionEvent.ReceiveFailed;
                break;

            case TransportMethodEnum.CloseShellOperationEx:
                connectFailed = RemoteSessionEvent.CloseFailed;
                break;

            case TransportMethodEnum.DisconnectShellEx:
                connectFailed = RemoteSessionEvent.DisconnectFailed;
                break;

            case TransportMethodEnum.ReconnectShellEx:
                connectFailed = RemoteSessionEvent.ReconnectFailed;
                break;
            }
            RemoteSessionStateMachineEventArgs arg = new RemoteSessionStateMachineEventArgs(connectFailed, e.Exception);

            this._stateMachine.RaiseEvent(arg, false);
        }
        /// <summary>
        /// This is the handler for Close event. It closes the connection.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        private void DoClose(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                RemoteSessionState oldState = _state;

                switch (oldState)
                {
                    case RemoteSessionState.ClosingConnection:
                    case RemoteSessionState.Closed:
                        // do nothing
                        break;

                    case RemoteSessionState.Connecting:
                    case RemoteSessionState.Connected:
                    case RemoteSessionState.Established:
                    case RemoteSessionState.EstablishedAndKeySent:  //server session will never be in this state.. TODO- remove this
                    case RemoteSessionState.EstablishedAndKeyReceived:
                    case RemoteSessionState.EstablishedAndKeyExchanged:
                    case RemoteSessionState.NegotiationReceived:
                    case RemoteSessionState.NegotiationSent:
                    case RemoteSessionState.NegotiationSending:
                        SetState(RemoteSessionState.ClosingConnection, fsmEventArg.Reason);
                        _session.SessionDataStructureHandler.CloseConnectionAsync(fsmEventArg.Reason);
                        break;

                    case RemoteSessionState.Idle:
                    case RemoteSessionState.UndefinedState:
                    default:
                        Exception forcedCloseException = new PSRemotingTransportException(fsmEventArg.Reason, RemotingErrorIdStrings.ForceClosed);
                        SetState(RemoteSessionState.Closed, forcedCloseException);
                        break;
                }

                CleanAll();
            }
        }
        internal void DoMessageReceived(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (_trace.TraceEventHandlers())
            {
                Guid runspacePoolId;
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }
                if (fsmEventArg.RemoteData == null)
                {
                    throw PSTraceSource.NewArgumentException("fsmEventArg");
                }
                RemotingTargetInterface targetInterface = fsmEventArg.RemoteData.TargetInterface;
                RemotingDataType        dataType        = fsmEventArg.RemoteData.DataType;
                RemoteDataEventArgs     arg             = null;
                switch (targetInterface)
                {
                case RemotingTargetInterface.Session:
                    switch (dataType)
                    {
                    case RemotingDataType.CreateRunspacePool:
                    {
                        arg = new RemoteDataEventArgs(fsmEventArg.RemoteData);
                        this._session.SessionDataStructureHandler.RaiseDataReceivedEvent(arg);
                    }
                    break;
                    }
                    return;

                case RemotingTargetInterface.RunspacePool:
                {
                    runspacePoolId = fsmEventArg.RemoteData.RunspacePoolId;
                    ServerRunspacePoolDriver runspacePoolDriver = this._session.GetRunspacePoolDriver(runspacePoolId);
                    if (runspacePoolDriver == null)
                    {
                        break;
                    }
                    runspacePoolDriver.DataStructureHandler.ProcessReceivedData(fsmEventArg.RemoteData);
                    return;
                }

                case RemotingTargetInterface.PowerShell:
                    runspacePoolId = fsmEventArg.RemoteData.RunspacePoolId;
                    this._session.GetRunspacePoolDriver(runspacePoolId).DataStructureHandler.DispatchMessageToPowerShell(fsmEventArg.RemoteData);
                    return;

                default:
                    goto Label_0151;
                }
                _trace.WriteLine("Server received data for Runspace (id: {0}), \r\n                                but the Runspace cannot be found", new object[] { runspacePoolId });
                PSRemotingDataStructureException   reason = new PSRemotingDataStructureException(RemotingErrorIdStrings.RunspaceCannotBeFound, new object[] { runspacePoolId });
                RemoteSessionStateMachineEventArgs args2  = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.FatalError, reason);
                this.RaiseEvent(args2);
                return;

                Label_0151 :;
                _trace.WriteLine("Server received data unknown targetInterface: {0}", new object[] { targetInterface });
                PSRemotingDataStructureException   exception2 = new PSRemotingDataStructureException(RemotingErrorIdStrings.ReceivedUnsupportedRemotingTargetInterfaceType, new object[] { targetInterface });
                RemoteSessionStateMachineEventArgs args3      = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.FatalError, exception2);
                this.RaiseEvent(args3);
            }
        }
        /// <summary>
        /// This is the handler for CloseCompleted event. It sets the new state to be Closed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        private void DoCloseCompleted(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.CloseCompleted, "StateEvent must be CloseCompleted");

                SetState(RemoteSessionState.Closed, fsmEventArg.Reason);
                // Close the session only after changing the state..this way
                // state machine will not process anything.
                _session.Close(fsmEventArg);
                CleanAll();
            }
        }
Пример #49
0
        /// <summary>
        /// This method is used by the input queue dispatching mechanism.
        /// It examines the data and takes appropriate actions.
        /// </summary>
        /// <param name="dataArg">
        /// The received client data.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// If the parameter is null.
        /// </exception>
        internal override void RaiseDataReceivedEvent(RemoteDataEventArgs dataArg)
        {
            if (dataArg == null)
            {
                throw PSTraceSource.NewArgumentNullException("dataArg");
            }

            RemoteDataObject <PSObject> rcvdData = dataArg.ReceivedData;

            RemotingTargetInterface targetInterface = rcvdData.TargetInterface;
            RemotingDataType        dataType        = rcvdData.DataType;

            Dbg.Assert(targetInterface == RemotingTargetInterface.Session, "targetInterface must be Session");

            switch (dataType)
            {
            case RemotingDataType.CreateRunspacePool:
            {
                // At this point, the negotiation is complete, so
                // need to import the clients public key
                CreateRunspacePoolReceived.SafeInvoke(this, dataArg);
            }

            break;

            case RemotingDataType.CloseSession:
                PSRemotingDataStructureException   reasonOfClose   = new PSRemotingDataStructureException(RemotingErrorIdStrings.ClientRequestedToCloseSession);
                RemoteSessionStateMachineEventArgs closeSessionArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close, reasonOfClose);
                _stateMachine.RaiseEvent(closeSessionArg);
                break;

            case RemotingDataType.SessionCapability:
                RemoteSessionCapability capability = null;
                try
                {
                    capability = RemotingDecoder.GetSessionCapability(rcvdData.Data);
                }
                catch (PSRemotingDataStructureException dse)
                {
                    // this will happen if expected properties are not
                    // received for session capability
                    throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerNotFoundCapabilityProperties,
                                                               dse.Message, PSVersionInfo.GitCommitId, RemotingConstants.ProtocolVersion);
                }

                RemoteSessionStateMachineEventArgs capabilityArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationReceived);
                capabilityArg.RemoteSessionCapability = capability;
                _stateMachine.RaiseEvent(capabilityArg);

                if (NegotiationReceived != null)
                {
                    RemoteSessionNegotiationEventArgs negotiationArg = new RemoteSessionNegotiationEventArgs(capability);
                    negotiationArg.RemoteData = rcvdData;
                    NegotiationReceived.SafeInvoke(this, negotiationArg);
                }

                break;

            case RemotingDataType.PublicKey:
            {
                string remotePublicKey = RemotingDecoder.GetPublicKey(rcvdData.Data);
                PublicKeyReceived.SafeInvoke(this, new RemoteDataEventArgs <string>(remotePublicKey));
            }

            break;

            default:
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ReceivedUnsupportedAction, dataType);
            }
        }
        /// <summary>
        /// This is the handler for ReceivedFailed event.
        /// This is an indication that the wire layer IO is no longer connected. So it raises
        /// a Close event to trigger a connection shutdown.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="fsmEventArg">
        /// This parameter contains the FSM event.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If the parameter <paramref name="fsmEventArg"/> is null.
        /// </exception>
        private void DoReceiveFailed(object sender, RemoteSessionStateMachineEventArgs fsmEventArg)
        {
            using (s_trace.TraceEventHandlers())
            {
                if (fsmEventArg == null)
                {
                    throw PSTraceSource.NewArgumentNullException("fsmEventArg");
                }

                Dbg.Assert(fsmEventArg.StateEvent == RemoteSessionEvent.ReceiveFailed, "StateEvent must be ReceivedFailed");

                RemoteSessionStateMachineEventArgs closeArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close);

                RaiseEventPrivate(closeArg);
            }
        }
Пример #51
0
        /// <summary>
        /// Dispatches data when it arrives from the input queue.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="dataArg">
        /// arg which contains the data received from input queue
        /// </param>
        internal void DispatchInputQueueData(object sender, RemoteDataEventArgs dataArg)
        {
            if (dataArg is null)
            {
                throw PSTraceSource.NewArgumentNullException(nameof(dataArg));
            }

            RemoteDataObject <PSObject> rcvdData = dataArg.ReceivedData;

            if (rcvdData is null)
            {
                throw PSTraceSource.NewArgumentException(nameof(dataArg));
            }

            RemotingDestination destination = rcvdData.Destination;

            if ((destination & RemotingDestination.Client) != RemotingDestination.Client)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.RemotingDestinationNotForMe, RemotingDestination.Client, destination);
            }

            RemotingTargetInterface targetInterface = rcvdData.TargetInterface;

            switch (targetInterface)
            {
            case RemotingTargetInterface.Session:
            {
                // Messages for session can cause statemachine state to change.
                // These messages are first processed by Sessiondata structure handler and depending
                // on the type of message, appropriate event is raised in state machine
                ProcessSessionMessages(dataArg);
                break;
            }

            case RemotingTargetInterface.RunspacePool:
            case RemotingTargetInterface.PowerShell:
                // Non Session messages do not change the state of the statemachine.
                // However instead of forwarding them to Runspace/pipeline here, an
                // event is raised in state machine which verified that state is
                // suitable for accepting these messages. if state is suitable statemachine
                // will call DoMessageForwading which will forward the messages appropriately
                RemoteSessionStateMachineEventArgs msgRcvArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.MessageReceived, null);
                if (StateMachine.CanByPassRaiseEvent(msgRcvArg))
                {
                    ProcessNonSessionMessages(dataArg.ReceivedData);
                }
                else
                {
                    StateMachine.RaiseEvent(msgRcvArg);
                }

                break;

            default:
            {
                Dbg.Assert(false, "we should not be encountering this");
            }

            break;
            }
        }
Пример #52
0
        /// <summary>
        /// Closes Session Connection Asynchronously.
        /// </summary>
        /// <remarks>
        /// Caller should register for ConnectionClosed event to get notified
        /// </remarks>
        public override void CloseAsync()
        {
            RemoteSessionStateMachineEventArgs closeArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close);

            SessionDataStructureHandler.StateMachine.RaiseEvent(closeArg);
        }
Пример #53
0
        /// <summary>
        /// Handler which handles transport errors.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal void HandleTransportError(object sender, TransportErrorOccuredEventArgs e)
        {
            Dbg.Assert(e != null, "HandleTransportError expects non-null eventargs");
            // handle uri redirections
            PSRemotingTransportRedirectException redirectException = e.Exception as PSRemotingTransportRedirectException;

            if ((redirectException != null) && (_maxUriRedirectionCount > 0))
            {
                Exception exception = null;

                try
                {
                    // honor max redirection count given by the user.
                    _maxUriRedirectionCount--;
                    PerformURIRedirection(redirectException.RedirectLocation);
                    return;
                }
                catch (ArgumentNullException argumentException)
                {
                    exception = argumentException;
                }
                catch (UriFormatException uriFormatException)
                {
                    exception = uriFormatException;
                }
                // if we are here, there must be an exception constructing a uri
                if (exception != null)
                {
                    PSRemotingTransportException newException =
                        new PSRemotingTransportException(PSRemotingErrorId.RedirectedURINotWellFormatted, RemotingErrorIdStrings.RedirectedURINotWellFormatted,
                                                         _session.Context.RemoteAddress.OriginalString,
                                                         redirectException.RedirectLocation);
                    newException.TransportMessage = e.Exception.TransportMessage;
                    e.Exception = newException;
                }
            }

            RemoteSessionEvent sessionEvent = RemoteSessionEvent.ConnectFailed;

            switch (e.ReportingTransportMethod)
            {
            case TransportMethodEnum.CreateShellEx:
                sessionEvent = RemoteSessionEvent.ConnectFailed;
                break;

            case TransportMethodEnum.SendShellInputEx:
            case TransportMethodEnum.CommandInputEx:
                sessionEvent = RemoteSessionEvent.SendFailed;
                break;

            case TransportMethodEnum.ReceiveShellOutputEx:
            case TransportMethodEnum.ReceiveCommandOutputEx:
                sessionEvent = RemoteSessionEvent.ReceiveFailed;
                break;

            case TransportMethodEnum.CloseShellOperationEx:
                sessionEvent = RemoteSessionEvent.CloseFailed;
                break;

            case TransportMethodEnum.DisconnectShellEx:
                sessionEvent = RemoteSessionEvent.DisconnectFailed;
                break;

            case TransportMethodEnum.ReconnectShellEx:
                sessionEvent = RemoteSessionEvent.ReconnectFailed;
                break;
            }

            RemoteSessionStateMachineEventArgs errorArgs =
                new RemoteSessionStateMachineEventArgs(sessionEvent, e.Exception);

            _stateMachine.RaiseEvent(errorArgs);
        }
Пример #54
0
        /// <summary>
        /// Handler to be used in cases, where setting the state is the
        /// only task being performed. This method also asserts
        /// if the specified event is valid for the current state of
        /// the state machine.
        /// </summary>
        /// <param name="sender">Sender of this event.</param>
        /// <param name="eventArgs">Event args.</param>
        private void SetStateHandler(object sender, RemoteSessionStateMachineEventArgs eventArgs)
        {
            switch (eventArgs.StateEvent)
            {
            case RemoteSessionEvent.NegotiationCompleted:
            {
                Dbg.Assert(_state == RemoteSessionState.NegotiationReceived,
                           "State can be set to Established only when current state is NegotiationReceived");
                SetState(RemoteSessionState.Established, null);
            }

            break;

            case RemoteSessionEvent.NegotiationReceived:
            {
                Dbg.Assert(eventArgs.RemoteSessionCapability != null,
                           "State can be set to NegotiationReceived only when RemoteSessionCapability is not null");
                if (eventArgs.RemoteSessionCapability == null)
                {
                    throw PSTraceSource.NewArgumentException(nameof(eventArgs));
                }

                SetState(RemoteSessionState.NegotiationReceived, null);
            }

            break;

            case RemoteSessionEvent.NegotiationSendCompleted:
            {
                Dbg.Assert((_state == RemoteSessionState.NegotiationSending) || (_state == RemoteSessionState.NegotiationSendingOnConnect),
                           "Negotiating send can be completed only when current state is NegotiationSending");

                SetState(RemoteSessionState.NegotiationSent, null);
            }

            break;

            case RemoteSessionEvent.ConnectFailed:
            {
                Dbg.Assert(_state == RemoteSessionState.Connecting,
                           "A ConnectFailed event can be raised only when the current state is Connecting");

                SetState(RemoteSessionState.ClosingConnection, eventArgs.Reason);
            }

            break;

            case RemoteSessionEvent.CloseFailed:
            {
                SetState(RemoteSessionState.Closed, eventArgs.Reason);
            }

            break;

            case RemoteSessionEvent.CloseCompleted:
            {
                SetState(RemoteSessionState.Closed, eventArgs.Reason);
            }

            break;

            case RemoteSessionEvent.KeyRequested:
            {
                Dbg.Assert(_state == RemoteSessionState.Established,
                           "Server can request a key only after the client reaches the Established state");

                if (_state == RemoteSessionState.Established)
                {
                    SetState(RemoteSessionState.EstablishedAndKeyRequested, eventArgs.Reason);
                }
            }

            break;

            case RemoteSessionEvent.KeyReceived:
            {
                Dbg.Assert(_state == RemoteSessionState.EstablishedAndKeySent,
                           "Key Receiving can only be raised after reaching the Established state");

                if (_state == RemoteSessionState.EstablishedAndKeySent)
                {
                    Timer tmp = Interlocked.Exchange(ref _keyExchangeTimer, null);
                    if (tmp != null)
                    {
                        tmp.Dispose();
                    }

                    _keyExchanged = true;
                    SetState(RemoteSessionState.Established, eventArgs.Reason);

                    if (_pendingDisconnect)
                    {
                        // session key exchange is complete, if there is a disconnect pending, process it now
                        _pendingDisconnect = false;
                        DoDisconnect(sender, eventArgs);
                    }
                }
            }

            break;

            case RemoteSessionEvent.KeySent:
            {
                Dbg.Assert(_state >= RemoteSessionState.Established,
                           "Client can send a public key only after reaching the Established state");

                Dbg.Assert(!_keyExchanged, "Client should do key exchange only once");

                if (_state == RemoteSessionState.Established ||
                    _state == RemoteSessionState.EstablishedAndKeyRequested)
                {
                    SetState(RemoteSessionState.EstablishedAndKeySent, eventArgs.Reason);

                    // start the timer and wait
                    _keyExchangeTimer = new Timer(HandleKeyExchangeTimeout, null, BaseTransportManager.ClientDefaultOperationTimeoutMs, Timeout.Infinite);
                }
            }

            break;

            case RemoteSessionEvent.DisconnectCompleted:
            {
                Dbg.Assert(_state == RemoteSessionState.Disconnecting || _state == RemoteSessionState.RCDisconnecting,
                           "DisconnectCompleted event received while state machine is in wrong state");

                if (_state == RemoteSessionState.Disconnecting || _state == RemoteSessionState.RCDisconnecting)
                {
                    SetState(RemoteSessionState.Disconnected, eventArgs.Reason);
                }
            }

            break;

            case RemoteSessionEvent.DisconnectFailed:
            {
                Dbg.Assert(_state == RemoteSessionState.Disconnecting,
                           "DisconnectCompleted event received while state machine is in wrong state");

                if (_state == RemoteSessionState.Disconnecting)
                {
                    SetState(RemoteSessionState.Disconnected, eventArgs.Reason);         // set state to disconnected even TODO. Put some ETW event describing the disconnect process failure
                }
            }

            break;

            case RemoteSessionEvent.ReconnectCompleted:
            {
                Dbg.Assert(_state == RemoteSessionState.Reconnecting,
                           "ReconnectCompleted event received while state machine is in wrong state");

                if (_state == RemoteSessionState.Reconnecting)
                {
                    SetState(RemoteSessionState.Established, eventArgs.Reason);
                }
            }

            break;
            }
        }
Пример #55
0
        // TODO: If this is not used remove this
        // internal override event EventHandler<RemoteDataEventArgs> DataReceived;

        /// <summary>
        /// This processes the object received from transport which are
        /// targeted for session
        /// </summary>
        /// <param name="arg">
        /// argument contains the data object
        /// </param>
        private void ProcessSessionMessages(RemoteDataEventArgs arg)
        {
            if (arg == null || arg.ReceivedData == null)
            {
                throw PSTraceSource.NewArgumentNullException("arg");
            }

            RemoteDataObject <PSObject> rcvdData = arg.ReceivedData;

            RemotingTargetInterface targetInterface = rcvdData.TargetInterface;

            Dbg.Assert(targetInterface == RemotingTargetInterface.Session, "targetInterface must be Session");

            RemotingDataType dataType = rcvdData.DataType;

            switch (dataType)
            {
            case RemotingDataType.CloseSession:
                PSRemotingDataStructureException   reasonOfClose   = new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerRequestedToCloseSession);
                RemoteSessionStateMachineEventArgs closeSessionArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close, reasonOfClose);
                _stateMachine.RaiseEvent(closeSessionArg);
                break;

            case RemotingDataType.SessionCapability:
                RemoteSessionCapability capability = null;
                try
                {
                    capability = RemotingDecoder.GetSessionCapability(rcvdData.Data);
                }
                catch (PSRemotingDataStructureException dse)
                {
                    // this will happen if expected properties are not
                    // received for session capability
                    throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ClientNotFoundCapabilityProperties,
                                                               dse.Message, PSVersionInfo.GitCommitId, RemotingConstants.ProtocolVersion);
                }

                RemoteSessionStateMachineEventArgs capabilityArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationReceived);
                capabilityArg.RemoteSessionCapability = capability;
                _stateMachine.RaiseEvent(capabilityArg);

                RemoteSessionNegotiationEventArgs negotiationArg = new RemoteSessionNegotiationEventArgs(capability);
                NegotiationReceived.SafeInvoke(this, negotiationArg);
                break;

            case RemotingDataType.EncryptedSessionKey:
            {
                String encryptedSessionKey = RemotingDecoder.GetEncryptedSessionKey(rcvdData.Data);
                EncryptedSessionKeyReceived.SafeInvoke(this, new RemoteDataEventArgs <string>(encryptedSessionKey));
            }
            break;

            case RemotingDataType.PublicKeyRequest:
            {
                PublicKeyRequestReceived.SafeInvoke(this, new RemoteDataEventArgs <string>(String.Empty));
            }
            break;

            default:
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ReceivedUnsupportedAction, dataType);
            }
            }
        }
Пример #56
0
 private void DoReconnect(object sender, RemoteSessionStateMachineEventArgs arg)
 {
     SetState(RemoteSessionState.Reconnecting, null);
 }
Пример #57
0
 internal bool CanByPassRaiseEvent(RemoteSessionStateMachineEventArgs arg) => arg.StateEvent == RemoteSessionEvent.MessageReceived && (this._state == RemoteSessionState.Established || this._state == RemoteSessionState.EstablishedAndKeyReceived || (this._state == RemoteSessionState.EstablishedAndKeySent || this._state == RemoteSessionState.EstablishedAndKeyExchanged));
Пример #58
0
        /// <summary>
        /// This method contains all the logic for handling the state machine
        /// for key exchange. All the different scenarios are covered in this
        /// </summary>
        /// <param name="sender">sender of this event, unused</param>
        /// <param name="eventArgs">event args</param>
        private void DoKeyExchange(object sender, RemoteSessionStateMachineEventArgs eventArgs)
        {
            //There are corner cases with disconnect that can result in client receiving outdated key exchange packets
            //***TODO*** Deal with this on the client side. Key exchange packets should have additional information
            //that identify the context of negotiation. Just like callId in SetMax and SetMinRunspaces messages
            Dbg.Assert(_state >= RemoteSessionState.Established,
                       "Key Receiving can only be raised after reaching the Established state");

            switch (eventArgs.StateEvent)
            {
            case RemoteSessionEvent.KeyReceived:
            {
                //does the server ever start key exchange process??? This may not be required
                if (_state == RemoteSessionState.EstablishedAndKeyRequested)
                {
                    // reset the timer
                    Timer tmp = Interlocked.Exchange(ref _keyExchangeTimer, null);
                    if (tmp != null)
                    {
                        tmp.Dispose();
                    }
                }

                // the key import would have been done
                // set state accordingly
                SetState(RemoteSessionState.EstablishedAndKeyReceived, eventArgs.Reason);

                // you need to send an encrypted session key to the client
                _session.SendEncryptedSessionKey();
            }
            break;

            case RemoteSessionEvent.KeySent:
            {
                if (_state == RemoteSessionState.EstablishedAndKeyReceived)
                {
                    // key exchange is now complete
                    SetState(RemoteSessionState.EstablishedAndKeyExchanged, eventArgs.Reason);
                }
            }
            break;

            case RemoteSessionEvent.KeyRequested:
            {
                if ((_state == RemoteSessionState.Established) || (_state == RemoteSessionState.EstablishedAndKeyExchanged))
                {
                    // the key has been sent set state accordingly
                    SetState(RemoteSessionState.EstablishedAndKeyRequested, eventArgs.Reason);

                    // start the timer
                    _keyExchangeTimer = new Timer(HandleKeyExchangeTimeout, null, BaseTransportManager.ServerDefaultKeepAliveTimeoutMs, Timeout.Infinite);
                }
            }
            break;

            case RemoteSessionEvent.KeyReceiveFailed:
            {
                if ((_state == RemoteSessionState.Established) || (_state == RemoteSessionState.EstablishedAndKeyExchanged))
                {
                    return;
                }

                DoClose(this, eventArgs);
            }
            break;

            case RemoteSessionEvent.KeySendFailed:
            {
                DoClose(this, eventArgs);
            }
            break;
            }
        }
Пример #59
0
        internal void ExecuteConnect(byte[] connectData, out byte[] connectResponseData)
        {
            RemoteSessionCapability sessionCapability;

            connectResponseData = null;
            Fragmentor fragmentor   = new Fragmentor(0x7fffffff, null);
            Fragmentor defragmentor = fragmentor;
            int        length       = connectData.Length;

            if (length < 0x15)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            FragmentedRemoteObject.GetFragmentId(connectData, 0);
            bool isStartFragment = FragmentedRemoteObject.GetIsStartFragment(connectData, 0);
            bool isEndFragment   = FragmentedRemoteObject.GetIsEndFragment(connectData, 0);
            int  blobLength      = FragmentedRemoteObject.GetBlobLength(connectData, 0);

            if (blobLength > (length - 0x15))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            if (!isStartFragment || !isEndFragment)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            RemoteSessionState state = this.SessionDataStructureHandler.StateMachine.State;

            if ((state != RemoteSessionState.Established) && (state != RemoteSessionState.EstablishedAndKeyExchanged))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnServerStateValidation);
            }
            MemoryStream serializedDataStream = new MemoryStream();

            serializedDataStream.Write(connectData, 0x15, blobLength);
            serializedDataStream.Seek(0L, SeekOrigin.Begin);
            RemoteDataObject <PSObject> obj2 = RemoteDataObject <PSObject> .CreateFrom(serializedDataStream, defragmentor);

            if (obj2 == null)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            if ((obj2.Destination != (RemotingDestination.InvalidDestination | RemotingDestination.Server)) || (obj2.DataType != RemotingDataType.SessionCapability))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            int num3 = (length - 0x15) - blobLength;

            if (num3 < 0x15)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            byte[] destinationArray = new byte[num3];
            Array.Copy(connectData, 0x15 + blobLength, destinationArray, 0, num3);
            FragmentedRemoteObject.GetFragmentId(destinationArray, 0);
            isStartFragment = FragmentedRemoteObject.GetIsStartFragment(destinationArray, 0);
            isEndFragment   = FragmentedRemoteObject.GetIsEndFragment(destinationArray, 0);
            blobLength      = FragmentedRemoteObject.GetBlobLength(destinationArray, 0);
            if (blobLength != (num3 - 0x15))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            if (!isStartFragment || !isEndFragment)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            serializedDataStream = new MemoryStream();
            serializedDataStream.Write(destinationArray, 0x15, blobLength);
            serializedDataStream.Seek(0L, SeekOrigin.Begin);
            RemoteDataObject <PSObject> obj3 = RemoteDataObject <PSObject> .CreateFrom(serializedDataStream, defragmentor);

            if (obj3 == null)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnServerStateValidation);
            }
            if ((obj3.Destination != (RemotingDestination.InvalidDestination | RemotingDestination.Server)) || (obj3.DataType != RemotingDataType.ConnectRunspacePool))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            try
            {
                sessionCapability = RemotingDecoder.GetSessionCapability(obj2.Data);
            }
            catch (PSRemotingDataStructureException)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            try
            {
                this.RunServerNegotiationAlgorithm(sessionCapability, true);
            }
            catch (PSRemotingDataStructureException exception)
            {
                throw exception;
            }
            int  minRunspaces = -1;
            int  maxRunspaces = -1;
            bool flag3        = false;

            if ((obj3.Data.Properties["MinRunspaces"] != null) && (obj3.Data.Properties["MinRunspaces"] != null))
            {
                try
                {
                    minRunspaces = RemotingDecoder.GetMinRunspaces(obj3.Data);
                    maxRunspaces = RemotingDecoder.GetMaxRunspaces(obj3.Data);
                    flag3        = true;
                }
                catch (PSRemotingDataStructureException)
                {
                    throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
                }
            }
            if (flag3 && (((minRunspaces == -1) || (maxRunspaces == -1)) || (minRunspaces > maxRunspaces)))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            if (this._runspacePoolDriver == null)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnServerStateValidation);
            }
            if (obj3.RunspacePoolId != this._runspacePoolDriver.InstanceId)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }
            if ((flag3 && (this._runspacePoolDriver.RunspacePool.GetMaxRunspaces() != maxRunspaces)) && (this._runspacePoolDriver.RunspacePool.GetMinRunspaces() != minRunspaces))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnMismatchedRunspacePoolProperties);
            }
            RemoteDataObject     obj4            = RemotingEncoder.GenerateServerSessionCapability(this._context.ServerCapability, this._runspacePoolDriver.InstanceId);
            RemoteDataObject     obj5            = RemotingEncoder.GenerateRunspacePoolInitData(this._runspacePoolDriver.InstanceId, this._runspacePoolDriver.RunspacePool.GetMaxRunspaces(), this._runspacePoolDriver.RunspacePool.GetMinRunspaces());
            SerializedDataStream streamToWriteTo = new SerializedDataStream(0x1000);

            streamToWriteTo.Enter();
            obj4.Serialize(streamToWriteTo, fragmentor);
            streamToWriteTo.Exit();
            streamToWriteTo.Enter();
            obj5.Serialize(streamToWriteTo, fragmentor);
            streamToWriteTo.Exit();
            byte[] buffer2 = streamToWriteTo.Read();
            streamToWriteTo.Dispose();
            connectResponseData = buffer2;
            ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object s) {
                RemoteSessionStateMachineEventArgs fsmEventArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.ConnectSession);
                this._sessionDSHandler.StateMachine.RaiseEvent(fsmEventArg);
            }));
            this._runspacePoolDriver.DataStructureHandler.ProcessConnect();
        }