Esempio n. 1
0
        public void StartServerAfterClientShouldWork()
        {
            using var server = TcpConnectionFactory.CreateServer(
                      15003);

            using var client = TcpConnectionFactory.CreateClient(
                      IPAddress.Loopback,
                      15003);

            client.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
            });

            server.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
            });

            AssertEx.IsTrue(() => server.State == ConnectionState.Connected);
            AssertEx.IsTrue(() => client.State == ConnectionState.Connected);

            server.Stop();
            client.Stop();

            AssertEx.IsTrue(() => server.State == ConnectionState.Disconnected);
            AssertEx.IsTrue(() => server.State == ConnectionState.Disconnected);
        }
        public async Task MessageReceivedWithStreamAndUsingBufferStreamShouldWork()
        {
            var serverReceivedDataEvent = new AsyncAutoResetEvent(false);

            int currentMessageSize = -1;

            using var server = TcpConnectionFactory.CreateServer(15022, new ServerConnectionSettings(useBufferedStream: true));
            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15022, new ClientConnectionSettings(useBufferedStream: true));

            client.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
            });

            server.Start(receivedActionStreamAsync: async(connection, stream, cancellationToken) =>
            {
                var bytesRead = await stream.ReadAsync(new byte[stream.Length], 0, (int)stream.Length, cancellationToken);
                Assert.AreEqual(currentMessageSize, bytesRead);
                serverReceivedDataEvent.Set();
            },
                         connectionStateChangedAction: (connection, fromState, toState) =>
            {
            });

            await client.WaitForStateAsync(ConnectionState.Connected);

            await server.WaitForStateAsync(ConnectionState.Connected);

            await client.SendDataAsync(new byte[currentMessageSize = 10]);

            (await serverReceivedDataEvent.WaitAsync(10000)).ShouldBeTrue();

            await client.SendDataAsync(new byte[currentMessageSize = 120]);

            (await serverReceivedDataEvent.WaitAsync(10000)).ShouldBeTrue();
        }
        public async Task MessageLargerThan64KBShouldBeTransimittedWithoutProblems()
        {
            var serverReceivedDataEvent = new AsyncAutoResetEvent(false);

            const int messageSize = 1024 * 128; //128kb

            using var server = TcpConnectionFactory.CreateServer(15010);

            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15010);

            client.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
            });

            server.Start((connection, data) =>
            {
                Assert.AreEqual(messageSize, data.Length);
                serverReceivedDataEvent.Set();
            },

                         connectionStateChangedAction: (connection, fromState, toState) =>
            {
            });

            await client.WaitForStateAsync(ConnectionState.Connected);

            await server.WaitForStateAsync(ConnectionState.Connected);

            await client.SendDataAsync(new byte[messageSize]);

            (await serverReceivedDataEvent.WaitAsync(10000)).ShouldBeTrue();
        }
Esempio n. 4
0
        public void ServerShouldMoveStateToLinkErrorIfClientDoesntConnect()
        {
            using var connectionLinkErrorEvent = new AutoResetEvent(false);
            using var connectionOkEvent        = new AutoResetEvent(false);

            using var server = TcpConnectionFactory.CreateServer(15006, new ServerConnectionSettings(connectionTimeoutMilliseconds: 1000));
            server.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
                if (toState == ConnectionState.LinkError)
                {
                    connectionLinkErrorEvent.Set();
                }
                else if (toState == ConnectionState.Connected)
                {
                    connectionOkEvent.Set();
                }
            });

            connectionLinkErrorEvent.WaitOne(10000).ShouldBeTrue();

            var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15006);

            client.Start();

            connectionOkEvent.WaitOne(10000).ShouldBeTrue();
        }
Esempio n. 5
0
        public void ClientShouldMoveStateToLinkErrorIfServerDoesntExist()
        {
            using var connectionLinkErrorEvent = new AutoResetEvent(false);
            using var connectionOkEvent        = new AutoResetEvent(false);
            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15005);

            client.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
                if (toState == ConnectionState.LinkError)
                {
                    connectionLinkErrorEvent.Set();
                }
                else if (toState == ConnectionState.Connected)
                {
                    connectionOkEvent.Set();
                }
            });

            connectionLinkErrorEvent.WaitOne(10000).ShouldBeTrue();

            var server = TcpConnectionFactory.CreateServer(15005);

            server.Start();

            connectionOkEvent.WaitOne(10000).ShouldBeTrue();
        }
        public void ClientShouldMoveStateToLinkErrorIfServerDoesntExist()
        {
            using var connectionLinkErrorEvent = new AutoResetEvent(false);
            using var connectionOkEvent        = new AutoResetEvent(false);
            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15005);

            client.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
                if (toState == ConnectionState.LinkError)
                {
                    connectionLinkErrorEvent.Set();
                }
                else if (toState == ConnectionState.Connected)
                {
                    connectionOkEvent.Set();
                }
            },
                         receivedActionStreamAsync: (connection, stream, cancellationToken) => {
                System.Diagnostics.Debug.Assert(false);
                return(Task.CompletedTask);
            });

            connectionLinkErrorEvent.WaitOne(10000).ShouldBeTrue();

            var server = TcpConnectionFactory.CreateServer(15005);

            server.Start();

            connectionOkEvent.WaitOne(10000).ShouldBeTrue();
        }
Esempio n. 7
0
        private static void RunClient()
        {
            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15000);

            client.Start(
                receivedAction: (connection, data) => Console.WriteLine($"Message from server: {Encoding.UTF8.GetString(data)}"),
                connectionStateChangedAction: (connection, fromState, toState) => Console.WriteLine($"Client connection state changed from {fromState} to {toState}"));

            RunConnection(client);
        }
Esempio n. 8
0
        /// <summary>
        /// relays the input clientStream to the server at the specified host name & port with the given httpCmd & headers as prefix
        /// Usefull for websocket requests
        /// </summary>
        /// <param name="bufferSize"></param>
        /// <param name="connectionTimeOutSeconds"></param>
        /// <param name="remoteHostName"></param>
        /// <param name="httpCmd"></param>
        /// <param name="httpVersion"></param>
        /// <param name="requestHeaders"></param>
        /// <param name="isHttps"></param>
        /// <param name="remotePort"></param>
        /// <param name="supportedProtocols"></param>
        /// <param name="remoteCertificateValidationCallback"></param>
        /// <param name="localCertificateSelectionCallback"></param>
        /// <param name="clientStream"></param>
        /// <param name="tcpConnectionFactory"></param>
        /// <returns></returns>
        internal static async Task SendRaw(int bufferSize, int connectionTimeOutSeconds,
                                           string remoteHostName, int remotePort, string httpCmd, Version httpVersion, Dictionary <string, HttpHeader> requestHeaders,
                                           bool isHttps, SslProtocols supportedProtocols,
                                           RemoteCertificateValidationCallback remoteCertificateValidationCallback, LocalCertificateSelectionCallback localCertificateSelectionCallback,
                                           Stream clientStream, TcpConnectionFactory tcpConnectionFactory, IPEndPoint upStreamEndPoint)
        {
            //prepare the prefix content
            StringBuilder sb = null;

            if (httpCmd != null || requestHeaders != null)
            {
                sb = new StringBuilder();

                if (httpCmd != null)
                {
                    sb.Append(httpCmd);
                    sb.Append(ProxyConstants.NewLine);
                }

                if (requestHeaders != null)
                {
                    foreach (var header in requestHeaders.Select(t => t.Value.ToString()))
                    {
                        sb.Append(header);
                        sb.Append(ProxyConstants.NewLine);
                    }
                }

                sb.Append(ProxyConstants.NewLine);
            }

            var tcpConnection = await tcpConnectionFactory.CreateClient(bufferSize, connectionTimeOutSeconds,
                                                                        remoteHostName, remotePort,
                                                                        httpVersion, isHttps,
                                                                        supportedProtocols, remoteCertificateValidationCallback, localCertificateSelectionCallback,
                                                                        null, null, clientStream, upStreamEndPoint);

            try
            {
                Stream tunnelStream = tcpConnection.Stream;

                //Now async relay all server=>client & client=>server data
                var sendRelay = clientStream.CopyToAsync(sb?.ToString() ?? string.Empty, tunnelStream);

                var receiveRelay = tunnelStream.CopyToAsync(string.Empty, clientStream);

                await Task.WhenAll(sendRelay, receiveRelay);
            }
            finally
            {
                tcpConnection.Dispose();
            }
        }
Esempio n. 9
0
        public void CancelClientPendingConnectionShouldJustWork()
        {
            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15002);

            client.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
            });

            client.Stop();

            AssertEx.IsTrue(() => client.State == ConnectionState.Disconnected);
        }
        public async Task ConnectionListenerShouldAcceptNewConnection()
        {
            using var multiPeerServer = TcpConnectionFactory.CreateMultiPeerServer(14000);

            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 14000);

            var receivedBackFromServerEvent = new AsyncAutoResetEvent(false);

            IConnection newConnection = null;

            multiPeerServer.Start((listener, c) =>
            {
                newConnection = c;
                newConnection.Start(
                    receivedActionStreamAsync: async(connection, stream, cancellationToken) =>
                {
                    using var memoryOwner = MemoryPool <byte> .Shared.Rent(4);
                    var buffer            = memoryOwner.Memory.Slice(0, 4);
                    await stream.ReadAsync(buffer, cancellationToken);
                    var pingString = Encoding.UTF8.GetString(buffer.Span);
                    await connection.SendDataAsync(
                        new Memory <byte>(Encoding.UTF8.GetBytes($"SERVER RECEIVED: {pingString}")));
                },
                    connectionStateChangedAction: (c, fromState, toState) =>
                {
                }
                    );
            });

            client.Start(
                receivedActionStreamAsync: async(connection, stream, cancellationToken) =>
            {
                using var memoryOwner = MemoryPool <byte> .Shared.Rent(21);
                var buffer            = memoryOwner.Memory.Slice(0, 21);
                await stream.ReadAsync(buffer, cancellationToken);
                if (Encoding.UTF8.GetString(buffer.Span) == "SERVER RECEIVED: PING")
                {
                    receivedBackFromServerEvent.Set();
                }
            },
                connectionStateChangedAction: (c, fromState, toState) => { }
                );

            await client.WaitForStateAsync(ConnectionState.Connected);

            await client.SendDataAsync(new Memory <byte>(Encoding.UTF8.GetBytes("PING")));

            (await receivedBackFromServerEvent.WaitAsync(100000)).ShouldBeTrue();

            multiPeerServer.Stop();
        }
        public async Task SendMessagesUsingMemoryBuffer()
        {
            using var server = TcpConnectionFactory.CreateServer(11001);

            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 11001);

            var receivedFromClientEvent = new AsyncAutoResetEvent(false);
            var receivedFromServerEvent = new AsyncAutoResetEvent(false);

            client.Start(
                receivedActionStreamAsync: async(connection, stream, cancellationToken) =>
            {
                using var memoryOwner = MemoryPool <byte> .Shared.Rent((int)stream.Length);
                await stream.ReadAsync(memoryOwner.Memory, cancellationToken);
                if (Encoding.UTF8.GetString(memoryOwner.Memory.Span) == "SENT FROM SERVER")
                {
                    receivedFromServerEvent.Set();
                }
            },
                connectionStateChangedAction: (c, fromState, toState) => { }
                );

            server.Start(
                receivedActionStreamAsync: async(connection, stream, cancellationToken) =>
            {
                using var memoryOwner = MemoryPool <byte> .Shared.Rent((int)stream.Length);
                await stream.ReadAsync(memoryOwner.Memory, cancellationToken);
                if (Encoding.UTF8.GetString(memoryOwner.Memory.Span) == "SENT FROM CLIENT")
                {
                    receivedFromClientEvent.Set();
                }
            },
                connectionStateChangedAction: (c, fromState, toState) => { }
                );

            //WaitHandle.WaitAll(new[] { clientConnectedEvent, serverConnectedEvent }, 4000).ShouldBeTrue();

            await client.WaitForStateAsync(ConnectionState.Connected);

            await server.WaitForStateAsync(ConnectionState.Connected);

            await client.SendDataAsync(new Memory <byte>(Encoding.UTF8.GetBytes("SENT FROM CLIENT")));

            await server.SendDataAsync(new Memory <byte>(Encoding.UTF8.GetBytes("SENT FROM SERVER")));

            //WaitHandle.WaitAll(new[] { receivedFromClientEvent, receivedFromServerEvent }, 10000).ShouldBeTrue();
            (await receivedFromClientEvent.WaitAsync(10000)).ShouldBe(true);
            (await receivedFromServerEvent.WaitAsync(10000)).ShouldBe(true);
        }
Esempio n. 12
0
        private static void RunClient()
        {
            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15000);

            client.Start(
                receivedAction: (connection, data) => Console.WriteLine($"Message from server: {Encoding.UTF8.GetString(data)}"),
                connectionStateChangedAction: (connection, fromState, toState) => Console.WriteLine($"Client connection state changed from {fromState} to {toState}"));

            while (true)
            {
                var message = Console.ReadLine();
                if (message == null)
                {
                    break;
                }

                client.SendDataAsync(Encoding.UTF8.GetBytes(message)).Wait();
            }
        }
        public void TcpConnectionShouldBeFullDuplex()
        {
            using var server = TcpConnectionFactory.CreateMultiPeerServer(15025);
            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15025);

            server.Start((listener, connection) =>
            {
                connection.Start(async(connection, stream, cancellationToken) =>
                {
                    var buffer = new byte[10];
                    stream.Read(buffer, 0, 10);
                    await connection.SendAsync((outStream, outCancellationToken) =>
                    {
                        outStream.Write(buffer, 0, 10);
                        return(Task.CompletedTask);
                    });
                });
            });

            int receivedMessageBackCount = 0;

            client.Start((connection, stream, cancellationToken) =>
            {
                stream.Read(new byte[10], 0, 10);
                receivedMessageBackCount++;
                return(Task.CompletedTask);
            });

            client.WaitForState(ConnectionState.Connected);

            for (int i = 0; i < 1000; i++)
            {
                client.SendAsync((stream, cancellationToken) =>
                {
                    stream.Write(new byte[10], 0, 10);
                    return(Task.CompletedTask);
                });
            }

            AssertEx.IsTrue(() => receivedMessageBackCount == 1000);
        }
Esempio n. 14
0
        public void ClientShouldReconnectToServerAfterServerRestart()
        {
            _logger.Verbose("Begin test ClientShouldReconnectToServerAfterServerRestart");

            using var server = TcpConnectionFactory.CreateServer(15004);
            using var client = TcpConnectionFactory.CreateClient(IPAddress.Loopback, 15004);

            server.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
                _logger.Verbose($"Server state change from {fromState} to {toState}");
            });

            client.Start(connectionStateChangedAction: (connection, fromState, toState) =>
            {
                _logger.Verbose($"Client state change from {fromState} to {toState}");
            });

            AssertEx.IsTrue(() => server.State == ConnectionState.Connected);
            AssertEx.IsTrue(() => client.State == ConnectionState.Connected);

            _logger.Verbose($"Stop server");
            server.Stop();

            AssertEx.IsTrue(() => server.State == ConnectionState.Disconnected);
            AssertEx.IsTrue(() => client.State == ConnectionState.LinkError);

            _logger.Verbose($"Start server");
            server.Start();

            _logger.Verbose($"Stop server");
            server.Stop();
            _logger.Verbose($"Stop client");
            client.Stop();

            AssertEx.IsTrue(() => server.State == ConnectionState.Disconnected);
            AssertEx.IsTrue(() => client.State == ConnectionState.Disconnected);

            _logger.Verbose("End test ClientShouldReconnectToServerAfterServerRestart");
        }
Esempio n. 15
0
        /// <summary>
        /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers as prefix
        /// Usefull for websocket requests
        /// </summary>
        /// <param name="server"></param>
        /// <param name="remoteHostName"></param>
        /// <param name="remotePort"></param>
        /// <param name="httpCmd"></param>
        /// <param name="httpVersion"></param>
        /// <param name="requestHeaders"></param>
        /// <param name="isHttps"></param>
        /// <param name="clientStream"></param>
        /// <param name="tcpConnectionFactory"></param>
        /// <param name="connection"></param>
        /// <returns></returns>
        internal static async Task SendRaw(ProxyServer server,
                                           string remoteHostName, int remotePort,
                                           string httpCmd, Version httpVersion, Dictionary <string, HttpHeader> requestHeaders,
                                           bool isHttps,
                                           Stream clientStream, TcpConnectionFactory tcpConnectionFactory,
                                           TcpConnection connection = null)
        {
            //prepare the prefix content
            StringBuilder sb = null;

            if (httpCmd != null || requestHeaders != null)
            {
                sb = new StringBuilder();

                if (httpCmd != null)
                {
                    sb.Append(httpCmd);
                    sb.Append(ProxyConstants.NewLine);
                }

                if (requestHeaders != null)
                {
                    foreach (var header in requestHeaders.Select(t => t.Value.ToString()))
                    {
                        sb.Append(header);
                        sb.Append(ProxyConstants.NewLine);
                    }
                }

                sb.Append(ProxyConstants.NewLine);
            }

            bool          connectionCreated = false;
            TcpConnection tcpConnection;

            //create new connection if connection is null
            if (connection == null)
            {
                tcpConnection = await tcpConnectionFactory.CreateClient(server,
                                                                        remoteHostName, remotePort,
                                                                        httpVersion, isHttps,
                                                                        null, null);

                connectionCreated = true;
            }
            else
            {
                tcpConnection = connection;
            }

            try
            {
                Stream tunnelStream = tcpConnection.Stream;

                //Now async relay all server=>client & client=>server data
                var sendRelay = clientStream.CopyToAsync(sb?.ToString() ?? string.Empty, tunnelStream);

                var receiveRelay = tunnelStream.CopyToAsync(string.Empty, clientStream);

                await Task.WhenAll(sendRelay, receiveRelay);
            }
            finally
            {
                //if connection was null
                //then a new connection was created
                //so dispose the new connection
                if (connectionCreated)
                {
                    tcpConnection.Dispose();
                    Interlocked.Decrement(ref server.serverConnectionCount);
                }
            }
        }