| File: Rpc\NativeRpcConnection.Dispatch.cs | Web Access |
| Project: src\src\Aspire.Hosting.Native.Server\Aspire.Hosting.Native.Server.csproj (Aspire.Hosting.Native.Server) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Security.Cryptography; using System.Text; using System.Text.Json.Nodes; namespace Aspire.Hosting.Native.Rpc; internal sealed partial class NativeRpcConnection { private JsonNode? Authenticate(JsonNode? parameters) { if (parameters is not JsonArray { Count: 1 } authentication) { throw RpcFault.InvalidArgument("Authentication requires one token."); } var supplied = Encoding.UTF8.GetBytes(RpcArguments.String(authentication[0])); try { _authenticated = CryptographicOperations.FixedTimeEquals(supplied, _token); return JsonValue.Create(_authenticated); } finally { CryptographicOperations.ZeroMemory(supplied); } } private JsonNode GetApplicationServer(JsonNode? parameters) { if (parameters is not null and not JsonArray { Count: 0 }) { throw RpcFault.InvalidArgument("Server entry-point discovery takes no arguments."); } return _handles.Add(_server, NativeRpcContract.ApplicationServerTypeId); } private static JsonNode GetCapabilities(JsonNode? parameters) { if (parameters is not null and not JsonArray { Count: 0 }) { throw RpcFault.InvalidArgument("Capability discovery takes no arguments."); } return s_contract.DeepClone(); } private JsonNode GetAppHostServerConfiguration(JsonNode? parameters) { if (_languages is null || parameters is not null and not JsonArray { Count: 0 } || _providers?.IsProvider(this) == true) { throw RpcFault.InvalidArgument("AppHost configuration requires an application connection and no arguments."); } return _languages.ProviderConfiguration(); } private JsonNode Bootstrap(string method, JsonNode? parameters) { if (_languages is null) { throw RpcFault.MethodNotFound("The RPC method is not implemented."); } if (parameters is not JsonArray { Count: > 0 and <= 2 } arguments || method == "getRuntimeSpec" && arguments.Count != 1 || arguments.Count == 2 && arguments[1] is not null) { throw RpcFault.InvalidArgument("Bootstrap requires a language and does not support assembly filtering."); } return method == "getRuntimeSpec" ? _languages.RuntimeSpec(RpcArguments.String(arguments[0])) : _languages.GeneratedSdk(RpcArguments.String(arguments[0])); } private async Task<JsonNode?> InvokeCapabilityAsync(JsonNode? parameters) { if (parameters is not JsonArray { Count: 2 } arguments || arguments[1] is not JsonObject capabilityArguments) { throw RpcFault.InvalidArgument("Capability invocation requires an ID and an argument object."); } var capabilityId = RpcArguments.String(arguments[0]); if (_providers is not null) { if (_providers.IsProvider(this)) { return await _providers.InvokeCoreAsync(this, capabilityId, capabilityArguments).ConfigureAwait(false); } if (!s_coreCapabilities.Contains(capabilityId)) { return await _providers.InvokeAsync(this, capabilityId, capabilityArguments).ConfigureAwait(false); } } return await NativeDispatch.InvokeAsync(_server, _handles, this, this, capabilityId, capabilityArguments).ConfigureAwait(false); } private async Task<JsonNode?> InvokeProviderControlAsync(string method, JsonNode? parameters) { switch (method) { case "getIntegrationCapabilities": if (_providers is null || parameters is not null and not JsonArray { Count: 0 }) { throw RpcFault.InvalidArgument("Provider discovery takes no arguments."); } return _providers.InspectCapabilities(); case "expectIntegrationHost": if (_providers is null || parameters is not JsonArray { Count: 1 } expectation || _providers.IsProvider(this)) { throw RpcFault.InvalidArgument("Expected registration requires an application connection and one package identity."); } return JsonValue.Create(_providers.Expect(this, RpcArguments.String(expectation[0]))); case "registerAsIntegrationHost": if (_providers is null || _peer is null || parameters is not JsonArray { Count: 1 } registration) { throw RpcFault.InvalidArgument("Provider registration requires one expected authority."); } await _providers.RegisterAsync(this, RpcArguments.String(registration[0]), _peer).ConfigureAwait(false); return JsonValue.Create(true); case "waitIntegrationHostRegistration": if (_providers is null || parameters is not JsonArray { Count: 1 } activation) { throw RpcFault.InvalidArgument("Provider activation requires one expected authority."); } await _providers.WaitRegistrationAsync(this, RpcArguments.String(activation[0])).ConfigureAwait(false); return JsonValue.Create(true); case "abandonIntegrationHostRegistration": if (_providers is null || parameters is not JsonArray { Count: 1 } abandonment) { throw RpcFault.InvalidArgument("Abandoning activation requires one expected authority."); } return JsonValue.Create(_providers.AbandonRegistration(this, RpcArguments.String(abandonment[0]))); case "invokeGuestCallback": if (_providers is null || parameters is not JsonArray { Count: 2 } callback || callback[1] is not JsonObject callbackArguments) { throw RpcFault.InvalidArgument("Callback invocation requires its authority and arguments."); } return await _providers.InvokeCallbackAsync(this, RpcArguments.String(callback[0]), callbackArguments).ConfigureAwait(false); default: throw RpcFault.MethodNotFound("The RPC method is not implemented."); } } }