static void Main(string[] args) { var debugMode = args.Any(a => a.Equals("--debug", StringComparison.OrdinalIgnoreCase)); #if WAIT_FOR_DEBUGGER while (!Debugger.IsAttached) { Thread.Sleep(1000); } Debugger.Break(); #endif StreamWriter logWriter = null; if (debugMode) { logWriter = File.CreateText("messages-" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".log"); logWriter.AutoFlush = true; } using (logWriter) using (var cin = Console.OpenStandardInput()) using (var bcin = new BufferedStream(cin)) using (var cout = Console.OpenStandardOutput()) using (var reader = new PartwiseStreamMessageReader(bcin)) using (var writer = new PartwiseStreamMessageWriter(cout)) { var contractResolver = new JsonRpcContractResolver { NamingStrategy = new CamelCaseJsonRpcNamingStrategy(), ParameterValueConverter = new LanguageServiceParameterValueConverter(), }; var clientHandler = new StreamRpcClientHandler(); var client = new JsonRpcClient(clientHandler); if (debugMode) { // We want to capture log all the LSP server-to-client calls as well clientHandler.MessageSending += (_, e) => { lock (logWriter) logWriter.WriteLine("{0} <C{1}", Utility.GetTimeStamp(), e.Message); }; clientHandler.MessageReceiving += (_, e) => { lock (logWriter) logWriter.WriteLine("{0} >C{1}", Utility.GetTimeStamp(), e.Message); }; } // Configure & build service host var session = new LanguageServerSession(client, contractResolver); var host = BuildServiceHost(logWriter, contractResolver, debugMode); var serverHandler = new StreamRpcServerHandler(host, StreamRpcServerHandlerOptions.ConsistentResponseSequence | StreamRpcServerHandlerOptions.SupportsRequestCancellation); serverHandler.DefaultFeatures.Set(session); // If we want server to stop, just stop the "source" using (serverHandler.Attach(reader, writer)) using (clientHandler.Attach(reader, writer)) { // Wait for the "stop" request. session.CancellationToken.WaitHandle.WaitOne(); } logWriter?.WriteLine("Exited"); } }
static void Main(string[] args) { CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-us"); Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; CommandLineArguments.ParseFrom(args); if (CommandLineArguments.WaitForDebugger) { while (!Debugger.IsAttached) { Thread.Sleep(1000); } Debugger.Break(); } var host = BuildServiceHost(); var serverHandler = new StreamRpcServerHandler(host); var clientHandler = new StreamRpcClientHandler(); var client = new JsonRpcClient(clientHandler); var serviceContext = new SandboxHost(client, CommandLineArguments.SandboxPath); serverHandler.DefaultFeatures.Set(serviceContext); // Messages come from Console ByLineTextMessageReader reader; ByLineTextMessageWriter writer; if (!string.IsNullOrEmpty(CommandLineArguments.RxHandle)) { var pipeClient = new AnonymousPipeClientStream(PipeDirection.In, CommandLineArguments.RxHandle); reader = new ByLineTextMessageReader(pipeClient); } else { reader = new ByLineTextMessageReader(Console.In); } if (!string.IsNullOrEmpty(CommandLineArguments.TxHandle)) { var pipeClient = new AnonymousPipeClientStream(PipeDirection.Out, CommandLineArguments.TxHandle); writer = new ByLineTextMessageWriter(pipeClient); } else { writer = new ByLineTextMessageWriter(Console.Out); } try { using (reader) using (writer) using (serverHandler.Attach(reader, writer)) using (clientHandler.Attach(reader, writer)) { // Started up. serviceContext.HostingClient.NotifyStarted(); // Wait for exit serviceContext.Disposal.Wait(); } } catch (ObjectDisposedException) { } }
public static async Task RunClientAsync(Stream clientStream) { await Task.Yield(); // We want this task to run on another thread. var clientHandler = new StreamRpcClientHandler(); using (var reader = new ByLineTextMessageReader(clientStream)) using (var writer = new ByLineTextMessageWriter(clientStream)) using (clientHandler.Attach(reader, writer)) { var client = new JsonRpcClient(clientHandler); var builder = new JsonRpcProxyBuilder { ContractResolver = myContractResolver }; var proxy = builder.CreateProxy <ILibraryService>(client); ClientWriteLine("Add books…"); await proxy.PutBookAsync(new Book("Somewhere Within the Shadows", "Juan Díaz Canales & Juanjo Guarnido", new DateTime(2004, 1, 1), "1596878177")); await proxy.PutBookAsync(new Book("Arctic Nation", "Juan Díaz Canales & Juanjo Guarnido", new DateTime(2004, 1, 1), "0743479351")); ClientWriteLine("Available books:"); foreach (var isbn in await proxy.EnumBooksIsbn()) { var book = await proxy.GetBookAsync(isbn); ClientWriteLine(book); } ClientWriteLine("Attempt to query for an inexistent ISBN…"); try { await proxy.GetBookAsync("test", true); } catch (JsonRpcRemoteException ex) { ClientWriteLine(ex); } ClientWriteLine("Attempt to pass some invalid argument…"); try { await proxy.PutBookAsync(null); } catch (JsonRpcRemoteException ex) { ClientWriteLine(ex); } ClientWriteLine("Will shut down server in 5 seconds…"); await Task.Delay(5000); proxy.Terminate(); } }
public void Connect(bool debugMode) { var logWriter = CreateLogWriter(true); using (logWriter) using (var cin = Console.OpenStandardInput()) using (var bcin = new BufferedStream(cin)) using (var cout = Console.OpenStandardOutput()) using (var reader = new PartwiseStreamMessageReader(bcin)) using (var writer = new PartwiseStreamMessageWriter(cout)) { var contractResolver = new JsonRpcContractResolver { NamingStrategy = new CamelCaseJsonRpcNamingStrategy(), ParameterValueConverter = new CamelCaseJsonValueConverter(), }; var clientHandler = new StreamRpcClientHandler(); var client = new JsonRpcClient(clientHandler); if (debugMode) { // We want to capture log all the LSP server-to-client calls as well clientHandler.MessageSending += (_, e) => { lock (logWriter) { logWriter.WriteLine("<C{0}", e.Message); } }; clientHandler.MessageReceiving += (_, e) => { lock (logWriter) { logWriter.WriteLine(">C{0}", e.Message); } }; } var session = new LanguageServerSession(client, contractResolver); _serviceManager.AddService(new SettingsManager(_serviceManager)); _serviceManager.AddService(new VsCodeClient(session.Client, _serviceManager)); _serviceManager.AddService(new Controller(_serviceManager)); // Configure & build service host var host = BuildServiceHost(logWriter, contractResolver, debugMode); var serverHandler = new StreamRpcServerHandler(host, StreamRpcServerHandlerOptions.ConsistentResponseSequence | StreamRpcServerHandlerOptions.SupportsRequestCancellation); serverHandler.DefaultFeatures.Set(session); var cts = new CancellationTokenSource(); // If we want server to stop, just stop the "source" using (serverHandler.Attach(reader, writer)) using (clientHandler.Attach(reader, writer)) using (new RConnection(_serviceManager, cts.Token)) { // Wait for the "stop" request. session.CancellationToken.WaitHandle.WaitOne(); cts.Cancel(); } logWriter?.WriteLine("Exited"); } }
private async Task RunAsync() { var host = BuildServiceHost(); var serverHandler = new StreamRpcServerHandler(host); var clientHandler = new StreamRpcClientHandler(); var client = new JsonRpcClient(clientHandler); using (var pipe = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous)) { var connectTask = pipe.ConnectAsync(); hostingClient = BuildHostingClient(client); serverHandler.DefaultFeatures.Set(this); var reader = new ByLineTextMessageReader(pipe) { LeaveReaderOpen = true }; var writer = new ByLineTextMessageWriter(pipe) { LeaveWriterOpen = true }; Ambient = new SandboxAmbient(hostingClient, SandboxId); await connectTask; using (reader) using (writer) using (serverHandler.Attach(reader, writer)) using (clientHandler.Attach(reader, writer)) { // Started up hostingClient.NotifyStarted(); // Wait for disposal await disposalTcs.Task; } } // Dispose if (_ClientModule != null) { if (_ClientModule is IDisposable d) { d.Dispose(); } _ClientModule = null; } // Final cleanup. // The owner will unload appdomain so a ThreadAbortException should be thrown here. hostCallback.NotifySandboxDisposed(SandboxId); }
static void Main(string[] args) { using (Stream cin = Console.OpenStandardInput()) using (BufferedStream bcin = new BufferedStream(cin)) using (Stream cout = Console.OpenStandardOutput()) using (PartwiseStreamMessageReader reader = new PartwiseStreamMessageReader(bcin)) using (PartwiseStreamMessageWriter writer = new PartwiseStreamMessageWriter(cout)) { JsonRpcContractResolver contractResolver = new JsonRpcContractResolver { NamingStrategy = new CamelCaseJsonRpcNamingStrategy(), ParameterValueConverter = new CamelCaseJsonValueConverter(), }; StreamRpcClientHandler clientHandler = new StreamRpcClientHandler(); JsonRpcClient client = new JsonRpcClient(clientHandler); clientHandler.MessageSending += (_, e) => { Console.Error.WriteLine("Sending: " + e.Message); }; clientHandler.MessageReceiving += (_, e) => { Console.Error.WriteLine("Receiving: " + e.Message); }; LanguageServerSession session = new LanguageServerSession(client, contractResolver); JsonRpcServiceHostBuilder builder = new JsonRpcServiceHostBuilder { ContractResolver = contractResolver }; builder.UseCancellationHandling(); builder.Register(typeof(Program).GetTypeInfo().Assembly); builder.Intercept(async(context, next) => { Console.Error.WriteLine("Request: " + context.Request); await next(); Console.Error.WriteLine("Response: " + context.Response); }); IJsonRpcServiceHost host = builder.Build(); StreamRpcServerHandler serverHandler = new StreamRpcServerHandler(host, StreamRpcServerHandlerOptions.ConsistentResponseSequence | StreamRpcServerHandlerOptions.SupportsRequestCancellation); serverHandler.DefaultFeatures.Set(session); using (serverHandler.Attach(reader, writer)) using (clientHandler.Attach(reader, writer)) { // Wait for the "stop" request. session.CancellationToken.WaitHandle.WaitOne(); } } }
private async Task RunClientAsync(Stream clientStream) { await Task.Yield(); // We want this task to run on another thread. // Initialize the client connection to the RPC server. var clientHandler = new StreamRpcClientHandler(); using (var reader = new ByLineTextMessageReader(clientStream)) using (var writer = new ByLineTextMessageWriter(clientStream)) using (clientHandler.Attach(reader, writer)) { var builder = new JsonRpcProxyBuilder { ContractResolver = MyContractResolver }; var proxy = builder.CreateProxy <Shared.IFileMonitor>(new JsonRpcClient(clientHandler)); // Create the function hooks after connection to the server. CreateHooks(); try { while (true) { Thread.Sleep(500); if (_queue.Count > 0) { string[] package = null; lock (_queue) { package = _queue.ToArray(); _queue.Clear(); } await proxy.OnCreateFile(package); } } } catch (Exception ex) { ClientWriteLine(ex.ToString()); } } }
public ClientTestHelper(MessageReader reader, MessageWriter writer) { ClientHandler = new StreamRpcClientHandler(); Client = new JsonRpcClient(ClientHandler); ClientMessageReader = reader; ClientMessageWriter = writer; // We use positional parameters when issuing cancelRequest request. Just for more test coverage. Client.RequestCancelling += (_, e) => { Client.SendNotificationAsync("cancelRequest", new JArray(e.RequestId.Value), CancellationToken.None); }; disposables.Add(ClientHandler.Attach(ClientMessageReader, ClientMessageWriter)); var proxyBuilder = new JsonRpcProxyBuilder { ContractResolver = Utility.DefaultContractResolver }; ClientStub = proxyBuilder.CreateProxy <ITestRpcContract>(Client); ClientExceptionStub = proxyBuilder.CreateProxy <ITestRpcExceptionContract>(Client); ClientCancellationStub = proxyBuilder.CreateProxy <ITestRpcCancellationContract>(Client); }
private static JsonRpcClient RpcClientFactory(IComponentContext context) { var cio = context.Resolve <ConsoleIoService>(); var handler = new StreamRpcClientHandler(); var disposable = handler.Attach(cio.ConsoleMessageReader, cio.ConsoleMessageWriter); var client = new JsonRpcClient(handler); if (context.Resolve <ApplicationConfiguration>().Debug) { var logger = context.Resolve <ILoggerFactory>().CreateLogger("CLIENT"); handler.MessageSending += (_, e) => { logger.LogTrace("< {@Request}", e.Message); }; handler.MessageReceiving += (_, e) => { logger.LogTrace("> {@Response}", e.Message); }; } return(client); }
// If initialization failed, the whole instance should just be discarded. internal async Task InitializeAsync() { if (state != SandboxState.Created) { throw new InvalidOperationException(); } var pipeName = "SandyBox." + Guid.NewGuid(); var pipe = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); disposables.Add(pipe); Id = await Owner.HostStub.CreateSandbox(Name, pipeName); var procReader = new ByLineTextMessageReader(pipe) { LeaveReaderOpen = true }; disposables.Add(procReader); var procWriter = new ByLineTextMessageWriter(pipe) { LeaveWriterOpen = true }; disposables.Add(procWriter); // Wait for sandbox to start up. using (var cts = new CancellationTokenSource(5000)) { Message startedMessage = null; try { await pipe.WaitForConnectionAsync(cts.Token); startedMessage = await procReader.ReadAsync(m => m is RequestMessage rm && rm.Method == "NotifyStarted", cts.Token); } catch (OperationCanceledException) { } if (startedMessage == null) { throw new ExecutionHostException(Prompts.CannotStartExecutionHost_MissingNotifyStarted); } } // HOST var hostBuilder = new JsonRpcServiceHostBuilder(); hostBuilder.Register <HostingClientService>(); var host = hostBuilder.Build(); var serverHandler = new StreamRpcServerHandler(host); serverHandler.DefaultFeatures.Set <ISandboxContextFeature>(new SandboxContextFeature(Owner, this)); disposables.Add(serverHandler.Attach(procReader, procWriter)); // CLIENT var clientHandler = new StreamRpcClientHandler(); RpcClient = new JsonRpcClient(clientHandler); disposables.Add(clientHandler.Attach(procReader, procWriter)); SandboxStub = JsonRpcExecutionHost.ProxyBuilder.CreateProxy <ISandboxStub>(RpcClient); disposables.Reverse(); // Dispose in the reversed order. state = SandboxState.Started; }
private async Task <Process> StartProcessAsync() { Debug.Assert(!_Process.IsValueCreated); // Can be called only once. Debug.Assert(disposables == null); Directory.CreateDirectory(WorkingDirectory); Process process = null; var localDisposables = new List <IDisposable>(); try { var txPipe = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable); localDisposables.Add(txPipe); var rxPipe = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable); localDisposables.Add(rxPipe); process = StartExecutionProcess(txPipe, rxPipe); localDisposables.Add(process); txPipe.DisposeLocalCopyOfClientHandle(); rxPipe.DisposeLocalCopyOfClientHandle(); var procReader = new ByLineTextMessageReader(rxPipe); localDisposables.Add(procReader); localDisposables.Remove(rxPipe); var procWriter = new ByLineTextMessageWriter(txPipe); localDisposables.Add(procWriter); localDisposables.Remove(txPipe); // Wait for host to start up. using (var cts = new CancellationTokenSource(5000)) { Message startedMessage = null; try { startedMessage = await procReader.ReadAsync(m => m is RequestMessage rm && rm.Method == "NotifyStarted", cts.Token); } catch (OperationCanceledException) { } if (startedMessage == null) { throw new ExecutionHostException(Prompts.CannotStartExecutionHost_MissingNotifyStarted); } } //// HOST //var hostBuilder = new JsonRpcServiceHostBuilder(); //// Currently this host does nothing. //var host = hostBuilder.Build(); //var serverHandler = new StreamRpcServerHandler(host); //serverHandler.DefaultFeatures.Set<ISandboxContextFeature>(new SandboxContextFeature(this, null)); //localDisposables.Add(serverHandler.Attach(procReader, procWriter)); // CLIENT var clientHandler = new StreamRpcClientHandler(); RpcClient = new JsonRpcClient(clientHandler); localDisposables.Add(clientHandler.Attach(procReader, procWriter)); HostStub = ProxyBuilder.CreateProxy <IHostStub>(RpcClient); return(process); } catch (Exception ex) { if (process != null) { try { if (!process.WaitForExit(1000)) { process.Kill(); } } catch (Exception ex1) { throw new AggregateException(ex, ex1); } } foreach (var d in localDisposables) { try { d.Dispose(); } catch (ObjectDisposedException) { // StreamWriter will attempt to flush before disposal, } catch (Exception ex1) { throw new AggregateException(ex, ex1); } } localDisposables = null; if (ex is ExecutionHostException) { throw; } throw new ExecutionHostException(Prompts.CannotStartExecutionHost, ex); } finally { if (localDisposables != null) { disposables = localDisposables; } } }