// handle sync reads from each end and pass to the other end public static async Task HandleClientAsync(CancellationToken cancelToken, IPluggableStreamAsync inputStream, IPluggableStreamAsync outputStream) { while (!cancelToken.IsCancellationRequested) { byte[] outputRead = new byte[MaxMessageSize]; byte[] inputRead = new byte[MaxMessageSize]; var readFromOutput = outputStream.ReadAsync(outputRead, 0, MaxMessageSize, cancelToken); var readFromInput = inputStream.ReadAsync(inputRead, 0, MaxMessageSize, cancelToken); while (!cancelToken.IsCancellationRequested) { int byteCount; var nextTask = await Task.WhenAny(new[] { readFromOutput, readFromInput }); Console.Write("."); if (nextTask == readFromInput) { try { byteCount = await nextTask; } catch (System.IO.IOException e) when((e.InnerException as SocketException)?.ErrorCode == 10054) { throw new OperationCanceledException("Input stream disconnected (WSACONNRESET)"); } OpDiag(Operation.InboundRead, byteCount, inputRead); if (byteCount == 0) { throw new OperationCanceledException("Input stream disconnected"); } var outputWrite = new byte[MaxMessageSize]; Array.Copy(inputRead, outputWrite, byteCount); var backTask = outputStream.WriteAsync(outputWrite, 0, byteCount, cancelToken); readFromInput = inputStream.ReadAsync(inputRead, 0, MaxMessageSize, cancelToken); } else if (nextTask == readFromOutput) { byteCount = await nextTask; OpDiag(Operation.OutboundRead, byteCount, outputRead); var inputWrite = new byte[MaxMessageSize]; Array.Copy(outputRead, inputWrite, byteCount); var backTask = inputStream.WriteAsync(inputWrite, 0, byteCount, cancelToken); readFromOutput = outputStream.ReadAsync(outputRead, 0, MaxMessageSize, cancelToken); } } } }
private static async Task ClientConnectAsync(CancellationToken cancelToken, IPluggableStreamAsync serverStream, BindingInfo clientBinding) { IPluggableStreamAsync clientStream; if (clientBinding.BindingType == BindingType.Serial) { using (var serialPortClient = new SerialPort(string.Format("COM{0}", clientBinding.Port), 115200, Parity.None, 8, StopBits.One)) { try { serialPortClient.DtrEnable = true; serialPortClient.Open(); } catch (UnauthorizedAccessException) { throw new InvalidOperationException("Could not connect COM port"); } clientStream = new PluggableStream(serialPortClient.BaseStream); Console.WriteLine("Connection made"); await StreamCrossover.HandleClientAsync(cancelToken, serverStream, clientStream); } } else if (clientBinding.BindingType == BindingType.Socket) { var ep = new IPEndPoint(IPAddress.Parse(clientBinding.Address), clientBinding.Port ?? 80); while (!cancelToken.IsCancellationRequested) { using (var socketClient = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) { try { socketClient.Connect(ep); } catch (SocketException e) { Console.WriteLine("Exception connecting to outgoing host: " + e + ": " + e.Message); await Task.Delay(10000); continue; } socketClient.NoDelay = true; clientStream = new PluggableSocket(socketClient); Console.WriteLine("Connection made"); try { await StreamCrossover.HandleClientAsync(cancelToken, serverStream, clientStream); } catch (Exception e) { Console.WriteLine(e.Message); } socketClient.Disconnect(false); if (!serverStream.IsConnected()) { return; } } } } else if (clientBinding.BindingType == BindingType.NamedPipe) { using (var pipeClient = new NamedPipeClientStream(".", clientBinding.Address, PipeDirection.InOut, PipeOptions.Asynchronous)) { pipeClient.Connect(); if (!pipeClient.IsConnected) { return; } clientStream = new PluggableStream(pipeClient); Console.WriteLine("Connection made"); try { await StreamCrossover.HandleClientAsync(cancelToken, serverStream, clientStream); } catch (Exception e) { Console.WriteLine(e.Message); } } } }