Plumbing TransferMode on the client side
This commit is contained in:
parent
90a6d8fdf7
commit
0ebd33a25c
|
|
@ -11,6 +11,8 @@ using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
using Microsoft.AspNetCore.SignalR.Internal;
|
using Microsoft.AspNetCore.SignalR.Internal;
|
||||||
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
|
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
|
||||||
|
using Microsoft.AspNetCore.Sockets;
|
||||||
|
using Microsoft.AspNetCore.Sockets.Features;
|
||||||
using Microsoft.AspNetCore.Sockets.Client;
|
using Microsoft.AspNetCore.Sockets.Client;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
|
@ -77,6 +79,18 @@ namespace Microsoft.AspNetCore.SignalR.Client
|
||||||
|
|
||||||
public async Task StartAsync()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
|
var transferModeFeature = _connection.Features.Get<ITransferModeFeature>();
|
||||||
|
if (transferModeFeature == null)
|
||||||
|
{
|
||||||
|
transferModeFeature = new TransferModeFeature();
|
||||||
|
_connection.Features.Set(transferModeFeature);
|
||||||
|
}
|
||||||
|
|
||||||
|
transferModeFeature.TransferMode =
|
||||||
|
(_protocol.Type == ProtocolType.Binary)
|
||||||
|
? TransferMode.Binary
|
||||||
|
: TransferMode.Text;
|
||||||
|
|
||||||
await _connection.StartAsync();
|
await _connection.StartAsync();
|
||||||
|
|
||||||
using (var memoryStream = new MemoryStream())
|
using (var memoryStream = new MemoryStream())
|
||||||
|
|
@ -389,5 +403,10 @@ namespace Microsoft.AspNetCore.SignalR.Client
|
||||||
ParameterTypes = parameterTypes;
|
ParameterTypes = parameterTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TransferModeFeature : ITransferModeFeature
|
||||||
|
{
|
||||||
|
public TransferMode TransferMode { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
|
||||||
{
|
{
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
|
ProtocolType Type { get; }
|
||||||
|
|
||||||
bool TryParseMessages(ReadOnlyBuffer<byte> input, IInvocationBinder binder, out IList<HubMessage> messages);
|
bool TryParseMessages(ReadOnlyBuffer<byte> input, IInvocationBinder binder, out IList<HubMessage> messages);
|
||||||
|
|
||||||
void WriteMessage(HubMessage message, Stream output);
|
void WriteMessage(HubMessage message, Stream output);
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
|
||||||
|
|
||||||
public string Name => "json";
|
public string Name => "json";
|
||||||
|
|
||||||
|
public ProtocolType Type => ProtocolType.Text;
|
||||||
|
|
||||||
public bool TryParseMessages(ReadOnlyBuffer<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
public bool TryParseMessages(ReadOnlyBuffer<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
||||||
{
|
{
|
||||||
messages = new List<HubMessage>();
|
messages = new List<HubMessage>();
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
|
||||||
|
|
||||||
public string Name => "messagepack";
|
public string Name => "messagepack";
|
||||||
|
|
||||||
|
public ProtocolType Type => ProtocolType.Binary;
|
||||||
|
|
||||||
public bool TryParseMessages(ReadOnlyBuffer<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
public bool TryParseMessages(ReadOnlyBuffer<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
||||||
{
|
{
|
||||||
messages = new List<HubMessage>();
|
messages = new List<HubMessage>();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
|
||||||
|
{
|
||||||
|
public enum ProtocolType
|
||||||
|
{
|
||||||
|
Binary,
|
||||||
|
Text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Sockets.Features
|
namespace Microsoft.AspNetCore.Sockets.Features
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Sockets.Features
|
||||||
|
{
|
||||||
|
public interface ITransferModeFeature
|
||||||
|
{
|
||||||
|
TransferMode TransferMode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Sockets.Client
|
namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
{
|
{
|
||||||
|
|
@ -16,5 +17,7 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
event Func<Task> Connected;
|
event Func<Task> Connected;
|
||||||
event Func<byte[], Task> Received;
|
event Func<byte[], Task> Received;
|
||||||
event Func<Exception, Task> Closed;
|
event Func<Exception, Task> Closed;
|
||||||
|
|
||||||
|
IFeatureCollection Features { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Sockets
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum TransferMode
|
||||||
|
{
|
||||||
|
Binary = 0x01,
|
||||||
|
Text = 0x02
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,14 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Sockets.Features;
|
||||||
using Microsoft.AspNetCore.Sockets.Client.Internal;
|
using Microsoft.AspNetCore.Sockets.Client.Internal;
|
||||||
using Microsoft.AspNetCore.Sockets.Internal;
|
using Microsoft.AspNetCore.Sockets.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
@ -35,6 +38,8 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
|
|
||||||
public Uri Url { get; }
|
public Uri Url { get; }
|
||||||
|
|
||||||
|
public IFeatureCollection Features { get; } = new FeatureCollection();
|
||||||
|
|
||||||
public event Func<Task> Connected;
|
public event Func<Task> Connected;
|
||||||
public event Func<byte[], Task> Received;
|
public event Func<byte[], Task> Received;
|
||||||
public event Func<Exception, Task> Closed;
|
public event Func<Exception, Task> Closed;
|
||||||
|
|
@ -48,7 +53,7 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public HttpConnection(Uri url, TransportType transportType)
|
public HttpConnection(Uri url, TransportType transportType)
|
||||||
: this(url, transportType, loggerFactory: null)
|
: this(url, transportType, loggerFactory: null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -262,7 +267,11 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
// Start the transport, giving it one end of the pipeline
|
// Start the transport, giving it one end of the pipeline
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _transport.StartAsync(connectUrl, applicationSide, _connectionId);
|
await _transport.StartAsync(connectUrl, applicationSide, requestedTransferMode: GetTransferMode(), connectionId: _connectionId);
|
||||||
|
|
||||||
|
// actual transfer mode can differ from the one that was requested so set it on the feature
|
||||||
|
Debug.Assert(_transport.Mode.HasValue, "transfer mode not set after transport started");
|
||||||
|
SetTransferMode(_transport.Mode.Value);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -271,6 +280,29 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TransferMode GetTransferMode()
|
||||||
|
{
|
||||||
|
var transferModeFeature = Features.Get<ITransferModeFeature>();
|
||||||
|
if (transferModeFeature == null)
|
||||||
|
{
|
||||||
|
return TransferMode.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return transferModeFeature.TransferMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetTransferMode(TransferMode transferMode)
|
||||||
|
{
|
||||||
|
var transferModeFeature = Features.Get<ITransferModeFeature>();
|
||||||
|
if (transferModeFeature == null)
|
||||||
|
{
|
||||||
|
transferModeFeature = new TransferModeFeature();
|
||||||
|
Features.Set(transferModeFeature);
|
||||||
|
}
|
||||||
|
|
||||||
|
transferModeFeature.TransferMode = transferMode;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ReceiveAsync()
|
private async Task ReceiveAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
{
|
{
|
||||||
public interface ITransport
|
public interface ITransport
|
||||||
{
|
{
|
||||||
Task StartAsync(Uri url, Channel<byte[], SendMessage> application, string connectionId);
|
Task StartAsync(Uri url, Channel<byte[], SendMessage> application, TransferMode requestedTransferMode, string connectionId);
|
||||||
Task StopAsync();
|
Task StopAsync();
|
||||||
|
TransferMode? Mode { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ namespace Microsoft.AspNetCore.Sockets.Client.Internal
|
||||||
internal static class SocketClientLoggerExtensions
|
internal static class SocketClientLoggerExtensions
|
||||||
{
|
{
|
||||||
// Category: Shared with LongPollingTransport, WebSocketsTransport and ServerSentEventsTransport
|
// Category: Shared with LongPollingTransport, WebSocketsTransport and ServerSentEventsTransport
|
||||||
private static readonly Action<ILogger, DateTime, string, Exception> _startTransport =
|
private static readonly Action<ILogger, DateTime, string, TransferMode, Exception> _startTransport =
|
||||||
LoggerMessage.Define<DateTime, string>(LogLevel.Information, 0, "{time}: Connection Id {connectionId}: Starting transport.");
|
LoggerMessage.Define<DateTime, string, TransferMode>(LogLevel.Information, 0, "{time}: Connection Id {connectionId}: Starting transport. Transfer mode: {transferMode}.");
|
||||||
|
|
||||||
private static readonly Action<ILogger, DateTime, string, Exception> _transportStopped =
|
private static readonly Action<ILogger, DateTime, string, Exception> _transportStopped =
|
||||||
LoggerMessage.Define<DateTime, string>(LogLevel.Debug, 1, "{time}: Connection Id {connectionId}: Transport stopped.");
|
LoggerMessage.Define<DateTime, string>(LogLevel.Debug, 1, "{time}: Connection Id {connectionId}: Transport stopped.");
|
||||||
|
|
@ -147,11 +147,11 @@ namespace Microsoft.AspNetCore.Sockets.Client.Internal
|
||||||
private static readonly Action<ILogger, DateTime, string, Exception> _stoppingClient =
|
private static readonly Action<ILogger, DateTime, string, Exception> _stoppingClient =
|
||||||
LoggerMessage.Define<DateTime, string>(LogLevel.Information, 18, "{time}: Connection Id {connectionId}: Stopping client.");
|
LoggerMessage.Define<DateTime, string>(LogLevel.Information, 18, "{time}: Connection Id {connectionId}: Stopping client.");
|
||||||
|
|
||||||
public static void StartTransport(this ILogger logger, string connectionId)
|
public static void StartTransport(this ILogger logger, string connectionId, TransferMode transferMode)
|
||||||
{
|
{
|
||||||
if (logger.IsEnabled(LogLevel.Information))
|
if (logger.IsEnabled(LogLevel.Information))
|
||||||
{
|
{
|
||||||
_startTransport(logger, DateTime.Now, connectionId, null);
|
_startTransport(logger, DateTime.Now, connectionId, transferMode, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
|
|
||||||
public Task Running { get; private set; } = Task.CompletedTask;
|
public Task Running { get; private set; } = Task.CompletedTask;
|
||||||
|
|
||||||
|
public TransferMode? Mode { get; private set; }
|
||||||
|
|
||||||
public LongPollingTransport(HttpClient httpClient)
|
public LongPollingTransport(HttpClient httpClient)
|
||||||
: this(httpClient, null)
|
: this(httpClient, null)
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -36,12 +38,18 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
_logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<LongPollingTransport>();
|
_logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<LongPollingTransport>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StartAsync(Uri url, Channel<byte[], SendMessage> application, string connectionId)
|
public Task StartAsync(Uri url, Channel<byte[], SendMessage> application, TransferMode requestedTransferMode, string connectionId)
|
||||||
{
|
{
|
||||||
_connectionId = connectionId;
|
if (requestedTransferMode != TransferMode.Binary && requestedTransferMode != TransferMode.Text)
|
||||||
_logger.StartTransport(_connectionId);
|
{
|
||||||
|
throw new ArgumentException("Invalid transfer mode.", nameof(requestedTransferMode));
|
||||||
|
}
|
||||||
|
|
||||||
_application = application;
|
_application = application;
|
||||||
|
Mode = requestedTransferMode;
|
||||||
|
_connectionId = connectionId;
|
||||||
|
|
||||||
|
_logger.StartTransport(_connectionId, Mode.Value);
|
||||||
|
|
||||||
// Start sending and polling (ask for binary if the server supports it)
|
// Start sending and polling (ask for binary if the server supports it)
|
||||||
_poller = Poll(url, _transportCts.Token);
|
_poller = Poll(url, _transportCts.Token);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
|
|
||||||
public Task Running { get; private set; } = Task.CompletedTask;
|
public Task Running { get; private set; } = Task.CompletedTask;
|
||||||
|
|
||||||
|
public TransferMode? Mode { get; private set; }
|
||||||
|
|
||||||
public ServerSentEventsTransport(HttpClient httpClient)
|
public ServerSentEventsTransport(HttpClient httpClient)
|
||||||
: this(httpClient, null)
|
: this(httpClient, null)
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -42,12 +44,19 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
_logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<ServerSentEventsTransport>();
|
_logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<ServerSentEventsTransport>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StartAsync(Uri url, Channel<byte[], SendMessage> application, string connectionId)
|
public Task StartAsync(Uri url, Channel<byte[], SendMessage> application, TransferMode requestedTransferMode, string connectionId)
|
||||||
{
|
{
|
||||||
_connectionId = connectionId;
|
if (requestedTransferMode != TransferMode.Binary && requestedTransferMode != TransferMode.Text)
|
||||||
_logger.StartTransport(_connectionId);
|
{
|
||||||
|
throw new ArgumentException("Invalid transfer mode.", nameof(requestedTransferMode));
|
||||||
|
}
|
||||||
|
|
||||||
_application = application;
|
_application = application;
|
||||||
|
Mode = TransferMode.Text; // Server Sent Events is a text only transport
|
||||||
|
_connectionId = connectionId;
|
||||||
|
|
||||||
|
_logger.StartTransport(_connectionId, Mode.Value);
|
||||||
|
|
||||||
var sendTask = SendUtils.SendMessages(url, _application, _httpClient, _transportCts, _logger, _connectionId);
|
var sendTask = SendUtils.SendMessages(url, _application, _httpClient, _transportCts, _logger, _connectionId);
|
||||||
var receiveTask = OpenConnection(_application, url, _transportCts.Token);
|
var receiveTask = OpenConnection(_application, url, _transportCts.Token);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Sockets.Features;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
|
{
|
||||||
|
public class TransferModeFeature : ITransferModeFeature
|
||||||
|
{
|
||||||
|
public TransferMode TransferMode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,10 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private string _connectionId;
|
private string _connectionId;
|
||||||
|
|
||||||
|
public Task Running { get; private set; } = Task.CompletedTask;
|
||||||
|
|
||||||
|
public TransferMode? Mode { get; private set; }
|
||||||
|
|
||||||
public WebSocketsTransport()
|
public WebSocketsTransport()
|
||||||
: this(null)
|
: this(null)
|
||||||
{
|
{
|
||||||
|
|
@ -32,9 +36,7 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
_logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<WebSocketsTransport>();
|
_logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<WebSocketsTransport>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Running { get; private set; } = Task.CompletedTask;
|
public async Task StartAsync(Uri url, Channel<byte[], SendMessage> application, TransferMode requestedTransferMode, string connectionId)
|
||||||
|
|
||||||
public async Task StartAsync(Uri url, Channel<byte[], SendMessage> application, string connectionId)
|
|
||||||
{
|
{
|
||||||
if (url == null)
|
if (url == null)
|
||||||
{
|
{
|
||||||
|
|
@ -46,10 +48,17 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
throw new ArgumentNullException(nameof(application));
|
throw new ArgumentNullException(nameof(application));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requestedTransferMode != TransferMode.Binary && requestedTransferMode != TransferMode.Text)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Invalid transfer mode.", nameof(requestedTransferMode));
|
||||||
|
}
|
||||||
|
|
||||||
_application = application;
|
_application = application;
|
||||||
|
Mode = requestedTransferMode;
|
||||||
_connectionId = connectionId;
|
_connectionId = connectionId;
|
||||||
|
|
||||||
_logger.StartTransport(_connectionId);
|
_logger.StartTransport(_connectionId, Mode.Value);
|
||||||
|
|
||||||
await Connect(url);
|
await Connect(url);
|
||||||
var sendTask = SendMessages(url);
|
var sendTask = SendMessages(url);
|
||||||
var receiveTask = ReceiveMessages(url);
|
var receiveTask = ReceiveMessages(url);
|
||||||
|
|
@ -145,6 +154,11 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
{
|
{
|
||||||
_logger.SendStarted(_connectionId);
|
_logger.SendStarted(_connectionId);
|
||||||
|
|
||||||
|
var webSocketMessageType =
|
||||||
|
Mode == TransferMode.Binary
|
||||||
|
? WebSocketMessageType.Binary
|
||||||
|
: WebSocketMessageType.Text;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (await _application.In.WaitToReadAsync(_transportCts.Token))
|
while (await _application.In.WaitToReadAsync(_transportCts.Token))
|
||||||
|
|
@ -155,7 +169,7 @@ namespace Microsoft.AspNetCore.Sockets.Client
|
||||||
{
|
{
|
||||||
_logger.ReceivedFromApp(_connectionId, message.Payload.Length);
|
_logger.ReceivedFromApp(_connectionId, message.Payload.Length);
|
||||||
|
|
||||||
await _webSocket.SendAsync(new ArraySegment<byte>(message.Payload), WebSocketMessageType.Text, true, _transportCts.Token);
|
await _webSocket.SendAsync(new ArraySegment<byte>(message.Payload), webSocketMessageType, true, _transportCts.Token);
|
||||||
|
|
||||||
message.SendResult.SetResult(null);
|
message.SendResult.SetResult(null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,15 @@ using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
using Microsoft.AspNetCore.Client.Tests;
|
using Microsoft.AspNetCore.Client.Tests;
|
||||||
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
||||||
|
using Microsoft.AspNetCore.Sockets.Features;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Moq.Protected;
|
using Moq.Protected;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
{
|
{
|
||||||
public class ConnectionTests
|
public class HttpConnectionTests
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CannotCreateConnectionWithNullUrl()
|
public void CannotCreateConnectionWithNullUrl()
|
||||||
|
|
@ -138,7 +137,6 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
: ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
: ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
var transport = new Mock<ITransport>();
|
var transport = new Mock<ITransport>();
|
||||||
transport.Setup(t => t.StopAsync()).Returns(async () => { await releaseDisposeTcs.Task; });
|
transport.Setup(t => t.StopAsync()).Returns(async () => { await releaseDisposeTcs.Task; });
|
||||||
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(transport.Object), loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(transport.Object), loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
||||||
|
|
@ -154,7 +152,7 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
releaseDisposeTcs.SetResult(null);
|
releaseDisposeTcs.SetResult(null);
|
||||||
await disposeTask.OrTimeout();
|
await disposeTask.OrTimeout();
|
||||||
|
|
||||||
transport.Verify(t => t.StartAsync(It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), It.IsAny<string>()), Times.Never);
|
transport.Verify(t => t.StartAsync(It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), It.IsAny<TransferMode>(), It.IsAny<string>()), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -180,7 +178,6 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
: ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
: ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
||||||
|
|
||||||
await connection.StartAsync();
|
await connection.StartAsync();
|
||||||
|
|
@ -205,8 +202,8 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
: ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
: ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var connectedEventRaisedTcs = new TaskCompletionSource<object>();
|
var connectedEventRaisedTcs = new TaskCompletionSource<object>();
|
||||||
|
|
@ -241,10 +238,9 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
});
|
});
|
||||||
|
|
||||||
var mockTransport = new Mock<ITransport>();
|
var mockTransport = new Mock<ITransport>();
|
||||||
mockTransport.Setup(t => t.StartAsync(It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), It.IsAny<string>()))
|
mockTransport.Setup(t => t.StartAsync(It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), It.IsAny<TransferMode>(), It.IsAny<string>()))
|
||||||
.Returns(Task.FromException(new InvalidOperationException("Transport failed to start")));
|
.Returns(Task.FromException(new InvalidOperationException("Transport failed to start")));
|
||||||
|
|
||||||
|
|
||||||
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
||||||
var connectedEventRaised = false;
|
var connectedEventRaised = false;
|
||||||
|
|
||||||
|
|
@ -281,7 +277,6 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
: ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
: ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
||||||
|
|
||||||
var closedEventTcs = new TaskCompletionSource<Exception>();
|
var closedEventTcs = new TaskCompletionSource<Exception>();
|
||||||
|
|
@ -350,8 +345,8 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
|
|
||||||
var mockTransport = new Mock<ITransport>();
|
var mockTransport = new Mock<ITransport>();
|
||||||
Channel<byte[], SendMessage> channel = null;
|
Channel<byte[], SendMessage> channel = null;
|
||||||
mockTransport.Setup(t => t.StartAsync(It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), It.IsAny<string>()))
|
mockTransport.Setup(t => t.StartAsync(It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), It.IsAny<TransferMode>(), It.IsAny<string>()))
|
||||||
.Returns<Uri, Channel<byte[], SendMessage>, string>((url, c, id) =>
|
.Returns<Uri, Channel<byte[], SendMessage>, TransferMode, string>((url, c, transferMode, connectionId) =>
|
||||||
{
|
{
|
||||||
channel = c;
|
channel = c;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
@ -365,9 +360,10 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
channel.Out.TryComplete();
|
channel.Out.TryComplete();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
});
|
});
|
||||||
|
mockTransport.SetupGet(t => t.Mode).Returns(TransferMode.Text);
|
||||||
|
|
||||||
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
||||||
|
|
||||||
var receivedInvoked = false;
|
var receivedInvoked = false;
|
||||||
connection.Received += m =>
|
connection.Received += m =>
|
||||||
{
|
{
|
||||||
|
|
@ -396,8 +392,8 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
|
|
||||||
var mockTransport = new Mock<ITransport>();
|
var mockTransport = new Mock<ITransport>();
|
||||||
Channel<byte[], SendMessage> channel = null;
|
Channel<byte[], SendMessage> channel = null;
|
||||||
mockTransport.Setup(t => t.StartAsync(It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), It.IsAny<string>()))
|
mockTransport.Setup(t => t.StartAsync(It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), It.IsAny<TransferMode>(), It.IsAny<string>()))
|
||||||
.Returns<Uri, Channel<byte[], SendMessage>, string>((url, c, id) =>
|
.Returns<Uri, Channel<byte[], SendMessage>, TransferMode, string>((url, c, transferMode, connectionId) =>
|
||||||
{
|
{
|
||||||
channel = c;
|
channel = c;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
@ -408,12 +404,13 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
channel.Out.TryComplete();
|
channel.Out.TryComplete();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
});
|
});
|
||||||
|
mockTransport.SetupGet(t => t.Mode).Returns(TransferMode.Text);
|
||||||
|
|
||||||
var callbackInvokedTcs = new TaskCompletionSource<object>();
|
var callbackInvokedTcs = new TaskCompletionSource<object>();
|
||||||
var closedTcs = new TaskCompletionSource<object>();
|
var closedTcs = new TaskCompletionSource<object>();
|
||||||
|
|
||||||
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
||||||
|
|
||||||
connection.Received +=
|
connection.Received +=
|
||||||
async m =>
|
async m =>
|
||||||
{
|
{
|
||||||
|
|
@ -584,7 +581,6 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
});
|
});
|
||||||
|
|
||||||
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
||||||
|
|
||||||
await connection.StartAsync();
|
await connection.StartAsync();
|
||||||
|
|
||||||
var exception = await Assert.ThrowsAsync<HttpRequestException>(
|
var exception = await Assert.ThrowsAsync<HttpRequestException>(
|
||||||
|
|
@ -773,5 +769,48 @@ namespace Microsoft.AspNetCore.Sockets.Client.Tests
|
||||||
|
|
||||||
Assert.Equal("No requested transports available on the server.", exception.Message);
|
Assert.Equal("No requested transports available on the server.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CanStartConnectionWithoutSettingTransferModeFeature()
|
||||||
|
{
|
||||||
|
var mockHttpHandler = new Mock<HttpMessageHandler>();
|
||||||
|
mockHttpHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
|
||||||
|
.Returns<HttpRequestMessage, CancellationToken>(async (request, cancellationToken) =>
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
return request.Method == HttpMethod.Options
|
||||||
|
? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse())
|
||||||
|
: ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
||||||
|
});
|
||||||
|
|
||||||
|
var mockTransport = new Mock<ITransport>();
|
||||||
|
Channel<byte[], SendMessage> channel = null;
|
||||||
|
mockTransport.Setup(t => t.StartAsync(It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), It.IsAny<TransferMode>(), It.IsAny<string>()))
|
||||||
|
.Returns<Uri, Channel<byte[], SendMessage>, TransferMode, string>((url, c, transferMode, connectionId) =>
|
||||||
|
{
|
||||||
|
channel = c;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
});
|
||||||
|
mockTransport.Setup(t => t.StopAsync())
|
||||||
|
.Returns(() =>
|
||||||
|
{
|
||||||
|
channel.Out.TryComplete();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
});
|
||||||
|
mockTransport.SetupGet(t => t.Mode).Returns(TransferMode.Binary);
|
||||||
|
|
||||||
|
var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object),
|
||||||
|
loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);
|
||||||
|
|
||||||
|
await connection.StartAsync().OrTimeout();
|
||||||
|
var transferModeFeature = connection.Features.Get<ITransferModeFeature>();
|
||||||
|
await connection.DisposeAsync().OrTimeout();
|
||||||
|
|
||||||
|
mockTransport.Verify(t => t.StartAsync(
|
||||||
|
It.IsAny<Uri>(), It.IsAny<Channel<byte[], SendMessage>>(), TransferMode.Text, It.IsAny<string>()), Times.Once);
|
||||||
|
Assert.NotNull(transferModeFeature);
|
||||||
|
Assert.Equal(TransferMode.Binary, transferModeFeature.TransferMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.SignalR.Internal;
|
using Microsoft.AspNetCore.SignalR.Internal;
|
||||||
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
|
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
|
||||||
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
||||||
|
|
@ -21,6 +22,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
public async Task StartAsyncCallsConnectionStart()
|
public async Task StartAsyncCallsConnectionStart()
|
||||||
{
|
{
|
||||||
var connection = new Mock<IConnection>();
|
var connection = new Mock<IConnection>();
|
||||||
|
connection.SetupGet(p => p.Features).Returns(new FeatureCollection());
|
||||||
connection.Setup(m => m.StartAsync()).Returns(Task.CompletedTask).Verifiable();
|
connection.Setup(m => m.StartAsync()).Returns(Task.CompletedTask).Verifiable();
|
||||||
var hubConnection = new HubConnection(connection.Object);
|
var hubConnection = new HubConnection(connection.Object);
|
||||||
await hubConnection.StartAsync();
|
await hubConnection.StartAsync();
|
||||||
|
|
@ -125,6 +127,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
{
|
{
|
||||||
var exception = new InvalidOperationException();
|
var exception = new InvalidOperationException();
|
||||||
var mockConnection = new Mock<IConnection>();
|
var mockConnection = new Mock<IConnection>();
|
||||||
|
mockConnection.SetupGet(p => p.Features).Returns(new FeatureCollection());
|
||||||
mockConnection
|
mockConnection
|
||||||
.Setup(m => m.DisposeAsync())
|
.Setup(m => m.DisposeAsync())
|
||||||
.Callback(() => mockConnection.Raise(c => c.Closed += null, exception))
|
.Callback(() => mockConnection.Raise(c => c.Closed += null, exception))
|
||||||
|
|
@ -144,6 +147,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
public async Task DoesNotThrowWhenClientMethodCalledButNoInvocationHandlerHasBeenSetUp()
|
public async Task DoesNotThrowWhenClientMethodCalledButNoInvocationHandlerHasBeenSetUp()
|
||||||
{
|
{
|
||||||
var mockConnection = new Mock<IConnection>();
|
var mockConnection = new Mock<IConnection>();
|
||||||
|
mockConnection.SetupGet(p => p.Features).Returns(new FeatureCollection());
|
||||||
|
|
||||||
var invocation = new InvocationMessage(Guid.NewGuid().ToString(), nonBlocking: true, target: "NonExistingMethod123", arguments: new object[] { true, "arg2", 123 });
|
var invocation = new InvocationMessage(Guid.NewGuid().ToString(), nonBlocking: true, target: "NonExistingMethod123", arguments: new object[] { true, "arg2", 123 });
|
||||||
|
|
||||||
|
|
@ -181,7 +185,9 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get => "MockHubProtocol"; }
|
public string Name => "MockHubProtocol";
|
||||||
|
|
||||||
|
public ProtocolType Type => ProtocolType.Binary;
|
||||||
|
|
||||||
public bool TryParseMessages(ReadOnlyBuffer<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
public bool TryParseMessages(ReadOnlyBuffer<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
||||||
|
using Microsoft.AspNetCore.Sockets;
|
||||||
using Microsoft.AspNetCore.Sockets.Client;
|
using Microsoft.AspNetCore.Sockets.Client;
|
||||||
using Microsoft.AspNetCore.Sockets.Internal;
|
using Microsoft.AspNetCore.Sockets.Internal;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
@ -43,7 +44,7 @@ namespace Microsoft.AspNetCore.Client.Tests
|
||||||
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty);
|
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId: string.Empty);
|
||||||
|
|
||||||
transportActiveTask = longPollingTransport.Running;
|
transportActiveTask = longPollingTransport.Running;
|
||||||
|
|
||||||
|
|
@ -79,7 +80,7 @@ namespace Microsoft.AspNetCore.Client.Tests
|
||||||
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = ChannelConnection.Create(connectionToTransport, transportToConnection);
|
var channelConnection = ChannelConnection.Create(connectionToTransport, transportToConnection);
|
||||||
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty);
|
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId: string.Empty);
|
||||||
|
|
||||||
await longPollingTransport.Running.OrTimeout();
|
await longPollingTransport.Running.OrTimeout();
|
||||||
Assert.True(transportToConnection.In.Completion.IsCompleted);
|
Assert.True(transportToConnection.In.Completion.IsCompleted);
|
||||||
|
|
@ -132,7 +133,7 @@ namespace Microsoft.AspNetCore.Client.Tests
|
||||||
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty);
|
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId: string.Empty);
|
||||||
|
|
||||||
var data = await transportToConnection.In.ReadAllAsync().OrTimeout();
|
var data = await transportToConnection.In.ReadAllAsync().OrTimeout();
|
||||||
await longPollingTransport.Running.OrTimeout();
|
await longPollingTransport.Running.OrTimeout();
|
||||||
|
|
@ -168,7 +169,7 @@ namespace Microsoft.AspNetCore.Client.Tests
|
||||||
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty);
|
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId: string.Empty);
|
||||||
|
|
||||||
var exception =
|
var exception =
|
||||||
await Assert.ThrowsAsync<HttpRequestException>(async () => await transportToConnection.In.Completion.OrTimeout());
|
await Assert.ThrowsAsync<HttpRequestException>(async () => await transportToConnection.In.Completion.OrTimeout());
|
||||||
|
|
@ -204,7 +205,7 @@ namespace Microsoft.AspNetCore.Client.Tests
|
||||||
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty);
|
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId: string.Empty);
|
||||||
|
|
||||||
await connectionToTransport.Out.WriteAsync(new SendMessage());
|
await connectionToTransport.Out.WriteAsync(new SendMessage());
|
||||||
|
|
||||||
|
|
@ -245,7 +246,7 @@ namespace Microsoft.AspNetCore.Client.Tests
|
||||||
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty);
|
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId: string.Empty);
|
||||||
|
|
||||||
connectionToTransport.Out.Complete();
|
connectionToTransport.Out.Complete();
|
||||||
|
|
||||||
|
|
@ -296,7 +297,7 @@ namespace Microsoft.AspNetCore.Client.Tests
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
|
||||||
// Start the transport
|
// Start the transport
|
||||||
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty);
|
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId: string.Empty);
|
||||||
|
|
||||||
// Wait for the transport to finish
|
// Wait for the transport to finish
|
||||||
await longPollingTransport.Running.OrTimeout();
|
await longPollingTransport.Running.OrTimeout();
|
||||||
|
|
@ -361,7 +362,7 @@ namespace Microsoft.AspNetCore.Client.Tests
|
||||||
await connectionToTransport.Out.WriteAsync(new SendMessage(Encoding.UTF8.GetBytes("World"), tcs2)).OrTimeout();
|
await connectionToTransport.Out.WriteAsync(new SendMessage(Encoding.UTF8.GetBytes("World"), tcs2)).OrTimeout();
|
||||||
|
|
||||||
// Start the transport
|
// Start the transport
|
||||||
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty);
|
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Binary, connectionId: string.Empty);
|
||||||
|
|
||||||
connectionToTransport.Out.Complete();
|
connectionToTransport.Out.Complete();
|
||||||
|
|
||||||
|
|
@ -378,5 +379,63 @@ namespace Microsoft.AspNetCore.Client.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(TransferMode.Binary)]
|
||||||
|
[InlineData(TransferMode.Text)]
|
||||||
|
public async Task LongPollingTransportSetsTransferMode(TransferMode transferMode)
|
||||||
|
{
|
||||||
|
var mockHttpHandler = new Mock<HttpMessageHandler>();
|
||||||
|
mockHttpHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
|
||||||
|
.Returns<HttpRequestMessage, CancellationToken>(async (request, cancellationToken) =>
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
return ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
||||||
|
});
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient(mockHttpHandler.Object))
|
||||||
|
{
|
||||||
|
var longPollingTransport = new LongPollingTransport(httpClient);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
|
||||||
|
Assert.Null(longPollingTransport.Mode);
|
||||||
|
await longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, transferMode, connectionId: string.Empty);
|
||||||
|
Assert.Equal(transferMode, longPollingTransport.Mode);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
await longPollingTransport.StopAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task LongPollingTransportThrowsForInvalidTransferMode()
|
||||||
|
{
|
||||||
|
var mockHttpHandler = new Mock<HttpMessageHandler>();
|
||||||
|
mockHttpHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
|
||||||
|
.Returns<HttpRequestMessage, CancellationToken>(async (request, cancellationToken) =>
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
return ResponseUtils.CreateResponse(HttpStatusCode.OK);
|
||||||
|
});
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient(mockHttpHandler.Object))
|
||||||
|
{
|
||||||
|
var longPollingTransport = new LongPollingTransport(httpClient);
|
||||||
|
var exception = await Assert.ThrowsAsync<ArgumentException>(() =>
|
||||||
|
longPollingTransport.StartAsync(new Uri("http://fakeuri.org"), null, TransferMode.Text | TransferMode.Binary, connectionId: string.Empty));
|
||||||
|
|
||||||
|
Assert.Contains("Invalid transfer mode.", exception.Message);
|
||||||
|
Assert.Equal("requestedTransferMode", exception.ParamName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
using Microsoft.AspNetCore.Client.Tests;
|
using Microsoft.AspNetCore.Client.Tests;
|
||||||
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
||||||
|
using Microsoft.AspNetCore.Sockets;
|
||||||
using Microsoft.AspNetCore.Sockets.Client;
|
using Microsoft.AspNetCore.Sockets.Client;
|
||||||
using Microsoft.AspNetCore.Sockets.Internal;
|
using Microsoft.AspNetCore.Sockets.Internal;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
@ -52,7 +53,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
await sseTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty).OrTimeout();
|
await sseTransport.StartAsync(
|
||||||
|
new Uri("http://fakeuri.org"), channelConnection, TransferMode.Text, connectionId: string.Empty).OrTimeout();
|
||||||
|
|
||||||
await eventStreamTcs.Task.OrTimeout();
|
await eventStreamTcs.Task.OrTimeout();
|
||||||
await sseTransport.StopAsync().OrTimeout();
|
await sseTransport.StopAsync().OrTimeout();
|
||||||
|
|
@ -103,7 +105,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
await sseTransport.StartAsync(
|
await sseTransport.StartAsync(
|
||||||
new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty).OrTimeout();
|
new Uri("http://fakeuri.org"), channelConnection, TransferMode.Text, connectionId: string.Empty).OrTimeout();
|
||||||
|
|
||||||
transportActiveTask = sseTransport.Running;
|
transportActiveTask = sseTransport.Running;
|
||||||
Assert.False(transportActiveTask.IsCompleted);
|
Assert.False(transportActiveTask.IsCompleted);
|
||||||
|
|
@ -150,7 +152,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
await sseTransport.StartAsync(
|
await sseTransport.StartAsync(
|
||||||
new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty).OrTimeout();
|
new Uri("http://fakeuri.org"), channelConnection, TransferMode.Text, connectionId: string.Empty).OrTimeout();
|
||||||
|
|
||||||
var exception = await Assert.ThrowsAsync<FormatException>(() => sseTransport.Running.OrTimeout());
|
var exception = await Assert.ThrowsAsync<FormatException>(() => sseTransport.Running.OrTimeout());
|
||||||
Assert.Equal("Incomplete message.", exception.Message);
|
Assert.Equal("Incomplete message.", exception.Message);
|
||||||
|
|
@ -195,7 +197,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
|
||||||
await sseTransport.StartAsync(
|
await sseTransport.StartAsync(
|
||||||
new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty).OrTimeout();
|
new Uri("http://fakeuri.org"), channelConnection, TransferMode.Text, connectionId: string.Empty).OrTimeout();
|
||||||
await eventStreamTcs.Task;
|
await eventStreamTcs.Task;
|
||||||
|
|
||||||
var sendTcs = new TaskCompletionSource<object>();
|
var sendTcs = new TaskCompletionSource<object>();
|
||||||
|
|
@ -241,7 +243,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
|
||||||
await sseTransport.StartAsync(
|
await sseTransport.StartAsync(
|
||||||
new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty).OrTimeout();
|
new Uri("http://fakeuri.org"), channelConnection, TransferMode.Text, connectionId: string.Empty).OrTimeout();
|
||||||
await eventStreamTcs.Task.OrTimeout();
|
await eventStreamTcs.Task.OrTimeout();
|
||||||
|
|
||||||
connectionToTransport.Out.TryComplete(null);
|
connectionToTransport.Out.TryComplete(null);
|
||||||
|
|
@ -270,7 +272,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
await sseTransport.StartAsync(
|
await sseTransport.StartAsync(
|
||||||
new Uri("http://fakeuri.org"), channelConnection, connectionId: string.Empty).OrTimeout();
|
new Uri("http://fakeuri.org"), channelConnection, TransferMode.Text, connectionId: string.Empty).OrTimeout();
|
||||||
|
|
||||||
var message = await transportToConnection.In.ReadAsync().AsTask().OrTimeout();
|
var message = await transportToConnection.In.ReadAsync().AsTask().OrTimeout();
|
||||||
Assert.Equal("3:abc", Encoding.ASCII.GetString(message));
|
Assert.Equal("3:abc", Encoding.ASCII.GetString(message));
|
||||||
|
|
@ -278,5 +280,58 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
await sseTransport.Running.OrTimeout();
|
await sseTransport.Running.OrTimeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(TransferMode.Text)]
|
||||||
|
[InlineData(TransferMode.Binary)]
|
||||||
|
public async Task SSETransportSetsTransferMode(TransferMode transferMode)
|
||||||
|
{
|
||||||
|
var mockHttpHandler = new Mock<HttpMessageHandler>();
|
||||||
|
mockHttpHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
|
||||||
|
.Returns<HttpRequestMessage, CancellationToken>(async (request, cancellationToken) =>
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
return new HttpResponseMessage { Content = new StringContent(string.Empty) };
|
||||||
|
});
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient(mockHttpHandler.Object))
|
||||||
|
{
|
||||||
|
var sseTransport = new ServerSentEventsTransport(httpClient);
|
||||||
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
Assert.Null(sseTransport.Mode);
|
||||||
|
await sseTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, transferMode, connectionId: string.Empty).OrTimeout();
|
||||||
|
Assert.Equal(TransferMode.Text, sseTransport.Mode);
|
||||||
|
await sseTransport.StopAsync().OrTimeout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SSETransportThrowsForInvalidTransferMode()
|
||||||
|
{
|
||||||
|
var mockHttpHandler = new Mock<HttpMessageHandler>();
|
||||||
|
mockHttpHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
|
||||||
|
.Returns<HttpRequestMessage, CancellationToken>(async (request, cancellationToken) =>
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
return new HttpResponseMessage { Content = new StringContent(string.Empty) };
|
||||||
|
});
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient(mockHttpHandler.Object))
|
||||||
|
{
|
||||||
|
var sseTransport = new ServerSentEventsTransport(httpClient);
|
||||||
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
var exception = await Assert.ThrowsAsync<ArgumentException>(() =>
|
||||||
|
sseTransport.StartAsync(new Uri("http://fakeuri.org"), null, TransferMode.Text | TransferMode.Binary, connectionId: string.Empty));
|
||||||
|
|
||||||
|
Assert.Contains("Invalid transfer mode.", exception.Message);
|
||||||
|
Assert.Equal("requestedTransferMode", exception.ParamName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Sockets.Client;
|
using Microsoft.AspNetCore.Sockets.Client;
|
||||||
using Microsoft.AspNetCore.Sockets.Internal.Formatters;
|
using Microsoft.AspNetCore.Sockets.Internal.Formatters;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
@ -34,6 +35,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
public ReadableChannel<byte[]> SentMessages => _sentMessages.In;
|
public ReadableChannel<byte[]> SentMessages => _sentMessages.In;
|
||||||
public WritableChannel<byte[]> ReceivedMessages => _receivedMessages.Out;
|
public WritableChannel<byte[]> ReceivedMessages => _receivedMessages.Out;
|
||||||
|
|
||||||
|
public IFeatureCollection Features { get; } = new FeatureCollection();
|
||||||
|
|
||||||
public TestConnection()
|
public TestConnection()
|
||||||
{
|
{
|
||||||
_receiveLoop = ReceiveLoopAsync(_receiveShutdownToken.Token);
|
_receiveLoop = ReceiveLoopAsync(_receiveShutdownToken.Token);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
||||||
using Microsoft.AspNetCore.Sockets;
|
using Microsoft.AspNetCore.Sockets;
|
||||||
|
using Microsoft.AspNetCore.Sockets.Features;
|
||||||
using Microsoft.AspNetCore.Sockets.Client;
|
using Microsoft.AspNetCore.Sockets.Client;
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
@ -78,6 +79,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
[ConditionalTheory]
|
[ConditionalTheory]
|
||||||
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2, SkipReason = "No WebSockets Client for this platform")]
|
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2, SkipReason = "No WebSockets Client for this platform")]
|
||||||
[MemberData(nameof(TransportTypes))]
|
[MemberData(nameof(TransportTypes))]
|
||||||
|
// TODO: transfer types
|
||||||
public async Task ConnectionCanSendAndReceiveMessages(TransportType transportType)
|
public async Task ConnectionCanSendAndReceiveMessages(TransportType transportType)
|
||||||
{
|
{
|
||||||
using (StartLog(out var loggerFactory, testName: $"ConnectionCanSendAndReceiveMessages_{transportType.ToString()}"))
|
using (StartLog(out var loggerFactory, testName: $"ConnectionCanSendAndReceiveMessages_{transportType.ToString()}"))
|
||||||
|
|
@ -88,6 +90,9 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
|
|
||||||
var url = _serverFixture.BaseUrl + "/echo";
|
var url = _serverFixture.BaseUrl + "/echo";
|
||||||
var connection = new HttpConnection(new Uri(url), transportType, loggerFactory);
|
var connection = new HttpConnection(new Uri(url), transportType, loggerFactory);
|
||||||
|
|
||||||
|
connection.Features.Set<ITransferModeFeature>(
|
||||||
|
new TransferModeFeature { TransferMode = TransferMode.Text });
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var receiveTcs = new TaskCompletionSource<string>();
|
var receiveTcs = new TaskCompletionSource<string>();
|
||||||
|
|
@ -163,6 +168,9 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
|
|
||||||
var url = _serverFixture.BaseUrl + "/echo";
|
var url = _serverFixture.BaseUrl + "/echo";
|
||||||
var connection = new HttpConnection(new Uri(url), loggerFactory);
|
var connection = new HttpConnection(new Uri(url), loggerFactory);
|
||||||
|
connection.Features.Set<ITransferModeFeature>(
|
||||||
|
new TransferModeFeature { TransferMode = TransferMode.Binary });
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var receiveTcs = new TaskCompletionSource<byte[]>();
|
var receiveTcs = new TaskCompletionSource<byte[]>();
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
using Microsoft.AspNetCore.SignalR.Tests.Common;
|
||||||
|
using Microsoft.AspNetCore.Sockets;
|
||||||
using Microsoft.AspNetCore.Sockets.Client;
|
using Microsoft.AspNetCore.Sockets.Client;
|
||||||
using Microsoft.AspNetCore.Sockets.Internal;
|
using Microsoft.AspNetCore.Sockets.Internal;
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
|
@ -40,7 +41,8 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
|
||||||
var webSocketsTransport = new WebSocketsTransport(loggerFactory);
|
var webSocketsTransport = new WebSocketsTransport(loggerFactory);
|
||||||
await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), channelConnection, connectionId: string.Empty).OrTimeout();
|
await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), channelConnection,
|
||||||
|
TransferMode.Binary, connectionId: string.Empty).OrTimeout();
|
||||||
await webSocketsTransport.StopAsync().OrTimeout();
|
await webSocketsTransport.StopAsync().OrTimeout();
|
||||||
await webSocketsTransport.Running.OrTimeout();
|
await webSocketsTransport.Running.OrTimeout();
|
||||||
}
|
}
|
||||||
|
|
@ -57,15 +59,18 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
|
||||||
var webSocketsTransport = new WebSocketsTransport(loggerFactory);
|
var webSocketsTransport = new WebSocketsTransport(loggerFactory);
|
||||||
await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), channelConnection, connectionId: string.Empty);
|
await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), channelConnection,
|
||||||
|
TransferMode.Binary, connectionId: string.Empty);
|
||||||
connectionToTransport.Out.TryComplete();
|
connectionToTransport.Out.TryComplete();
|
||||||
await webSocketsTransport.Running.OrTimeout();
|
await webSocketsTransport.Running.OrTimeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalFact]
|
[ConditionalTheory]
|
||||||
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2, SkipReason = "No WebSockets Client for this platform")]
|
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2, SkipReason = "No WebSockets Client for this platform")]
|
||||||
public async Task WebSocketsTransportStopsWhenConnectionClosedByTheServer()
|
[InlineData(TransferMode.Text)]
|
||||||
|
[InlineData(TransferMode.Binary)]
|
||||||
|
public async Task WebSocketsTransportStopsWhenConnectionClosedByTheServer(TransferMode transferMode)
|
||||||
{
|
{
|
||||||
using (StartLog(out var loggerFactory))
|
using (StartLog(out var loggerFactory))
|
||||||
{
|
{
|
||||||
|
|
@ -74,7 +79,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
|
||||||
var webSocketsTransport = new WebSocketsTransport(loggerFactory);
|
var webSocketsTransport = new WebSocketsTransport(loggerFactory);
|
||||||
await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), channelConnection, connectionId: string.Empty);
|
await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), channelConnection, transferMode, connectionId: string.Empty);
|
||||||
|
|
||||||
var sendTcs = new TaskCompletionSource<object>();
|
var sendTcs = new TaskCompletionSource<object>();
|
||||||
connectionToTransport.Out.TryWrite(new SendMessage(new byte[] { 0x42 }, sendTcs));
|
connectionToTransport.Out.TryWrite(new SendMessage(new byte[] { 0x42 }, sendTcs));
|
||||||
|
|
@ -86,5 +91,48 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
||||||
Assert.Equal(new byte[] { 0x42 }, buffer);
|
Assert.Equal(new byte[] { 0x42 }, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2, SkipReason = "No WebSockets Client for this platform")]
|
||||||
|
[InlineData(TransferMode.Text)]
|
||||||
|
[InlineData(TransferMode.Binary)]
|
||||||
|
public async Task WebSocketsTransportSetsTransferMode(TransferMode transferMode)
|
||||||
|
{
|
||||||
|
using (StartLog(out var loggerFactory))
|
||||||
|
{
|
||||||
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
|
||||||
|
var webSocketsTransport = new WebSocketsTransport(loggerFactory);
|
||||||
|
|
||||||
|
Assert.Null(webSocketsTransport.Mode);
|
||||||
|
await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/echo"), channelConnection,
|
||||||
|
transferMode, connectionId: string.Empty).OrTimeout();
|
||||||
|
Assert.Equal(transferMode, webSocketsTransport.Mode);
|
||||||
|
|
||||||
|
await webSocketsTransport.StopAsync().OrTimeout();
|
||||||
|
await webSocketsTransport.Running.OrTimeout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalFact]
|
||||||
|
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2, SkipReason = "No WebSockets Client for this platform")]
|
||||||
|
public async Task WebSocketsTransportThrowsForInvalidTransferMode()
|
||||||
|
{
|
||||||
|
using (StartLog(out var loggerFactory))
|
||||||
|
{
|
||||||
|
var connectionToTransport = Channel.CreateUnbounded<SendMessage>();
|
||||||
|
var transportToConnection = Channel.CreateUnbounded<byte[]>();
|
||||||
|
var channelConnection = new ChannelConnection<SendMessage, byte[]>(connectionToTransport, transportToConnection);
|
||||||
|
|
||||||
|
var webSocketsTransport = new WebSocketsTransport(loggerFactory);
|
||||||
|
var exception = await Assert.ThrowsAsync<ArgumentException>(() =>
|
||||||
|
webSocketsTransport.StartAsync(new Uri("http://fakeuri.org"), channelConnection, TransferMode.Text | TransferMode.Binary, connectionId: string.Empty));
|
||||||
|
|
||||||
|
Assert.Contains("Invalid transfer mode.", exception.Message);
|
||||||
|
Assert.Equal("requestedTransferMode", exception.ParamName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue