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;
            }
        }
Exemplo n.º 3
0
        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;
            }
        }
Exemplo n.º 4
0
        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;
            }
        }
Exemplo n.º 5
0
        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();
            }
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 8
0
        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;
                }
            }
        }
Exemplo n.º 10
0
        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();
            }
        }
Exemplo n.º 12
0
        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();
            }
        }
Exemplo n.º 13
0
        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();
            }
        }
Exemplo n.º 14
0
        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;
                    }
                }
            }
        }
Exemplo n.º 15
0
        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);
            }
        }
Exemplo n.º 16
0
        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);
                    }
                }
            }
        }