public async Task AckSentBeforeSubsequentWrite()
        {
            var stream = new MockStream()
            {
                ExpectedReadData = new byte[][]
                {
                    new byte[] { 0, (byte)MessageTag.CONNECT_SUCCESS_SID, 0, 0, 0, 1, 0 },
                    new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 1, 1 }
                },
                ExpectedWriteData = new byte[][]
                {
                    new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 1, 1 },
                    new byte[] { 0, (byte)MessageTag.ACK, 0, 0, 0, 0, 0, 0, 0, 1 },
                    new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 1, 2 }
                }
            };
            var endpoint = new MockSshRelayEndpoint()
            {
                ExpectedStream = stream
            };
            var relay = new SshRelayStream(endpoint);

            // Write and read something.
            byte[] request = new byte[] { 1 };
            await relay.WriteAsync(request, 0, request.Length, tokenSource.Token);

            byte[] buffer    = new byte[relay.MinReadSize];
            int    bytesRead = await relay.ReadAsync(buffer, 0, buffer.Length, tokenSource.Token);

            Assert.AreEqual(1, bytesRead);

            Assert.AreEqual(1, stream.WriteCount);
            Assert.AreEqual(2, stream.ReadCount);

            // Write a second request - this should cause an ACK to be sent first.
            request = new byte[] { 2 };
            await relay.WriteAsync(request, 0, request.Length, tokenSource.Token);

            Assert.AreEqual(3, stream.WriteCount);
            Assert.AreEqual(2, stream.ReadCount);
        }
Example #2
0
        public async Task AckTrimsUnacknoledgedQueue()
        {
            byte[] request = new byte[] { 1, 2, 3, 4 };

            var stream = new MockStream()
            {
                ExpectedReadData = new byte[][]
                {
                    new byte[] { 0, (byte)MessageTag.ACK, 0, 0, 0, 0, 0, 0, 0, (byte)request.Length },
                    new byte[] { 0, (byte)MessageTag.ACK, 0, 0, 0, 0, 0, 0, 0, (byte)(request.Length * 3) },
                    new byte[] { }
                }
            };
            var endpoint = new MockSshRelayEndpoint()
            {
                ExpectedStream = stream
            };
            var relay = new SshRelayStream(endpoint);

            Assert.AreEqual(0, relay.UnacknoledgedMessageCount);
            Assert.AreEqual(0, relay.ExpectedAck);

            // Send 3 messages.
            await relay.WriteAsync(request, 0, request.Length, tokenSource.Token);

            await relay.WriteAsync(request, 0, request.Length, tokenSource.Token);

            await relay.WriteAsync(request, 0, request.Length, tokenSource.Token);

            Assert.AreEqual(3, relay.UnacknoledgedMessageCount);
            Assert.AreEqual((byte)(request.Length * 3), relay.ExpectedAck);

            // Receive 2 ACKs.
            byte[] buffer    = new byte[relay.MinReadSize];
            int    bytesRead = await relay.ReadAsync(buffer, 0, buffer.Length, tokenSource.Token);

            Assert.AreEqual(0, bytesRead);
            Assert.AreEqual(0, relay.UnacknoledgedMessageCount);
            Assert.AreEqual(0, relay.ExpectedAck);
        }
Example #3
0
        public async Task ReadAfterForcefulServerCloseCausesAnotherConnectIfNoDataReadBefore(
            [Values(
                 WebSocketCloseStatus.EndpointUnavailable,
                 WebSocketCloseStatus.InvalidMessageType,
                 WebSocketCloseStatus.ProtocolError,
                 (WebSocketCloseStatus)CloseCode.BAD_ACK,
                 (WebSocketCloseStatus)CloseCode.ERROR_UNKNOWN,
                 (WebSocketCloseStatus)CloseCode.INVALID_TAG,
                 (WebSocketCloseStatus)CloseCode.INVALID_WEBSOCKET_OPCODE,
                 (WebSocketCloseStatus)CloseCode.REAUTHENTICATION_REQUIRED
                 )] WebSocketCloseStatus closeStatus)
        {
            var endpoint = new MockSshRelayEndpoint()
            {
                ExpectedStreams = new[] {
                    new MockStream()
                    {
                        ExpectServerCloseCodeOnRead = closeStatus
                    },
                    new MockStream()
                    {
                        ExpectedReadData = new byte[][]
                        {
                            new byte[] { 0, (byte)MessageTag.CONNECT_SUCCESS_SID, 0, 0, 0, 1, 0 },
                            new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 2, 1, 2 }
                        }
                    }
                }
            };
            var relay = new SshRelayStream(endpoint);

            // connection breaks, triggering another connect.
            var buffer    = new byte[relay.MinReadSize];
            int bytesRead = await relay.ReadAsync(buffer, 0, buffer.Length, tokenSource.Token);

            Assert.AreEqual(2, bytesRead);
            Assert.AreEqual(2, endpoint.ConnectCount);
            Assert.AreEqual(0, endpoint.ReconnectCount);
        }
Example #4
0
        public async Task ReadFailedReconnectCausesException(
            [Values(
                 (WebSocketCloseStatus)CloseCode.SID_UNKNOWN,
                 (WebSocketCloseStatus)CloseCode.SID_IN_USE
                 )] WebSocketCloseStatus closeStatus)
        {
            var endpoint = new MockSshRelayEndpoint()
            {
                ExpectedStreams = new[] {
                    new MockStream()
                    {
                        ExpectedReadData = new byte[][]
                        {
                            new byte[] { 0, (byte)MessageTag.CONNECT_SUCCESS_SID, 0, 0, 0, 1, 0 },
                            new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 1, 1 }
                        },
                        ExpectServerCloseCodeOnRead = WebSocketCloseStatus.ProtocolError
                    },
                    new MockStream()
                    {
                        ExpectServerCloseCodeOnRead = closeStatus
                    }
                }
            };
            var relay = new SshRelayStream(endpoint);

            // read data
            var buffer    = new byte[relay.MinReadSize];
            int bytesRead = await relay.ReadAsync(buffer, 0, buffer.Length, tokenSource.Token);

            Assert.AreEqual(1, bytesRead);

            // connection breaks, triggering a reconnect that will fail.
            AssertEx.ThrowsAggregateException <WebSocketStreamClosedByServerException>(() =>
            {
                relay.ReadAsync(buffer, 0, buffer.Length, tokenSource.Token).Wait();
            });
        }
Example #5
0
        public async Task ConnectionOpenedByFirstRead()
        {
            var stream = new MockStream()
            {
                ExpectedReadData = new byte[][]
                {
                    new byte[] { 0, (byte)MessageTag.CONNECT_SUCCESS_SID, 0, 0, 0, 1, 0 },
                    new byte[] { }
                }
            };
            var endpoint = new MockSshRelayEndpoint()
            {
                ExpectedStream = stream
            };
            var relay = new SshRelayStream(endpoint);

            Assert.AreEqual(0, endpoint.ConnectCount);

            byte[] buffer = new byte[relay.MinReadSize];
            await relay.ReadAsync(buffer, 0, buffer.Length, tokenSource.Token);

            Assert.AreEqual(1, endpoint.ConnectCount);
        }
Example #6
0
        public async Task DataHeaderIsTrimmed()
        {
            var endpoint = new MockSshRelayEndpoint()
            {
                ExpectedStream = new MockStream()
                {
                    ExpectedReadData = new byte[][]
                    {
                        new byte[] { 0, (byte)MessageTag.CONNECT_SUCCESS_SID, 0, 0, 0, 1, 0 },
                        new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 2, 0xA, 0xB },
                        new byte[] { }
                    }
                }
            };
            var relay = new SshRelayStream(endpoint);

            byte[] buffer    = new byte[relay.MinReadSize];
            int    bytesRead = await relay.ReadAsync(buffer, 0, buffer.Length, tokenSource.Token);

            Assert.AreEqual(2, bytesRead);
            Assert.AreEqual(0xA, buffer[0]);
            Assert.AreEqual(0xB, buffer[1]);
        }
        public async Task WriteAfterForcefulServerCloseCausesReconnectAndDataBeingResentIfDataReadBefore(
            [Values(
                 WebSocketCloseStatus.EndpointUnavailable,
                 WebSocketCloseStatus.InvalidMessageType,
                 WebSocketCloseStatus.ProtocolError,
                 (WebSocketCloseStatus)CloseCode.BAD_ACK,
                 (WebSocketCloseStatus)CloseCode.ERROR_UNKNOWN,
                 (WebSocketCloseStatus)CloseCode.INVALID_TAG,
                 (WebSocketCloseStatus)CloseCode.SID_UNKNOWN,
                 (WebSocketCloseStatus)CloseCode.FAILED_TO_CONNECT_TO_BACKEND,
                 (WebSocketCloseStatus)CloseCode.INVALID_WEBSOCKET_OPCODE,
                 (WebSocketCloseStatus)CloseCode.REAUTHENTICATION_REQUIRED
                 )] WebSocketCloseStatus closeStatus)
        {
            var endpoint = new MockSshRelayEndpoint()
            {
                ExpectedStreams = new[]
                {
                    new MockStream()
                    {
                        ExpectedWriteData = new byte[][]
                        {
                            new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 1, 1 },
                            new byte[] { 0, (byte)MessageTag.ACK, 0, 0, 0, 0, 0, 0, 0, 2 },
                            new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 1, 2 },
                        },
                        ExpectedReadData = new byte[][]
                        {
                            new byte[] { 0, (byte)MessageTag.CONNECT_SUCCESS_SID, 0, 0, 0, 1, 0 },
                            new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 2, 1, 2 }
                        },
                        ExpectServerCloseCodeOnWrite = closeStatus
                    },
                    new MockStream()
                    {
                        ExpectedWriteData = new byte[][]
                        {
                            new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 1, 1 },
                            new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 1, 2 },
                            new byte[] { 0, (byte)MessageTag.DATA, 0, 0, 0, 1, 3 },
                        }
                    }
                }
            };
            var relay = new SshRelayStream(endpoint);

            // Write a request.
            var request = new byte[] { 1 };
            await relay.WriteAsync(request, 0, request.Length, tokenSource.Token);

            // Read something..
            var buffer    = new byte[relay.MinReadSize];
            int bytesRead = await relay.ReadAsync(buffer, 0, buffer.Length, tokenSource.Token);

            Assert.AreEqual(2, bytesRead);

            // Write another request, causing an ACK to be sent.
            request = new byte[] { 2 };
            await relay.WriteAsync(request, 0, request.Length, tokenSource.Token);

            // Write another request - this should cause a reconnect and resend.
            request = new byte[] { 3 };
            await relay.WriteAsync(request, 0, request.Length, tokenSource.Token);

            Assert.AreEqual(1, endpoint.ConnectCount);
            Assert.AreEqual(1, endpoint.ReconnectCount);
        }