示例#1
0
        public override SbListener Create(GrpcConnection connection, string name)
        {
            var instance = new SbListenerStub(name);

            Instances.Add(instance);
            return(instance);
        }
示例#2
0
        public async Task DeviceServiceTest()
        {
            var serverBuilder = new RpcServiceDefinitionsBuilder();

            serverBuilder.RegisterService <IThermostatService>();
            var host = new GrpcServer(serverBuilder, null, this.options);

            host.AddEndPoint(CreateEndPoint());

            host.Start();
            try
            {
                var serviceImpl = new ThermostatServiceImpl();
                using (var publishScope = host.PublishInstance(serviceImpl))
                {
                    var            objectId   = publishScope.Value.ObjectId;
                    GrpcConnection connection = this.CreateGrpcConnection();

                    var clientService = connection.GetServiceInstance <IThermostatServiceClient>(objectId);
                    var acoId         = clientService.DeviceAcoId;

                    var baseClientService = (IDeviceServiceClient)clientService;
                    var acoId2            = baseClientService.DeviceAcoId;
                    Assert.AreEqual(acoId, acoId2);
                }
            }
            finally
            {
                await host.ShutdownAsync();
            }
        }
        public void StartPreGame(LaunchOption launchOption, bool rgpEnabled, bool renderdocEnabled,
                                 SshTarget target, out GrpcConnection grpcConnection,
                                 out ITransportSession transportSession)
        {
            lock (thisLock)
            {
                grpcConnection        = null;
                this.transportSession = transportSession = transportSessionFactory.Create();
                if (transportSession == null)
                {
                    Trace.WriteLine("Unable to start the debug transport, invalid session.");
                    throw new YetiDebugTransportException(ErrorStrings.FailedToStartTransport);
                }

                if (!LaunchPreGameProcesses(launchOption, rgpEnabled, renderdocEnabled, target))
                {
                    Stop(ExitReason.Unknown);
                    throw new YetiDebugTransportException(
                              "Failed to launch all needed pre-game processes");
                }

                Trace.WriteLine("Started debug transport.  Session ID: " +
                                transportSession.GetSessionId());

                // The grpcConnection is created during the launch of one of the processes.
                grpcConnection = this.grpcConnection;
            }
        }
示例#4
0
        public void SetUp()
        {
            var callInvokerFactory = new PipeCallInvokerFactory();

            mainThreadContext = new FakeMainThreadContext();
            taskContext       = mainThreadContext.JoinableTaskContext;
            connection        = new GrpcConnection(taskContext.Factory, callInvokerFactory.Create());
        }
示例#5
0
 public override SbDebugger Create(
     GrpcConnection connection, bool sourceInitFiles, TimeSpan retryWaitTime)
 {
     if (waitTime > retryWaitTime)
     {
         return(null);
     }
     return(Debugger);
 }
 public ServerInfo(PipeServiceBinder server, PipeCallInvoker callInvoker,
                   GrpcConnection connection, RemoteObjectStores stores,
                   LldbMockFactories mockFactories)
 {
     Server        = server;
     CallInvoker   = callInvoker;
     Connection    = connection;
     Stores        = stores;
     MockFactories = mockFactories;
 }
        SbListener CreateListener(GrpcConnection grpcConnection)
        {
            var lldbListener = _lldbListenerFactory.Create(grpcConnection, "LLDBWorker Listener");

            if (lldbListener == null)
            {
                throw new AttachException(VSConstants.E_ABORT,
                                          ErrorStrings.FailedToCreateDebugListener);
            }

            return(lldbListener);
        }
 // Exits and disposes of all processes, the TransportSession, and GrpcConnection.
 public void Stop(ExitReason exitReason)
 {
     lock (thisLock)
     {
         // Stop the grpc connection first because it depends on the the grpc server process
         // that is managed by the process manager.
         grpcConnection?.Shutdown();
         grpcConnection = null;
         grpcCallInvoker?.Dispose();
         grpcCallInvoker = null;
         transportSession?.Dispose();
         transportSession = null;
         processManager?.StopAll(exitReason);
         processManager = null;
     }
 }
        SbPlatform CreateRemotePlatform(GrpcConnection grpcConnection, SbDebugger debugger)
        {
            string platformName;

            if (debugger.IsPlatformAvailable(_remoteLldbPlatformName))
            {
                _stadiaPlatformAvailable = true;
                platformName             = _remoteLldbPlatformName;
            }
            else
            {
                platformName = _fallbackRemoteLldbPlatformName;
            }

            return(_lldbPlatformFactory.Create(platformName, grpcConnection));
        }
        public void SetUp()
        {
            var factory = new GrpcPlatformFactoryFake(null);

            factory.AddFakeProcess("linux-remote", "myGame", 2222);
            factory.AddFakeProcess("linux-remote", "ssh", 443244);
            factory.AddFakeProcess("linux-remote", "blah", 4545);

            var callInvokerFactory = new PipeCallInvokerFactory();
            var grpcConnection     =
                new GrpcConnection(new JoinableTaskContext().Factory, callInvokerFactory.Create());

            platform       = factory.Create("linux-remote", grpcConnection);
            connectOptions = new GrpcPlatformConnectOptionsFactory()
                             .Create("http://any/url");
            shellCommandFactory = new GrpcPlatformShellCommandFactory();
        }
        private ServerInfo CreateServer(
            PipeCallInvokerFactory callInvokerFactory, GrpcConnectionFactory connectionFactory)
        {
            PipeCallInvoker callInvoker = callInvokerFactory.Create();
            GrpcConnection  connection  = connectionFactory.Create(callInvoker);

            string[] inPipeHandles, outPipeHandles;
            callInvoker.GetClientPipeHandles(out inPipeHandles, out outPipeHandles);

            // Note: The client's out handles are the server's in handles and vice versa.
            PipeServiceBinder server = new PipeServiceBinder(outPipeHandles, inPipeHandles);
            var stores        = new RemoteObjectStores();
            var mockFactories = new LldbMockFactories();

            BindServices(server, stores, mockFactories);
            server.Start();
            return(new ServerInfo(server, callInvoker, connection, stores, mockFactories));
        }
        public void SetUp()
        {
            var taskContext = new JoinableTaskContext();
            PipeCallInvokerFactory callInvokerFactory = new PipeCallInvokerFactory();
            PipeCallInvoker        callInvoker        = callInvokerFactory.Create();

            _grpcConnection  = new GrpcConnection(taskContext.Factory, callInvoker);
            _callback        = Substitute.For <IDebugEventCallback2>();
            _debuggerOptions = new YetiVSI.DebuggerOptions.DebuggerOptions
            {
                [DebuggerOption.CLIENT_LOGGING] = DebuggerOptionState.DISABLED
            };
            _libPaths = new HashSet <string> {
                "some/path", "some/other/path", _gameBinary
            };
            _programId   = Guid.Empty;
            _task        = Substitute.For <ICancelable>();
            _process     = new DebugProcessStub(enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM, _pid);
            _fileSystem  = new MockFileSystem();
            _debugEngine = Substitute.For <IDebugEngine3>();
            _gameLaunch  = Substitute.For <IVsiGameLaunch>();
        }
示例#13
0
        ProcessStartData CreateDebuggerGrpcServerProcessStartData()
        {
            var startInfo = new ProcessStartInfo
            {
                FileName = Path.Combine(YetiConstants.RootDir,
                                        YetiConstants.DebuggerGrpcServerExecutable),
            };

            // (internal): grpcCallInvoker must be created right before the process is created!
            // If it is created before the other processes are created, they'll hold on to the
            // pipes and they won't get closed if the GRPC server shuts down.
            Action <ProcessStartInfo> beforeStart = (processStartInfo) =>
            {
                grpcCallInvoker                   = grpcCallInvokerFactory.Create();
                grpcConnection                    = grpcConnectionFactory.Create(grpcCallInvoker);
                grpcConnection.RpcException      += StopWithException;
                grpcConnection.AsyncRpcCompleted += onAsyncRpcCompleted;

                grpcCallInvoker.GetClientPipeHandles(out string[] inPipeHandles,
                                                     out string[] outPipeHandles);

                // Note: The server's input pipes are the client's output pipes and vice versa.
                processStartInfo.Arguments = $"-i {string.Join(",", outPipeHandles)} " +
                                             $"-o {string.Join(",", inPipeHandles)}";
            };

            // Dispose client handles right after start. This is necessary so that pipes are closed
            // when the server exits.
            Action afterStart = () => { grpcCallInvoker.DisposeLocalCopyOfClientPipeHandles(); };

            var rootDir = YetiConstants.RootDir;

#if USE_LOCAL_PYTHON_AND_TOOLCHAIN
            // This is gated by the <DeployPythonAndToolchainDependencies> project setting to speed
            // up the build.
            var pythonRoot   = File.ReadAllText(Path.Combine(rootDir, "local_python_dir.txt")).Trim();
            var toolchainDir = File.ReadAllText(Path.Combine(rootDir, "local_toolchain_dir.txt"))
                               .Trim();
            var lldbSitePackagesDir = Path.Combine(toolchainDir, "windows", "lib", "site-packages");
            var libLldbDir          = Path.Combine(toolchainDir, "windows", "bin");

            // Quick sanity check that all directories exist.
            var notFoundDir = !Directory.Exists(pythonRoot) ? pythonRoot :
                              !Directory.Exists(lldbSitePackagesDir) ? lldbSitePackagesDir :
                              !Directory.Exists(libLldbDir) ? libLldbDir : null;
            if (!string.IsNullOrEmpty(notFoundDir))
            {
                // Note: This error is only shown to internal VSI devs, not to external devs.
                throw new YetiDebugTransportException(
                          "You have set the <DeployPythonAndToolchainDependencies> project setting to " +
                          $"False to speed up deployment, but the Python/toolchain dir {notFoundDir} " +
                          "moved. Either fix the wrong directory (preferred) or set " +
                          "<DeployPythonAndToolchainDependencies> to False.");
            }
#else
            var pythonRoot          = Path.Combine(rootDir, "Python3");
            var lldbSitePackagesDir = Path.Combine(YetiConstants.LldbDir, "site-packages");
            var libLldbDir          = Path.Combine(YetiConstants.LldbDir, "bin");
#endif

            // Search paths for dLLs.
            startInfo.Environment["PATH"] = string.Join(";", new string[]
            {
                rootDir,
                pythonRoot,
                libLldbDir
            });

            // Search paths for Python files.
            startInfo.Environment["PYTHONPATH"] = string.Join(";", new string[]
            {
                Path.Combine(pythonRoot, "Lib"),
                lldbSitePackagesDir
            });

            // Do not display console windows when launching processes. In our case,
            // we do not want the scp process to show the console window.
            startInfo.Environment["LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"] = "true";

            Trace.WriteLine($"Starting {startInfo.FileName} with" + Environment.NewLine +
                            $"\tPATH={(startInfo.Environment["PATH"])}" + Environment.NewLine +
                            $"\tPYTHONPATH={(startInfo.Environment["PYTHONPATH"])}");

            // Use the directory with the binary as working directory. Normally it doesn't matter,
            // because the server doesn't load any files via relative paths and the dependent DLLs
            // are available via PATH and PYTHONPATH. However when debugging or just running the
            // extension from Visual Studio the working directory is set to the output build
            // directory. The working directory has precedence for loading DLLs, so liblldb.dll is
            // picked up from the build output directory, NOT the deployed extension.
            startInfo.WorkingDirectory = Path.GetDirectoryName(startInfo.FileName);

            // Uncomment to enable GRPC debug logging for DebuggerGrpcServer.exe.
            // This is currently very verbose, and you will most likely want to restrict logging to
            // a subset.
            //
            //lldbGrpcStartInfo.EnvironmentVariables["GRPC_TRACE"] = "all";
            //lldbGrpcStartInfo.EnvironmentVariables["GRPC_VERBOSITY"] = "DEBUG";
            return(new ProcessStartData("lldb grpc server", startInfo, beforeStart: beforeStart,
                                        afterStart: afterStart));
        }
        public async Task <ILldbAttachedProgram> LaunchAsync(
            ICancelable task, IDebugProcess2 process, Guid programId, uint?attachPid,
            DebuggerOptions.DebuggerOptions debuggerOptions, HashSet <string> libPaths,
            GrpcConnection grpcConnection, int localDebuggerPort, string targetIpAddress,
            int targetPort, IDebugEventCallback2 callback)
        {
            var       launchSucceeded = false;
            Stopwatch launchTimer     = Stopwatch.StartNew();


            // This should be the first request to the DebuggerGrpcServer.  Providing a retry wait
            // time allows us to connect to a DebuggerGrpcServer that is slow to start. Note that
            // we postpone sourcing .lldbinit until we are done with our initialization so that
            // the users can override our defaults.
            var lldbDebugger =
                _lldbDebuggerFactory.Create(grpcConnection, false, TimeSpan.FromSeconds(10));

            if (lldbDebugger == null)
            {
                throw new AttachException(VSConstants.E_ABORT, ErrorStrings.FailedToCreateDebugger);
            }

            if (debuggerOptions[DebuggerOption.CLIENT_LOGGING] == DebuggerOptionState.ENABLED)
            {
                lldbDebugger.EnableLog("lldb", new List <string> {
                    "default", "module"
                });

                // TODO: Disable 'dwarf' logs until we can determine why this
                // causes LLDB to hang.
                // lldbDebugger.EnableLog("dwarf", new List<string> { "default" });
            }

            if (_fastExpressionEvaluation)
            {
                lldbDebugger.EnableFastExpressionEvaluation();
            }

            lldbDebugger.SetDefaultLLDBSettings();

            // Apply .lldbinit after we set our settings so that the user can override our
            // defaults with a custom .lldbinit.
            LoadLocalLldbInit(lldbDebugger);

            // Add exec search paths, so that LLDB can find the executable and any dependent
            // libraries.  If LLDB is able to find the files locally, it won't try to download
            // them from the remote server, saving valuable time on attach.
            foreach (string path in libPaths)
            {
                lldbDebugger.SetLibrarySearchPath(path);
            }

            lldbDebugger.SetAsync(true);

            SbPlatform lldbPlatform;

            switch (_launchOption)
            {
            case LaunchOption.AttachToGame:
            // Fall through.
            case LaunchOption.LaunchGame:
                lldbPlatform = CreateRemotePlatform(grpcConnection, lldbDebugger);
                if (lldbPlatform == null)
                {
                    throw new AttachException(VSConstants.E_FAIL,
                                              ErrorStrings.FailedToCreateLldbPlatform);
                }
                task.ThrowIfCancellationRequested();
                Trace.WriteLine("Attempting to connect debugger");
                task.Progress.Report("Connecting to debugger");

                string connectRemoteUrl      = $"{_lldbConnectUrl}:{localDebuggerPort}";
                string connectRemoteArgument =
                    CreateConnectRemoteArgument(connectRemoteUrl, targetIpAddress, targetPort);

                SbPlatformConnectOptions lldbConnectOptions =
                    _lldbPlatformConnectOptionsFactory.Create(connectRemoteArgument);

                IAction debugerWaitAction =
                    _actionRecorder.CreateToolAction(ActionType.DebugWaitDebugger);

                bool TryConnectRemote()
                {
                    if (lldbPlatform.ConnectRemote(lldbConnectOptions).Success())
                    {
                        return(true);
                    }

                    VerifyGameIsReady(debugerWaitAction);
                    return(false);
                }

                try
                {
                    debugerWaitAction.Record(() => RetryWithTimeout(
                                                 task, TryConnectRemote, _launchRetryDelay,
                                                 _launchTimeout, launchTimer));
                }
                catch (TimeoutException e)
                {
                    throw new AttachException(
                              VSConstants.E_ABORT,
                              ErrorStrings.FailedToConnectDebugger(lldbConnectOptions.GetUrl()), e);
                }
                Trace.WriteLine("LLDB successfully connected");
                break;

            case LaunchOption.AttachToCore:
                lldbPlatform = _lldbPlatformFactory.Create(_localLldbPlatformName, grpcConnection);
                if (lldbPlatform == null)
                {
                    throw new AttachException(VSConstants.E_FAIL,
                                              ErrorStrings.FailedToCreateLldbPlatform);
                }
                break;

            default:
                throw new AttachException(VSConstants.E_ABORT, ErrorStrings.InvalidLaunchOption(
                                              _launchOption.ToString()));
            }

            lldbDebugger.SetSelectedPlatform(lldbPlatform);

            task.ThrowIfCancellationRequested();
            task.Progress.Report("Debugger is attaching (this can take a while)");

            RemoteTarget lldbTarget = null;

            if (_launchOption == LaunchOption.LaunchGame &&
                !string.IsNullOrEmpty(_executableFullPath))
            {
                var createExecutableTargetAction =
                    _actionRecorder.CreateToolAction(ActionType.DebugCreateExecutableTarget);
                createExecutableTargetAction.Record(
                    () => lldbTarget = CreateTarget(lldbDebugger, _executableFullPath));
            }
            else
            {
                lldbTarget = CreateTarget(lldbDebugger, "");
            }

            var lldbListener = CreateListener(grpcConnection);

            // This is required to catch breakpoint change events.
            lldbTarget.AddListener(lldbListener, EventType.STATE_CHANGED);
            var listenerSubscriber = new LldbListenerSubscriber(lldbListener);
            var eventHandler       = new EventHandler <FileUpdateReceivedEventArgs>(
                (s, e) => ListenerSubscriberOnFileUpdateReceived(task, e));

            listenerSubscriber.FileUpdateReceived += eventHandler;
            listenerSubscriber.Start();

            try
            {
                if (_launchOption == LaunchOption.AttachToCore)
                {
                    var       loadCoreAction      = _actionRecorder.CreateToolAction(ActionType.DebugLoadCore);
                    SbProcess lldbDebuggerProcess = null;
                    loadCoreAction.Record(() =>
                                          lldbDebuggerProcess = LoadCore(lldbTarget, loadCoreAction));

                    await _taskContext.Factory.SwitchToMainThreadAsync();

                    return(_attachedProgramFactory.Create(
                               process, programId, _debugEngine, callback, lldbDebugger, lldbTarget,
                               listenerSubscriber, lldbDebuggerProcess,
                               lldbDebugger.GetCommandInterpreter(), true, new NullExceptionManager(),
                               _moduleSearchLogHolder, remotePid: 0));
                }

                // Get process ID.
                uint processId = 0;
                switch (_launchOption)
                {
                case LaunchOption.AttachToGame:
                    if (!attachPid.HasValue)
                    {
                        throw new AttachException(VSConstants.E_ABORT,
                                                  ErrorStrings.FailedToRetrieveProcessId);
                    }

                    processId = attachPid.Value;
                    break;

                case LaunchOption.LaunchGame:
                    // Since we have no way of knowing when the remote process actually
                    // starts, try a few times to get the pid.

                    IAction debugWaitAction =
                        _actionRecorder.CreateToolAction(ActionType.DebugWaitProcess);

                    bool TryGetRemoteProcessId()
                    {
                        if (GetRemoteProcessId(_executableFileName, lldbPlatform, out processId))
                        {
                            return(true);
                        }

                        VerifyGameIsReady(debugWaitAction);
                        return(false);
                    }

                    try
                    {
                        debugWaitAction.Record(() => RetryWithTimeout(
                                                   task, TryGetRemoteProcessId, _launchRetryDelay,
                                                   _launchTimeout, launchTimer));
                    }
                    catch (TimeoutException e)
                    {
                        throw new AttachException(VSConstants.E_ABORT,
                                                  ErrorStrings.FailedToRetrieveProcessId, e);
                    }

                    break;
                }

                Trace.WriteLine("Attaching to pid " + processId);
                var debugAttachAction = _actionRecorder.CreateToolAction(ActionType.DebugAttach);

                SbProcess debuggerProcess = null;
                debugAttachAction.Record(() => {
                    var moduleFileLoadRecorder =
                        _moduleFileLoadRecorderFactory.Create(debugAttachAction);
                    moduleFileLoadRecorder.RecordBeforeLoad(Array.Empty <SbModule>());

                    debuggerProcess = lldbTarget.AttachToProcessWithID(lldbListener, processId,
                                                                       out SbError lldbError);
                    if (lldbError.Fail())
                    {
                        throw new AttachException(
                            VSConstants.E_ABORT,
                            GetLldbAttachErrorDetails(lldbError, lldbPlatform, processId));
                    }

                    RecordModules(lldbTarget, moduleFileLoadRecorder);
                });

                var exceptionManager = _exceptionManagerFactory.Create(debuggerProcess);

                await _taskContext.Factory.SwitchToMainThreadAsync();

                ILldbAttachedProgram attachedProgram = _attachedProgramFactory.Create(
                    process, programId, _debugEngine, callback, lldbDebugger, lldbTarget,
                    listenerSubscriber, debuggerProcess, lldbDebugger.GetCommandInterpreter(),
                    false, exceptionManager, _moduleSearchLogHolder, processId);
                launchSucceeded = true;
                return(attachedProgram);
            }
            finally
            {
                // clean up the SBListener subscriber
                listenerSubscriber.FileUpdateReceived -= eventHandler;
                // stop the SBListener subscriber completely if the game failed to launch
                if (!launchSucceeded)
                {
                    listenerSubscriber.Stop();
                }
            }
        }
示例#15
0
 public override SbPlatform Create(string platformName, GrpcConnection grpcConnection) =>
 new SbPlatformFake(platformName,
                    _platformProcesses.Where(p => p.PlatformName == platformName),
                    _connectRecorder, _processCommandToOutput, _connectRemoteStatuses,
                    _runStatuses);
        /// <summary>
        /// TODO: Use factories instead of using this.connnectionType.
        /// </summary>
        /// <param name="serviceDefinitionsProvider"></param>
        /// <param name="proxyDefinitionsProvider"></param>
        /// <returns></returns>
        protected (IRpcServerHost, IRpcChannel) CreateServerAndConnection(
            IRpcServiceDefinitionsProvider serviceDefinitionsProvider = null,
            Action <RpcServerOptions> configServerOptions             = null,
            Action <RpcClientOptions> configClientOptions             = null,
            Action <IServiceCollection> configureServices             = null)
        {
            var rpcServerId = RpcServerId.NewId();

            var serverOptions = new RpcServerOptions {
                Serializer = this.serializer
            };
            var clientOptions = new RpcClientOptions {
                Serializer = this.serializer
            };

            configServerOptions?.Invoke(serverOptions);
            configClientOptions?.Invoke(clientOptions);

            IServiceProvider services = GetServiceProvider(configureServices);

            switch (this.ConnectionType)
            {
            case RpcConnectionType.LightweightTcp:
            case RpcConnectionType.LightweightSslTcp:
            {
                var host = new LightweightRpcServer(rpcServerId, serviceDefinitionsProvider, services, serverOptions, this.LightweightOptions,
                                                    loggerFactory: services.GetService <ILoggerFactory>());

                SslServerOptions sslServerOptions = null;
                if (this.ConnectionType == RpcConnectionType.LightweightSslTcp)
                {
                    sslServerOptions = new SslServerOptions(new X509Certificate2(TestCertificates.ServerPFXPath, "1111"));
                }

                host.AddEndPoint(new TcpRpcEndPoint("127.0.0.1", TcpTestPort, false, sslServerOptions));

                SslClientOptions sslClientOptions = null;
                if (this.ConnectionType == RpcConnectionType.LightweightSslTcp)
                {
                    sslClientOptions = new SslClientOptions {
                        RemoteCertificateValidationCallback = this.ValidateTestCertificate
                    };
                }
                var connection = new TcpRpcConnection(
                    new RpcConnectionInfo("TCP", new Uri($"lightweight.tcp://127.0.0.1:{TcpTestPort}"), rpcServerId),
                    sslClientOptions,
                    clientOptions.AsImmutable(),
                    this.LightweightOptions);

                return(host, connection);
            }

            case RpcConnectionType.LightweightNamedPipe:
            {
                var server = new LightweightRpcServer(rpcServerId, serviceDefinitionsProvider, services, serverOptions, this.LightweightOptions,
                                                      loggerFactory: services.GetService <ILoggerFactory>());
                server.AddEndPoint(new NamedPipeRpcEndPoint("testpipe"));

                var connection = new NamedPipeRpcConnection(
                    new RpcConnectionInfo(new Uri("lightweight.pipe://./testpipe")),
                    clientOptions.AsImmutable(),
                    this.LightweightOptions);

                return(server, connection);
            }

            case RpcConnectionType.LightweightInproc:
            {
                Pipe requestPipe  = new Pipe(new PipeOptions(readerScheduler: PipeScheduler.ThreadPool));
                Pipe responsePipe = new Pipe(new PipeOptions(readerScheduler: PipeScheduler.Inline));

                var host = new LightweightRpcServer(rpcServerId, serviceDefinitionsProvider, services, serverOptions,
                                                    loggerFactory: services.GetService <ILoggerFactory>());
                host.AddEndPoint(new InprocRpcEndPoint(new DirectDuplexPipe(requestPipe.Reader, responsePipe.Writer)));

                var connection = new InprocRpcConnection(new RpcConnectionInfo("Direct", new Uri("direct:localhost"), rpcServerId),
                                                         new DirectDuplexPipe(responsePipe.Reader, requestPipe.Writer), clientOptions.AsImmutable());
                return(host, connection);
            }

            case RpcConnectionType.Grpc:
            {
                var host = new GrpcServer(rpcServerId, serviceDefinitionsProvider, services, serverOptions);
                host.AddEndPoint(GrpcCoreFullStackTestsBase.CreateEndPoint());

                var connection = new GrpcConnection(
                    new RpcConnectionInfo("TCP", new Uri($"grpc://localhost:{GrpcCoreFullStackTestsBase.GrpcTestPort}"), rpcServerId),
                    TestCertificates.GrpcSslCredentials, clientOptions.AsImmutable());
                return(host, connection);
            }

#if PLAT_NET_GRPC
            case RpcConnectionType.NetGrpc:
            {
                var server = CreateNetGrpcServer(serviceDefinitionsProvider, rpcServerId, serverOptions, configureServices);
                //var host = new GrpcServer(rpcServerId, serviceDefinitionsBuilder, null, options);
                //host.AddEndPoint(GrpcCoreFullStackTestsBase.CreateEndPoint());

                var handler = new System.Net.Http.HttpClientHandler();
                handler.ServerCertificateCustomValidationCallback =
                    (httpRequestMessage, cert, cetChain, policyErrors) =>
                {
                    return(true);
                };
                var channelOptions = new GrpcNet.Client.GrpcChannelOptions()
                {
                    HttpClient        = new System.Net.Http.HttpClient(handler),
                    DisposeHttpClient = true
                };


                var connection = new NetGrpcConnection(
                    new RpcConnectionInfo("net-grpc", new Uri($"grpc://localhost:{GrpcCoreFullStackTestsBase.GrpcTestPort}"), rpcServerId),
                    clientOptions.AsImmutable(), channelOptions);
                return(server, connection);
            }
#endif
            }

            throw new NotSupportedException();
        }