public async Task NamedPipeWriteViaAsyncFileStream(bool asyncWrites) { string name = Guid.NewGuid().ToString("N"); using (var server = new NamedPipeServerStream(name, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) { Task serverTask = Task.Run(async () => { await server.WaitForConnectionAsync(); for (int i = 0; i < 6; i++) Assert.Equal(i, server.ReadByte()); }); WaitNamedPipeW(@"\\.\pipe\" + name, -1); using (SafeFileHandle clientHandle = CreateFileW(@"\\.\pipe\" + name, GENERIC_WRITE, FileShare.None, IntPtr.Zero, FileMode.Open, (int)PipeOptions.Asynchronous, IntPtr.Zero)) using (var client = new FileStream(clientHandle, FileAccess.Write, bufferSize: 3, isAsync: true)) { var data = new[] { new byte[] { 0, 1 }, new byte[] { 2, 3 }, new byte[] { 4, 5 } }; foreach (byte[] arr in data) { if (asyncWrites) await client.WriteAsync(arr, 0, arr.Length); else client.Write(arr, 0, arr.Length); } } await serverTask; } }
private async Task PrivateRunAsync(CancellationToken cancellationToken) { using (var pipe = new NamedPipeServerStream(ServerInfo.Name, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) { while (!cancellationToken.IsCancellationRequested) { await pipe.WaitForConnectionAsync(cancellationToken); using (var reader = new NonClosingStreamReader(pipe)) using (var writer = new NonClosingStreamWriter(pipe) { AutoFlush = true }) { var input = await reader.ReadCommandAsync(); _log.Information("Retrieved input {Input}", input); switch (input) { case NamedPipeCommand.FindRepo: await writer.WriteAsync(NamedPipeCommand.Ready); await FindRepo(writer, await reader.ReadLineAsync(), cancellationToken); break; case NamedPipeCommand.GetAllRepos: await writer.WriteAsync(NamedPipeCommand.Ready); await GetAllRepos(writer, cancellationToken); break; case NamedPipeCommand.RemoveRepo: await writer.WriteAsync(NamedPipeCommand.Ready); await RemoveRepo(writer, reader, cancellationToken); break; case NamedPipeCommand.ClearCache: await writer.WriteAsync(NamedPipeCommand.Ready); await ProcessClearCacheAsync(writer, cancellationToken); break; case NamedPipeCommand.ExpandGitCommand: await writer.WriteAsync(NamedPipeCommand.Ready); await ProcessExpandGitCommandAsync(writer, reader, cancellationToken); break; default: await writer.WriteAsync(NamedPipeCommand.BadCommand); break; } } // This must be after the reader and writer are closed // Otherwise, an InvalidOperationException is thrown pipe.WaitForPipeDrain(); pipe.Disconnect(); } } }
private static int PingPong_OtherProcess(string inName, string outName) { // Create pipes with the supplied names using (var inbound = new NamedPipeClientStream(".", inName, PipeDirection.In)) using (var outbound = new NamedPipeServerStream(outName, PipeDirection.Out)) { // Wait for the connections to be established Task.WaitAll(inbound.ConnectAsync(), outbound.WaitForConnectionAsync()); // Repeatedly read then write bytes from and to the other process for (int i = 0; i < 10; i++) { int b = inbound.ReadByte(); outbound.WriteByte((byte)b); } } return SuccessExitCode; }
public void PingPong() { // Create names for two pipes string outName = Guid.NewGuid().ToString("N"); string inName = Guid.NewGuid().ToString("N"); // Create the two named pipes, one for each direction, then create // another process with which to communicate using (var outbound = new NamedPipeServerStream(outName, PipeDirection.Out)) using (var inbound = new NamedPipeClientStream(".", inName, PipeDirection.In)) using (var remote = RemoteInvoke(PingPong_OtherProcess, outName, inName)) { // Wait for both pipes to be connected Task.WaitAll(outbound.WaitForConnectionAsync(), inbound.ConnectAsync()); // Repeatedly write then read a byte to and from the other process for (byte i = 0; i < 10; i++) { outbound.WriteByte(i); int received = inbound.ReadByte(); Assert.Equal(i, received); } } }
public async Task NamedPipeReadViaAsyncFileStream(bool asyncReads) { string name = Guid.NewGuid().ToString("N"); using (var server = new NamedPipeServerStream(name, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) { Task serverTask = Task.Run(async () => { await server.WaitForConnectionAsync(); await server.WriteAsync(new byte[] { 0, 1, 2, 3, 4, 5 }, 0, 6); }); WaitNamedPipeW(@"\\.\pipe\" + name, -1); using (SafeFileHandle clientHandle = CreateFileW(@"\\.\pipe\" + name, GENERIC_READ, FileShare.None, IntPtr.Zero, FileMode.Open, (int)PipeOptions.Asynchronous, IntPtr.Zero)) using (var client = new FileStream(clientHandle, FileAccess.Read, bufferSize: 3, isAsync: true)) { var arr = new byte[1]; for (int i = 0; i < 6; i++) { Assert.Equal(1, asyncReads ? await client.ReadAsync(arr, 0, 1) : client.Read(arr, 0, 1)); Assert.Equal(i, arr[0]); } } await serverTask; } }
private Task RunAsync(string mutexId, string pipeId, CancellationTokenSource cancellationTokenSource) { var cancellationToken = cancellationTokenSource.Token; return Task.Run(async () => { try { using (var mutex = new Mutex(false, mutexId)) { //ミューテックスの所有権を要求する if (!mutex.WaitOne(0, false)) { //すでに起動していると判断して終了 return; } try { //mutexDictionary.TryAdd(mutexId, mutex); while (true) { cancellationToken.ThrowIfCancellationRequested(); using (var pipeServer = new NamedPipeServerStream(pipeId, PipeDirection.In)) { // Wait for a client to connect await pipeServer.WaitForConnectionAsync(cancellationToken); try { using (var sr = new StreamReader(pipeServer)) { while (pipeServer.IsConnected) { var text = sr.ReadLine(); if (text != null) { this.LineReceivedSubject.OnNext(text); } cancellationToken.ThrowIfCancellationRequested(); } } } catch (IOException e) { // Catch the IOException that is raised if the pipe is broken // or disconnected. } } } } finally { mutex.ReleaseMutex(); mutex.Close(); } } } catch (Exception e) { this.LineReceivedSubject.OnError(e); } }, cancellationToken); }
public async Task NamedPipeViaFileStream_CancellationRequested_OperationCanceled() { string name = Guid.NewGuid().ToString("N"); using (var server = new NamedPipeServerStream(name, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) { Task serverTask = server.WaitForConnectionAsync(); Assert.True(WaitNamedPipeW(@"\\.\pipe\" + name, -1)); using (SafeFileHandle clientHandle = CreateFileW(@"\\.\pipe\" + name, GENERIC_READ, FileShare.None, IntPtr.Zero, FileMode.Open, (int)PipeOptions.Asynchronous, IntPtr.Zero)) using (var client = new FileStream(clientHandle, FileAccess.Read, bufferSize: 3, isAsync: true)) { await serverTask; var cts = new CancellationTokenSource(); Task clientTask = client.CopyToAsync(new MemoryStream(), 0x1000, cts.Token); Assert.False(clientTask.IsCompleted); cts.Cancel(); await Assert.ThrowsAsync<OperationCanceledException>(() => clientTask); } } }
public async Task NamedPipeViaFileStream_AllDataCopied(bool useAsync, int writeSize, int numWrites) { long totalLength = writeSize * numWrites; var expectedData = new byte[totalLength]; new Random(42).NextBytes(expectedData); var results = new MemoryStream(); var pipeOptions = useAsync ? PipeOptions.Asynchronous : PipeOptions.None; string name = Guid.NewGuid().ToString("N"); using (var server = new NamedPipeServerStream(name, PipeDirection.Out, 1, PipeTransmissionMode.Byte, pipeOptions)) { Task serverTask = Task.Run(async () => { await server.WaitForConnectionAsync(); for (int i = 0; i < numWrites; i++) { await server.WriteAsync(expectedData, i * writeSize, writeSize); } server.Dispose(); }); Assert.True(WaitNamedPipeW(@"\\.\pipe\" + name, -1)); using (SafeFileHandle clientHandle = CreateFileW(@"\\.\pipe\" + name, GENERIC_READ, FileShare.None, IntPtr.Zero, FileMode.Open, (int)pipeOptions, IntPtr.Zero)) using (var client = new FileStream(clientHandle, FileAccess.Read, bufferSize: 3, isAsync: useAsync)) { Task copyTask = client.CopyToAsync(results, (int)totalLength); await await Task.WhenAny(serverTask, copyTask); await copyTask; } } byte[] actualData = results.ToArray(); Assert.Equal(expectedData.Length, actualData.Length); Assert.Equal<byte>(expectedData, actualData); }
private async Task ConnectToBrokerWorker() { Trace.Assert(_brokerProcess == null); string rhostBrokerExe = Path.Combine(_rhostDirectory, RHostBrokerExe); if (!_services.FileSystem.FileExists(rhostBrokerExe)) { throw new RHostBrokerBinaryMissingException(); } Process process = null; try { string pipeName = Guid.NewGuid().ToString(); using (var serverUriPipe = new NamedPipeServerStream(pipeName, PipeDirection.In)) { var psi = new ProcessStartInfo { FileName = rhostBrokerExe, UseShellExecute = false, Arguments = $" --logging:logHostOutput {Log.LogVerbosity >= LogVerbosity.Normal}" + $" --logging:logPackets {Log.LogVerbosity == LogVerbosity.Traffic}" + $" --server.urls http://127.0.0.1:0" + // :0 means first available ephemeral port $" --startup:name \"{Name}\"" + $" --startup:writeServerUrlsToPipe {pipeName}" + $" --lifetime:parentProcessId {Process.GetCurrentProcess().Id}" + $" --security:secret \"{_credentials.Password}\"" + $" --R:autoDetect false" + $" --R:interpreters:{InterpreterId}:name \"{Name}\"" + $" --R:interpreters:{InterpreterId}:basePath \"{_rHome.TrimTrailingSlash()}\"" }; if (!ShowConsole) { psi.CreateNoWindow = true; } process = StartBroker(psi); process.EnableRaisingEvents = true; var cts = new CancellationTokenSource(100000); process.Exited += delegate { cts.Cancel(); _brokerProcess = null; _connectLock.EnqueueReset(); }; await serverUriPipe.WaitForConnectionAsync(cts.Token); var serverUriData = new MemoryStream(); try { // Pipes are special in that a zero-length read is not an indicator of end-of-stream. // Stream.CopyTo uses a zero-length read as indicator of end-of-stream, so it cannot // be used here. Instead, copy the data manually, using PipeStream.IsConnected to detect // when the other side has finished writing and closed the pipe. var buffer = new byte[0x1000]; do { int count = await serverUriPipe.ReadAsync(buffer, 0, buffer.Length, cts.Token); serverUriData.Write(buffer, 0, count); } while (serverUriPipe.IsConnected); } catch (OperationCanceledException) { throw new RHostDisconnectedException("Timed out while waiting for broker process to report its endpoint URI"); } string serverUriStr = Encoding.UTF8.GetString(serverUriData.ToArray()); Uri[] serverUri; try { serverUri = Json.DeserializeObject<Uri[]>(serverUriStr); } catch (JsonSerializationException ex) { throw new RHostDisconnectedException($"Invalid JSON for endpoint URIs received from broker ({ex.Message}): {serverUriStr}"); } if (serverUri?.Length != 1) { throw new RHostDisconnectedException($"Unexpected number of endpoint URIs received from broker: {serverUriStr}"); } CreateHttpClient(serverUri[0]); } if (DisposableBag.TryAdd(DisposeBrokerProcess)) { _brokerProcess = process; } } finally { if (_brokerProcess == null) { try { process?.Kill(); } catch (Exception) { } finally { process?.Dispose(); } } } }
public static async Task ClientCloneTests() { const string pipeName = "fooClientclone"; byte[] msg1 = new byte[] { 5, 7, 9, 10 }; byte[] received0 = new byte[] { }; byte[] received1 = new byte[] { 0, 0, 0, 0 }; using (NamedPipeServerStream server = new NamedPipeServerStream(pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte)) using (NamedPipeClientStream clientBase = new NamedPipeClientStream(".", pipeName, PipeDirection.Out, PipeOptions.None)) { await Task.WhenAll(server.WaitForConnectionAsync(), clientBase.ConnectAsync()); using (NamedPipeClientStream client = new NamedPipeClientStream(PipeDirection.Out, false, true, clientBase.SafePipeHandle)) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Assert.Equal(1, client.NumberOfServerInstances); } Assert.Equal(PipeTransmissionMode.Byte, client.TransmissionMode); Task clientTask = Task.Run(() => client.Write(msg1, 0, msg1.Length)); int len1 = server.Read(received1, 0, msg1.Length); await clientTask; Assert.Equal(msg1.Length, len1); Assert.Equal(msg1, received1); // test special cases of buffer lengths = 0 int len0 = server.Read(received0, 0, 0); Assert.Equal(0, len0); Assert.Equal(0, await server.ReadAsync(received0, 0, 0)); } } }
public static async Task ClientServerOneWayOperations( string pipeName, PipeDirection serverDirection, bool asyncServerPipe, bool asyncClientPipe, bool asyncServerOps, bool asyncClientOps) { PipeDirection clientDirection = serverDirection == PipeDirection.Out ? PipeDirection.In : PipeDirection.Out; PipeOptions serverOptions = asyncServerPipe ? PipeOptions.Asynchronous : PipeOptions.None; PipeOptions clientOptions = asyncClientPipe ? PipeOptions.Asynchronous : PipeOptions.None; using (NamedPipeServerStream server = new NamedPipeServerStream(pipeName, serverDirection, 1, PipeTransmissionMode.Byte, serverOptions)) { byte[] received = new byte[] { 0 }; Task clientTask = Task.Run(async () => { using (NamedPipeClientStream client = new NamedPipeClientStream(".", pipeName, clientDirection, clientOptions)) { if (asyncClientOps) { await client.ConnectAsync(); if (clientDirection == PipeDirection.In) { received = await ReadBytesAsync(client, sendBytes.Length); } else { await WriteBytesAsync(client, sendBytes); } } else { client.Connect(); if (clientDirection == PipeDirection.In) { received = ReadBytes(client, sendBytes.Length); } else { WriteBytes(client, sendBytes); } } } }); if (asyncServerOps) { await server.WaitForConnectionAsync(); if (serverDirection == PipeDirection.Out) { await WriteBytesAsync(server, sendBytes); } else { received = await ReadBytesAsync(server, sendBytes.Length); } } else { server.WaitForConnection(); if (serverDirection == PipeDirection.Out) { WriteBytes(server, sendBytes); } else { received = ReadBytes(server, sendBytes.Length); } } await clientTask; Assert.Equal(sendBytes, received); server.Disconnect(); Assert.False(server.IsConnected); } }
private static async Task<int> CreateServerFailsConnectionCore(string pipeName, CancellationToken cancellationToken) { var connections = 0; try { while (!cancellationToken.IsCancellationRequested) { using (var pipeStream = new NamedPipeServerStream(pipeName, PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) { await pipeStream.WaitForConnectionAsync(cancellationToken); connections++; } } } catch (Exception) { // Exceptions are okay and expected here } return connections; }
public override async Task<IAsyncTransport> CreateAsync(Address address) { NamedPipeServerStream server = new NamedPipeServerStream(address.Path, PipeDirection.InOut, 4, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); #if DOTNET await server.WaitForConnectionAsync(); #else await Task.Factory.FromAsync( (c, s) => server.BeginWaitForConnection(c, s), (r) => server.EndWaitForConnection(r), null); #endif return new NamedPipeTransport(server); }
public async Task<Tuple<Int32, string>> ListenerAcceptAsync( int listenerId ) { // Get the listener (which is just a pipe name) // TODO: I guess that technically we should do some sort of check to // make sure that no connections are being accepted on this // endpoint. Perhaps change listener map to add cancellation token? string pipeName = null; lock (this) { if (!_listeners.TryGetValue(listenerId, out pipeName)) { return Tuple.Create(0, "invalid listener id"); } } // Create the connection // NOTE: It is essential that the PipeOptions.Asynchronous option be // specified, or the ReadAsync and WriteAsync methods will block // (and I don't mean they'll call await and halt - I mean they'll // never return a Task object) var connection = new NamedPipeServerStream( pipeName, PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous ); // Try to accept a connection asynchronously try { await connection.WaitForConnectionAsync(); } catch (Exception e) { return Tuple.Create(-1, e.Message); } // Store the connection Int32 connectionId = -1; lock (this) { // Compute the next connection id. Watch for overflow, because // we use -1 as the invalid identifier. if (_nextConnectionId < 0) { connection.Close(); return Tuple.Create(-1, "connection ids exhausted"); } connectionId = _nextConnectionId++; // Do the storage _connections[connectionId] = connection; } // All done return Tuple.Create(connectionId, ""); }