public async Task SendAsync_Cancel_Success(Uri server) { await TestCancellation((cws) => { var cts = new CancellationTokenSource(5); return(cws.SendAsync( WebSocketData.GetBufferFromText(".delay5sec"), WebSocketMessageType.Text, true, cts.Token)); }, server); }
public static async Task TestEcho( Uri server, WebSocketMessageType type, int timeOutMilliseconds, ITestOutputHelper output, HttpMessageInvoker?invoker = null) { var cts = new CancellationTokenSource(timeOutMilliseconds); string message = "Hello WebSockets!"; string closeMessage = "Good bye!"; var receiveBuffer = new byte[100]; var receiveSegment = new ArraySegment <byte>(receiveBuffer); using (ClientWebSocket cws = await GetConnectedWebSocket(server, timeOutMilliseconds, output, invoker: invoker)) { output.WriteLine("TestEcho: SendAsync starting."); await cws.SendAsync(WebSocketData.GetBufferFromText(message), type, true, cts.Token); output.WriteLine("TestEcho: SendAsync done."); Assert.Equal(WebSocketState.Open, cws.State); output.WriteLine("TestEcho: ReceiveAsync starting."); WebSocketReceiveResult recvRet = await cws.ReceiveAsync(receiveSegment, cts.Token); output.WriteLine("TestEcho: ReceiveAsync done."); Assert.Equal(WebSocketState.Open, cws.State); Assert.Equal(message.Length, recvRet.Count); Assert.Equal(type, recvRet.MessageType); Assert.True(recvRet.EndOfMessage); Assert.Null(recvRet.CloseStatus); Assert.Null(recvRet.CloseStatusDescription); var recvSegment = new ArraySegment <byte>(receiveSegment.Array, receiveSegment.Offset, recvRet.Count); Assert.Equal(message, WebSocketData.GetTextFromBuffer(recvSegment)); output.WriteLine("TestEcho: CloseAsync starting."); Task taskClose = cws.CloseAsync(WebSocketCloseStatus.NormalClosure, closeMessage, cts.Token); Assert.True( (cws.State == WebSocketState.Open) || (cws.State == WebSocketState.CloseSent) || (cws.State == WebSocketState.CloseReceived) || (cws.State == WebSocketState.Closed), "State immediately after CloseAsync : " + cws.State); await taskClose; output.WriteLine("TestEcho: CloseAsync done."); Assert.Equal(WebSocketState.Closed, cws.State); Assert.Equal(WebSocketCloseStatus.NormalClosure, cws.CloseStatus); Assert.Equal(closeMessage, cws.CloseStatusDescription); } }
public async Task Abort_SendAndAbort_Success(Uri server) { await TestCancellation(async (cws) => { var cts = new CancellationTokenSource(TimeOutMilliseconds); Task t = cws.SendAsync( WebSocketData.GetBufferFromText(".delay5sec"), WebSocketMessageType.Text, true, cts.Token); cws.Abort(); await t; }, server); }
public async Task ConnectAsync_CookieHeaders_Success(Uri server) { using (var cws = new ClientWebSocket()) { Assert.Null(cws.Options.Cookies); cws.Options.Cookies = new CookieContainer(); Cookie cookie1 = new Cookie("Cookies", "Are Yummy"); Cookie cookie2 = new Cookie("Especially", "Chocolate Chip"); Cookie secureCookie = new Cookie("Occasionally", "Raisin"); secureCookie.Secure = true; cws.Options.Cookies.Add(server, cookie1); cws.Options.Cookies.Add(server, cookie2); cws.Options.Cookies.Add(server, secureCookie); using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { Task taskConnect = cws.ConnectAsync(server, cts.Token); Assert.True( cws.State == WebSocketState.None || cws.State == WebSocketState.Connecting || cws.State == WebSocketState.Open, "State immediately after ConnectAsync incorrect: " + cws.State); await taskConnect; } Assert.Equal(WebSocketState.Open, cws.State); byte[] buffer = new byte[65536]; var segment = new ArraySegment <byte>(buffer); WebSocketReceiveResult recvResult; using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { recvResult = await cws.ReceiveAsync(segment, cts.Token); } Assert.Equal(WebSocketMessageType.Text, recvResult.MessageType); string headers = WebSocketData.GetTextFromBuffer(segment); Assert.True(headers.Contains("Cookies=Are Yummy")); Assert.True(headers.Contains("Especially=Chocolate Chip")); Assert.Equal(server.Scheme == "wss", headers.Contains("Occasionally=Raisin")); await cws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } }
public async Task CloseAsync_ServerInitiatedClose_Success(Uri server, bool useCloseOutputAsync) { const string closeWebSocketMetaCommand = ".close"; using (ClientWebSocket cws = await GetConnectedWebSocket(server, TimeOutMilliseconds, _output)) { var cts = new CancellationTokenSource(TimeOutMilliseconds); _output.WriteLine("SendAsync starting."); await cws.SendAsync( WebSocketData.GetBufferFromText(closeWebSocketMetaCommand), WebSocketMessageType.Text, true, cts.Token); _output.WriteLine("SendAsync done."); var recvBuffer = new byte[256]; _output.WriteLine("ReceiveAsync starting."); WebSocketReceiveResult recvResult = await cws.ReceiveAsync(new ArraySegment <byte>(recvBuffer), cts.Token); _output.WriteLine("ReceiveAsync done."); // Verify received server-initiated close message. Assert.Equal(WebSocketCloseStatus.NormalClosure, recvResult.CloseStatus); Assert.Equal(closeWebSocketMetaCommand, recvResult.CloseStatusDescription); Assert.Equal(WebSocketMessageType.Close, recvResult.MessageType); // Verify current websocket state as CloseReceived which indicates only partial close. Assert.Equal(WebSocketState.CloseReceived, cws.State); Assert.Equal(WebSocketCloseStatus.NormalClosure, cws.CloseStatus); Assert.Equal(closeWebSocketMetaCommand, cws.CloseStatusDescription); // Send back close message to acknowledge server-initiated close. _output.WriteLine("Close starting."); await(useCloseOutputAsync ? cws.CloseOutputAsync(WebSocketCloseStatus.InvalidMessageType, string.Empty, cts.Token) : cws.CloseAsync(WebSocketCloseStatus.InvalidMessageType, string.Empty, cts.Token)); _output.WriteLine("Close done."); Assert.Equal(WebSocketState.Closed, cws.State); // Verify that there is no follow-up echo close message back from the server by // making sure the close code and message are the same as from the first server close message. Assert.Equal(WebSocketCloseStatus.NormalClosure, cws.CloseStatus); Assert.Equal(closeWebSocketMetaCommand, cws.CloseStatusDescription); } }
public async Task CloseOutputAsync_ServerInitiated_CanSend(Uri server) { string message = "Hello WebSockets!"; var expectedCloseStatus = WebSocketCloseStatus.NormalClosure; var expectedCloseDescription = ".shutdown"; using (ClientWebSocket cws = await WebSocketHelper.GetConnectedWebSocket(server, TimeOutMilliseconds, _output)) { var cts = new CancellationTokenSource(TimeOutMilliseconds); await cws.SendAsync( WebSocketData.GetBufferFromText(".shutdown"), WebSocketMessageType.Text, true, cts.Token); // Should be able to receive a shutdown message. var recvBuffer = new byte[100]; var segmentRecv = new ArraySegment <byte>(recvBuffer); WebSocketReceiveResult recvResult = await cws.ReceiveAsync(segmentRecv, cts.Token); Assert.Equal(0, recvResult.Count); Assert.Equal(expectedCloseStatus, recvResult.CloseStatus); Assert.Equal(expectedCloseDescription, recvResult.CloseStatusDescription); // Verify WebSocket state Assert.Equal(expectedCloseStatus, cws.CloseStatus); Assert.Equal(expectedCloseDescription, cws.CloseStatusDescription); Assert.Equal(WebSocketState.CloseReceived, cws.State); // Should be able to send. await cws.SendAsync(WebSocketData.GetBufferFromText(message), WebSocketMessageType.Text, true, cts.Token); // Cannot change the close status/description with the final close. var closeStatus = WebSocketCloseStatus.InvalidPayloadData; var closeDescription = "CloseOutputAsync_Client_Description"; await cws.CloseAsync(closeStatus, closeDescription, cts.Token); Assert.Equal(expectedCloseStatus, cws.CloseStatus); Assert.Equal(expectedCloseDescription, cws.CloseStatusDescription); Assert.Equal(WebSocketState.Closed, cws.State); } }
public async Task CloseOutputAsync_Cancel_Success(Uri server) { await TestCancellation(async (cws) => { var cts = new CancellationTokenSource(5); var ctsDefault = new CancellationTokenSource(TimeOutMilliseconds); await cws.SendAsync( WebSocketData.GetBufferFromText(".delay5sec"), WebSocketMessageType.Text, true, ctsDefault.Token); var recvBuffer = new byte[100]; var segment = new ArraySegment <byte>(recvBuffer); await cws.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "CancelShutdown", cts.Token); }, server); }
public async Task ConnectAsync_AddHostHeader_Success() { Uri server = System.Net.Test.Common.Configuration.WebSockets.RemoteEchoServer; // Send via the physical address such as "corefx-net.cloudapp.net" // Set the Host header to logical address like "subdomain.corefx-net.cloudapp.net" // Verify the scenario works and the remote server received "Host: subdomain.corefx-net.cloudapp.net" string logicalHost = "subdomain." + server.Host; using (var cws = new ClientWebSocket()) { // Set the Host header to the logical address cws.Options.SetRequestHeader("Host", logicalHost); using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { // Connect using the physical address Task taskConnect = cws.ConnectAsync(server, cts.Token); Assert.True( (cws.State == WebSocketState.None) || (cws.State == WebSocketState.Connecting) || (cws.State == WebSocketState.Open), "State immediately after ConnectAsync incorrect: " + cws.State); await taskConnect; } Assert.Equal(WebSocketState.Open, cws.State); byte[] buffer = new byte[65536]; var segment = new ArraySegment <byte>(buffer, 0, buffer.Length); WebSocketReceiveResult recvResult; using (var cts = new CancellationTokenSource(TimeOutMilliseconds)) { recvResult = await cws.ReceiveAsync(segment, cts.Token); } Assert.Equal(WebSocketMessageType.Text, recvResult.MessageType); string headers = WebSocketData.GetTextFromBuffer(segment); Assert.Contains($"Host:{logicalHost}", headers, StringComparison.Ordinal); await cws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } }
public async Task Abort_ReceiveAndAbort_Success(Uri server) { await TestCancellation(async (cws) => { var ctsDefault = new CancellationTokenSource(TimeOutMilliseconds); await cws.SendAsync( WebSocketData.GetBufferFromText(".delay5sec"), WebSocketMessageType.Text, true, ctsDefault.Token); var recvBuffer = new byte[100]; var segment = new ArraySegment <byte>(recvBuffer); Task t = cws.ReceiveAsync(segment, ctsDefault.Token); cws.Abort(); await t; }, server); }
public async Task CloseOutputAsync_ClientInitiated_CanReceive_CanClose(Uri server) { string message = "Hello WebSockets!"; using (ClientWebSocket cws = await WebSocketHelper.GetConnectedWebSocket(server, TimeOutMilliseconds, _output)) { var cts = new CancellationTokenSource(TimeOutMilliseconds); // See issue for Browser websocket differences https://github.com/dotnet/runtime/issues/45538 var closeStatus = PlatformDetection.IsBrowser ? WebSocketCloseStatus.NormalClosure : WebSocketCloseStatus.InvalidPayloadData; string closeDescription = "CloseOutputAsync_Client_InvalidPayloadData"; await cws.SendAsync(WebSocketData.GetBufferFromText(message), WebSocketMessageType.Text, true, cts.Token); // Need a short delay as per WebSocket rfc6455 section 5.5.1 there isn't a requirement to receive any // data fragments after a close has been sent. The delay allows the received data fragment to be // available before calling close. The WinRT MessageWebSocket implementation doesn't allow receiving // after a call to Close. await Task.Delay(500); await cws.CloseOutputAsync(closeStatus, closeDescription, cts.Token); // Should be able to receive the message echoed by the server. var recvBuffer = new byte[100]; var segmentRecv = new ArraySegment <byte>(recvBuffer); WebSocketReceiveResult recvResult = await cws.ReceiveAsync(segmentRecv, cts.Token); Assert.Equal(message.Length, recvResult.Count); segmentRecv = new ArraySegment <byte>(segmentRecv.Array, 0, recvResult.Count); Assert.Equal(message, WebSocketData.GetTextFromBuffer(segmentRecv)); Assert.Null(recvResult.CloseStatus); Assert.Null(recvResult.CloseStatusDescription); await cws.CloseAsync(closeStatus, closeDescription, cts.Token); Assert.Equal(closeStatus, cws.CloseStatus); Assert.Equal(closeDescription, cws.CloseStatusDescription); } }
public async Task SendAsync_SendZeroLengthPayloadAsEndOfMessage_Success(Uri server) { using (ClientWebSocket cws = await WebSocketHelper.GetConnectedWebSocket(server, TimeOutMilliseconds, _output)) { var cts = new CancellationTokenSource(TimeOutMilliseconds); string message = "hello"; await SendAsync( cws, WebSocketData.GetBufferFromText(message), WebSocketMessageType.Text, false, cts.Token); Assert.Equal(WebSocketState.Open, cws.State); await SendAsync( cws, new ArraySegment <byte>(new byte[0]), WebSocketMessageType.Text, true, cts.Token); Assert.Equal(WebSocketState.Open, cws.State); var recvBuffer = new byte[100]; var receiveSegment = new ArraySegment <byte>(recvBuffer); WebSocketReceiveResult recvRet = await ReceiveAsync(cws, receiveSegment, cts.Token); Assert.Equal(WebSocketState.Open, cws.State); Assert.Equal(message.Length, recvRet.Count); Assert.Equal(WebSocketMessageType.Text, recvRet.MessageType); Assert.True(recvRet.EndOfMessage); Assert.Null(recvRet.CloseStatus); Assert.Null(recvRet.CloseStatusDescription); var recvSegment = new ArraySegment <byte>(receiveSegment.Array, receiveSegment.Offset, recvRet.Count); Assert.Equal(message, WebSocketData.GetTextFromBuffer(recvSegment)); } }
// This will also pass when no exception is thrown. Current implementation doesn't throw. public async Task ReceiveAsync_MultipleOutstandingReceiveOperations_Throws(Uri server) { using (ClientWebSocket cws = await WebSocketHelper.GetConnectedWebSocket(server, TimeOutMilliseconds, _output)) { var cts = new CancellationTokenSource(TimeOutMilliseconds); Task[] tasks = new Task[2]; await SendAsync( cws, WebSocketData.GetBufferFromText(".delay5sec"), WebSocketMessageType.Text, true, cts.Token); var recvBuffer = new byte[100]; var recvSegment = new ArraySegment <byte>(recvBuffer); try { for (int i = 0; i < tasks.Length; i++) { tasks[i] = ReceiveAsync(cws, recvSegment, cts.Token); } await Task.WhenAll(tasks); Assert.Equal(WebSocketState.Open, cws.State); } catch (Exception ex) { if (ex is InvalidOperationException) { Assert.Equal( ResourceHelper.GetExceptionMessage( "net_Websockets_AlreadyOneOutstandingOperation", "ReceiveAsync"), ex.Message); Assert.True(WebSocketState.Aborted == cws.State, cws.State + " state when InvalidOperationException"); } else if (ex is WebSocketException) { // Multiple cases. Assert.True(WebSocketState.Aborted == cws.State, cws.State + " state when WebSocketException"); WebSocketError errCode = (ex as WebSocketException).WebSocketErrorCode; Assert.True( (errCode == WebSocketError.InvalidState) || (errCode == WebSocketError.Success), "WebSocketErrorCode"); } else if (ex is OperationCanceledException) { Assert.True(WebSocketState.Aborted == cws.State, cws.State + " state when OperationCanceledException"); } else { Assert.True(false, "Unexpected exception: " + ex.Message); } } } }