Ejemplo 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;
                result       = _dataToBeSent[(int)DataPriorityType.PromptResponse].ReadOrRegisterCallback(_onSendCollectionDataAvailable);
                priorityType = DataPriorityType.PromptResponse;

                if (result is null)
                {
                    result       = _dataToBeSent[(int)DataPriorityType.Default].ReadOrRegisterCallback(_onSendCollectionDataAvailable);
                    priorityType = DataPriorityType.Default;
                }
                // no data to return..so register the callback.
                if (result is null)
                {
                    // register callback.
                    _onDataAvailableCallback = callback;
                }

                return(result);
            }
        }
Ejemplo n.º 2
0
        private void OnDataAvailable(byte[] data, bool isEndFragment)
        {
            lock (_readSyncObject)
            {
                // PromptResponse and Default priority collection can both raise at the
                // same time. This will take care of the situation.
                if (_isHandlingCallback)
                {
                    return;
                }

                _isHandlingCallback = true;
            }

            if (_onDataAvailableCallback != null)
            {
                DataPriorityType prType;
                // now get the fragment and call the callback..
                byte[] result = ReadOrRegisterCallback(_onDataAvailableCallback, out prType);

                if (result != null)
                {
                    // reset the onDataAvailableCallback so that we dont notify
                    // multiple times. we are resetting before actually calling
                    // the callback to make sure the caller calls ReadOrRegisterCallback
                    // at a later point and we dont loose the callback handle.
                    OnDataAvailableCallback realCallback = _onDataAvailableCallback;
                    _onDataAvailableCallback = null;
                    realCallback(result, prType);
                }
            }

            _isHandlingCallback = false;
        }
Ejemplo n.º 3
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);
            }
        }
Ejemplo n.º 4
0
 internal SerializedDataStream(int fragmentSize, OnDataAvailableCallback callbackToNotify) : this(fragmentSize)
 {
     if (callbackToNotify != null)
     {
         this.notifyOnWriteFragmentImmediately = true;
         this.onDataAvailableCallback          = callbackToNotify;
     }
 }
Ejemplo n.º 5
0
 internal SerializedDataStream(int fragmentSize, OnDataAvailableCallback callbackToNotify) : this(fragmentSize)
 {
     if (callbackToNotify != null)
     {
         this.notifyOnWriteFragmentImmediately = true;
         this.onDataAvailableCallback = callbackToNotify;
     }
 }
Ejemplo n.º 6
0
 internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback)
 {
     lock (this.syncObject)
     {
         if (this.length <= 0L)
         {
             this.onDataAvailableCallback = callback;
             return(null);
         }
         int    count  = (this.length > this.fragmentSize) ? this.fragmentSize : ((int)this.length);
         byte[] buffer = new byte[count];
         this.Read(buffer, 0, count);
         return(buffer);
     }
 }
Ejemplo n.º 7
0
        /// <summary>
        /// Returns a byte[] which holds data of fragment size (or) serialized data of
        /// one object, which ever is greater. If data is not currently available, then
        /// the callback is registered and called whenever the data is available.
        /// </summary>
        /// <param name="callback">
        /// callback to call once the data becomes available.
        /// </param>
        /// <returns>
        /// a byte[] holding data read from the stream
        /// </returns>
        internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback)
        {
            lock (_syncObject)
            {
                if (_length <= 0)
                {
                    _onDataAvailableCallback = callback;
                    return(null);
                }

                int    bytesToRead = _length > _fragmentSize ? _fragmentSize : (int)_length;
                byte[] result      = new byte[bytesToRead];
                Read(result, 0, bytesToRead);
                return(result);
            }
        }
 internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback, out DataPriorityType priorityType)
 {
     lock (this.readSyncObject)
     {
         priorityType = DataPriorityType.Default;
         byte[] buffer = null;
         buffer       = this.dataToBeSent[1].ReadOrRegisterCallback(this.onSendCollectionDataAvailable);
         priorityType = DataPriorityType.PromptResponse;
         if (buffer == null)
         {
             buffer       = this.dataToBeSent[0].ReadOrRegisterCallback(this.onSendCollectionDataAvailable);
             priorityType = DataPriorityType.Default;
         }
         if (buffer == null)
         {
             this.onDataAvailableCallback = callback;
         }
         return(buffer);
     }
 }
 private void OnDataAvailable(byte[] data, bool isEndFragment)
 {
     lock (this.readSyncObject)
     {
         if (this.isHandlingCallback)
         {
             return;
         }
         this.isHandlingCallback = true;
     }
     if (this.onDataAvailableCallback != null)
     {
         DataPriorityType type;
         byte[]           buffer = this.ReadOrRegisterCallback(this.onDataAvailableCallback, out type);
         if (buffer != null)
         {
             OnDataAvailableCallback onDataAvailableCallback = this.onDataAvailableCallback;
             this.onDataAvailableCallback = null;
             onDataAvailableCallback(buffer, type);
         }
     }
     this.isHandlingCallback = false;
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Process data coming from the transport. This method analyses the data
        /// and if an object can be created, it creates one and calls the
        /// <paramref name="callback"/> with the deserialized object. This method
        /// does not assume all fragments to be available. So if not enough fragments are
        /// available it will simply return..
        /// </summary>
        /// <param name="data">
        /// Data to process.
        /// </param>
        /// <param name="callback">
        /// Callback to call once a complete deserialized object is available.
        /// </param>
        /// <returns>
        /// Defragmented Object if any, otherwise null.
        /// </returns>
        /// <exception cref="PSRemotingTransportException">
        /// 1. Fragment Ids not in sequence
        /// 2. Object Ids does not match
        /// 3. The current deserialized object size of the received data exceeded
        /// allowed maximum object size. The current deserialized object size is {0}.
        /// Allowed maximum object size is {1}.
        /// </exception>
        /// <remarks>
        /// Might throw other exceptions as the deserialized object is handled here.
        /// </remarks>
        internal void ProcessRawData(byte[] data, OnDataAvailableCallback callback)
        {
            Dbg.Assert(data != null, "Cannot process null data");
            Dbg.Assert(callback != null, "Callback cannot be null");

            lock (_syncObject)
            {
                if (_isDisposed)
                {
                    return;
                }

                _numberOfThreadsProcessing++;
                if (_numberOfThreadsProcessing > _maxNumberOfThreadsToAllowForProcessing)
                {
                    Dbg.Assert(false, "Multiple threads are not allowed in ProcessRawData.");
                }
            }

            try
            {
                _pendingDataStream.Write(data, 0, data.Length);

                // this do loop will process one deserialized object.
                // using a loop allows to process multiple objects within
                // the same packet
                while (true)
                {
                    if (_pendingDataStream.Length <= FragmentedRemoteObject.HeaderLength)
                    {
                        // there is not enough data to be processed.
                        s_baseTracer.WriteLine("Not enough data to process. Data is less than header length. Data length is {0}. Header Length {1}.",
                                               _pendingDataStream.Length, FragmentedRemoteObject.HeaderLength);
                        return;
                    }

                    byte[] dataRead = _pendingDataStream.ToArray();

                    // there is enough data to process here. get the fragment header
                    long objectId = FragmentedRemoteObject.GetObjectId(dataRead, 0);
                    if (objectId <= 0)
                    {
                        throw new PSRemotingTransportException(RemotingErrorIdStrings.ObjectIdCannotBeLessThanZero);
                    }

                    long fragmentId = FragmentedRemoteObject.GetFragmentId(dataRead, 0);
                    bool sFlag      = FragmentedRemoteObject.GetIsStartFragment(dataRead, 0);
                    bool eFlag      = FragmentedRemoteObject.GetIsEndFragment(dataRead, 0);
                    int  blobLength = FragmentedRemoteObject.GetBlobLength(dataRead, 0);

                    if ((s_baseTracer.Options & PSTraceSourceOptions.WriteLine) != PSTraceSourceOptions.None)
                    {
                        s_baseTracer.WriteLine("Object Id: {0}", objectId);
                        s_baseTracer.WriteLine("Fragment Id: {0}", fragmentId);
                        s_baseTracer.WriteLine("Start Flag: {0}", sFlag);
                        s_baseTracer.WriteLine("End Flag: {0}", eFlag);
                        s_baseTracer.WriteLine("Blob Length: {0}", blobLength);
                    }

                    int totalLengthOfFragment = 0;

                    try
                    {
                        totalLengthOfFragment = checked (FragmentedRemoteObject.HeaderLength + blobLength);
                    }
                    catch (System.OverflowException)
                    {
                        s_baseTracer.WriteLine("Fragment too big.");
                        ResetReceiveData();
                        PSRemotingTransportException e = new PSRemotingTransportException(RemotingErrorIdStrings.ObjectIsTooBig);
                        throw e;
                    }

                    if (_pendingDataStream.Length < totalLengthOfFragment)
                    {
                        s_baseTracer.WriteLine("Not enough data to process packet. Data is less than expected blob length. Data length {0}. Expected Length {1}.",
                                               _pendingDataStream.Length, totalLengthOfFragment);
                        return;
                    }

                    // ensure object size limit is not reached
                    if (_maxReceivedObjectSize.HasValue)
                    {
                        _totalReceivedObjectSizeSoFar = unchecked (_totalReceivedObjectSizeSoFar + totalLengthOfFragment);
                        if ((_totalReceivedObjectSizeSoFar < 0) || (_totalReceivedObjectSizeSoFar > _maxReceivedObjectSize.Value))
                        {
                            s_baseTracer.WriteLine("ObjectSize > MaxReceivedObjectSize. ObjectSize is {0}. MaxReceivedObjectSize is {1}",
                                                   _totalReceivedObjectSizeSoFar, _maxReceivedObjectSize);
                            PSRemotingTransportException e = null;

                            if (_isCreateByClientTM)
                            {
                                e = new PSRemotingTransportException(PSRemotingErrorId.ReceivedObjectSizeExceededMaximumClient,
                                                                     RemotingErrorIdStrings.ReceivedObjectSizeExceededMaximumClient,
                                                                     _totalReceivedObjectSizeSoFar, _maxReceivedObjectSize);
                            }
                            else
                            {
                                e = new PSRemotingTransportException(PSRemotingErrorId.ReceivedObjectSizeExceededMaximumServer,
                                                                     RemotingErrorIdStrings.ReceivedObjectSizeExceededMaximumServer,
                                                                     _totalReceivedObjectSizeSoFar, _maxReceivedObjectSize);
                            }

                            ResetReceiveData();
                            throw e;
                        }
                    }

                    // appears like stream doesn't have individual position marker for read and write
                    // since we are going to read from now...
                    _pendingDataStream.Seek(0, SeekOrigin.Begin);

                    // we have enough data to process..so read the data from the stream and process.
                    byte[] oneFragment = new byte[totalLengthOfFragment];
                    // this will change position back to totalLengthOfFragment
                    int dataCount = _pendingDataStream.Read(oneFragment, 0, totalLengthOfFragment);
                    Dbg.Assert(dataCount == totalLengthOfFragment, "Unable to read enough data from the stream. Read failed");

                    PSEtwLog.LogAnalyticVerbose(
                        PSEventId.ReceivedRemotingFragment, PSOpcode.Receive, PSTask.None,
                        PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic,
                        (Int64)objectId,
                        (Int64)fragmentId,
                        sFlag ? 1 : 0,
                        eFlag ? 1 : 0,
                        (UInt32)blobLength,
                        new PSETWBinaryBlob(oneFragment, FragmentedRemoteObject.HeaderLength, blobLength));

                    byte[] extraData = null;
                    if (totalLengthOfFragment < _pendingDataStream.Length)
                    {
                        // there is more data in the stream than fragment size..so save that data
                        extraData = new byte[_pendingDataStream.Length - totalLengthOfFragment];
                        _pendingDataStream.Read(extraData, 0, (int)(_pendingDataStream.Length - totalLengthOfFragment));
                    }

                    // reset incoming stream.
                    _pendingDataStream.Dispose();
                    _pendingDataStream = new MemoryStream();
                    if (extraData != null)
                    {
                        _pendingDataStream.Write(extraData, 0, extraData.Length);
                    }

                    if (sFlag)
                    {
                        _canIgnoreOffSyncFragments = false; // reset this upon receiving a start fragment of a fresh object
                        _currentObjectId           = objectId;
                        // Memory streams created with an unsigned byte array provide a non-resizable stream view
                        // of the data, and can only be written to. When using a byte array, you can neither append
                        // to nor shrink the stream, although you might be able to modify the existing contents
                        // depending on the parameters passed into the constructor. Empty memory streams are
                        // resizable, and can be written to and read from.
                        _dataToProcessStream = new MemoryStream();
                    }
                    else
                    {
                        // check if the data belongs to the same object as the start fragment
                        if (objectId != _currentObjectId)
                        {
                            s_baseTracer.WriteLine("ObjectId != CurrentObjectId");
                            // TODO - drop an ETW event
                            ResetReceiveData();
                            if (!_canIgnoreOffSyncFragments)
                            {
                                PSRemotingTransportException e = new PSRemotingTransportException(RemotingErrorIdStrings.ObjectIdsNotMatching);
                                throw e;
                            }
                            else
                            {
                                s_baseTracer.WriteLine("Ignoring ObjectId != CurrentObjectId");
                                continue;
                            }
                        }

                        if (fragmentId != (_currentFrgId + 1))
                        {
                            s_baseTracer.WriteLine("Fragment Id is not in sequence.");
                            // TODO - drop an ETW event
                            ResetReceiveData();
                            if (!_canIgnoreOffSyncFragments)
                            {
                                PSRemotingTransportException e = new PSRemotingTransportException(RemotingErrorIdStrings.FragmentIdsNotInSequence);
                                throw e;
                            }
                            else
                            {
                                s_baseTracer.WriteLine("Ignoring Fragment Id is not in sequence.");
                                continue;
                            }
                        }
                    }

                    // make fragment id from this packet as the current fragment id
                    _currentFrgId = fragmentId;
                    // store the blob in a separate stream
                    _dataToProcessStream.Write(oneFragment, FragmentedRemoteObject.HeaderLength, blobLength);

                    if (eFlag)
                    {
                        try
                        {
                            // appears like stream doesn't individual position marker for read and write
                            // since we are going to read from now..i am resetting position to 0.
                            _dataToProcessStream.Seek(0, SeekOrigin.Begin);
                            RemoteDataObject <PSObject> remoteObject = RemoteDataObject <PSObject> .CreateFrom(_dataToProcessStream, _defragmentor);

                            s_baseTracer.WriteLine("Runspace Id: {0}", remoteObject.RunspacePoolId);
                            s_baseTracer.WriteLine("PowerShell Id: {0}", remoteObject.PowerShellId);
                            // notify the caller that a deserialized object is available.
                            callback(remoteObject);
                        }
                        finally
                        {
                            // Reset the receive data buffers and start the process again.
                            ResetReceiveData();
                        }

                        if (_isDisposed)
                        {
                            break;
                        }
                    }
                }
            }
            finally
            {
                lock (_syncObject)
                {
                    if (_isDisposed && (_numberOfThreadsProcessing == 1))
                    {
                        ReleaseResources();
                    }

                    _numberOfThreadsProcessing--;
                }
            }
        }
Ejemplo n.º 11
0
        internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback)
        {
            lock (this.syncObject)
			{
                if (this.length <= 0L)
                {
                    this.onDataAvailableCallback = callback;
                    return null;
                }
                int count = (this.length > this.fragmentSize) ? this.fragmentSize : ((int) this.length);
                byte[] buffer = new byte[count];
                this.Read(buffer, 0, count);
                return buffer;
            }
        }
Ejemplo n.º 12
0
        internal void ProcessRawData(byte[] data, OnDataAvailableCallback callback)
        {
            lock (this.syncObject)
            {
                if (this.isDisposed)
                {
                    return;
                }
                this.numberOfThreadsProcessing++;
                int maxNumberOfThreadsToAllowForProcessing = this.maxNumberOfThreadsToAllowForProcessing;
                int numberOfThreadsProcessing = this.numberOfThreadsProcessing;
            }
            try
            {
                this.pendingDataStream.Write(data, 0, data.Length);
Label_005A:
                if (this.pendingDataStream.Length <= 0x15L)
                {
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Not enough data to process. Data is less than header length. Data length is {0}. Header Length {1}.", new object[] { this.pendingDataStream.Length, 0x15 }), new object[0]);
                }
                else
                {
                    byte[] fragmentBytes = this.pendingDataStream.GetBuffer();
                    long   objectId      = FragmentedRemoteObject.GetObjectId(fragmentBytes, 0);
                    if (objectId <= 0L)
                    {
                        throw new PSRemotingTransportException(RemotingErrorIdStrings.ObjectIdCannotBeLessThanZero);
                    }
                    long fragmentId      = FragmentedRemoteObject.GetFragmentId(fragmentBytes, 0);
                    bool isStartFragment = FragmentedRemoteObject.GetIsStartFragment(fragmentBytes, 0);
                    bool isEndFragment   = FragmentedRemoteObject.GetIsEndFragment(fragmentBytes, 0);
                    int  blobLength      = FragmentedRemoteObject.GetBlobLength(fragmentBytes, 0);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Object Id: {0}", new object[] { objectId }), new object[0]);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Fragment Id: {0}", new object[] { fragmentId }), new object[0]);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Start Flag: {0}", new object[] { isStartFragment }), new object[0]);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "End Flag: {0}", new object[] { isEndFragment }), new object[0]);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Blob Length: {0}", new object[] { blobLength }), new object[0]);
                    int count = 0;
                    try
                    {
                        count = 0x15 + blobLength;
                    }
                    catch (OverflowException)
                    {
                        baseTracer.WriteLine("Fragement too big.", new object[0]);
                        this.ResetRecieveData();
                        PSRemotingTransportException exception = new PSRemotingTransportException(RemotingErrorIdStrings.ObjectIsTooBig);
                        throw exception;
                    }
                    if (this.pendingDataStream.Length < count)
                    {
                        baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Not enough data to process packet. Data is less than expected blob length. Data length {0}. Expected Length {1}.", new object[] { this.pendingDataStream.Length, count }), new object[0]);
                    }
                    else
                    {
                        if (this.maxReceivedObjectSize.HasValue)
                        {
                            this.totalReceivedObjectSizeSoFar += count;
                            if ((this.totalReceivedObjectSizeSoFar < 0) || (this.totalReceivedObjectSizeSoFar > this.maxReceivedObjectSize.Value))
                            {
                                baseTracer.WriteLine("ObjectSize > MaxReceivedObjectSize. ObjectSize is {0}. MaxReceivedObjectSize is {1}", new object[] { this.totalReceivedObjectSizeSoFar, this.maxReceivedObjectSize });
                                PSRemotingTransportException exception2 = null;
                                if (this.isCreateByClientTM)
                                {
                                    exception2 = new PSRemotingTransportException(PSRemotingErrorId.ReceivedObjectSizeExceededMaximumClient, RemotingErrorIdStrings.ReceivedObjectSizeExceededMaximumClient, new object[] { this.totalReceivedObjectSizeSoFar, this.maxReceivedObjectSize });
                                }
                                else
                                {
                                    exception2 = new PSRemotingTransportException(PSRemotingErrorId.ReceivedObjectSizeExceededMaximumServer, RemotingErrorIdStrings.ReceivedObjectSizeExceededMaximumServer, new object[] { this.totalReceivedObjectSizeSoFar, this.maxReceivedObjectSize });
                                }
                                this.ResetRecieveData();
                                throw exception2;
                            }
                        }
                        this.pendingDataStream.Seek(0L, SeekOrigin.Begin);
                        byte[] buffer = new byte[count];
                        this.pendingDataStream.Read(buffer, 0, count);
                        PSEtwLog.LogAnalyticVerbose(PSEventId.ReceivedRemotingFragment, PSOpcode.Receive, PSTask.None, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, objectId, fragmentId, isStartFragment ? 1 : 0, isEndFragment ? 1 : 0, (int)blobLength, new PSETWBinaryBlob(buffer, 0x15, blobLength));
                        byte[] buffer3 = null;
                        if (count < this.pendingDataStream.Length)
                        {
                            buffer3 = new byte[this.pendingDataStream.Length - count];
                            this.pendingDataStream.Read(buffer3, 0, ((int)this.pendingDataStream.Length) - count);
                        }
                        this.pendingDataStream.Close();
                        this.pendingDataStream = new MemoryStream();
                        if (buffer3 != null)
                        {
                            this.pendingDataStream.Write(buffer3, 0, buffer3.Length);
                        }
                        if (isStartFragment)
                        {
                            this.canIgnoreOffSyncFragments = false;
                            this.currentObjectId           = objectId;
                            this.dataToProcessStream       = new MemoryStream();
                        }
                        else
                        {
                            if (objectId != this.currentObjectId)
                            {
                                baseTracer.WriteLine("ObjectId != CurrentObjectId", new object[0]);
                                this.ResetRecieveData();
                                if (!this.canIgnoreOffSyncFragments)
                                {
                                    PSRemotingTransportException exception3 = new PSRemotingTransportException(RemotingErrorIdStrings.ObjectIdsNotMatching);
                                    throw exception3;
                                }
                                baseTracer.WriteLine("Ignoring ObjectId != CurrentObjectId", new object[0]);
                                goto Label_005A;
                            }
                            if (fragmentId != (this.currentFrgId + 1L))
                            {
                                baseTracer.WriteLine("Fragment Id is not in sequence.", new object[0]);
                                this.ResetRecieveData();
                                if (!this.canIgnoreOffSyncFragments)
                                {
                                    PSRemotingTransportException exception4 = new PSRemotingTransportException(RemotingErrorIdStrings.FragmetIdsNotInSequence);
                                    throw exception4;
                                }
                                baseTracer.WriteLine("Ignoring Fragment Id is not in sequence.", new object[0]);
                                goto Label_005A;
                            }
                        }
                        this.currentFrgId = fragmentId;
                        this.dataToProcessStream.Write(buffer, 0x15, blobLength);
                        if (!isEndFragment)
                        {
                            goto Label_005A;
                        }
                        try
                        {
                            this.dataToProcessStream.Seek(0L, SeekOrigin.Begin);
                            RemoteDataObject <PSObject> obj2 = RemoteDataObject <PSObject> .CreateFrom(this.dataToProcessStream, this.defragmentor);

                            baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Runspace Id: {0}", new object[] { obj2.RunspacePoolId }), new object[0]);
                            baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "PowerShell Id: {0}", new object[] { obj2.PowerShellId }), new object[0]);
                            callback(obj2);
                        }
                        finally
                        {
                            this.ResetRecieveData();
                        }
                        if (!this.isDisposed && this.pendingDataStream.Length > 0x15L)
                        {
                            goto Label_005A;
                        }
                    }
                }
            }
            finally
            {
                lock (this.syncObject)
                {
                    if (this.isDisposed && (this.numberOfThreadsProcessing == 1))
                    {
                        this.ReleaseResources();
                    }
                    this.numberOfThreadsProcessing--;
                }
            }
        }
Ejemplo n.º 13
0
        internal void ProcessRawData(byte[] data, OnDataAvailableCallback callback)
        {
            lock (this.syncObject)
            {
                if (this.isDisposed)
                {
                    return;
                }
                this.numberOfThreadsProcessing++;
                int maxNumberOfThreadsToAllowForProcessing = this.maxNumberOfThreadsToAllowForProcessing;
                int numberOfThreadsProcessing = this.numberOfThreadsProcessing;
            }
            try
            {
                this.pendingDataStream.Write(data, 0, data.Length);
            Label_005A:
                if (this.pendingDataStream.Length <= 0x15L)
                {
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Not enough data to process. Data is less than header length. Data length is {0}. Header Length {1}.", new object[] { this.pendingDataStream.Length, 0x15 }), new object[0]);
                }
                else
                {
                    byte[] fragmentBytes = this.pendingDataStream.GetBuffer();
                    long objectId = FragmentedRemoteObject.GetObjectId(fragmentBytes, 0);
                    if (objectId <= 0L)
                    {
                        throw new PSRemotingTransportException(RemotingErrorIdStrings.ObjectIdCannotBeLessThanZero);
                    }
                    long fragmentId = FragmentedRemoteObject.GetFragmentId(fragmentBytes, 0);
                    bool isStartFragment = FragmentedRemoteObject.GetIsStartFragment(fragmentBytes, 0);
                    bool isEndFragment = FragmentedRemoteObject.GetIsEndFragment(fragmentBytes, 0);
                    int blobLength = FragmentedRemoteObject.GetBlobLength(fragmentBytes, 0);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Object Id: {0}", new object[] { objectId }), new object[0]);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Fragment Id: {0}", new object[] { fragmentId }), new object[0]);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Start Flag: {0}", new object[] { isStartFragment }), new object[0]);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "End Flag: {0}", new object[] { isEndFragment }), new object[0]);
                    baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Blob Length: {0}", new object[] { blobLength }), new object[0]);
                    int count = 0;
                    try
                    {
                        count = 0x15 + blobLength;
                    }
                    catch (OverflowException)
                    {
                        baseTracer.WriteLine("Fragement too big.", new object[0]);
                        this.ResetRecieveData();
                        PSRemotingTransportException exception = new PSRemotingTransportException(RemotingErrorIdStrings.ObjectIsTooBig);
                        throw exception;
                    }
                    if (this.pendingDataStream.Length < count)
                    {
                        baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Not enough data to process packet. Data is less than expected blob length. Data length {0}. Expected Length {1}.", new object[] { this.pendingDataStream.Length, count }), new object[0]);
                    }
                    else
                    {
                        if (this.maxReceivedObjectSize.HasValue)
                        {
                            this.totalReceivedObjectSizeSoFar += count;
                            if ((this.totalReceivedObjectSizeSoFar < 0) || (this.totalReceivedObjectSizeSoFar > this.maxReceivedObjectSize.Value))
                            {
                                baseTracer.WriteLine("ObjectSize > MaxReceivedObjectSize. ObjectSize is {0}. MaxReceivedObjectSize is {1}", new object[] { this.totalReceivedObjectSizeSoFar, this.maxReceivedObjectSize });
                                PSRemotingTransportException exception2 = null;
                                if (this.isCreateByClientTM)
                                {
                                    exception2 = new PSRemotingTransportException(PSRemotingErrorId.ReceivedObjectSizeExceededMaximumClient, RemotingErrorIdStrings.ReceivedObjectSizeExceededMaximumClient, new object[] { this.totalReceivedObjectSizeSoFar, this.maxReceivedObjectSize });
                                }
                                else
                                {
                                    exception2 = new PSRemotingTransportException(PSRemotingErrorId.ReceivedObjectSizeExceededMaximumServer, RemotingErrorIdStrings.ReceivedObjectSizeExceededMaximumServer, new object[] { this.totalReceivedObjectSizeSoFar, this.maxReceivedObjectSize });
                                }
                                this.ResetRecieveData();
                                throw exception2;
                            }
                        }
                        this.pendingDataStream.Seek(0L, SeekOrigin.Begin);
                        byte[] buffer = new byte[count];
                        this.pendingDataStream.Read(buffer, 0, count);
                        PSEtwLog.LogAnalyticVerbose(PSEventId.ReceivedRemotingFragment, PSOpcode.Receive, PSTask.None, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, objectId, fragmentId, isStartFragment ? 1 : 0, isEndFragment ? 1 : 0, (int) blobLength, new PSETWBinaryBlob(buffer, 0x15, blobLength));
                        byte[] buffer3 = null;
                        if (count < this.pendingDataStream.Length)
                        {
                            buffer3 = new byte[this.pendingDataStream.Length - count];
                            this.pendingDataStream.Read(buffer3, 0, ((int) this.pendingDataStream.Length) - count);
                        }
                        this.pendingDataStream.Close();
                        this.pendingDataStream = new MemoryStream();
                        if (buffer3 != null)
                        {
                            this.pendingDataStream.Write(buffer3, 0, buffer3.Length);
                        }
                        if (isStartFragment)
                        {
                            this.canIgnoreOffSyncFragments = false;
                            this.currentObjectId = objectId;
                            this.dataToProcessStream = new MemoryStream();
                        }
                        else
                        {
                            if (objectId != this.currentObjectId)
                            {
                                baseTracer.WriteLine("ObjectId != CurrentObjectId", new object[0]);
                                this.ResetRecieveData();
                                if (!this.canIgnoreOffSyncFragments)
                                {
                                    PSRemotingTransportException exception3 = new PSRemotingTransportException(RemotingErrorIdStrings.ObjectIdsNotMatching);
                                    throw exception3;
                                }
                                baseTracer.WriteLine("Ignoring ObjectId != CurrentObjectId", new object[0]);
                                goto Label_005A;
                            }
                            if (fragmentId != (this.currentFrgId + 1L))
                            {
                                baseTracer.WriteLine("Fragment Id is not in sequence.", new object[0]);
                                this.ResetRecieveData();
                                if (!this.canIgnoreOffSyncFragments)
                                {
                                    PSRemotingTransportException exception4 = new PSRemotingTransportException(RemotingErrorIdStrings.FragmetIdsNotInSequence);
                                    throw exception4;
                                }
                                baseTracer.WriteLine("Ignoring Fragment Id is not in sequence.", new object[0]);
                                goto Label_005A;
                            }
                        }
                        this.currentFrgId = fragmentId;
                        this.dataToProcessStream.Write(buffer, 0x15, blobLength);
                        if (!isEndFragment)
                        {
                            goto Label_005A;
                        }
                        try
                        {
                            this.dataToProcessStream.Seek(0L, SeekOrigin.Begin);
                            RemoteDataObject<PSObject> obj2 = RemoteDataObject<PSObject>.CreateFrom(this.dataToProcessStream, this.defragmentor);
                            baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Runspace Id: {0}", new object[] { obj2.RunspacePoolId }), new object[0]);
                            baseTracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "PowerShell Id: {0}", new object[] { obj2.PowerShellId }), new object[0]);
                            callback(obj2);
                        }
                        finally
                        {
                            this.ResetRecieveData();
                        }
						if (!this.isDisposed && this.pendingDataStream.Length > 0x15L)
                        {
                            goto Label_005A;
                        }
                    }
                }
            }
            finally
            {
                lock (this.syncObject)
                {
                    if (this.isDisposed && (this.numberOfThreadsProcessing == 1))
                    {
                        this.ReleaseResources();
                    }
                    this.numberOfThreadsProcessing--;
                }
            }
        }