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) { } }
static void Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; // Here we use two connected streams to simulate the console I/O // Content written to streams.Item1 will be read from streams.Item2, vice versa. var streams = FullDuplexStream.CreateStreams(); // Let's start the test client first. var clientTask = RunClientAsync(streams.Item2); // Configure & build service host var host = BuildServiceHost(); // Messages come from Stream var serverHandler = new StreamRpcServerHandler(host); // Though it's suggested that all feature types be interface types, for sake of // simplicity, here we just use a concrete class. var session = new LibrarySessionFeature(); serverHandler.DefaultFeatures.Set(session); // Connect the datablocks // If we want server to stop, just stop the source using (var reader = new ByLineTextMessageReader(streams.Item1)) using (var writer = new ByLineTextMessageWriter(streams.Item1)) using (serverHandler.Attach(reader, writer)) { // Wait for exit session.CancellationToken.WaitHandle.WaitOne(); } Console.WriteLine("Server exited."); // Wait for the client to exit. clientTask.GetAwaiter().GetResult(); }
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 async Task ByLineMessagesOverSocketsTest() { var serverListener = new TcpListener(IPAddress.Loopback, TcpLocalTestPort); serverListener.Start(); try { using (var tcpClient = new TcpClient()) { var serverAsync = serverListener.AcceptTcpClientAsync(); await tcpClient.ConnectAsync(IPAddress.Loopback, TcpLocalTestPort); using (var tcpServer = await serverAsync) using (var ss = tcpServer.GetStream()) using (var cs = tcpClient.GetStream()) { using (var clientReader = new ByLineTextMessageReader(cs)) using (var clientWriter = new ByLineTextMessageWriter(cs)) using (var serverReader = new ByLineTextMessageReader(ss)) using (var serverWriter = new ByLineTextMessageWriter(ss)) using (var server = new ServerTestHelper(this, serverReader, serverWriter, StreamRpcServerHandlerOptions.None)) using (var client = new ClientTestHelper(clientReader, clientWriter)) using (var server1 = new ServerTestHelper(this, clientReader, clientWriter, StreamRpcServerHandlerOptions.None)) using (var client1 = new ClientTestHelper(serverReader, serverWriter)) { async Task ClientTestAsync() { await Task.Yield(); await TestRoutines.TestStubAsync(client.ClientStub); await TestRoutines.TestStubAsync(client.ClientExceptionStub); } async Task Client1TestAsync() { await Task.Yield(); await TestRoutines.TestStubAsync(client1.ClientStub); await TestRoutines.TestStubAsync(client1.ClientExceptionStub); } await Task.WhenAll(ClientTestAsync(), Client1TestAsync()); } } } } finally { serverListener.Stop(); } }
public async Task PartwiseStreamCancellationTest() { (var ss, var cs) = FullDuplexStream.CreatePair(); using (var clientReader = new ByLineTextMessageReader(cs)) using (var clientWriter = new ByLineTextMessageWriter(cs)) using (var serverReader = new ByLineTextMessageReader(ss)) using (var serverWriter = new ByLineTextMessageWriter(ss)) using (var server = new ServerTestHelper(this, serverReader, serverWriter, StreamRpcServerHandlerOptions.SupportsRequestCancellation)) using (var client = new ClientTestHelper(clientReader, clientWriter)) { await TestRoutines.TestCancellationAsync(client.ClientCancellationStub); } }
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); }
/// <param name="manualIo">Simply read messages from console, line by line, /// instead of using language server protocol's specification.</param> public ConsoleIoService(bool manualIo) { if (manualIo) { ConsoleMessageReader = new ByLineTextMessageReader(Console.In); ConsoleMessageWriter = new ByLineTextMessageWriter(Console.Out); } else { var cin = Console.OpenStandardInput(); var bcin = new BufferedStream(cin); var cout = Console.OpenStandardOutput(); ConsoleMessageReader = new PartwiseStreamMessageReader(bcin); ConsoleMessageWriter = new PartwiseStreamMessageWriter(cout); } }
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 async Task ServerHandlerTest() { var request = new RequestMessage(123, "add", JToken.FromObject(new { x = 20, y = 35 })); (var ss, var cs) = FullDuplexStream.CreatePair(); using (var clientReader = new StreamReader(cs)) using (var clientWriter = new StreamWriter(cs)) using (var serverReader = new ByLineTextMessageReader(ss)) using (var serverWriter = new ByLineTextMessageWriter(ss)) { async Task <ResponseMessage> WaitForResponse() { var sw = Stopwatch.StartNew(); var content = await clientReader.ReadLineAsync(); Output.WriteLine($"Received response in {sw.Elapsed}."); return((ResponseMessage)Message.LoadJson(content)); } async Task <ResponseMessage> SendRequest(MessageId messageId) { request.Id = messageId; request.WriteJson(clientWriter); clientWriter.WriteLine(); await clientWriter.FlushAsync(); var response = await WaitForResponse(); Assert.Equal(messageId, response.Id); Assert.Null(response.Error); Assert.Equal(55, (int)response.Result); return(response); } using (var server = new ServerTestHelper(this, serverReader, serverWriter, StreamRpcServerHandlerOptions.None)) { await SendRequest(123); await SendRequest("abc"); } } }
public void HandleConnection(IPC.IConnection connection) { Console.WriteLine($"Connection received from pipe {_pipeName}"); var pipeServer = connection.ServerStream; IJsonRpcServiceHost host = BuildServiceHost(_service); var serverHandler = new StreamRpcServerHandler(host); serverHandler.DefaultFeatures.Set(_session); using (var reader = new ByLineTextMessageReader(pipeServer)) using (var writer = new ByLineTextMessageWriter(pipeServer)) using (serverHandler.Attach(reader, writer)) { // Wait for exit _session.CancellationToken.WaitHandle.WaitOne(); } }
public async Task ConsistentResponseSequenceTest() { (var ss, var cs) = FullDuplexStream.CreatePair(); using (var clientReader = new ByLineTextMessageReader(cs)) using (var clientWriter = new ByLineTextMessageWriter(cs)) using (var serverReader = new ByLineTextMessageReader(ss)) using (var serverWriter = new ByLineTextMessageWriter(ss)) using (var client = new ClientTestHelper(clientReader, clientWriter)) { using (var server = new ServerTestHelper(this, serverReader, serverWriter, StreamRpcServerHandlerOptions.None)) { // The responses are ordered by the time of completion. var delayTask = client.ClientStub.DelayAsync(TimeSpan.FromMilliseconds(200), CancellationToken.None); var addTask = client.ClientStub.AddAsync(3, -4); var result = await addTask; Assert.Equal(-1, result); // addTask completes first. Assert.False(delayTask.IsCompleted); await delayTask; } using (var server = new ServerTestHelper(this, serverReader, serverWriter, StreamRpcServerHandlerOptions.ConsistentResponseSequence)) { // The responses are in the same order as the requests. var delayTask = client.ClientStub.DelayAsync(TimeSpan.FromMilliseconds(200), CancellationToken.None); var addTask = client.ClientStub.AddAsync(10, 20); await Task.Delay(100); // addTask is held up. Assert.False(addTask.IsCompleted); await delayTask; var result = await addTask; Assert.Equal(30, result); } } }
public async Task PartwiseStreamInteropTest() { (var ss, var cs) = FullDuplexStream.CreatePair(); using (var clientReader = new ByLineTextMessageReader(cs)) using (var clientWriter = new ByLineTextMessageWriter(cs)) using (var serverReader = new ByLineTextMessageReader(ss)) using (var serverWriter = new ByLineTextMessageWriter(ss)) using (var server = new ServerTestHelper(this, serverReader, serverWriter, StreamRpcServerHandlerOptions.None)) using (var client = new ClientTestHelper(clientReader, clientWriter)) { var e = Assert.Raises <MessageEventArgs>(h => client.ClientHandler.MessageSending += h, h => client.ClientHandler.MessageSending -= h, () => client.ClientStub.One()); Assert.Equal("one", ((RequestMessage)e.Arguments.Message).Method); e = Assert.Raises <MessageEventArgs>(h => client.ClientHandler.MessageReceiving += h, h => client.ClientHandler.MessageReceiving -= h, () => client.ClientStub.One()); Assert.Equal(new JValue(1), ((ResponseMessage)e.Arguments.Message).Result); await TestRoutines.TestStubAsync(client.ClientStub); await TestRoutines.TestStubAsync(client.ClientExceptionStub); } }
// 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; } } }