Example #1
0
        private async void ProcessMessagesOnConnection(HybridConnectionStream connection, CancellationToken token)
        {
            try
            {
                try
                {
                    try
                    {
                        while (!token.IsCancellationRequested)
                        {
                            IFeatureCollection features = await _featureSerializerManager.ReadAsync(connection, new[] { typeof(IHttpRequestFeature) }, token);

                            PrepareDefaultFeatures(features);

                            await _requestReceivedCallback(features, token);

                            await _featureSerializerManager.WriteAsync(connection, features, new[] { typeof(IHttpResponseFeature) }, token);
                        }
                    }
                    finally
                    {
                        await connection.ShutdownAsync(token);
                    }
                }
                catch (IOException)
                { }
                catch (RelayException)
                { }
            }
            finally
            {
                await connection.CloseAsync(token);
            }
        }
Example #2
0
 public async Task Stop()
 {
     if (null != _hybridConnectionStream)
     {
         await _hybridConnectionStream.ShutdownAsync(CancellationToken.None);
     }
 }
Example #3
0
        private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection, CancellationTokenSource cts)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("New session established...");
            Console.ForegroundColor = ConsoleColor.White;

            // The connection is a fully bidrectional stream.
            // We put a stream reader and a stream writer over it
            // which allows us to read UTF-8 text that comes from
            // the sender and to write text replies back.
            var reader = new StreamReader(relayConnection);
            var writer = new StreamWriter(relayConnection)
            {
                AutoFlush = true
            };

            // Write the line back to the client, prepending "Echo:"
            await writer.WriteLineAsync("Hello client from the server!");

            while (!cts.IsCancellationRequested)
            {
                try
                {
                    // Read a line of input until a newline is encountered
                    var line = await reader.ReadLineAsync();

                    if (string.IsNullOrEmpty(line))
                    {
                        // If there's no input data, we will signal that
                        // we will no longer send data on this connection
                        // and then break out of the processing loop.
                        await relayConnection.ShutdownAsync(cts.Token);

                        break;
                    }

                    // Output the line on the console
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("Received from client: " + line);
                    Console.ForegroundColor = ConsoleColor.White;

                    // Write the line back to the client, prepending "Echo:"
                    await writer.WriteLineAsync($"Thanks for sending: {line}");
                }
                catch (Exception ex)
                {
                    // Catch an IO exception that is likely caused because
                    // the client disconnected.
                    Console.WriteLine("Looks like the client closed connection...");
                    break;
                }
            }

            Console.WriteLine("Session ended with client...");

            // Closing the connection
            await relayConnection.CloseAsync(cts.Token);
        }
Example #4
0
        static async Task CloseConnection(HybridConnectionStream hybridConnectionStream)
        {
            using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1)))
            {
                await hybridConnectionStream.ShutdownAsync(cts.Token);

                await hybridConnectionStream.CloseAsync(cts.Token);
            }
        }
        private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection, CancellationTokenSource cts)
        {
            Console.WriteLine("New session");

            // The connection is a fully bidrectional stream.
            // Put a stream reader and a stream writer over it.
            // This allows you to read UTF-8 text that comes from
            // the sender, and to write text replies back.
            var reader = new StreamReader(relayConnection);
            var writer = new StreamWriter(relayConnection)
            {
                AutoFlush = true
            };

            while (!cts.IsCancellationRequested)
            {
                try
                {
                    // Read a line of input until a newline is encountered.
                    var line = await reader.ReadLineAsync();

                    if (string.IsNullOrEmpty(line))
                    {
                        // If there's no input data, signal that
                        // you will no longer send data on this connection.
                        // Then, break out of the processing loop.
                        await relayConnection.ShutdownAsync(cts.Token);

                        break;
                    }

                    // Write the line on the console.
                    Console.WriteLine(line);

                    // Write the line back to the client, prepended with "Echo:"
                    await writer.WriteLineAsync($"Echo: {line}");
                }
                catch (IOException)
                {
                    // Catch an I/O exception. This likely occurred when
                    // the client disconnected.
                    Console.WriteLine("Client closed connection");
                    break;
                }
            }

            Console.WriteLine("End session");

            // Close the connection.
            await relayConnection.CloseAsync(cts.Token);
        }
Example #6
0
        public async Task CloseAsync(CancellationToken token)
        {
            try
            {
                if (_connection == null)
                {
                    return;
                }
                await _connection.ShutdownAsync(token);

                await _connection.CloseAsync(token);
            }
            finally
            {
                IsOpen      = false;
                GoodStatus  = false;
                _connection = null;
            }
        }
Example #7
0
        private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection,
                                                              CancellationTokenSource cts)
        {
            Console.WriteLine("New	session");
            //	The	connection	is	a	fully	bidrectional	stream, enabling	the	Listener
            //to	echo	the	text	from	the	Sender.
            var reader = new StreamReader(relayConnection);
            var writer = new StreamWriter(relayConnection)
            {
                AutoFlush = true
            };

            while (!cts.IsCancellationRequested)
            {
                try
                {
                    //	Read	a	line	of	input	until	a	newline	is encountered
                    var line = await reader.ReadLineAsync();

                    if (string.IsNullOrEmpty(line))
                    {
                        await relayConnection.ShutdownAsync(cts.Token);

                        break;
                    }

                    Console.WriteLine(line);
                    //	Echo	the	line	back	to	the	client
                    await writer.WriteLineAsync($"Echo:	{line}");
                }
                catch (IOException)
                {
                    Console.WriteLine("Client	closed	connection");
                    break;
                }
            }

            Console.WriteLine("End	session");
            //	Close	the	connection
            await relayConnection.CloseAsync(cts.Token);
        }
Example #8
0
        private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection, CancellationTokenSource cts)
        {
            Console.WriteLine("New Session");

            var reader = new StreamReader(relayConnection);
            var writer = new StreamWriter(relayConnection)
            {
                AutoFlush = true
            };

            while (!cts.IsCancellationRequested)
            {
                try
                {
                    var line = reader.ReadLine();

                    if (string.IsNullOrEmpty(line))
                    {
                        await relayConnection.ShutdownAsync(cts.Token);

                        break;
                    }

                    Console.WriteLine(line);
                    await writer.WriteLineAsync($"Echo: {line}");
                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
            }

            Console.WriteLine("End session");
            await relayConnection.CloseAsync(cts.Token);
        }
        private Task OnNewClient(Guid streamId, HybridConnectionStream stream, CancellationToken token)
        {
            return(Task.Factory.StartNew(async() =>
            {
                var buffer = new byte[65536];

                while (true)
                {
                    var id = Guid.Empty;
                    int remotePort = 0;
                    var count = 0;
                    Int32 controlCommand = ControlCommands.Forward;
                    Int32 frameSize = 0;
                    Int32 bytesRead = 0;
                    var memStream = new MemoryStream();

                    // read control command
                    count = await stream.ReadAsync(buffer, 0, sizeof(Int32));
                    if (0 == count || token.IsCancellationRequested)
                    {
                        break;
                    }

                    controlCommand = BitConverter.ToInt32(new ArraySegment <byte>(buffer, 0, sizeof(Int32)).ToArray(), 0);

                    if (ControlCommands.Forward == controlCommand)
                    {
                        // read forwarding preamble
                        count = await stream.ReadAsync(buffer, 0, 16 + sizeof(Int32) + sizeof(Int32));

                        if (0 == count || token.IsCancellationRequested)
                        {
                            break;
                        }

                        id = new Guid(new ArraySegment <byte>(buffer, 0, 16).ToArray());
                        remotePort = BitConverter.ToInt32(new ArraySegment <byte>(buffer, 16, sizeof(Int32)).ToArray(), 0);
                        frameSize = BitConverter.ToInt32(new ArraySegment <byte>(buffer, 16 + sizeof(Int32), sizeof(Int32)).ToArray(), 0);

                        if (!_validPorts.Contains(remotePort))
                        {
                            _logger.LogError($"Connection on port {remotePort} not allowed for hybrid connectio  {_connectionName}.");

                            stream.Close();
                        }

                        while (true)
                        {
                            var length = frameSize - bytesRead > buffer.Length ? buffer.Length : frameSize - bytesRead;
                            count = await stream.ReadAsync(buffer, 0, length);

                            if (0 == count || token.IsCancellationRequested)
                            {
                                break;
                            }

                            bytesRead += count;
                            await memStream.WriteAsync(buffer, 0, count);

                            if (bytesRead == frameSize)
                            {
                                await _demultiplexer.Demultiplex(streamId, id, remotePort, memStream.ToArray());
                                break;
                            }
                        }

                        if (0 == count || token.IsCancellationRequested)
                        {
                            break;
                        }
                    }
                    else
                    {
                        count = await stream.ReadAsync(buffer, 0, 16);
                        if (0 == count || token.IsCancellationRequested)
                        {
                            break;
                        }

                        id = new Guid(new ArraySegment <byte>(buffer, 0, 16).ToArray());

                        await _demultiplexer.ClientConnectionClosed(streamId, id);
                    }
                }

                lock (_syncRoot)
                {
                    _hybridConnectionStreams.Remove(streamId);
                }

                await stream.ShutdownAsync(_cts.Token);
            }));
        }
Example #10
0
        private IObservable <IMessage> _observableRelayStringLine(HybridConnectionStream connection, CancellationToken ct, TimeSpan timeout)
        => Observable.Create <IMessage>(
            obs =>
        {
            _relayStateObserver.OnNext(RelayListenerConnectionState.Receiving);

            var reader = new StreamReader(connection);

            var writer = new StreamWriter(connection)
            {
                AutoFlush = true
            };

            var readerObservable = Observable.FromAsync(reader.ReadLineAsync);

            var disposableText = Observable.While(
                () => !ct.IsCancellationRequested,
                readerObservable)
                                 .Subscribe(stringLine =>
            {
                // If there's no input data, signal that
                // you will no longer send data on this connection.
                // Then, break out of the processing loop.

                Debug.WriteLine(stringLine);

                if (string.IsNullOrEmpty(stringLine))
                {
                    writer?.Dispose();

                    try
                    {
                        connection?.ShutdownAsync(ct)?.Wait(new CancellationTokenSource(timeout).Token);
                    }
                    catch (AggregateException)
                    {
                        // Ignore if connection already closed
                    }

                    obs.OnCompleted();
                }

                obs.OnNext(new Message(stringLine, writer));
            },
                                            ex =>
            {
                Debug.WriteLine(ex.ToString());
                if (ex is IOException)
                {
                    // Catch an I/O exception. This likely occurred when
                    // the client disconnected.
                }
                else
                {
                    obs.OnError(ex);
                }
            },
                                            obs.OnCompleted);

            return(new CompositeDisposable(
                       disposableText,
                       Disposable.Create(() =>
            {
                _relayStateObserver.OnNext(RelayListenerConnectionState.Listening);

                writer?.Dispose();
                reader?.Dispose();

                try
                {
                    connection?.ShutdownAsync(ct)?.Wait(new CancellationTokenSource(timeout).Token);
                }
                catch (AggregateException)
                {
                    // Ignore if connection already closed
                }
            })));
        });
Example #11
0
        async Task HandleRelayConnectionAsync(HybridConnectionStream hybridConnectionStream)
        {
            try
            {
                using (hybridConnectionStream)
                {
                    string portName = null;

                    hybridConnectionStream.WriteTimeout = 60000;

                    // read and write 4-byte header
                    // we don't do anything with this version preamble just yet; it really
                    // is insurance for when we might have to break protocol.
                    var versionPreamble = new byte[3];
                    for (int read = 0; read < versionPreamble.Length;)
                    {
                        var r = await hybridConnectionStream.ReadAsync(versionPreamble, read,
                                                                       versionPreamble.Length - read);

                        if (r == 0)
                        {
                            await hybridConnectionStream.ShutdownAsync(CancellationToken.None);

                            return;
                        }

                        read += r;
                    }

                    // version 1.0 and stream mode (0)
                    if (versionPreamble[0] == 1 && versionPreamble[1] == 0 &&
                        (versionPreamble[2] == 0 || versionPreamble[2] == 1))
                    {
                        // For version 1.0, the version preamble is followed by a single byte
                        // length indicator and then that number of bytes with of UTF-8 encoded
                        // port-name string.
                        var portNameBuffer = new byte[256];
                        var r = await hybridConnectionStream.ReadAsync(portNameBuffer, 0, 1);

                        if (r == 0)
                        {
                            await hybridConnectionStream.ShutdownAsync(CancellationToken.None);

                            return;
                        }

                        for (int read = 0; read < portNameBuffer[0];)
                        {
                            r = await hybridConnectionStream.ReadAsync(portNameBuffer, read + 1,
                                                                       portNameBuffer[0] - read);

                            if (r == 0)
                            {
                                await hybridConnectionStream.ShutdownAsync(CancellationToken.None);

                                return;
                            }

                            read += r;
                        }

                        portName = Encoding.UTF8.GetString(portNameBuffer, 1, portNameBuffer[0]);
                    }
                    else
                    {
                        // if we don't understand the version, we write a 0.0 version preamble back and shut down the connection
                        versionPreamble = new byte[] { 0, 0, 0 };
                        await hybridConnectionStream.WriteAsync(versionPreamble, 0, versionPreamble.Length);
                        await CloseConnection(hybridConnectionStream);

                        return;
                    }

                    if (remoteForwarders.TryGetValue(portName, out var forwarder))
                    {
                        if (forwarder is UdpRemoteForwarder && versionPreamble[2] != 1)
                        {
                            // bad datagram indicator
                            versionPreamble = new byte[] { 0, 0, 1 };
                            await hybridConnectionStream.WriteAsync(versionPreamble, 0, versionPreamble.Length);
                            await CloseConnection(hybridConnectionStream);

                            return;
                        }
                        else if (!(forwarder is UdpRemoteForwarder) && versionPreamble[2] == 1)
                        {
                            // mismatch
                            versionPreamble = new byte[] { 0, 0, 255 };
                            await hybridConnectionStream.WriteAsync(versionPreamble, 0, versionPreamble.Length);
                            await CloseConnection(hybridConnectionStream);

                            return;
                        }

                        // write out 1.0 and handle the stream
                        versionPreamble = new byte[] { 1, 0, versionPreamble[2] };
                        await hybridConnectionStream.WriteAsync(versionPreamble, 0, versionPreamble.Length);

                        await forwarder.HandleConnectionAsync(hybridConnectionStream);
                        await CloseConnection(hybridConnectionStream);
                    }
                    else
                    {
                        await CloseConnection(hybridConnectionStream);
                    }
                }
            }
            catch (Exception e)
            {
                BridgeEventSource.Log.HandledExceptionAsWarning(activity, e);
            }
        }