async Task BridgeSocketConnectionAsync(TcpClient tcpClient) { EventTraceActivity bridgeActivity = BridgeEventSource.NewActivity("LocalForwardBridgeConnection"); try { BridgeEventSource.Log.LocalForwardBridgeConnectionStarting(bridgeActivity, tcpClient, HybridConnectionClient); using (var hybridConnectionStream = await HybridConnectionClient.CreateConnectionAsync()) { // read and write 4-byte header byte[] rd = new byte[4]; int read = 0; hybridConnectionStream.Write(new byte[] { 1, 0, 0, 0 }, 0, 4); for (; read < 4; read += hybridConnectionStream.Read(rd, read, 4 - read)) { ; } BridgeEventSource.Log.LocalForwardBridgeConnectionStart(bridgeActivity, tcpClient, HybridConnectionClient); if (tcpClient.Connected) { await Task.WhenAll( StreamPump.RunAsync(hybridConnectionStream, tcpClient.GetStream(), () => tcpClient.Client.Shutdown(SocketShutdown.Send), cancellationTokenSource.Token), StreamPump.RunAsync(tcpClient.GetStream(), hybridConnectionStream, () => hybridConnectionStream.Shutdown(), cancellationTokenSource.Token)); } } BridgeEventSource.Log.LocalForwardBridgeConnectionStop(bridgeActivity, tcpClient, HybridConnectionClient); } catch (Exception e) { BridgeEventSource.Log.LocalForwardBridgeConnectionFailed(bridgeActivity, e); throw; } }
public void Run(IPEndPoint listenEndpoint) { if (this.IsOpen) { throw BridgeEventSource.Log.ThrowingException(new InvalidOperationException(), this); } this.listenerActivity = BridgeEventSource.NewActivity("LocalForwardListener"); try { this.IsOpen = true; BridgeEventSource.Log.LocalForwardListenerStarting(listenerActivity, listenEndpoint); this.tcpListener = new TcpListener(listenEndpoint); this.tcpListener.Start(); this.acceptSocketLoop = Task.Factory.StartNew(AcceptSocketLoopAsync); this.acceptSocketLoop.ContinueWith(AcceptSocketLoopFaulted, TaskContinuationOptions.OnlyOnFaulted); BridgeEventSource.Log.LocalForwardListenerStart(listenerActivity, tcpListener); } catch (Exception exception) { BridgeEventSource.Log.LocalForwardListenerStartFailed(listenerActivity, exception); this.LastError = exception; throw; } }
public void Run(string socketEndpoint) { this.localEndpoint = socketEndpoint; if (this.IsOpen) { throw BridgeEventSource.Log.ThrowingException(new InvalidOperationException(), this); } this.listenerActivity = BridgeEventSource.NewActivity("LocalForwardListener"); try { this.IsOpen = true; BridgeEventSource.Log.LocalForwardListenerStarting(listenerActivity, localEndpoint); this.socketListener = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP); this.socketListener.Bind(new UnixDomainSocketEndPoint(socketEndpoint)); this.socketListener.Listen(5); this.acceptSocketLoop = Task.Factory.StartNew(AcceptSocketLoopAsync); this.acceptSocketLoop.ContinueWith(AcceptSocketLoopFaulted, TaskContinuationOptions.OnlyOnFaulted); BridgeEventSource.Log.LocalForwardListenerStart(listenerActivity, localEndpoint); } catch (Exception exception) { BridgeEventSource.Log.LocalForwardListenerStartFailed(listenerActivity, exception); this.LastError = exception; throw; } }
public void Run(IPEndPoint listenEndpoint) { this.localEndpoint = listenEndpoint.ToString(); if (this.IsOpen) { throw BridgeEventSource.Log.ThrowingException(new InvalidOperationException(), this); } this.listenerActivity = BridgeEventSource.NewActivity("LocalForwardListener"); try { this.IsOpen = true; BridgeEventSource.Log.LocalForwardListenerStarting(listenerActivity, localEndpoint); this.udpClient = new UdpClient(listenEndpoint); this.receiveDatagramLoop = Task.Factory.StartNew(ReceiveDatagramAsync); this.receiveDatagramLoop.ContinueWith(ReceiveLoopFaulted, TaskContinuationOptions.OnlyOnFaulted); BridgeEventSource.Log.LocalForwardListenerStart(listenerActivity, localEndpoint); } catch (Exception exception) { BridgeEventSource.Log.LocalForwardListenerStartFailed(listenerActivity, exception); this.LastError = exception; throw; } }
async Task AcceptSocketLoopAsync() { while (!cancellationTokenSource.Token.IsCancellationRequested) { var socketActivity = BridgeEventSource.NewActivity("LocalForwardSocket"); Socket socket; try { socket = await this.socketListener.AcceptAsync(); } catch (ObjectDisposedException) { // occurs on shutdown and signals that we need to exit return; } BridgeEventSource.Log.LocalForwardSocketAccepted(socketActivity, localEndpoint); this.LastAttempt = DateTime.Now; BridgeSocketConnectionAsync(socket) .ContinueWith((t, s) => { if (t.Exception != null) { BridgeEventSource.Log.LocalForwardSocketError(socketActivity, localEndpoint, t.Exception); } socket.Dispose(); }, TaskContinuationOptions.OnlyOnFaulted) .ContinueWith((t, s) => { try { BridgeEventSource.Log.LocalForwardSocketComplete(socketActivity, localEndpoint); socket.Close(); BridgeEventSource.Log.LocalForwardSocketClosed(socketActivity, localEndpoint); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } BridgeEventSource.Log.LocalForwardSocketCloseFailed(socketActivity, localEndpoint, e); socket.Dispose(); } }, TaskContinuationOptions.OnlyOnRanToCompletion) .Fork(); } }
void StartEndpoint(LocalForward localForward) { var startActivity = BridgeEventSource.NewActivity("LocalForwardBridgeStart", activity); Uri hybridConnectionUri = null; TcpLocalForwardBridge tcpListenerBridge = null; BridgeEventSource.Log.LocalForwardBridgeStarting(startActivity, localForward); var rcbs = localForward.RelayConnectionStringBuilder ?? new RelayConnectionStringBuilder(config.AzureRelayConnectionString); rcbs.EntityPath = localForward.RelayName; hybridConnectionUri = new Uri(rcbs.Endpoint, rcbs.EntityPath); try { IPHostEntry localHostEntry = Dns.GetHostEntry(Dns.GetHostName()); // Resolve the host name. Whether this is in the hosts file or in some // form of DNS server shouldn't matter for us here (means we do not touch // the hosts file in this process), but the address MUST resolve to a local // endpoint or to a loopback endpoint IPAddress bindToAddress; Random rnd = new Random(); if (!IPAddress.TryParse(localForward.BindAddress, out bindToAddress)) { IPHostEntry hostEntry = Dns.GetHostEntry(localForward.BindAddress); bindToAddress = hostEntry.AddressList[rnd.Next(hostEntry.AddressList.Length)]; } if (bindToAddress != null) { tcpListenerBridge = TcpLocalForwardBridge.FromConnectionString(rcbs); tcpListenerBridge.Run(new IPEndPoint(bindToAddress, localForward.BindPort)); this.listenerBridges.Add(hybridConnectionUri.AbsoluteUri, tcpListenerBridge); } BridgeEventSource.Log.LocalForwardBridgeStart(startActivity, bindToAddress, localForward); } catch (Exception e) { BridgeEventSource.Log.LocalForwardBridgeStartFailure(startActivity, localForward, e); if (!config.ExitOnForwardFailure.HasValue || config.ExitOnForwardFailure.Value) { throw; } } }
internal void UpdateConfig(Config config) { EventTraceActivity updateActivity = BridgeEventSource.NewActivity("UpdateConfig", activity); BridgeEventSource.Log.LocalForwardConfigUpdating(updateActivity, config, this.config); this.config = config; // stopping the listeners will actually not cut existing // connections. StopEndpoints(); StartEndpoints(config.LocalForward); BridgeEventSource.Log.LocalForwardConfigUpdated(updateActivity); }
void StopEndpoint(RemoteForwardBridge forwardBridge) { EventTraceActivity stopActivity = BridgeEventSource.NewActivity("RemoteForwardBridgeStop", activity); try { BridgeEventSource.Log.RemoteForwardBridgeStopping(stopActivity, forwardBridge.ToString()); forwardBridge.Close(); BridgeEventSource.Log.RemoteForwardBridgeStop(stopActivity, forwardBridge.ToString()); } catch (Exception exception) { BridgeEventSource.Log.RemoteForwardBridgeStopFailure(stopActivity, exception); if (Fx.IsFatal(exception)) { throw; } } }
void StopEndpoint(SocketLocalForwardBridge socketLocalForwardBridge) { EventTraceActivity stopActivity = BridgeEventSource.NewActivity("LocalForwardBridgeStop", activity); try { BridgeEventSource.Log.LocalForwardBridgeStopping(stopActivity, socketLocalForwardBridge.GetSocketInfo()); socketLocalForwardBridge.Close(); BridgeEventSource.Log.LocalForwardBridgeStop(stopActivity, socketLocalForwardBridge.GetSocketInfo(), socketLocalForwardBridge.HybridConnectionClient.Address.ToString()); } catch (Exception e) { BridgeEventSource.Log.LocalForwardBridgeStopFailure(stopActivity, socketLocalForwardBridge.GetSocketInfo(), e); if (Fx.IsFatal(e)) { throw; } } }
void StopEndpoint(TcpLocalForwardBridge tcpLocalForwardBridge) { EventTraceActivity stopActivity = BridgeEventSource.NewActivity("LocalForwardBridgeStop", activity); try { BridgeEventSource.Log.LocalForwardBridgeStopping(stopActivity, tcpLocalForwardBridge); tcpLocalForwardBridge.Close(); BridgeEventSource.Log.LocalForwardBridgeStop(stopActivity, tcpLocalForwardBridge); } catch (Exception e) { BridgeEventSource.Log.LocalForwardBridgeStopFailure(stopActivity, tcpLocalForwardBridge, e); if (Fx.IsFatal(e)) { throw; } } }
async Task AcceptSocketLoopAsync() { while (!cancellationTokenSource.Token.IsCancellationRequested) { var socketActivity = BridgeEventSource.NewActivity("LocalForwardSocket"); var socket = await this.tcpListener.AcceptTcpClientAsync(); BridgeEventSource.Log.LocalForwardSocketAccepted(socketActivity, socket); this.LastAttempt = DateTime.Now; BridgeSocketConnectionAsync(socket) .ContinueWith((t, s) => { BridgeEventSource.Log.LocalForwardSocketError(socketActivity, socket, t.Exception); socket.Dispose(); }, TaskContinuationOptions.OnlyOnFaulted) .ContinueWith((t, s) => { try { BridgeEventSource.Log.LocalForwardSocketComplete(socketActivity, socket); socket.Close(); BridgeEventSource.Log.LocalForwardSocketClosed(socketActivity, socket); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } BridgeEventSource.Log.LocalForwardSocketCloseFailed(socketActivity, socket, e); socket.Dispose(); } }, TaskContinuationOptions.OnlyOnRanToCompletion) .Fork(); } }
void StartEndpoint(RemoteForward remoteForward) { Uri hybridConnectionUri = null; EventTraceActivity stopActivity = BridgeEventSource.NewActivity("RemoteForwardBridgeStart", activity); stopActivity.DiagnosticsActivity.Start(); try { BridgeEventSource.Log.RemoteForwardBridgeStarting(stopActivity, this, remoteForward); var rcbs = remoteForward.RelayConnectionStringBuilder ?? new RelayConnectionStringBuilder(this.config.AzureRelayConnectionString); rcbs.EntityPath = remoteForward.RelayName; hybridConnectionUri = new Uri(rcbs.Endpoint, rcbs.EntityPath); RemoteForwardBridge remoteForwardBridge = null; try { var remoteForwarders = new Dictionary <string, IRemoteForwarder>(); foreach (var binding in remoteForward.Bindings) { #if !NETFRAMEWORK if (!string.IsNullOrEmpty(binding.LocalSocket)) { if (Environment.OSVersion.Platform == PlatformID.Win32NT) { BridgeEventSource.Log.ThrowingException( new NotSupportedException("Unix sockets are not supported on Windows")); } var socketRemoteForwarder = new SocketRemoteForwarder(binding.PortName, binding.LocalSocket); remoteForwarders.Add(socketRemoteForwarder.PortName, socketRemoteForwarder); } else #endif if (binding.HostPort > 0) { var tcpRemoteForwarder = new TcpRemoteForwarder(this.config, binding.PortName, binding.Host, binding.HostPort); remoteForwarders.Add(tcpRemoteForwarder.PortName, tcpRemoteForwarder); } else if (binding.HostPort < 0) { var udpRemoteForwarder = new UdpRemoteForwarder(this.config, binding.PortName, binding.Host, -binding.HostPort); remoteForwarders.Add(udpRemoteForwarder.PortName, udpRemoteForwarder); } } remoteForwardBridge = new RemoteForwardBridge(config, rcbs, remoteForwarders); remoteForwardBridge.Online += (s, e) => { NotifyOnline(hybridConnectionUri, remoteForward); BridgeEventSource.Log.RemoteForwardBridgeOnline(stopActivity, hybridConnectionUri, remoteForwardBridge); }; remoteForwardBridge.Offline += (s, e) => { NotifyOffline(hybridConnectionUri, remoteForward); BridgeEventSource.Log.RemoteForwardBridgeOffline(stopActivity, hybridConnectionUri, remoteForwardBridge); }; remoteForwardBridge.Connecting += (s, e) => { NotifyConnecting(hybridConnectionUri, remoteForward); BridgeEventSource.Log.RemoteForwardBridgeConnecting(stopActivity, hybridConnectionUri, remoteForwardBridge); }; remoteForwardBridge.Open().Wait(); this.forwardBridges.Add(hybridConnectionUri.AbsoluteUri, remoteForwardBridge); BridgeEventSource.Log.RemoteForwardBridgeStart(stopActivity, hybridConnectionUri.AbsoluteUri); } catch (Exception exception) { BridgeEventSource.Log.RemoteForwardBridgeStartFailure(stopActivity, hybridConnectionUri, exception); if (Fx.IsFatal(exception)) { throw; } try { if (remoteForwardBridge != null) { remoteForwardBridge.Dispose(); } } catch (Exception e) { if (Fx.IsFatal(exception)) { throw; } BridgeEventSource.Log.HandledExceptionAsWarning(this, e); } if (!this.config.ExitOnForwardFailure.HasValue || this.config.ExitOnForwardFailure.Value) { throw; } } } finally { stopActivity.DiagnosticsActivity.Stop(); } }
void StartEndpoint(RemoteForward remoteForward) { Uri hybridConnectionUri = null; TcpRemoteForwardBridge tcpRemoteForwardBridge = null; EventTraceActivity stopActivity = BridgeEventSource.NewActivity("RemoteForwardBridgeStart", activity); stopActivity.DiagnosticsActivity.Start(); try { BridgeEventSource.Log.RemoteForwardBridgeStarting(stopActivity, this, remoteForward); var rcbs = remoteForward.RelayConnectionStringBuilder ?? new RelayConnectionStringBuilder(this.config.AzureRelayConnectionString); rcbs.EntityPath = remoteForward.RelayName; hybridConnectionUri = new Uri(rcbs.Endpoint, rcbs.EntityPath); try { tcpRemoteForwardBridge = new TcpRemoteForwardBridge(rcbs, remoteForward.Host, remoteForward.HostPort); tcpRemoteForwardBridge.Online += (s, e) => { NotifyOnline(hybridConnectionUri, remoteForward); BridgeEventSource.Log.RemoteForwardBridgeOnline(stopActivity, hybridConnectionUri, tcpRemoteForwardBridge); }; tcpRemoteForwardBridge.Offline += (s, e) => { NotifyOffline(hybridConnectionUri, remoteForward); BridgeEventSource.Log.RemoteForwardBridgeOffline(stopActivity, hybridConnectionUri, tcpRemoteForwardBridge); }; tcpRemoteForwardBridge.Connecting += (s, e) => { NotifyConnecting(hybridConnectionUri, remoteForward); BridgeEventSource.Log.RemoteForwardBridgeConnecting(stopActivity, hybridConnectionUri, tcpRemoteForwardBridge); }; tcpRemoteForwardBridge.Open().Wait(); this.clientBridges.Add(hybridConnectionUri.AbsoluteUri, tcpRemoteForwardBridge); BridgeEventSource.Log.RemoteForwardBridgeStart(stopActivity, hybridConnectionUri.AbsoluteUri); } catch (Exception exception) { BridgeEventSource.Log.RemoteForwardBridgeStartFailure(stopActivity, hybridConnectionUri, exception); if (Fx.IsFatal(exception)) { throw; } try { if (tcpRemoteForwardBridge != null) { tcpRemoteForwardBridge.Dispose(); } } catch (Exception e) { if (Fx.IsFatal(exception)) { throw; } BridgeEventSource.Log.HandledExceptionAsWarning(this, e); } if (!this.config.ExitOnForwardFailure.HasValue || this.config.ExitOnForwardFailure.Value) { throw; } } } finally { stopActivity.DiagnosticsActivity.Stop(); } }
void StartEndpoint(LocalForward localForward, LocalForwardBinding binding) { var startActivity = BridgeEventSource.NewActivity("LocalForwardBridgeStart", activity); Uri hybridConnectionUri = null; BridgeEventSource.Log.LocalForwardBridgeStarting(startActivity, localForward); var rcbs = localForward.RelayConnectionStringBuilder ?? new RelayConnectionStringBuilder(config.AzureRelayConnectionString); rcbs.EntityPath = localForward.RelayName; hybridConnectionUri = new Uri(rcbs.Endpoint, rcbs.EntityPath); #if !NETFRAMEWORK if (!string.IsNullOrEmpty(binding.BindLocalSocket)) { if (Environment.OSVersion.Platform == PlatformID.Win32NT) { BridgeEventSource.Log.ThrowingException( new NotSupportedException("Unix sockets are not supported on Windows")); } SocketLocalForwardBridge socketListenerBridge = null; try { { socketListenerBridge = SocketLocalForwardBridge.FromConnectionString(this.config, rcbs, binding.PortName); socketListenerBridge.Run(binding.BindLocalSocket); this.socketListenerBridges.Add(hybridConnectionUri.AbsoluteUri, socketListenerBridge); } BridgeEventSource.Log.LocalForwardBridgeStart(startActivity, IPAddress.Any, localForward); } catch (Exception e) { BridgeEventSource.Log.LocalForwardBridgeStartFailure(startActivity, localForward, e); if (!config.ExitOnForwardFailure.HasValue || config.ExitOnForwardFailure.Value) { throw; } } return; } #endif if (binding.BindPort > 0) { TcpLocalForwardBridge tcpListenerBridge = null; try { IPHostEntry localHostEntry = Dns.GetHostEntry(Dns.GetHostName()); // Resolve the host name. Whether this is in the hosts file or in some // form of DNS server shouldn't matter for us here (means we do not touch // the hosts file in this process), but the address MUST resolve to a local // endpoint or to a loopback endpoint IPAddress bindToAddress; Random rnd = new Random(); if (!IPAddress.TryParse(binding.BindAddress, out bindToAddress)) { IPHostEntry hostEntry = Dns.GetHostEntry(binding.BindAddress); bindToAddress = hostEntry.AddressList[rnd.Next(hostEntry.AddressList.Length)]; } if (bindToAddress != null) { tcpListenerBridge = TcpLocalForwardBridge.FromConnectionString(this.config, rcbs, binding.PortName); tcpListenerBridge.Run(new IPEndPoint(bindToAddress, binding.BindPort)); this.listenerBridges.Add(hybridConnectionUri.AbsoluteUri, tcpListenerBridge); } BridgeEventSource.Log.LocalForwardBridgeStart(startActivity, bindToAddress, localForward); } catch (Exception e) { BridgeEventSource.Log.LocalForwardBridgeStartFailure(startActivity, localForward, e); if (!config.ExitOnForwardFailure.HasValue || config.ExitOnForwardFailure.Value) { throw; } } } else if (binding.BindPort < 0) { UdpLocalForwardBridge udpListenerBridge = null; try { IPHostEntry localHostEntry = Dns.GetHostEntry(Dns.GetHostName()); // Resolve the host name. Whether this is in the hosts file or in some // form of DNS server shouldn't matter for us here (means we do not touch // the hosts file in this process), but the address MUST resolve to a local // endpoint or to a loopback endpoint IPAddress bindToAddress; Random rnd = new Random(); if (!IPAddress.TryParse(binding.BindAddress, out bindToAddress)) { IPHostEntry hostEntry = Dns.GetHostEntry(binding.BindAddress); bindToAddress = hostEntry.AddressList[rnd.Next(hostEntry.AddressList.Length)]; } if (bindToAddress != null) { udpListenerBridge = UdpLocalForwardBridge.FromConnectionString(this.config, rcbs, binding.PortName); udpListenerBridge.Run(new IPEndPoint(bindToAddress, -binding.BindPort)); this.udpBridges.Add(hybridConnectionUri.AbsoluteUri, udpListenerBridge); } BridgeEventSource.Log.LocalForwardBridgeStart(startActivity, bindToAddress, localForward); } catch (Exception e) { BridgeEventSource.Log.LocalForwardBridgeStartFailure(startActivity, localForward, e); if (!config.ExitOnForwardFailure.HasValue || config.ExitOnForwardFailure.Value) { throw; } } } }
async Task BridgeSocketConnectionAsync(Socket socket) { EventTraceActivity bridgeActivity = BridgeEventSource.NewActivity("LocalForwardBridgeConnection"); try { BridgeEventSource.Log.LocalForwardBridgeConnectionStarting(bridgeActivity, localEndpoint, HybridConnectionClient); socket.SendBufferSize = socket.ReceiveBufferSize = 65536; socket.SendTimeout = 60000; var tcpstream = new NetworkStream(socket); using (var hybridConnectionStream = await HybridConnectionClient.CreateConnectionAsync()) { // read and write 4-byte header hybridConnectionStream.WriteTimeout = 60000; // write the 1.0 header with the portname for this connection byte[] portNameBytes = Encoding.UTF8.GetBytes(PortName); byte[] preamble = { /*major*/ 1, /*minor*/ 0, /*stream */ 0, (byte)portNameBytes.Length }; await hybridConnectionStream.WriteAsync(preamble, 0, preamble.Length); await hybridConnectionStream.WriteAsync(portNameBytes, 0, portNameBytes.Length); byte[] replyPreamble = new byte[3]; for (int read = 0; read < replyPreamble.Length;) { var r = await hybridConnectionStream.ReadAsync(replyPreamble, read, replyPreamble.Length - read); if (r == 0) { await hybridConnectionStream.ShutdownAsync(CancellationToken.None); await hybridConnectionStream.CloseAsync(CancellationToken.None); throw new InvalidOperationException($"Malformed preamble from server"); } read += r; } if (!(replyPreamble[0] == 1 && replyPreamble[1] == 0 && replyPreamble[2] == 0)) { // version not supported await hybridConnectionStream.ShutdownAsync(CancellationToken.None); await hybridConnectionStream.CloseAsync(CancellationToken.None); throw new InvalidOperationException($"Unsupported protocol version: Server reply {replyPreamble[0]} {replyPreamble[1]} {replyPreamble[2]}"); } BridgeEventSource.Log.LocalForwardBridgeConnectionStart(bridgeActivity, localEndpoint, HybridConnectionClient); try { CancellationTokenSource socketAbort = new CancellationTokenSource(); await Task.WhenAll( StreamPump.RunAsync(hybridConnectionStream, tcpstream, () => socket.Shutdown(SocketShutdown.Send), socketAbort.Token) .ContinueWith((t) => socketAbort.Cancel(), TaskContinuationOptions.OnlyOnFaulted), StreamPump.RunAsync(tcpstream, hybridConnectionStream, () => hybridConnectionStream?.Shutdown(), socketAbort.Token)) .ContinueWith((t) => socketAbort.Cancel(), TaskContinuationOptions.OnlyOnFaulted); using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1))) { await hybridConnectionStream.CloseAsync(cts.Token); } } catch { if (socket.Connected) { socket.Close(0); } throw; } } BridgeEventSource.Log.LocalForwardBridgeConnectionStop(bridgeActivity, localEndpoint, HybridConnectionClient); } catch (Exception e) { BridgeEventSource.Log.LocalForwardBridgeConnectionFailed(bridgeActivity, e); } }
async Task ReceiveDatagramAsync() { while (!cancellationTokenSource.Token.IsCancellationRequested) { var socketActivity = BridgeEventSource.NewActivity("LocalForwardSocket"); UdpReceiveResult datagram; try { datagram = await this.udpClient.ReceiveAsync(); } catch (ObjectDisposedException) { // occurs on shutdown and signals that we need to exit return; } BridgeEventSource.Log.LocalForwardSocketAccepted(socketActivity, localEndpoint); this.LastAttempt = DateTime.Now; if (routes.TryGetValue(datagram.RemoteEndPoint, out var route)) { using (var ct = new CancellationTokenSource(TimeSpan.FromSeconds(1))) { await route.SendAsync(datagram, ct.Token); } } else { var hybridConnectionStream = await HybridConnectionClient.CreateConnectionAsync(); // read and write version preamble hybridConnectionStream.WriteTimeout = 60000; // write the 1.0 header with the portname for this connection byte[] portNameBytes = Encoding.UTF8.GetBytes(PortName); byte[] preamble = { /*major*/ 1, /*minor*/ 0, /*dgram*/ 1, (byte)portNameBytes.Length }; await hybridConnectionStream.WriteAsync(preamble, 0, preamble.Length); await hybridConnectionStream.WriteAsync(portNameBytes, 0, portNameBytes.Length); byte[] replyPreamble = new byte[3]; for (int read = 0; read < replyPreamble.Length;) { var r = await hybridConnectionStream.ReadAsync(replyPreamble, read, replyPreamble.Length - read); if (r == 0) { await hybridConnectionStream.ShutdownAsync(CancellationToken.None); await hybridConnectionStream.CloseAsync(CancellationToken.None); return; } read += r; } if (!(replyPreamble[0] == 1 && replyPreamble[1] == 0 && replyPreamble[2] == 1)) { // version not supported await hybridConnectionStream.ShutdownAsync(CancellationToken.None); await hybridConnectionStream.CloseAsync(CancellationToken.None); return; } var newRoute = new UdpRoute(udpClient, datagram.RemoteEndPoint, hybridConnectionStream, () => { routes.Remove(datagram.RemoteEndPoint); }); routes.Add(datagram.RemoteEndPoint, newRoute); newRoute.StartReceiving(); using (var ct = new CancellationTokenSource(TimeSpan.FromSeconds(1))) { await newRoute.SendAsync(datagram, ct.Token); } } } }