internal override void SendNegotiationAsync() { using (ServerRemoteSessionDSHandlerlImpl._trace.TraceMethod()) { RemoteDataObject sessionCapability = RemotingEncoder.GenerateServerSessionCapability(this._session.Context.ServerCapability, Guid.Empty); this._stateMachine.RaiseEvent(new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationSendCompleted)); this._transportManager.SendDataToClient <PSObject>(RemoteDataObject <PSObject> .CreateFrom(sessionCapability.Destination, sessionCapability.DataType, sessionCapability.RunspacePoolId, sessionCapability.PowerShellId, (PSObject)sessionCapability.Data), false); } }
internal override void SendNegotiationAsync() { RemoteDataObject obj2 = RemotingEncoder.GenerateServerSessionCapability(this._session.Context.ServerCapability, Guid.Empty); RemoteSessionStateMachineEventArgs fsmEventArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationSendCompleted); this._stateMachine.RaiseEvent(fsmEventArg); RemoteDataObject <PSObject> data = RemoteDataObject <PSObject> .CreateFrom(obj2.Destination, obj2.DataType, obj2.RunspacePoolId, obj2.PowerShellId, (PSObject)obj2.Data); this._transportManager.SendDataToClient <PSObject>(data, false, false); }
private void ProcessSessionMessages(RemoteDataEventArgs arg) { using (ClientRemoteSessionDSHandlerImpl._trace.TraceMethod()) { RemoteDataObject <PSObject> remoteDataObject = arg != null && arg.ReceivedData != null ? arg.ReceivedData : throw ClientRemoteSessionDSHandlerImpl._trace.NewArgumentNullException(nameof(arg)); int targetInterface = (int)remoteDataObject.TargetInterface; RemotingDataType dataType = remoteDataObject.DataType; switch (dataType) { case RemotingDataType.SessionCapability: RemoteSessionCapability sessionCapability; try { sessionCapability = RemotingDecoder.GetSessionCapability((object)remoteDataObject.Data); } catch (PSRemotingDataStructureException ex) { throw new PSRemotingDataStructureException(PSRemotingErrorId.ClientNotFoundCapabilityProperties, new object[3] { (object)ex.Message, (object)PSVersionInfo.BuildVersion, (object)RemotingConstants.ProtocolVersion }); } this._stateMachine.RaiseEvent(new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationReceived) { RemoteSessionCapability = sessionCapability }); if (this.NegotiationReceived == null) { break; } this.NegotiationReceived((object)this, new RemoteSessionNegotiationEventArgs(sessionCapability)); break; case RemotingDataType.CloseSession: this._stateMachine.RaiseEvent(new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close, (Exception) new PSRemotingDataStructureException(PSRemotingErrorId.ServerRequestedToCloseSession, new object[0]))); break; case RemotingDataType.EncryptedSessionKey: this.EncryptedSessionKeyReceived((object)this, new RemoteDataEventArgs <string>((object)RemotingDecoder.GetEncryptedSessionKey(remoteDataObject.Data))); break; case RemotingDataType.PublicKeyRequest: this.PublicKeyRequestReceived((object)this, new RemoteDataEventArgs <string>((object)string.Empty)); break; default: throw new PSRemotingDataStructureException(PSRemotingErrorId.ReceivedUnsupportedAction, new object[1] { (object)dataType }); } } }
private void ProcessSessionMessages(RemoteDataEventArgs arg) { if ((arg == null) || (arg.ReceivedData == null)) { throw PSTraceSource.NewArgumentNullException("arg"); } RemoteDataObject <PSObject> receivedData = arg.ReceivedData; RemotingTargetInterface targetInterface = receivedData.TargetInterface; RemotingDataType dataType = receivedData.DataType; switch (dataType) { case RemotingDataType.SessionCapability: { RemoteSessionCapability remoteSessionCapability = null; try { remoteSessionCapability = RemotingDecoder.GetSessionCapability(receivedData.Data); } catch (PSRemotingDataStructureException exception2) { throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ClientNotFoundCapabilityProperties, new object[] { exception2.Message, PSVersionInfo.BuildVersion, RemotingConstants.ProtocolVersion }); } RemoteSessionStateMachineEventArgs args2 = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationReceived) { RemoteSessionCapability = remoteSessionCapability }; this._stateMachine.RaiseEvent(args2, false); RemoteSessionNegotiationEventArgs eventArgs = new RemoteSessionNegotiationEventArgs(remoteSessionCapability); this.NegotiationReceived.SafeInvoke <RemoteSessionNegotiationEventArgs>(this, eventArgs); return; } case RemotingDataType.CloseSession: { PSRemotingDataStructureException reason = new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerRequestedToCloseSession); RemoteSessionStateMachineEventArgs args = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close, reason); this._stateMachine.RaiseEvent(args, false); return; } case RemotingDataType.EncryptedSessionKey: { string encryptedSessionKey = RemotingDecoder.GetEncryptedSessionKey(receivedData.Data); this.EncryptedSessionKeyReceived.SafeInvoke <RemoteDataEventArgs <string> >(this, new RemoteDataEventArgs <string>(encryptedSessionKey)); return; } case RemotingDataType.PublicKeyRequest: this.PublicKeyRequestReceived.SafeInvoke <RemoteDataEventArgs <string> >(this, new RemoteDataEventArgs <string>(string.Empty)); return; } throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ReceivedUnsupportedAction, new object[] { dataType }); }
/// <summary> /// This processes the object received from transport which are /// not targeted for session /// </summary> /// <param name="rcvdData"> /// received data. /// </param> internal void ProcessNonSessionMessages(RemoteDataObject <PSObject> rcvdData) { // TODO: Consider changing to Dbg.Assert() if (rcvdData == null) { throw PSTraceSource.NewArgumentNullException("rcvdData"); } RemotingTargetInterface targetInterface = rcvdData.TargetInterface; Guid clientRunspacePoolId; RemoteRunspacePoolInternal runspacePool; switch (targetInterface) { case RemotingTargetInterface.Session: Dbg.Assert(false, "The session remote data is handled my session data structure handler, not here"); break; case RemotingTargetInterface.RunspacePool: clientRunspacePoolId = rcvdData.RunspacePoolId; runspacePool = _session.GetRunspacePool(clientRunspacePoolId); if (runspacePool != null) { // GETBACK runspacePool.DataStructureHandler.ProcessReceivedData(rcvdData); } else { // The runspace pool may have been removed on the client side, // so, we should just ignore the message. s_trace.WriteLine(@"Client received data for Runspace (id: {0}), but the Runspace cannot be found", clientRunspacePoolId); } break; case RemotingTargetInterface.PowerShell: clientRunspacePoolId = rcvdData.RunspacePoolId; runspacePool = _session.GetRunspacePool(clientRunspacePoolId); // GETBACK runspacePool.DataStructureHandler.DispatchMessageToPowerShell(rcvdData); break; default: break; } }
internal void Fragment <T>(RemoteDataObject <T> obj, SerializedDataStream dataToBeSent) { dataToBeSent.Enter(); try { obj.Serialize(dataToBeSent, this); } finally { dataToBeSent.Exit(); } }
internal void Execute(Action <ErrorRecord> writeErrorAction) { if (this._remoteHostCall.IsVoidMethod) { this.ExecuteVoid(writeErrorAction); } else { RemotingDataType dataType = (this._clientPowerShellId == Guid.Empty) ? RemotingDataType.RemoteRunspaceHostResponseData : RemotingDataType.RemotePowerShellHostResponseData; RemoteDataObject <PSObject> data = RemoteDataObject <PSObject> .CreateFrom(RemotingDestination.InvalidDestination | RemotingDestination.Server, dataType, this._clientRunspacePoolId, this._clientPowerShellId, this._remoteHostCall.ExecuteNonVoidMethod(this._clientHost).Encode()); this._transportManager.DataToBeSentCollection.Add <PSObject>(data, DataPriorityType.PromptResponse); } }
internal T ExecuteMethod <T>(RemoteHostMethodId methodId, object[] parameters) { long newCallId = this._serverDispatchTable.CreateNewCallId(); this._transportManager.SendDataToClient <PSObject>(RemoteDataObject <PSObject> .CreateFrom(RemotingDestination.Client, this._remoteHostCallDataType, this._clientRunspacePoolId, this._clientPowerShellId, new RemoteHostCall(newCallId, methodId, parameters).Encode()), false); RemoteHostResponse response = this._serverDispatchTable.GetResponse(newCallId, (RemoteHostResponse)null); if (response == null) { throw RemoteHostExceptions.NewRemoteHostCallFailedException(methodId); } response.SimulateExecution(); return((T)response.SimulateExecution()); }
/// <summary> /// Adds data to this collection. The data is fragmented in this method /// before being stored into the collection. So the calling thread /// will get affected, if it tries to add a huge object. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="data"> /// data to be added to the collection. Caller should make sure this is not /// null. /// </param> /// <param name="priority"> /// Priority of the data. /// </param> internal void Add <T>(RemoteDataObject <T> data, DataPriorityType priority) { Dbg.Assert(data != null, "Cannot send null data object"); Dbg.Assert(_fragmentor != null, "Fragmentor cannot be null while adding objects"); Dbg.Assert(_dataToBeSent != null, "Serialized streams are not initialized"); // make sure the only one object is fragmented and added to the collection // at any give time. This way the order of fragment is maintained // in the SendDataCollection(s). lock (_dataSyncObjects[(int)priority]) { _fragmentor.Fragment <T>(data, _dataToBeSent[(int)priority]); } }
/// <summary> /// Clubing negotiation packet + runspace creation and then doing transportManager.ConnectAsync(). /// This will save us 2 network calls by doing all the work in one network call. /// </summary> private void HandleNegotiationSendingStateChange() { RemoteSessionCapability clientCapability = _session.Context.ClientCapability; Dbg.Assert(clientCapability.RemotingDestination == RemotingDestination.Server, "Expected clientCapability.RemotingDestination == RemotingDestination.Server"); //Encode and send the negotiation reply RemoteDataObject data = RemotingEncoder.GenerateClientSessionCapability( clientCapability, _session.RemoteRunspacePoolInternal.InstanceId); RemoteDataObject <PSObject> dataAsPSObject = RemoteDataObject <PSObject> .CreateFrom( data.Destination, data.DataType, data.RunspacePoolId, data.PowerShellId, (PSObject)data.Data); _transportManager.DataToBeSentCollection.Add <PSObject>(dataAsPSObject); }
/// <summary> /// The method performs the fragmentation operation. /// All fragments of the same object have the same ObjectId. /// All fragments of the same object have the same ObjectId. /// Each fragment has its own Fragment Id. Fragment Id always starts from zero (0), /// and increments sequentially with an increment of 1. /// The last fragment is indicated by an End of Fragment marker. /// </summary> /// <param name="obj"> /// The object to be fragmented. Caller should make sure this is not null. /// </param> /// <param name="dataToBeSent"> /// Caller specified dataToStore to which the fragments are added /// one-by-one /// </param> internal void Fragment <T>(RemoteDataObject <T> obj, SerializedDataStream dataToBeSent) { Dbg.Assert(obj != null, "Cannot fragment a null object"); Dbg.Assert(dataToBeSent != null, "SendDataCollection cannot be null"); dataToBeSent.Enter(); try { obj.Serialize(dataToBeSent, this); } finally { dataToBeSent.Exit(); } }
private void HandleCreateRunspacePool(object sender, RemoteDataEventArgs createRunspaceEventArg) { using (ServerRemoteSession._trace.TraceMethod()) { RemoteDataObject <PSObject> remoteDataObject = createRunspaceEventArg != null ? createRunspaceEventArg.ReceivedData : throw ServerRemoteSession._trace.NewArgumentNullException(nameof(createRunspaceEventArg)); if (this._context != null) { this._senderInfo.ClientTimeZone = this._context.ClientCapability.TimeZone; } this._senderInfo.ApplicationArguments = RemotingDecoder.GetApplicationArguments(remoteDataObject.Data); ConfigurationDataFromXML configData = PSSessionConfiguration.LoadEndPointConfiguration(this._configProviderId, this._initParameters); configData.InitializationScriptForOutOfProcessRunspace = this._initScriptForOutOfProcRS; this.maxRecvdObjectSize = configData.MaxReceivedObjectSizeMB; this.maxRecvdDataSizeCommand = configData.MaxReceivedCommandSizeMB; this._sessionConfigProvider = configData.CreateEndPointConfigurationInstance(); PSPrimitiveDictionary applicationPrivateData = this._sessionConfigProvider.GetApplicationPrivateData(this._senderInfo); InitialSessionState initialSessionState = this._sessionConfigProvider.GetInitialSessionState(this._senderInfo); if (initialSessionState == null) { throw ServerRemoteSession._trace.NewInvalidOperationException("RemotingErrorIdStrings", "InitialSessionStateNull", (object)this._configProviderId); } initialSessionState.ThrowOnRunspaceOpenError = true; initialSessionState.Variables.Add(new SessionStateVariableEntry("PSSenderInfo", (object)this._senderInfo, PSRemotingErrorInvariants.FormatResourceString(PSRemotingErrorId.PSSenderInfoDescription), ScopedItemOptions.ReadOnly)); if (!string.IsNullOrEmpty(configData.EndPointConfigurationTypeName)) { this.maxRecvdObjectSize = this._sessionConfigProvider.GetMaximumReceivedObjectSize(this._senderInfo); this.maxRecvdDataSizeCommand = this._sessionConfigProvider.GetMaximumReceivedDataSizePerCommand(this._senderInfo); } this._sessionDSHandler.TransportManager.ReceivedDataCollection.MaximumReceivedObjectSize = this.maxRecvdObjectSize; Guid runspacePoolId = remoteDataObject.RunspacePoolId; int minRunspaces = RemotingDecoder.GetMinRunspaces(remoteDataObject.Data); int maxRunspaces = RemotingDecoder.GetMaxRunspaces(remoteDataObject.Data); PSThreadOptions threadOptions = RemotingDecoder.GetThreadOptions(remoteDataObject.Data); ApartmentState apartmentState = RemotingDecoder.GetApartmentState((object)remoteDataObject.Data); HostInfo hostInfo = RemotingDecoder.GetHostInfo(remoteDataObject.Data); if (this._runspacePoolDriver != null) { throw new PSRemotingDataStructureException(PSRemotingErrorId.RunspaceAlreadyExists, new object[1] { (object)this._runspacePoolDriver.InstanceId }); } bool isAdministrator = this._senderInfo.UserInfo.IsInRole(WindowsBuiltInRole.Administrator); this._runspacePoolDriver = new ServerRunspacePoolDriver(runspacePoolId, minRunspaces, maxRunspaces, threadOptions, apartmentState, hostInfo, initialSessionState, applicationPrivateData, configData, this.SessionDataStructureHandler.TransportManager, isAdministrator, this._context.ServerCapability); this._runspacePoolDriver.Closed += new EventHandler <EventArgs>(this.HandleResourceClosing); this._runspacePoolDriver.Start(); } }
/// <summary> /// This method sends the server side capability negotiation packet to the client. /// </summary> internal override void SendNegotiationAsync() { RemoteSessionCapability serverCapability = _session.Context.ServerCapability; RemoteDataObject data = RemotingEncoder.GenerateServerSessionCapability(serverCapability, Guid.Empty); RemoteSessionStateMachineEventArgs negotiationSendCompletedArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationSendCompleted); _stateMachine.RaiseEvent(negotiationSendCompletedArg); RemoteDataObject <PSObject> dataToBeSent = RemoteDataObject <PSObject> .CreateFrom( data.Destination, data.DataType, data.RunspacePoolId, data.PowerShellId, (PSObject)data.Data); // send data to client..flush is not true as we expect to send state changed // information (from runspace creation) _transportManager.SendDataToClient <PSObject>(dataToBeSent, false); }
/// <summary> /// Execute. /// </summary> internal void Execute(Action <ErrorRecord> writeErrorAction) { if (_remoteHostCall.IsVoidMethod) { ExecuteVoid(writeErrorAction); } else { RemotingDataType remotingDataType = _clientPowerShellId == Guid.Empty ? RemotingDataType.RemoteRunspaceHostResponseData : RemotingDataType.RemotePowerShellHostResponseData; RemoteHostResponse remoteHostResponse = _remoteHostCall.ExecuteNonVoidMethod(_clientHost); RemoteDataObject <PSObject> dataToBeSent = RemoteDataObject <PSObject> .CreateFrom( RemotingDestination.Server, remotingDataType, _clientRunspacePoolId, _clientPowerShellId, remoteHostResponse.Encode()); _transportManager.DataToBeSentCollection.Add <PSObject>(dataToBeSent, DataPriorityType.PromptResponse); } }
/// <summary> /// Execute void method. /// </summary> internal void ExecuteVoidMethod(RemoteHostMethodId methodId, object[] parameters) { Dbg.Assert(parameters != null, "Expected parameters != null"); // Use void call ID so that the call is known to not have a return value. long callId = ServerDispatchTable.VoidCallId; RemoteHostCall remoteHostCall = new RemoteHostCall(callId, methodId, parameters); // Dispatch the call but don't wait for response since the return value is void. // TODO: remove redundant data from the RemoteHostCallPacket. RemoteDataObject<PSObject> dataToBeSent = RemoteDataObject<PSObject>.CreateFrom(RemotingDestination.Client, _remoteHostCallDataType, _clientRunspacePoolId, _clientPowerShellId, remoteHostCall.Encode()); // flush is not used here..since this is a void method and server host // does not expect anything from client..so let the transport manager buffer // and send as much data as possible. _transportManager.SendDataToClient(dataToBeSent, false); }
internal void OnDataAvailableCallback(RemoteDataObject <PSObject> remoteObject) { PSEtwLog.LogAnalyticInformational(PSEventId.TransportReceivedObject, PSOpcode.Open, PSTask.None, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, new object[] { remoteObject.RunspacePoolId.ToString(), remoteObject.PowerShellId.ToString(), (int)remoteObject.Destination, (int)remoteObject.DataType, (int)remoteObject.TargetInterface }); this.PowerShellGuidObserver.SafeInvoke(remoteObject.PowerShellId, EventArgs.Empty); RemoteDataEventArgs eventArgs = new RemoteDataEventArgs(remoteObject); if (remoteObject.DataType == RemotingDataType.RunspacePoolStateInfo) { System.Diagnostics.Debug.WriteLine("RunspacePool State Opened Received"); Thread.Sleep(800); //HACK: Delay reception in local mode... TODO: Find why!!! cannot have a Wait somewhere _slowed = true; } this.DataReceived.SafeInvoke <RemoteDataEventArgs>(this, eventArgs); }
internal void DispatchInputQueueData(object sender, RemoteDataEventArgs dataArg) { if (dataArg == null) { throw PSTraceSource.NewArgumentNullException("dataArg"); } RemoteDataObject <PSObject> receivedData = dataArg.ReceivedData; if (receivedData == null) { throw PSTraceSource.NewArgumentException("dataArg"); } RemotingDestination destination = receivedData.Destination; var d = receivedData.Data; if ((destination & (RemotingDestination.InvalidDestination | RemotingDestination.Client)) != (RemotingDestination.InvalidDestination | RemotingDestination.Client)) { throw new PSRemotingDataStructureException(RemotingErrorIdStrings.RemotingDestinationNotForMe, new object[] { RemotingDestination.InvalidDestination | RemotingDestination.Client, destination }); } switch (receivedData.TargetInterface) { case RemotingTargetInterface.Session: this.ProcessSessionMessages(dataArg); return; case RemotingTargetInterface.RunspacePool: case RemotingTargetInterface.PowerShell: { RemoteSessionStateMachineEventArgs arg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.MessageReceived, null); if (!this.StateMachine.CanByPassRaiseEvent(arg)) { this.StateMachine.RaiseEvent(arg, false); return; } this.ProcessNonSessionMessages(dataArg.ReceivedData); return; } } }
internal static RemoteDataObject <T> CreateFrom(Stream serializedDataStream, Fragmentor defragmentor) { if ((serializedDataStream.Length - serializedDataStream.Position) < 40L) { PSRemotingTransportException exception = new PSRemotingTransportException(PSRemotingErrorId.NotEnoughHeaderForRemoteDataObject, RemotingErrorIdStrings.NotEnoughHeaderForRemoteDataObject, new object[] { 0x3d }); throw exception; } RemotingDestination destination = (RemotingDestination)RemoteDataObject <T> .DeserializeUInt(serializedDataStream); RemotingDataType dataType = (RemotingDataType)RemoteDataObject <T> .DeserializeUInt(serializedDataStream); Guid runspacePoolId = RemoteDataObject <T> .DeserializeGuid(serializedDataStream); Guid powerShellId = RemoteDataObject <T> .DeserializeGuid(serializedDataStream); object valueToConvert = null; if ((serializedDataStream.Length - 40L) > 0L) { valueToConvert = defragmentor.DeserializeToPSObject(serializedDataStream); } return(new RemoteDataObject <T>(destination, dataType, runspacePoolId, powerShellId, (T)LanguagePrimitives.ConvertTo(valueToConvert, typeof(T), CultureInfo.CurrentCulture))); }
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--; } } }
/// <summary> /// Adds data to this collection. The data is fragmented in this method /// before being stored into the collection. So the calling thread /// will get affected, if it tries to add a huge object. /// /// The data is added with Default priority. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="data"> /// data to be added to the collection. Caller should make sure this is not /// null. /// </param> internal void Add <T>(RemoteDataObject <T> data) { Add <T>(data, DataPriorityType.Default); }
/// <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 abstract void RaiseKeyExchangeMessageReceived(RemoteDataObject <PSObject> receivedData);
internal void ExecuteVoidMethod(RemoteHostMethodId methodId, object[] parameters) => this._transportManager.SendDataToClient <PSObject>(RemoteDataObject <PSObject> .CreateFrom(RemotingDestination.Client, this._remoteHostCallDataType, this._clientRunspacePoolId, this._clientPowerShellId, new RemoteHostCall(-100L, methodId, parameters).Encode()), false);
internal void DispatchInputQueueData(object sender, RemoteDataEventArgs dataEventArg) { using (ServerRemoteSession._trace.TraceMethod()) { RemoteDataObject <PSObject> remoteDataObject = dataEventArg != null ? dataEventArg.ReceivedData : throw ServerRemoteSession._trace.NewArgumentNullException(nameof(dataEventArg)); RemotingDestination remotingDestination = remoteDataObject != null ? remoteDataObject.Destination : throw ServerRemoteSession._trace.NewArgumentException(nameof(dataEventArg)); if ((remotingDestination & this.MySelf) != this.MySelf) { throw new PSRemotingDataStructureException(PSRemotingErrorId.RemotingDestinationNotForMe, new object[2] { (object)this.MySelf, (object)remotingDestination }); } RemotingTargetInterface targetInterface = remoteDataObject.TargetInterface; RemotingDataType dataType = remoteDataObject.DataType; switch (targetInterface) { case RemotingTargetInterface.Session: switch (dataType) { case RemotingDataType.SessionCapability: this._sessionDSHandler.RaiseDataReceivedEvent(dataEventArg); return; case RemotingDataType.CloseSession: this._sessionDSHandler.RaiseDataReceivedEvent(dataEventArg); return; case RemotingDataType.CreateRunspacePool: RemoteSessionStateMachineEventArgs fsmEventArg1 = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.MessageReceived); if (this.SessionDataStructureHandler.StateMachine.CanByPassRaiseEvent(fsmEventArg1)) { fsmEventArg1.RemoteData = remoteDataObject; this.SessionDataStructureHandler.StateMachine.DoMessageReceived((object)this, fsmEventArg1); return; } this.SessionDataStructureHandler.StateMachine.RaiseEvent(fsmEventArg1); return; case RemotingDataType.PublicKey: this._sessionDSHandler.RaiseDataReceivedEvent(dataEventArg); return; default: return; } case RemotingTargetInterface.RunspacePool: case RemotingTargetInterface.PowerShell: RemoteSessionStateMachineEventArgs fsmEventArg2 = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.MessageReceived); if (this.SessionDataStructureHandler.StateMachine.CanByPassRaiseEvent(fsmEventArg2)) { fsmEventArg2.RemoteData = remoteDataObject; this.SessionDataStructureHandler.StateMachine.DoMessageReceived((object)this, fsmEventArg2); break; } this.SessionDataStructureHandler.StateMachine.RaiseEvent(fsmEventArg2); break; } } }
/// <summary> /// Raise the public key received event /// </summary> /// <param name="receivedData">received data</param> /// <remarks>This method is a hook to be called /// from the transport manager</remarks> internal override void RaiseKeyExchangeMessageReceived(RemoteDataObject <PSObject> receivedData) { ProcessSessionMessages(new RemoteDataEventArgs(receivedData)); }
// TODO: If this is not used remove this // internal override event EventHandler<RemoteDataEventArgs> DataReceived; /// <summary> /// This processes the object received from transport which are /// targeted for session /// </summary> /// <param name="arg"> /// argument contains the data object /// </param> private void ProcessSessionMessages(RemoteDataEventArgs arg) { if (arg == null || arg.ReceivedData == null) { throw PSTraceSource.NewArgumentNullException("arg"); } RemoteDataObject <PSObject> rcvdData = arg.ReceivedData; RemotingTargetInterface targetInterface = rcvdData.TargetInterface; Dbg.Assert(targetInterface == RemotingTargetInterface.Session, "targetInterface must be Session"); RemotingDataType dataType = rcvdData.DataType; switch (dataType) { case RemotingDataType.CloseSession: PSRemotingDataStructureException reasonOfClose = new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerRequestedToCloseSession); RemoteSessionStateMachineEventArgs closeSessionArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close, reasonOfClose); _stateMachine.RaiseEvent(closeSessionArg); break; case RemotingDataType.SessionCapability: RemoteSessionCapability capability = null; try { capability = RemotingDecoder.GetSessionCapability(rcvdData.Data); } catch (PSRemotingDataStructureException dse) { // this will happen if expected properties are not // received for session capability throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ClientNotFoundCapabilityProperties, dse.Message, PSVersionInfo.GitCommitId, RemotingConstants.ProtocolVersion); } RemoteSessionStateMachineEventArgs capabilityArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationReceived); capabilityArg.RemoteSessionCapability = capability; _stateMachine.RaiseEvent(capabilityArg); RemoteSessionNegotiationEventArgs negotiationArg = new RemoteSessionNegotiationEventArgs(capability); NegotiationReceived.SafeInvoke(this, negotiationArg); break; case RemotingDataType.EncryptedSessionKey: { String encryptedSessionKey = RemotingDecoder.GetEncryptedSessionKey(rcvdData.Data); EncryptedSessionKeyReceived.SafeInvoke(this, new RemoteDataEventArgs <string>(encryptedSessionKey)); } break; case RemotingDataType.PublicKeyRequest: { PublicKeyRequestReceived.SafeInvoke(this, new RemoteDataEventArgs <string>(String.Empty)); } break; default: { throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ReceivedUnsupportedAction, dataType); } } }
private void HandleNegotiationSendingStateChange() { RemoteDataObject sessionCapability = RemotingEncoder.GenerateClientSessionCapability(this._session.Context.ClientCapability, this._session.RemoteRunspacePoolInternal.InstanceId); this._transportManager.DataToBeSentCollection.Add <PSObject>(RemoteDataObject <PSObject> .CreateFrom(sessionCapability.Destination, sessionCapability.DataType, sessionCapability.RunspacePoolId, sessionCapability.PowerShellId, (PSObject)sessionCapability.Data)); }
/// <summary> /// Raise the public key received event /// </summary> /// <param name="receivedData">received data</param> /// <remarks>This method is a hook to be called /// from the transport manager</remarks> internal override void RaiseKeyExchangeMessageReceived(RemoteDataObject <PSObject> receivedData) { RaiseDataReceivedEvent(new RemoteDataEventArgs(receivedData)); }
/// <summary> /// Dispatches data when it arrives from the input queue. /// </summary> /// <param name="sender"></param> /// <param name="dataArg"> /// arg which contains the data received from input queue /// </param> internal void DispatchInputQueueData(object sender, RemoteDataEventArgs dataArg) { if (dataArg is null) { throw PSTraceSource.NewArgumentNullException(nameof(dataArg)); } RemoteDataObject <PSObject> rcvdData = dataArg.ReceivedData; if (rcvdData is null) { throw PSTraceSource.NewArgumentException(nameof(dataArg)); } RemotingDestination destination = rcvdData.Destination; if ((destination & RemotingDestination.Client) != RemotingDestination.Client) { throw new PSRemotingDataStructureException(RemotingErrorIdStrings.RemotingDestinationNotForMe, RemotingDestination.Client, destination); } RemotingTargetInterface targetInterface = rcvdData.TargetInterface; switch (targetInterface) { case RemotingTargetInterface.Session: { // Messages for session can cause statemachine state to change. // These messages are first processed by Sessiondata structure handler and depending // on the type of message, appropriate event is raised in state machine ProcessSessionMessages(dataArg); break; } case RemotingTargetInterface.RunspacePool: case RemotingTargetInterface.PowerShell: // Non Session messages do not change the state of the statemachine. // However instead of forwarding them to Runspace/pipeline here, an // event is raised in state machine which verified that state is // suitable for accepting these messages. if state is suitable statemachine // will call DoMessageForwading which will forward the messages appropriately RemoteSessionStateMachineEventArgs msgRcvArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.MessageReceived, null); if (StateMachine.CanByPassRaiseEvent(msgRcvArg)) { ProcessNonSessionMessages(dataArg.ReceivedData); } else { StateMachine.RaiseEvent(msgRcvArg); } break; default: { Dbg.Assert(false, "we should not be encountering this"); } break; } }
/// <summary> /// This method is used by the input queue dispatching mechanism. /// It examines the data and takes appropriate actions. /// </summary> /// <param name="dataArg"> /// The received client data. /// </param> /// <exception cref="ArgumentNullException"> /// If the parameter is null. /// </exception> internal override void RaiseDataReceivedEvent(RemoteDataEventArgs dataArg) { if (dataArg == null) { throw PSTraceSource.NewArgumentNullException("dataArg"); } RemoteDataObject <PSObject> rcvdData = dataArg.ReceivedData; RemotingTargetInterface targetInterface = rcvdData.TargetInterface; RemotingDataType dataType = rcvdData.DataType; Dbg.Assert(targetInterface == RemotingTargetInterface.Session, "targetInterface must be Session"); switch (dataType) { case RemotingDataType.CreateRunspacePool: { // At this point, the negotiation is complete, so // need to import the clients public key CreateRunspacePoolReceived.SafeInvoke(this, dataArg); } break; case RemotingDataType.CloseSession: PSRemotingDataStructureException reasonOfClose = new PSRemotingDataStructureException(RemotingErrorIdStrings.ClientRequestedToCloseSession); RemoteSessionStateMachineEventArgs closeSessionArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.Close, reasonOfClose); _stateMachine.RaiseEvent(closeSessionArg); break; case RemotingDataType.SessionCapability: RemoteSessionCapability capability = null; try { capability = RemotingDecoder.GetSessionCapability(rcvdData.Data); } catch (PSRemotingDataStructureException dse) { // this will happen if expected properties are not // received for session capability throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ServerNotFoundCapabilityProperties, dse.Message, PSVersionInfo.GitCommitId, RemotingConstants.ProtocolVersion); } RemoteSessionStateMachineEventArgs capabilityArg = new RemoteSessionStateMachineEventArgs(RemoteSessionEvent.NegotiationReceived); capabilityArg.RemoteSessionCapability = capability; _stateMachine.RaiseEvent(capabilityArg); if (NegotiationReceived != null) { RemoteSessionNegotiationEventArgs negotiationArg = new RemoteSessionNegotiationEventArgs(capability); negotiationArg.RemoteData = rcvdData; NegotiationReceived.SafeInvoke(this, negotiationArg); } break; case RemotingDataType.PublicKey: { string remotePublicKey = RemotingDecoder.GetPublicKey(rcvdData.Data); PublicKeyReceived.SafeInvoke(this, new RemoteDataEventArgs <string>(remotePublicKey)); } break; default: throw new PSRemotingDataStructureException(RemotingErrorIdStrings.ReceivedUnsupportedAction, dataType); } }