Removed EndOfMessage from Message (#513)

* Removed EndOfMessage from Message
- The webSockets transport no longer supports partial payloads so
this feature is now gone.
This commit is contained in:
David Fowler 2017-06-03 08:32:28 -10:00 committed by GitHub
parent eee2683b5e
commit 42e2715a95
22 changed files with 30 additions and 147 deletions

View File

@ -45,7 +45,7 @@ namespace SocialWeather
? MessageType.Binary ? MessageType.Binary
: MessageType.Text; : MessageType.Text;
connection.Transport.Output.TryWrite(new Message(ms.ToArray(), format, endOfMessage: true)); connection.Transport.Output.TryWrite(new Message(ms.ToArray(), format));
} }
} }

View File

@ -29,7 +29,7 @@ namespace SocketsSample.EndPoints
// We can avoid the copy here but we'll deal with that later // We can avoid the copy here but we'll deal with that later
var text = Encoding.UTF8.GetString(message.Payload); var text = Encoding.UTF8.GetString(message.Payload);
text = $"{connection.ConnectionId}: {text}"; text = $"{connection.ConnectionId}: {text}";
await Broadcast(Encoding.UTF8.GetBytes(text), message.Type, message.EndOfMessage); await Broadcast(Encoding.UTF8.GetBytes(text), message.Type);
} }
} }
} }
@ -43,10 +43,10 @@ namespace SocketsSample.EndPoints
private Task Broadcast(string text) private Task Broadcast(string text)
{ {
return Broadcast(Encoding.UTF8.GetBytes(text), MessageType.Text, endOfMessage: true); return Broadcast(Encoding.UTF8.GetBytes(text), MessageType.Text);
} }
private Task Broadcast(byte[] payload, MessageType format, bool endOfMessage) private Task Broadcast(byte[] payload, MessageType format)
{ {
var tasks = new List<Task>(Connections.Count); var tasks = new List<Task>(Connections.Count);
@ -54,8 +54,7 @@ namespace SocketsSample.EndPoints
{ {
tasks.Add(c.Transport.Output.WriteAsync(new Message( tasks.Add(c.Transport.Output.WriteAsync(new Message(
payload, payload,
format, format)));
endOfMessage)));
} }
return Task.WhenAll(tasks); return Task.WhenAll(tasks);

View File

@ -10,7 +10,6 @@ A transport is required to have the following attributes:
1. Frame-based - Messages have fixed length (as opposed to streaming, where data is just pushed throughout the connection) 1. Frame-based - Messages have fixed length (as opposed to streaming, where data is just pushed throughout the connection)
1. Frame Metadata - Able to encode one piece of Frame Metadata 1. Frame Metadata - Able to encode one piece of Frame Metadata
* `Type` - Either `Binary` or `Text`. * `Type` - Either `Binary` or `Text`.
1. Able to handle partial messages from the Server application (i.e. where `EndOfMessage` is `false`). The transport can opt to implement this by buffering, since only WebSockets natively supports this functionality.
1. Binary-safe - Able to transmit arbitrary binary data, regardless of content 1. Binary-safe - Able to transmit arbitrary binary data, regardless of content
1. Text-safe - Able to transmit arbitrary text data, preserving the content. Line-endings must be preserved **but may be converted to a different format**. For example `\r\n` may be converted to `\n`. This is due to quirks in some transports (Server Sent Events). If the exact line-ending needs to be preserved, the data should be sent as a `Binary` message. 1. Text-safe - Able to transmit arbitrary text data, preserving the content. Line-endings must be preserved **but may be converted to a different format**. For example `\r\n` may be converted to `\n`. This is due to quirks in some transports (Server Sent Events). If the exact line-ending needs to be preserved, the data should be sent as a `Binary` message.
@ -30,7 +29,7 @@ For the Long-Polling and Server-Sent events transports, there are two additional
The WebSockets transport is unique in that it is full duplex, and a persistent connection that can be established in a single operation. As a result, the client is not required to use the `OPTIONS [endpoint-base]` request to establish a connection in advance. It also includes all the necessary metadata in it's own frame metadata. The WebSockets transport is unique in that it is full duplex, and a persistent connection that can be established in a single operation. As a result, the client is not required to use the `OPTIONS [endpoint-base]` request to establish a connection in advance. It also includes all the necessary metadata in it's own frame metadata.
The WebSocket transport is activated by making a WebSocket connection to `[endpoint-base]`. The **optional** `connectionId` query string value is used to identify the connection to attach to. If there is no `connectionId` query string value, a new connection is established. If the parameter is specified but there is no connection with the specified ID value, a `404 Not Found` response is returned. Upon receiving this request, the connection is established and the server responds with a WebSocket upgrade (`101 Switching Protocols`) immediately ready for frames to be sent/received. The WebSocket OpCode field is used to indicate the type of the frame (Text or Binary) and the WebSocket "FIN" flag is used to indicate the end of a message. The WebSocket transport is activated by making a WebSocket connection to `[endpoint-base]`. The **optional** `connectionId` query string value is used to identify the connection to attach to. If there is no `connectionId` query string value, a new connection is established. If the parameter is specified but there is no connection with the specified ID value, a `404 Not Found` response is returned. Upon receiving this request, the connection is established and the server responds with a WebSocket upgrade (`101 Switching Protocols`) immediately ready for frames to be sent/received. The WebSocket OpCode field is used to indicate the type of the frame (Text or Binary).
Establishing a second WebSocket connection when there is already a WebSocket connection associated with the Endpoints connection is not permitted and will fail with a `409 Conflict` status code. Establishing a second WebSocket connection when there is already a WebSocket connection associated with the Endpoints connection is not permitted and will fail with a `409 Conflict` status code.

View File

@ -301,7 +301,7 @@ namespace Microsoft.AspNetCore.SignalR.Redis
{ {
var protocol = connection.Metadata.Get<IHubProtocol>(HubConnectionMetadataNames.HubProtocol); var protocol = connection.Metadata.Get<IHubProtocol>(HubConnectionMetadataNames.HubProtocol);
var data = await protocol.WriteToArrayAsync(hubMessage); var data = await protocol.WriteToArrayAsync(hubMessage);
var message = new Message(data, protocol.MessageType, endOfMessage: true); var message = new Message(data, protocol.MessageType);
while (await connection.Transport.Output.WaitToWriteAsync()) while (await connection.Transport.Output.WaitToWriteAsync())
{ {

View File

@ -110,7 +110,7 @@ namespace Microsoft.AspNetCore.SignalR
{ {
var protocol = connection.Metadata.Get<IHubProtocol>(HubConnectionMetadataNames.HubProtocol); var protocol = connection.Metadata.Get<IHubProtocol>(HubConnectionMetadataNames.HubProtocol);
var payload = await protocol.WriteToArrayAsync(hubMessage); var payload = await protocol.WriteToArrayAsync(hubMessage);
var message = new Message(payload, protocol.MessageType, endOfMessage: true); var message = new Message(payload, protocol.MessageType);
while (await connection.Transport.Output.WaitToWriteAsync()) while (await connection.Transport.Output.WaitToWriteAsync())
{ {

View File

@ -229,7 +229,7 @@ namespace Microsoft.AspNetCore.SignalR
private async Task SendMessageAsync(ConnectionContext connection, IHubProtocol protocol, HubMessage hubMessage) private async Task SendMessageAsync(ConnectionContext connection, IHubProtocol protocol, HubMessage hubMessage)
{ {
var payload = await protocol.WriteToArrayAsync(hubMessage); var payload = await protocol.WriteToArrayAsync(hubMessage);
var message = new Message(payload, protocol.MessageType, endOfMessage: true); var message = new Message(payload, protocol.MessageType);
while (await connection.Transport.Output.WaitToWriteAsync()) while (await connection.Transport.Output.WaitToWriteAsync())
{ {

View File

@ -119,7 +119,7 @@ namespace Microsoft.AspNetCore.Sockets.Client
logger.LogDebug("Writing '{0}' message to the server", message.Type); logger.LogDebug("Writing '{0}' message to the server", message.Type);
var payload = message.Payload ?? Array.Empty<byte>(); var payload = message.Payload ?? Array.Empty<byte>();
if (!MessageFormatter.TryWriteMessage(new Message(payload, message.Type, endOfMessage: true), output, format)) if (!MessageFormatter.TryWriteMessage(new Message(payload, message.Type), output, format))
{ {
// We didn't get any more memory! // We didn't get any more memory!
throw new InvalidOperationException("Unable to write message to pipeline"); throw new InvalidOperationException("Unable to write message to pipeline");

View File

@ -115,13 +115,13 @@ namespace Microsoft.AspNetCore.Sockets.Client
offset += incomingMessage[i].Count; offset += incomingMessage[i].Count;
} }
message = new Message(messageBuffer, messageType, receiveResult.EndOfMessage); message = new Message(messageBuffer, messageType);
} }
else else
{ {
var buffer = new byte[incomingMessage[0].Count]; var buffer = new byte[incomingMessage[0].Count];
Buffer.BlockCopy(incomingMessage[0].Array, incomingMessage[0].Offset, buffer, 0, incomingMessage[0].Count); Buffer.BlockCopy(incomingMessage[0].Array, incomingMessage[0].Offset, buffer, 0, incomingMessage[0].Count);
message = new Message(buffer, messageType, receiveResult.EndOfMessage); message = new Message(buffer, messageType);
} }
_logger.LogInformation("Passing message to application. Payload size: {0}", message.Payload.Length); _logger.LogInformation("Passing message to application. Payload size: {0}", message.Payload.Length);

View File

@ -16,14 +16,6 @@ namespace Microsoft.AspNetCore.Sockets.Internal.Formatters
public static bool TryWriteMessage(Message message, IOutput output, MessageFormat format) public static bool TryWriteMessage(Message message, IOutput output, MessageFormat format)
{ {
if (!message.EndOfMessage)
{
// This is a truely exceptional condition since we EXPECT callers to have already
// buffered incomplete messages and synthesized the correct, complete message before
// giving it to us. Hence we throw, instead of returning false.
throw new ArgumentException("Cannot format message where endOfMessage is false using this format", nameof(message));
}
return format == MessageFormat.Text ? return format == MessageFormat.Text ?
TextMessageFormatter.TryWriteMessage(message, output) : TextMessageFormatter.TryWriteMessage(message, output) :
BinaryMessageFormatter.TryWriteMessage(message, output); BinaryMessageFormatter.TryWriteMessage(message, output);

View File

@ -23,14 +23,6 @@ namespace Microsoft.AspNetCore.Sockets.Internal.Formatters
public static bool TryWriteMessage(Message message, IOutput output) public static bool TryWriteMessage(Message message, IOutput output)
{ {
if (!message.EndOfMessage)
{
// This is a truely exceptional condition since we EXPECT callers to have already
// buffered incomplete messages and synthesized the correct, complete message before
// giving it to us. Hence we throw, instead of returning false.
throw new InvalidOperationException("Cannot format message where endOfMessage is false using this format");
}
var typeIndicator = GetTypeIndicator(message.Type); var typeIndicator = GetTypeIndicator(message.Type);
// Write the Data Prefix // Write the Data Prefix

View File

@ -7,7 +7,6 @@ namespace Microsoft.AspNetCore.Sockets
{ {
public struct Message public struct Message
{ {
public bool EndOfMessage { get; }
public MessageType Type { get; } public MessageType Type { get; }
// REVIEW: We need a better primitive to use here. Memory<byte> would be good, // REVIEW: We need a better primitive to use here. Memory<byte> would be good,
@ -16,12 +15,6 @@ namespace Microsoft.AspNetCore.Sockets
public byte[] Payload { get; } public byte[] Payload { get; }
public Message(byte[] payload, MessageType type) public Message(byte[] payload, MessageType type)
: this(payload, type, endOfMessage: true)
{
}
public Message(byte[] payload, MessageType type, bool endOfMessage)
{ {
if (payload == null) if (payload == null)
{ {
@ -29,7 +22,6 @@ namespace Microsoft.AspNetCore.Sockets
} }
Type = type; Type = type;
EndOfMessage = endOfMessage;
Payload = payload; Payload = payload;
} }
} }

View File

@ -161,13 +161,13 @@ namespace Microsoft.AspNetCore.Sockets.Transports
offset += incomingMessage[i].Count; offset += incomingMessage[i].Count;
} }
message = new Message(messageBuffer, messageType, receiveResult.EndOfMessage); message = new Message(messageBuffer, messageType);
} }
else else
{ {
var buffer = new byte[incomingMessage[0].Count]; var buffer = new byte[incomingMessage[0].Count];
Buffer.BlockCopy(incomingMessage[0].Array, incomingMessage[0].Offset, buffer, 0, incomingMessage[0].Count); Buffer.BlockCopy(incomingMessage[0].Array, incomingMessage[0].Offset, buffer, 0, incomingMessage[0].Count);
message = new Message(buffer, messageType, receiveResult.EndOfMessage); message = new Message(buffer, messageType);
} }
_logger.LogInformation("Passing message to application. Payload size: {length}", message.Payload.Length); _logger.LogInformation("Passing message to application. Payload size: {length}", message.Payload.Length);
@ -199,11 +199,11 @@ namespace Microsoft.AspNetCore.Sockets.Transports
if (_logger.IsEnabled(LogLevel.Debug)) if (_logger.IsEnabled(LogLevel.Debug))
{ {
_logger.LogDebug("Sending Type: {messageType}, size: {size}, EndOfMessage: {endOfMessage}", _logger.LogDebug("Sending Type: {messageType}, size: {size}",
message.Type, message.EndOfMessage, message.Payload.Length); message.Type, message.Payload.Length);
} }
await ws.SendAsync(new ArraySegment<byte>(message.Payload), messageType, message.EndOfMessage, CancellationToken.None); await ws.SendAsync(new ArraySegment<byte>(message.Payload), messageType, endOfMessage: true, cancellationToken: CancellationToken.None);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
throw new InvalidOperationException("Connection must be started before SendAsync can be called"); throw new InvalidOperationException("Connection must be started before SendAsync can be called");
} }
var message = new Message(data, type, endOfMessage: true); var message = new Message(data, type);
while (await _sentMessages.Out.WaitToWriteAsync(cancellationToken)) while (await _sentMessages.Out.WaitToWriteAsync(cancellationToken))
{ {
if (_sentMessages.Out.TryWrite(message)) if (_sentMessages.Out.TryWrite(message))

View File

@ -110,7 +110,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
var invocationId = GetInvocationId(); var invocationId = GetInvocationId();
var payload = await _protocol.WriteToArrayAsync(new InvocationMessage(invocationId, nonBlocking: false, target: methodName, arguments: args)); var payload = await _protocol.WriteToArrayAsync(new InvocationMessage(invocationId, nonBlocking: false, target: methodName, arguments: args));
await Application.Output.WriteAsync(new Message(payload, _protocol.MessageType, endOfMessage: true)); await Application.Output.WriteAsync(new Message(payload, _protocol.MessageType));
return invocationId; return invocationId;
} }

View File

@ -93,16 +93,5 @@ namespace Microsoft.AspNetCore.Sockets.Tests.Internal.Formatters
Assert.Equal(encoded, output.ToArray().Slice(offset).ToArray()); Assert.Equal(encoded, output.ToArray().Slice(offset).ToArray());
} }
[Fact]
public void WriteInvalidMessages()
{
var message = new Message(new byte[0], MessageType.Binary, endOfMessage: false);
var output = new ArrayOutput(chunkSize: 8); // Use small chunks to test Advance/Enlarge and partial payload writing
var ex = Assert.Throws<ArgumentException>(() =>
MessageFormatter.TryWriteMessage(message, output, MessageFormat.Binary));
Assert.Equal($"Cannot format message where endOfMessage is false using this format{Environment.NewLine}Parameter name: message", ex.Message);
Assert.Equal("message", ex.ParamName);
}
} }
} }

View File

@ -10,16 +10,6 @@ namespace Microsoft.AspNetCore.Sockets.Tests.Internal.Formatters
{ {
public class ServerSentEventsMessageFormatterTests public class ServerSentEventsMessageFormatterTests
{ {
[Fact]
public void WriteInvalidMessages()
{
var message = new Message(new byte[0], MessageType.Binary, endOfMessage: false);
var output = new ArrayOutput(chunkSize: 8); // Use small chunks to test Advance/Enlarge and partial payload writing
var ex = Assert.Throws<InvalidOperationException>(() =>
ServerSentEventsMessageFormatter.TryWriteMessage(message, output));
Assert.Equal("Cannot format message where endOfMessage is false using this format", ex.Message);
}
[Theory] [Theory]
[InlineData("data: T\r\n\r\n", MessageType.Text, "")] [InlineData("data: T\r\n\r\n", MessageType.Text, "")]
[InlineData("data: T\r\ndata: Hello, World\r\n\r\n", MessageType.Text, "Hello, World")] [InlineData("data: T\r\ndata: Hello, World\r\n\r\n", MessageType.Text, "Hello, World")]

View File

@ -66,16 +66,5 @@ namespace Microsoft.AspNetCore.Sockets.Tests.Internal.Formatters
Assert.Equal(encoded, Encoding.UTF8.GetString(output.ToArray())); Assert.Equal(encoded, Encoding.UTF8.GetString(output.ToArray()));
} }
[Fact]
public void WriteInvalidMessages()
{
var message = new Message(new byte[0], MessageType.Binary, endOfMessage: false);
var output = new ArrayOutput(chunkSize: 8); // Use small chunks to test Advance/Enlarge and partial payload writing
var ex = Assert.Throws<ArgumentException>(() =>
MessageFormatter.TryWriteMessage(message, output, MessageFormat.Text));
Assert.Equal($"Cannot format message where endOfMessage is false using this format{Environment.NewLine}Parameter name: message", ex.Message);
Assert.Equal("message", ex.ParamName);
}
} }
} }

View File

@ -11,14 +11,12 @@ namespace Microsoft.AspNetCore.Sockets.Tests
{ {
public static void AssertMessage(Message message, MessageType messageType, byte[] payload) public static void AssertMessage(Message message, MessageType messageType, byte[] payload)
{ {
Assert.True(message.EndOfMessage);
Assert.Equal(messageType, message.Type); Assert.Equal(messageType, message.Type);
Assert.Equal(payload, message.Payload); Assert.Equal(payload, message.Payload);
} }
public static void AssertMessage(Message message, MessageType messageType, string payload) public static void AssertMessage(Message message, MessageType messageType, string payload)
{ {
Assert.True(message.EndOfMessage);
Assert.Equal(messageType, message.Type); Assert.Equal(messageType, message.Type);
Assert.Equal(payload, Encoding.UTF8.GetString(message.Payload)); Assert.Equal(payload, Encoding.UTF8.GetString(message.Payload));
} }
@ -27,16 +25,14 @@ namespace Microsoft.AspNetCore.Sockets.Tests
{ {
return new Message( return new Message(
payload, payload,
type, type);
endOfMessage: true);
} }
public static Message CreateMessage(string payload, MessageType type) public static Message CreateMessage(string payload, MessageType type)
{ {
return new Message( return new Message(
Encoding.UTF8.GetBytes(payload), Encoding.UTF8.GetBytes(payload),
type, type);
endOfMessage: true);
} }
} }
} }

View File

@ -458,7 +458,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
var buffer = Encoding.UTF8.GetBytes("Hello World"); var buffer = Encoding.UTF8.GetBytes("Hello World");
// Write to the transport so the poll yields // Write to the transport so the poll yields
await state.Connection.Transport.Output.WriteAsync(new Message(buffer, MessageType.Text, endOfMessage: true)); await state.Connection.Transport.Output.WriteAsync(new Message(buffer, MessageType.Text));
await task; await task;
@ -490,7 +490,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
var buffer = Encoding.UTF8.GetBytes("Hello World"); var buffer = Encoding.UTF8.GetBytes("Hello World");
// Write to the application // Write to the application
await state.Application.Output.WriteAsync(new Message(buffer, MessageType.Text, endOfMessage: true)); await state.Application.Output.WriteAsync(new Message(buffer, MessageType.Text));
await task; await task;
@ -521,7 +521,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
var buffer = Encoding.UTF8.GetBytes("Hello World"); var buffer = Encoding.UTF8.GetBytes("Hello World");
// Write to the application // Write to the application
await state.Application.Output.WriteAsync(new Message(buffer, MessageType.Text, endOfMessage: true)); await state.Application.Output.WriteAsync(new Message(buffer, MessageType.Text));
await task; await task;

View File

@ -42,8 +42,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
await channel.Out.WriteAsync(new Message( await channel.Out.WriteAsync(new Message(
Encoding.UTF8.GetBytes("Hello World"), Encoding.UTF8.GetBytes("Hello World"),
MessageType.Text, MessageType.Text));
endOfMessage: true));
Assert.True(channel.Out.TryComplete()); Assert.True(channel.Out.TryComplete());
@ -70,16 +69,13 @@ namespace Microsoft.AspNetCore.Sockets.Tests
await channel.Out.WriteAsync(new Message( await channel.Out.WriteAsync(new Message(
Encoding.UTF8.GetBytes("Hello"), Encoding.UTF8.GetBytes("Hello"),
MessageType.Text, MessageType.Text));
endOfMessage: true));
await channel.Out.WriteAsync(new Message( await channel.Out.WriteAsync(new Message(
Encoding.UTF8.GetBytes(" "), Encoding.UTF8.GetBytes(" "),
MessageType.Text, MessageType.Text));
endOfMessage: true));
await channel.Out.WriteAsync(new Message( await channel.Out.WriteAsync(new Message(
Encoding.UTF8.GetBytes("World"), Encoding.UTF8.GetBytes("World"),
MessageType.Text, MessageType.Text));
endOfMessage: true));
Assert.True(channel.Out.TryComplete()); Assert.True(channel.Out.TryComplete());

View File

@ -62,8 +62,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
await channel.Out.WriteAsync(new Message( await channel.Out.WriteAsync(new Message(
Encoding.UTF8.GetBytes(message), Encoding.UTF8.GetBytes(message),
MessageType.Text, MessageType.Text));
endOfMessage: true));
Assert.True(channel.Out.TryComplete()); Assert.True(channel.Out.TryComplete());

View File

@ -47,7 +47,6 @@ namespace Microsoft.AspNetCore.Sockets.Tests
await feature.Client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); await feature.Client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
var message = await applicationSide.Input.In.ReadAsync(); var message = await applicationSide.Input.In.ReadAsync();
Assert.True(message.EndOfMessage);
Assert.Equal(format, message.Type); Assert.Equal(format, message.Type);
Assert.Equal("Hello", Encoding.UTF8.GetString(message.Payload)); Assert.Equal("Hello", Encoding.UTF8.GetString(message.Payload));
@ -63,53 +62,6 @@ namespace Microsoft.AspNetCore.Sockets.Tests
} }
} }
[Theory]
[InlineData(MessageType.Text, WebSocketMessageType.Text)]
[InlineData(MessageType.Binary, WebSocketMessageType.Binary)]
public async Task IncompleteMessagesAreWrittenAsMultiFrameWebSocketMessages(MessageType format, WebSocketMessageType webSocketMessageType)
{
var transportToApplication = Channel.CreateUnbounded<Message>();
var applicationToTransport = Channel.CreateUnbounded<Message>();
var transportSide = new ChannelConnection<Message>(applicationToTransport, transportToApplication);
var applicationSide = new ChannelConnection<Message>(transportToApplication, applicationToTransport);
using (var feature = new TestWebSocketConnectionFeature())
{
var ws = new WebSocketsTransport(new WebSocketOptions(), transportSide, new LoggerFactory());
// Give the server socket to the transport and run it
var transport = ws.ProcessSocketAsync(await feature.AcceptAsync());
// Run the client socket
var client = feature.Client.ExecuteAndCaptureFramesAsync();
// Write multi-frame message to the output channel, and then complete it
await applicationSide.Output.Out.WriteAsync(new Message(
Encoding.UTF8.GetBytes("Hello"),
format,
endOfMessage: false));
await applicationSide.Output.Out.WriteAsync(new Message(
Encoding.UTF8.GetBytes("World"),
format,
endOfMessage: true));
Assert.True(applicationSide.Output.Out.TryComplete());
// The client should finish now, as should the server
var clientSummary = await client;
await feature.Client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
await transport;
Assert.Equal(2, clientSummary.Received.Count);
Assert.False(clientSummary.Received[0].EndOfMessage);
Assert.Equal(webSocketMessageType, clientSummary.Received[0].MessageType);
Assert.Equal("Hello", Encoding.UTF8.GetString(clientSummary.Received[0].Buffer));
Assert.True(clientSummary.Received[1].EndOfMessage);
Assert.Equal(webSocketMessageType, clientSummary.Received[1].MessageType);
Assert.Equal("World", Encoding.UTF8.GetString(clientSummary.Received[1].Buffer));
}
}
[Theory] [Theory]
[InlineData(MessageType.Text, WebSocketMessageType.Text)] [InlineData(MessageType.Text, WebSocketMessageType.Text)]
[InlineData(MessageType.Binary, WebSocketMessageType.Binary)] [InlineData(MessageType.Binary, WebSocketMessageType.Binary)]
@ -134,8 +86,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
// Write to the output channel, and then complete it // Write to the output channel, and then complete it
await applicationSide.Output.Out.WriteAsync(new Message( await applicationSide.Output.Out.WriteAsync(new Message(
Encoding.UTF8.GetBytes("Hello"), Encoding.UTF8.GetBytes("Hello"),
format, format));
endOfMessage: true));
Assert.True(applicationSide.Output.Out.TryComplete()); Assert.True(applicationSide.Output.Out.TryComplete());
// The client should finish now, as should the server // The client should finish now, as should the server
@ -185,7 +136,6 @@ namespace Microsoft.AspNetCore.Sockets.Tests
// Read that frame from the input // Read that frame from the input
var message = await applicationSide.Input.In.ReadAsync(); var message = await applicationSide.Input.In.ReadAsync();
Assert.True(message.EndOfMessage);
Assert.Equal(format, message.Type); Assert.Equal(format, message.Type);
Assert.Equal("Hello", Encoding.UTF8.GetString(message.Payload)); Assert.Equal("Hello", Encoding.UTF8.GetString(message.Payload));