public async Task WhenAckIsRead_ThenUnacknoledgedQueueIsTrimmed() { 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); }
public async Task WhenServerClosesConnectionForcefullyOnFirstRead_ThenConnectIsRetried( [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); }
public async Task WhenServerClosesConnectionForcefullyOnSubsequentReadAndReconnectFails_ThenReadFailsWithException( [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(); }); }
public async Task WhenPerformingFirstRead_ThenConnectionIsOpened() { 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); }
public async Task WhenReadingData_ThenDataHeaderIsTrimmed() { 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 WhenDataReadAndServerClosesConnectionForcefullyOnSubsequentWrite_ThenConnectIsRetriedAndDataIsResent( [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); }