MegaBites-AI/Windows-powershell
0308
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Management.Automation.Remoting.Server;5 6using Dbg = System.Management.Automation.Diagnostics;7 8namespace System.Management.Automation.Remoting9{10 /// <summary>11 /// Responsible for routing messages from the server, blocking the callers and12 /// then waking them up when there is a response to their message.13 /// </summary>14 internal class ServerMethodExecutor15 {16 /// <summary>17 /// Default client pipeline id.18 /// </summary>19 private const long DefaultClientPipelineId = -1;20 21 /// <summary>22 /// Client runspace pool id.23 /// </summary>24 private readonly Guid _clientRunspacePoolId;25 26 /// <summary>27 /// Client power shell id.28 /// </summary>29 private readonly Guid _clientPowerShellId;30 31 /// <summary>32 /// Server dispatch table.33 /// </summary>34 private readonly ServerDispatchTable _serverDispatchTable;35 36 /// <summary>37 /// Remote host call data type.38 /// </summary>39 private readonly RemotingDataType _remoteHostCallDataType;40 41 /// <summary>42 /// Transport manager.43 /// </summary>44 private readonly AbstractServerTransportManager _transportManager;45 46 /// <summary>47 /// Constructor for ServerMethodExecutor.48 /// </summary>49 internal ServerMethodExecutor(50 Guid clientRunspacePoolId, Guid clientPowerShellId,51 AbstractServerTransportManager transportManager)52 {53 _clientRunspacePoolId = clientRunspacePoolId;54 _clientPowerShellId = clientPowerShellId;55 Dbg.Assert(transportManager != null, "Expected transportManager != null");56 _transportManager = transportManager;57 _remoteHostCallDataType =58 clientPowerShellId == Guid.Empty ? RemotingDataType.RemoteHostCallUsingRunspaceHost : RemotingDataType.RemoteHostCallUsingPowerShellHost;59 _serverDispatchTable = new ServerDispatchTable();60 }61 62 /// <summary>63 /// Handle remote host response from client.64 /// </summary>65 internal void HandleRemoteHostResponseFromClient(RemoteHostResponse remoteHostResponse)66 {67 Dbg.Assert(remoteHostResponse != null, "Expected remoteHostResponse != null");68 _serverDispatchTable.SetResponse(remoteHostResponse.CallId, remoteHostResponse);69 }70 71 /// <summary>72 /// Abort all calls.73 /// </summary>74 internal void AbortAllCalls()75 {76 _serverDispatchTable.AbortAllCalls();77 }78 79 /// <summary>80 /// Execute void method.81 /// </summary>82 internal void ExecuteVoidMethod(RemoteHostMethodId methodId)83 {84 ExecuteVoidMethod(methodId, Array.Empty<object>());85 }86 87 /// <summary>88 /// Execute void method.89 /// </summary>90 internal void ExecuteVoidMethod(RemoteHostMethodId methodId, object[] parameters)91 {92 Dbg.Assert(parameters != null, "Expected parameters != null");93 94 // Use void call ID so that the call is known to not have a return value.95 const long callId = ServerDispatchTable.VoidCallId;96 RemoteHostCall remoteHostCall = new RemoteHostCall(callId, methodId, parameters);97 98 // Dispatch the call but don't wait for response since the return value is void.99 100 // TODO: remove redundant data from the RemoteHostCallPacket.101 RemoteDataObject<PSObject> dataToBeSent = RemoteDataObject<PSObject>.CreateFrom(RemotingDestination.Client,102 _remoteHostCallDataType, _clientRunspacePoolId, _clientPowerShellId,103 remoteHostCall.Encode());104 // flush is not used here..since this is a void method and server host105 // does not expect anything from client..so let the transport manager buffer106 // and send as much data as possible.107 _transportManager.SendDataToClient(dataToBeSent, false);108 }109 110 /// <summary>111 /// Execute method.112 /// </summary>113 internal T ExecuteMethod<T>(RemoteHostMethodId methodId)114 {115 return ExecuteMethod<T>(methodId, Array.Empty<object>());116 }117 118 /// <summary>119 /// Execute method.120 /// </summary>121 internal T ExecuteMethod<T>(RemoteHostMethodId methodId, object[] parameters)122 {123 Dbg.Assert(parameters != null, "Expected parameters != null");124 125 // Create the method call object.126 long callId = _serverDispatchTable.CreateNewCallId();127 RemoteHostCall remoteHostCall = new RemoteHostCall(callId, methodId, parameters);128 129 RemoteDataObject<PSObject> dataToBeSent = RemoteDataObject<PSObject>.CreateFrom(RemotingDestination.Client,130 _remoteHostCallDataType, _clientRunspacePoolId, _clientPowerShellId,131 remoteHostCall.Encode());132 // report that execution is pending host response133 _transportManager.SendDataToClient(dataToBeSent, false, true);134 135 // Wait for response.136 RemoteHostResponse remoteHostResponse = _serverDispatchTable.GetResponse(callId, null);137 138 // Null means that the response PSObject was not received and there was an error.139 if (remoteHostResponse == null)140 {141 throw RemoteHostExceptions.NewRemoteHostCallFailedException(methodId);142 }143 144 // Process the response.145 object returnValue = remoteHostResponse.SimulateExecution();146 Dbg.Assert(returnValue is T, "Expected returnValue is T");147 return (T)remoteHostResponse.SimulateExecution();148 }149 }150}151 