/// <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); } }
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; }
/// <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); } }
internal SerializedDataStream(int fragmentSize, OnDataAvailableCallback callbackToNotify) : this(fragmentSize) { if (callbackToNotify != null) { this.notifyOnWriteFragmentImmediately = true; this.onDataAvailableCallback = callbackToNotify; } }
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); } }
/// <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; }
/// <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--; } } }
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; } }
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--; } } }
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--; } } }