diff --git a/.travis.yml b/.travis.yml index 06281bb0ef..537cb2cac5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ addons: - libunwind8 branches: only: - - dev + - master - /^release\/.*$/ - /^(.*\/)?ci-.*$/ before_install: diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml index a19cee5885..86145193a5 100644 --- a/.vsts-pipelines/builds/ci-internal.yml +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -7,7 +7,7 @@ resources: - repository: buildtools type: git name: aspnet-BuildTools - ref: refs/heads/release/2.2 + ref: refs/heads/master phases: - template: .vsts-pipelines/templates/phases/default-build.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index 1cca5b68cc..bc06c7a25a 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -9,7 +9,7 @@ resources: type: github endpoint: DotNet-Bot GitHub Connection name: aspnet/BuildTools - ref: refs/heads/release/2.2 + ref: refs/heads/master phases: - template: .vsts-pipelines/templates/phases/default-build.yml@buildtools diff --git a/benchmarkapps/BenchmarkServer/signalr.json b/benchmarkapps/BenchmarkServer/signalr.json index 23c53f7088..d8d47bba67 100644 --- a/benchmarkapps/BenchmarkServer/signalr.json +++ b/benchmarkapps/BenchmarkServer/signalr.json @@ -3,7 +3,7 @@ "Client": "SignalR", "Source": { "Repository": "https://github.com/aspnet/SignalR.git", - "BranchOrCommit": "release/2.2", + "BranchOrCommit": "dev", "Project": "benchmarkapps/BenchmarkServer/BenchmarkServer.csproj" }, "Connections": 10, diff --git a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/DefaultHubDispatcherBenchmark.cs b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/DefaultHubDispatcherBenchmark.cs index 3da8b6d0cc..d7431ed28b 100644 --- a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/DefaultHubDispatcherBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/DefaultHubDispatcherBenchmark.cs @@ -54,6 +54,7 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks { public string Name { get; } public int Version => 1; + public int MinorVersion => 0; public TransferFormat TransferFormat { get; } public bool IsVersionSupported(int version) diff --git a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisHubLifetimeManagerBenchmark.cs b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisHubLifetimeManagerBenchmark.cs index 3e333ddd74..b0eea531bb 100644 --- a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisHubLifetimeManagerBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisHubLifetimeManagerBenchmark.cs @@ -177,6 +177,7 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks public string Name => _name; public int Version => _innerProtocol.Version; + public int MinorVersion => _innerProtocol.MinorVersion; public TransferFormat TransferFormat => _innerProtocol.TransferFormat; diff --git a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisProtocolBenchmark.cs b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisProtocolBenchmark.cs index 3008ed999c..1f72f922fe 100644 --- a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisProtocolBenchmark.cs +++ b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisProtocolBenchmark.cs @@ -126,6 +126,7 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks public string Name { get; } public int Version => 1; + public int MinorVersion => 0; public TransferFormat TransferFormat => TransferFormat.Text; diff --git a/build/dependencies.props b/build/dependencies.props index dd2ee7f9af..b085209c06 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,72 +5,72 @@ 0.10.13 3.1.0 - 2.2.0-preview1-34823 - 2.2.0-preview1-17102 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10015 1.7.3.4 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 4.5.0 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 4.6.0-preview1-26727-04 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 2.2.0-preview1-26618-02 15.6.1 4.7.49 2.0.3 11.0.2 1.2.6 - 4.5.0 - 4.5.0 - 4.5.1 - 4.5.0 + 4.6.0-preview1-26727-04 + 4.6.0-preview1-26727-04 + 4.6.0-preview1-26717-04 + 4.6.0-preview1-26727-04 3.1.1 4.3.0 - 4.5.1 - 4.5.0 - 4.5.1 + 4.6.0-preview1-26727-04 + 4.6.0-preview1-26727-04 + 4.6.0-preview1-26727-04 2.3.1 2.3.1 2.3.1 diff --git a/build/repo.props b/build/repo.props index fc909de537..472d056854 100644 --- a/build/repo.props +++ b/build/repo.props @@ -15,7 +15,6 @@ Internal.AspNetCore.Universe.Lineup - 2.2.0-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/clients/ts/signalr/src/HandshakeProtocol.ts b/clients/ts/signalr/src/HandshakeProtocol.ts index ba6906ef5f..eebc8fc57e 100644 --- a/clients/ts/signalr/src/HandshakeProtocol.ts +++ b/clients/ts/signalr/src/HandshakeProtocol.ts @@ -10,6 +10,7 @@ export interface HandshakeRequestMessage { export interface HandshakeResponseMessage { readonly error: string; + readonly minorVersion: number; } export class HandshakeProtocol { diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 28cd6a5b03..8c70cbad9f 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17102 -commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 +version:3.0.0-alpha1-10015 +commithash:3f36e5c2f061712f76f2766c435d2555681d5c55 diff --git a/korebuild.json b/korebuild.json index 78afb8c137..ce2e15a055 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,6 +1,6 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json", - "channel": "release/2.2", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsets": { "nodejs": { "required": true, diff --git a/run.ps1 b/run.ps1 index 3b27382468..34604c7175 100644 --- a/run.ps1 +++ b/run.ps1 @@ -52,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -192,7 +192,7 @@ if (!$DotNetHome) { else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute diff --git a/run.sh b/run.sh index 02aac15874..61f7a53385 100755 --- a/run.sh +++ b/run.sh @@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild diff --git a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs index 2ccf688ca0..47f4adf4c6 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs @@ -52,6 +52,7 @@ namespace Microsoft.AspNetCore.SignalR.Client // Transient state to a connection private ConnectionState _connectionState; + private int _serverProtocolMinorVersion; public event Func Closed; @@ -721,6 +722,8 @@ namespace Microsoft.AspNetCore.SignalR.Client $"Unable to complete handshake with the server due to an error: {message.Error}"); } + _serverProtocolMinorVersion = message.MinorVersion; + break; } } @@ -739,11 +742,12 @@ namespace Microsoft.AspNetCore.SignalR.Client } } } + + // shutdown if we're unable to read handshake // Ignore HubException because we throw it when we receive a handshake response with an error - // And we don't need to log that the handshake failed + // And because we already have the error, we don't need to log that the handshake failed catch (Exception ex) when (!(ex is HubException)) { - // shutdown if we're unable to read handshake Log.ErrorReceivingHandshakeResponse(_logger, ex); throw; } @@ -816,7 +820,7 @@ namespace Microsoft.AspNetCore.SignalR.Client finally { // The buffer was sliced up to where it was consumed, so we can just advance to the start. - // We mark examined as buffer.End so that if we didn't receive a full frame, we'll wait for more data + // We mark examined as `buffer.End` so that if we didn't receive a full frame, we'll wait for more data // before yielding the read again. connectionState.Connection.Transport.Input.AdvanceTo(buffer.Start, buffer.End); } @@ -865,7 +869,6 @@ namespace Microsoft.AspNetCore.SignalR.Client // There is no need to start a new task if there is no Closed event registered if (closed != null) { - // Fire-and-forget the closed event _ = RunClosedEvent(closed, connectionState.CloseException); } diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeProtocol.cs index 89e72f3ece..c661990524 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeProtocol.cs @@ -3,7 +3,9 @@ using System; using System.Buffers; +using System.Collections.Concurrent; using System.IO; +using System.Text; using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.SignalR.Internal; using Newtonsoft.Json; @@ -17,26 +19,31 @@ namespace Microsoft.AspNetCore.SignalR.Protocol { private const string ProtocolPropertyName = "protocol"; private const string ProtocolVersionPropertyName = "version"; + private const string MinorVersionPropertyName = "minorVersion"; private const string ErrorPropertyName = "error"; private const string TypePropertyName = "type"; - /// - /// The serialized representation of a success handshake. - /// - public static ReadOnlyMemory SuccessHandshakeData; + private static ConcurrentDictionary> _messageCache = new ConcurrentDictionary>(); - static HandshakeProtocol() + public static ReadOnlySpan GetSuccessfulHandshake(IHubProtocol protocol) { - var memoryBufferWriter = MemoryBufferWriter.Get(); - try + ReadOnlyMemory result; + if(!_messageCache.TryGetValue(protocol, out result)) { - WriteResponseMessage(HandshakeResponseMessage.Empty, memoryBufferWriter); - SuccessHandshakeData = memoryBufferWriter.ToArray(); - } - finally - { - MemoryBufferWriter.Return(memoryBufferWriter); + var memoryBufferWriter = MemoryBufferWriter.Get(); + try + { + WriteResponseMessage(new HandshakeResponseMessage(protocol.MinorVersion), memoryBufferWriter); + result = memoryBufferWriter.ToArray(); + _messageCache.TryAdd(protocol, result); + } + finally + { + MemoryBufferWriter.Return(memoryBufferWriter); + } } + + return result.Span; } /// @@ -87,6 +94,9 @@ namespace Microsoft.AspNetCore.SignalR.Protocol writer.WriteValue(responseMessage.Error); } + writer.WritePropertyName(MinorVersionPropertyName); + writer.WriteValue(responseMessage.MinorVersion); + writer.WriteEndObject(); writer.Flush(); } @@ -122,6 +132,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol JsonUtils.CheckRead(reader); JsonUtils.EnsureObjectStart(reader); + int? minorVersion = null; string error = null; var completed = false; @@ -141,6 +152,9 @@ namespace Microsoft.AspNetCore.SignalR.Protocol case ErrorPropertyName: error = JsonUtils.ReadAsString(reader, ErrorPropertyName); break; + case MinorVersionPropertyName: + minorVersion = JsonUtils.ReadAsInt32(reader, MinorVersionPropertyName); + break; default: reader.Skip(); break; @@ -154,7 +168,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol } }; - responseMessage = (error != null) ? new HandshakeResponseMessage(error) : HandshakeResponseMessage.Empty; + responseMessage = new HandshakeResponseMessage(minorVersion, error); return true; } } diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeResponseMessage.cs b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeResponseMessage.cs index 4288ea94e2..9e2454bbe9 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeResponseMessage.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeResponseMessage.cs @@ -11,20 +11,41 @@ namespace Microsoft.AspNetCore.SignalR.Protocol /// /// An empty response message with no error. /// - public static readonly HandshakeResponseMessage Empty = new HandshakeResponseMessage(null); + public static readonly HandshakeResponseMessage Empty = new HandshakeResponseMessage(error: null); /// /// Gets the optional error message. /// public string Error { get; } + /// + /// Highest minor protocol version that the server supports. + /// + public int MinorVersion { get; } + + /// + /// Initializes a new instance of the class. + /// An error response does need a minor version. Since the handshake has failed, any extra data will be ignored. + /// + /// Error encountered by the server, indicating why the handshake has failed. + public HandshakeResponseMessage(string error) : this(null, error) { } + + /// + /// Initializes a new instance of the class. + /// A reponse with a minor version indicates success, and doesn't require an error field. + /// + /// The highest protocol minor version that the server supports. + public HandshakeResponseMessage(int minorVersion) : this(minorVersion, null) { } + /// /// Initializes a new instance of the class. /// - /// An optional response error message. A null error message indicates a succesful handshake. - public HandshakeResponseMessage(string error) + /// Error encountered by the server, indicating why the handshake has failed. + /// The highest protocol minor version that the server supports. + public HandshakeResponseMessage(int? minorVersion, string error) { - // Note that a response with an empty string for error in the JSON is considered an errored response + // MinorVersion defaults to 0, because old servers don't send a minor version + MinorVersion = minorVersion ?? 0; Error = error; } } diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/IHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/IHubProtocol.cs index 7aaedc65fa..99b7fe5d36 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/IHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/IHubProtocol.cs @@ -18,10 +18,15 @@ namespace Microsoft.AspNetCore.SignalR.Protocol string Name { get; } /// - /// Gets the version of the protocol. + /// Gets the major version of the protocol. /// int Version { get; } + /// + /// Gets the minor version of the protocol. + /// + int MinorVersion { get; } + /// /// Gets the transfer format of the protocol. /// diff --git a/src/Microsoft.AspNetCore.SignalR.Common/breakingchanges.netcore.json b/src/Microsoft.AspNetCore.SignalR.Common/breakingchanges.netcore.json new file mode 100644 index 0000000000..3cd71f82e7 --- /dev/null +++ b/src/Microsoft.AspNetCore.SignalR.Common/breakingchanges.netcore.json @@ -0,0 +1,12 @@ +[ + { + "TypeId": "public static class Microsoft.AspNetCore.SignalR.Protocol.HandshakeProtocol", + "MemberId": "public static System.ReadOnlyMemory SuccessHandshakeData", + "Kind": "Removal" + }, + { + "TypeId": "public interface Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol", + "MemberId": "System.Int32 get_MinorVersion()", + "Kind": "Addition" + } +] \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.SignalR.Core/HubConnectionContext.cs b/src/Microsoft.AspNetCore.SignalR.Core/HubConnectionContext.cs index a67fa133df..5aaa164cea 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/HubConnectionContext.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/HubConnectionContext.cs @@ -301,10 +301,9 @@ namespace Microsoft.AspNetCore.SignalR try { - if (message == HandshakeResponseMessage.Empty) + if (message.Error == null) { - // success response is always an empty object so send cached data - _connectionContext.Transport.Output.Write(HandshakeProtocol.SuccessHandshakeData.Span); + _connectionContext.Transport.Output.Write(HandshakeProtocol.GetSuccessfulHandshake(Protocol)); } else { @@ -419,7 +418,8 @@ namespace Microsoft.AspNetCore.SignalR } Log.HandshakeComplete(_logger, Protocol.Name); - await WriteHandshakeResponseAsync(HandshakeResponseMessage.Empty); + + await WriteHandshakeResponseAsync(new HandshakeResponseMessage(Protocol.MinorVersion)); return true; } } diff --git a/src/Microsoft.AspNetCore.SignalR.Protocols.Json/Protocol/JsonHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Protocols.Json/Protocol/JsonHubProtocol.cs index e6ea079714..54400a2199 100644 --- a/src/Microsoft.AspNetCore.SignalR.Protocols.Json/Protocol/JsonHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Protocols.Json/Protocol/JsonHubProtocol.cs @@ -32,6 +32,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol private static readonly string ProtocolName = "json"; private static readonly int ProtocolVersion = 1; + private static readonly int ProtocolMinorVersion = 0; /// /// Gets the serializer used to serialize invocation arguments and return values. @@ -60,6 +61,9 @@ namespace Microsoft.AspNetCore.SignalR.Protocol /// public int Version => ProtocolVersion; + /// + public int MinorVersion => ProtocolMinorVersion; + /// public TransferFormat TransferFormat => TransferFormat.Text; diff --git a/src/Microsoft.AspNetCore.SignalR.Protocols.MessagePack/Protocol/MessagePackHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Protocols.MessagePack/Protocol/MessagePackHubProtocol.cs index 0b693605bf..6f6a76252e 100644 --- a/src/Microsoft.AspNetCore.SignalR.Protocols.MessagePack/Protocol/MessagePackHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Protocols.MessagePack/Protocol/MessagePackHubProtocol.cs @@ -29,13 +29,17 @@ namespace Microsoft.AspNetCore.SignalR.Protocol private static readonly string ProtocolName = "messagepack"; private static readonly int ProtocolVersion = 1; - + private static readonly int ProtocolMinorVersion = 0; + /// public string Name => ProtocolName; /// public int Version => ProtocolVersion; + /// + public int MinorVersion => ProtocolMinorVersion; + /// public TransferFormat TransferFormat => TransferFormat.Binary; diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/VersionJsonHubProtocol.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/VersionJsonHubProtocol.cs index 86766b088b..8c0e761386 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/VersionJsonHubProtocol.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/VersionJsonHubProtocol.cs @@ -25,6 +25,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public string Name => _innerProtocol.Name; public int Version => _version; public TransferFormat TransferFormat => _innerProtocol.TransferFormat; + public int MinorVersion => 0; // not used in this test class, just for interface conformance public bool TryParseMessage(ref ReadOnlySequence input, IInvocationBinder binder, out HubMessage message) { diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.Protocol.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.Protocol.cs index 642a897946..a24d6cf3ce 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.Protocol.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.Protocol.cs @@ -63,6 +63,28 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests } } + [Fact] + public async Task ClientIsOkayReceivingMinorVersionInHandshake() + { + // We're just testing that the client doesn't fail when a minor version is added to the handshake + // The client doesn't actually use that version anywhere yet so there's nothing else to test at this time + + var connection = new TestConnection(autoHandshake: false); + var hubConnection = CreateHubConnection(connection); + try + { + var startTask = hubConnection.StartAsync(); + var message = await connection.ReadHandshakeAndSendResponseAsync(56); + + await startTask; + } + finally + { + await hubConnection.DisposeAsync().OrTimeout(); + await connection.DisposeAsync().OrTimeout(); + } + } + [Fact] public async Task InvokeSendsAnInvocationMessage() { diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.cs index 4951413baf..c95fd91df8 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.cs @@ -169,6 +169,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public string Name => "MockHubProtocol"; public int Version => 1; + public int MinorVersion => 1; public TransferFormat TransferFormat => TransferFormat.Binary; diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/TestConnection.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/TestConnection.cs index fe979ef5a8..7309fdee70 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/TestConnection.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/TestConnection.cs @@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests return this; } - public async Task ReadHandshakeAndSendResponseAsync() + public async Task ReadHandshakeAndSendResponseAsync(int minorVersion = 0) { var s = await ReadSentTextMessageAsync(); @@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests var output = MemoryBufferWriter.Get(); try { - HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, output); + HandshakeProtocol.WriteResponseMessage(new HandshakeResponseMessage(minorVersion), output); response = output.ToArray(); } finally diff --git a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/HandshakeProtocolTests.cs b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/HandshakeProtocolTests.cs index c19b88e6c3..d74d6c4a64 100644 --- a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/HandshakeProtocolTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/HandshakeProtocolTests.cs @@ -38,6 +38,17 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol Assert.Equal(error, response.Error); } + [Theory] + [InlineData("{\"error\":\"\",\"minorVersion\":34}\u001e", 34)] + [InlineData("{\"error\":\"flump flump flump\",\"minorVersion\":112}\u001e", 112)] + public void ParsingResponseMessageGivesMinorVersion(string json, int version) + { + var message = new ReadOnlySequence(Encoding.UTF8.GetBytes(json)); + + Assert.True(HandshakeProtocol.TryParseResponseMessage(ref message, out var response)); + Assert.Equal(version, response.MinorVersion); + } + [Fact] public void ParsingHandshakeRequestNotCompleteReturnsFalse() { diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/DummyHubProtocol.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/DummyHubProtocol.cs index 74ca4eaf04..8ce5aa6029 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/DummyHubProtocol.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/DummyHubProtocol.cs @@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public string Name { get; } public int Version => 1; + public int MinorVersion => 0; public TransferFormat TransferFormat => TransferFormat.Text; public DummyHubProtocol(string name, Action onWrite = null) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs index 371307737f..c76ef5e892 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests private List<(Action handler, object state)> _heartbeatHandlers; private static int _id; - private readonly IHubProtocol _protocol; + private IHubProtocol _protocol; private readonly IInvocationBinder _invocationBinder; private readonly CancellationTokenSource _cts; diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTestUtils/Utils.cs b/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTestUtils/Utils.cs index 3e041bd509..294ec7922f 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTestUtils/Utils.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTestUtils/Utils.cs @@ -64,9 +64,9 @@ namespace Microsoft.AspNetCore.SignalR.Tests return services.BuildServiceProvider(); } - public static Connections.ConnectionHandler GetHubConnectionHandler(Type hubType) + public static Connections.ConnectionHandler GetHubConnectionHandler(Type hubType, Action addServices = null) { - var serviceProvider = CreateServiceProvider(); + var serviceProvider = CreateServiceProvider(addServices); return (Connections.ConnectionHandler)serviceProvider.GetService(GetConnectionHandlerType(hubType)); } } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.cs index 02a5146e02..04156ad03b 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.cs @@ -2381,6 +2381,30 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } + [Fact] + public async Task ServerReportsProtocolMinorVersion() + { + var testProtocol = new Mock(); + testProtocol.Setup(m => m.Name).Returns("CustomProtocol"); + testProtocol.Setup(m => m.MinorVersion).Returns(112); + testProtocol.Setup(m => m.IsVersionSupported(It.IsAny())).Returns(true); + testProtocol.Setup(m => m.TransferFormat).Returns(TransferFormat.Binary); + + var connectionHandler = HubConnectionHandlerTestUtils.GetHubConnectionHandler(typeof(HubT), + (services) => services.AddSingleton(testProtocol.Object)); + + using (var client = new TestClient(protocol: testProtocol.Object)) + { + var connectionHandlerTask = await client.ConnectAsync(connectionHandler); + + Assert.NotNull(client.HandshakeResponseMessage); + Assert.Equal(112, client.HandshakeResponseMessage.MinorVersion); + + client.Dispose(); + await connectionHandlerTask.OrTimeout(); + } + } + private class CustomHubActivator : IHubActivator where THub : Hub { public int ReleaseCount; diff --git a/version.props b/version.props index 6bbf74dd35..4ef0f74454 100644 --- a/version.props +++ b/version.props @@ -1,8 +1,8 @@ - + - 1.1.0 0.1.0-preview1 - preview1 + 3.0.0 + alpha1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000