internal PriorityReceiveDataCollection(Fragmentor defragmentor, bool createdByClientTM)
 {
     this.defragmentor = defragmentor;
     string[] names = Enum.GetNames(typeof(DataPriorityType));
     this.recvdData = new ReceiveDataCollection[names.Length];
     for (int i = 0; i < names.Length; i++)
     {
         this.recvdData[i] = new ReceiveDataCollection(defragmentor, createdByClientTM);
     }
     this.isCreateByClientTM = createdByClientTM;
 }
示例#2
0
 internal ReceiveDataCollection(Fragmentor defragmentor, bool createdByClientTM)
 {
     this.defragmentor = defragmentor;
     this.isCreateByClientTM = createdByClientTM;
 }
示例#3
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;
        }
示例#4
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();
 }