Esempio n. 1
0
        /// <summary>
        /// Gets the fragment or if no fragment is available registers the callback which
        /// gets called once a fragment is available. These 2 steps are performed in a
        /// synchronized way.
        ///
        /// While getting a fragment the following algorithm is used:
        /// 1. If this is the first time or if the last fragment read is an EndFragment,
        ///    then a new set of fragments is chosen based on the implicit priority.
        ///    PromptResponse is higher in priority order than default.
        /// 2. If last fragment read is not an EndFragment, then next fragment is chosen from
        ///    the priority collection as the last fragment. This will ensure fragments
        ///    are sent in order.
        /// </summary>
        /// <param name="callback">
        /// Callback to call once data is available. (This will be used if no data is currently
        /// available).
        /// </param>
        /// <param name="priorityType">
        /// Priority stream to which the returned object belongs to, if any.
        /// If the call does not return any data, the value of this "out" parameter
        /// is undefined.
        /// </param>
        /// <returns>
        /// A FragmentRemoteObject if available, otherwise null.
        /// </returns>
        internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback,
                                               out DataPriorityType priorityType)
        {
            lock (_readSyncObject)
            {
                priorityType = DataPriorityType.Default;
                // Send data from which ever stream that has data directly.
                byte[] result = null;
                SerializedDataStream promptDataToBeSent = _dataToBeSent[(int)DataPriorityType.PromptResponse];
                if (promptDataToBeSent is not null)
                {
                    result       = promptDataToBeSent.ReadOrRegisterCallback(_onSendCollectionDataAvailable);
                    priorityType = DataPriorityType.PromptResponse;
                }

                if (result == null)
                {
                    SerializedDataStream defaultDataToBeSent = _dataToBeSent[(int)DataPriorityType.Default];
                    if (defaultDataToBeSent is not null)
                    {
                        result       = defaultDataToBeSent.ReadOrRegisterCallback(_onSendCollectionDataAvailable);
                        priorityType = DataPriorityType.Default;
                    }
                }

                // No data to return..so register the callback.
                if (result == null)
                {
                    // Register callback.
                    _onDataAvailableCallback = callback;
                }

                return(result);
            }
        }
 protected BaseClientCommandTransportManager(ClientRemotePowerShell shell, PSRemotingCryptoHelper cryptoHelper, BaseClientSessionTransportManager sessnTM) : base(sessnTM.RunspacePoolInstanceId, cryptoHelper)
 {
     RemoteDataObject obj2;
     base.Fragmentor.FragmentSize = sessnTM.Fragmentor.FragmentSize;
     base.Fragmentor.TypeTable = sessnTM.Fragmentor.TypeTable;
     base.dataToBeSent.Fragmentor = base.Fragmentor;
     this.powershellInstanceId = shell.PowerShell.InstanceId;
     this.cmdText = new StringBuilder();
     foreach (Command command in shell.PowerShell.Commands.Commands)
     {
         this.cmdText.Append(command.CommandText);
         this.cmdText.Append(" | ");
     }
     this.cmdText.Remove(this.cmdText.Length - 3, 3);
     if (shell.PowerShell.IsGetCommandMetadataSpecialPipeline)
     {
         obj2 = RemotingEncoder.GenerateGetCommandMetadata(shell);
     }
     else
     {
         obj2 = RemotingEncoder.GenerateCreatePowerShell(shell);
     }
     this.serializedPipeline = new SerializedDataStream(base.Fragmentor.FragmentSize);
     base.Fragmentor.Fragment<object>(obj2, this.serializedPipeline);
 }
Esempio n. 3
0
 internal void Enter()
 {
     this.isEntered  = true;
     this.fragmentId = 0L;
     this.currentFragment.ObjectId        = SerializedDataStream.GetObjectId();
     this.currentFragment.FragmentId      = this.fragmentId;
     this.currentFragment.IsStartFragment = true;
     this.currentFragment.BlobLength      = 0;
     this.currentFragment.Blob            = new byte[this.fragmentSize];
 }
Esempio n. 4
0
 internal void Fragment <T>(RemoteDataObject <T> obj, SerializedDataStream dataToBeSent)
 {
     dataToBeSent.Enter();
     try
     {
         obj.Serialize(dataToBeSent, this);
     }
     finally
     {
         dataToBeSent.Exit();
     }
 }
Esempio n. 5
0
        /// <summary>
        /// The method performs the fragmentation operation.
        /// All fragments of the same object have the same ObjectId.
        /// All fragments of the same object have the same ObjectId.
        /// Each fragment has its own Fragment Id. Fragment Id always starts from zero (0),
        /// and increments sequentially with an increment of 1.
        /// The last fragment is indicated by an End of Fragment marker.
        /// </summary>
        /// <param name="obj">
        /// The object to be fragmented. Caller should make sure this is not null.
        /// </param>
        /// <param name="dataToBeSent">
        /// Caller specified dataToStore to which the fragments are added
        /// one-by-one
        /// </param>
        internal void Fragment <T>(RemoteDataObject <T> obj, SerializedDataStream dataToBeSent)
        {
            Dbg.Assert(obj != null, "Cannot fragment a null object");
            Dbg.Assert(dataToBeSent != null, "SendDataCollection cannot be null");

            dataToBeSent.Enter();
            try
            {
                obj.Serialize(dataToBeSent, this);
            }
            finally
            {
                dataToBeSent.Exit();
            }
        }
Esempio n. 6
0
        /// <summary>
        /// ExecutesConnect. expects client capability and connect_runspacepool PSRP 
        /// messages in connectData. 
        /// If negotiation is successful and max and min runspaces in connect_runspacepool
        /// match the associated runspace pool parameters, it builds up server capability
        /// and runspace_initinfo in connectResponseData.
        /// This is a version of Connect that executes the whole connect algorithm in one single
        /// hop. 
        /// This algorithm is being executed synchronously without associating with state machine. 
        /// </summary>
        /// <param name="connectData"></param>
        /// <param name="connectResponseData"></param>
        /// The operation is being outside the statemachine because of multiple reasons associated with design simplicity
        /// - Support automatic disconnect and let wsman server stack take care of connection state
        /// - The response data should not travel in transports output stream but as part of connect response
        /// - We want this operation to be synchronous
        internal void ExecuteConnect(byte[] connectData, out byte[] connectResponseData)
        {
            connectResponseData = null;
            Fragmentor fragmentor = new Fragmentor(int.MaxValue, null);
            Fragmentor defragmentor = fragmentor;

            int totalDataLen = connectData.Length;

            if (totalDataLen < FragmentedRemoteObject.HeaderLength)
            {
                //raise exception
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            //TODO: Follow up on comment from Krishna regarding having the serialization/deserialization separate for this 
            // operation. This could be integrated as helper functions in fragmentor/serializer components
            long fragmentId = FragmentedRemoteObject.GetFragmentId(connectData, 0);
            bool sFlag = FragmentedRemoteObject.GetIsStartFragment(connectData, 0);
            bool eFlag = FragmentedRemoteObject.GetIsEndFragment(connectData, 0);
            int blobLength = FragmentedRemoteObject.GetBlobLength(connectData, 0);

            if (blobLength > totalDataLen - FragmentedRemoteObject.HeaderLength)
            {
                //raise exception
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            if (!sFlag || !eFlag)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            //if session is not in expected state
            RemoteSessionState currentState = SessionDataStructureHandler.StateMachine.State;
            if (currentState != RemoteSessionState.Established &&
                currentState != RemoteSessionState.EstablishedAndKeyExchanged)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnServerStateValidation);
            }

            //process first message
            MemoryStream serializedStream = new MemoryStream();
            serializedStream.Write(connectData, FragmentedRemoteObject.HeaderLength, blobLength);

            serializedStream.Seek(0, SeekOrigin.Begin);
            RemoteDataObject<PSObject> capabilityObject = RemoteDataObject<PSObject>.CreateFrom(serializedStream, defragmentor);

            if (capabilityObject == null)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            if ((capabilityObject.Destination != RemotingDestination.Server) || (capabilityObject.DataType != RemotingDataType.SessionCapability))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            //process second message
            int secondFragmentLength = totalDataLen - FragmentedRemoteObject.HeaderLength - blobLength;
            if (secondFragmentLength < FragmentedRemoteObject.HeaderLength)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            byte[] secondFragment = new byte[secondFragmentLength];
            Array.Copy(connectData, FragmentedRemoteObject.HeaderLength + blobLength, secondFragment, 0, secondFragmentLength);

            fragmentId = FragmentedRemoteObject.GetFragmentId(secondFragment, 0);
            sFlag = FragmentedRemoteObject.GetIsStartFragment(secondFragment, 0);
            eFlag = FragmentedRemoteObject.GetIsEndFragment(secondFragment, 0);
            blobLength = FragmentedRemoteObject.GetBlobLength(secondFragment, 0);

            if (blobLength != secondFragmentLength - FragmentedRemoteObject.HeaderLength)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            if (!sFlag || !eFlag)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            //process second message
            serializedStream = new MemoryStream();
            serializedStream.Write(secondFragment, FragmentedRemoteObject.HeaderLength, blobLength);

            serializedStream.Seek(0, SeekOrigin.Begin);
            RemoteDataObject<PSObject> connectRunspacePoolObject = RemoteDataObject<PSObject>.CreateFrom(serializedStream, defragmentor);

            if (connectRunspacePoolObject == null)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnServerStateValidation);
            }

            if ((connectRunspacePoolObject.Destination != RemotingDestination.Server) || (connectRunspacePoolObject.DataType != RemotingDataType.ConnectRunspacePool))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            //We have the two objects required for validating the connect operation
            RemoteSessionCapability clientCapability;
            try
            {
                clientCapability = RemotingDecoder.GetSessionCapability(capabilityObject.Data);
            }
            catch (PSRemotingDataStructureException)
            {
                // this will happen if expected properties are not
                // received for session capability
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            try
            {
                RunServerNegotiationAlgorithm(clientCapability, true);
            }
            catch (PSRemotingDataStructureException ex)
            {
                throw ex;
            }

            //validate client connect_runspacepool request
            int clientRequestedMinRunspaces = -1;
            int clientRequestedMaxRunspaces = -1;
            bool clientRequestedRunspaceCount = false;
            if (connectRunspacePoolObject.Data.Properties[RemoteDataNameStrings.MinRunspaces] != null && connectRunspacePoolObject.Data.Properties[RemoteDataNameStrings.MinRunspaces] != null)
            {
                try
                {
                    clientRequestedMinRunspaces = RemotingDecoder.GetMinRunspaces(connectRunspacePoolObject.Data);
                    clientRequestedMaxRunspaces = RemotingDecoder.GetMaxRunspaces(connectRunspacePoolObject.Data);
                    clientRequestedRunspaceCount = true;
                }
                catch (PSRemotingDataStructureException)
                {
                    throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
                }
            }

            //these should be positive and max should be greater than min
            if (clientRequestedRunspaceCount &&
                (clientRequestedMinRunspaces == -1 || clientRequestedMaxRunspaces == -1 || clientRequestedMinRunspaces > clientRequestedMaxRunspaces))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            if (_runspacePoolDriver == null)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnServerStateValidation);
            }

            //currently only one runspace pool per session is allowed. make sure this ID in connect message is the same
            if (connectRunspacePoolObject.RunspacePoolId != _runspacePoolDriver.InstanceId)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnInputValidation);
            }

            //we currently dont support adjusting runspace count on a connect operation.
            //there is a potential race here where in the runspace pool driver is still yet to process a queued
            //setMax or setMinrunspaces request. 
            //TODO: resolve this race.. probably by letting the runspace pool consume all messages before we execute this.
            if (clientRequestedRunspaceCount
                && (_runspacePoolDriver.RunspacePool.GetMaxRunspaces() != clientRequestedMaxRunspaces)
                && (_runspacePoolDriver.RunspacePool.GetMinRunspaces() != clientRequestedMinRunspaces))
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerConnectFailedOnMismatchedRunspacePoolProperties);
            }

            // all client messages are validated
            // now build up the server capabilities and connect response messages to be piggybacked on connect response
            RemoteDataObject capability = RemotingEncoder.GenerateServerSessionCapability(Context.ServerCapability, _runspacePoolDriver.InstanceId);
            RemoteDataObject runspacepoolInitData = RemotingEncoder.GenerateRunspacePoolInitData(_runspacePoolDriver.InstanceId,
                                                                                               _runspacePoolDriver.RunspacePool.GetMaxRunspaces(),
                                                                                               _runspacePoolDriver.RunspacePool.GetMinRunspaces());

            //having this stream operating separately will result in out of sync fragment Ids. but this is still OK
            //as this is executed only when connecting from a new client that does not have any previous fragments context.
            //no problem even if fragment Ids in this response and the sessiontransport stream clash (interfere) and its guaranteed
            // that the fragments in connect response are always complete (enclose a complete object).
            SerializedDataStream stream = new SerializedDataStream(4 * 1024);//Each message with fragment headers cannot cross 4k
            stream.Enter();
            capability.Serialize(stream, fragmentor);
            stream.Exit();
            stream.Enter();
            runspacepoolInitData.Serialize(stream, fragmentor);
            stream.Exit();
            byte[] outbuffer = stream.Read();
            Dbg.Assert(outbuffer != null, "connet response data should be serialized");
            stream.Dispose();
            //we are done
            connectResponseData = outbuffer;

            //enqueue a connect event in state machine to let session do any other post-connect operation
            // Do this outside of the synchronous connect operation, as otherwise connect can easily get deadlocked
            ThreadPool.QueueUserWorkItem(new WaitCallback(
                delegate (object state)
                {
                    RemoteSessionStateMachineEventArgs startEventArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.ConnectSession);
                    SessionDataStructureHandler.StateMachine.RaiseEvent(startEventArg);
                }));

            _runspacePoolDriver.DataStructureHandler.ProcessConnect();
            return;
        }
Esempio n. 7
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();
 }
Esempio n. 8
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();
        }