diff --git a/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs b/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs index 7795798a75..503101f77c 100644 --- a/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs +++ b/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs @@ -13,22 +13,22 @@ namespace Microsoft.AspNetCore.Http.Connections { public static class NegotiateProtocol { - // Use C#7.3's ReadOnlySpan optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/ private const string ConnectionIdPropertyName = "connectionId"; - private static ReadOnlySpan ConnectionIdPropertyNameBytes => new byte[] { (byte)'c', (byte)'o', (byte)'n', (byte)'n', (byte)'e', (byte)'c', (byte)'t', (byte)'i', (byte)'o', (byte)'n', (byte)'I', (byte)'d' }; + private static JsonEncodedText ConnectionIdPropertyNameBytes = JsonEncodedText.Encode(ConnectionIdPropertyName); private const string UrlPropertyName = "url"; - private static ReadOnlySpan UrlPropertyNameBytes => new byte[] { (byte)'u', (byte)'r', (byte)'l' }; + private static JsonEncodedText UrlPropertyNameBytes = JsonEncodedText.Encode(UrlPropertyName); private const string AccessTokenPropertyName = "accessToken"; - private static ReadOnlySpan AccessTokenPropertyNameBytes => new byte[] { (byte)'a', (byte)'c', (byte)'c', (byte)'e', (byte)'s', (byte)'s', (byte)'T', (byte)'o', (byte)'k', (byte)'e', (byte)'n' }; + private static JsonEncodedText AccessTokenPropertyNameBytes = JsonEncodedText.Encode(AccessTokenPropertyName); private const string AvailableTransportsPropertyName = "availableTransports"; - private static ReadOnlySpan AvailableTransportsPropertyNameBytes => new byte[] { (byte)'a', (byte)'v', (byte)'a', (byte)'i', (byte)'l', (byte)'a', (byte)'b', (byte)'l', (byte)'e', (byte)'T', (byte)'r', (byte)'a', (byte)'n', (byte)'s', (byte)'p', (byte)'o', (byte)'r', (byte)'t', (byte)'s' }; + private static JsonEncodedText AvailableTransportsPropertyNameBytes = JsonEncodedText.Encode(AvailableTransportsPropertyName); private const string TransportPropertyName = "transport"; - private static ReadOnlySpan TransportPropertyNameBytes => new byte[] { (byte)'t', (byte)'r', (byte)'a', (byte)'n', (byte)'s', (byte)'p', (byte)'o', (byte)'r', (byte)'t' }; + private static JsonEncodedText TransportPropertyNameBytes = JsonEncodedText.Encode(TransportPropertyName); private const string TransferFormatsPropertyName = "transferFormats"; - private static ReadOnlySpan TransferFormatsPropertyNameBytes => new byte[] { (byte)'t', (byte)'r', (byte)'a', (byte)'n', (byte)'s', (byte)'f', (byte)'e', (byte)'r', (byte)'F', (byte)'o', (byte)'r', (byte)'m', (byte)'a', (byte)'t', (byte)'s' }; + private static JsonEncodedText TransferFormatsPropertyNameBytes = JsonEncodedText.Encode(TransferFormatsPropertyName); private const string ErrorPropertyName = "error"; - private static ReadOnlySpan ErrorPropertyNameBytes => new byte[] { (byte)'e', (byte)'r', (byte)'r', (byte)'o', (byte)'r' }; + private static JsonEncodedText ErrorPropertyNameBytes = JsonEncodedText.Encode(ErrorPropertyName); + // Use C#7.3's ReadOnlySpan optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/ // Used to detect ASP.NET SignalR Server connection attempt private static ReadOnlySpan ProtocolVersionPropertyNameBytes => new byte[] { (byte)'P', (byte)'r', (byte)'o', (byte)'t', (byte)'o', (byte)'c', (byte)'o', (byte)'l', (byte)'V', (byte)'e', (byte)'r', (byte)'s', (byte)'i', (byte)'o', (byte)'n' }; @@ -120,19 +120,19 @@ namespace Microsoft.AspNetCore.Http.Connections switch (reader.TokenType) { case JsonTokenType.PropertyName: - if (reader.TextEquals(UrlPropertyNameBytes)) + if (reader.TextEquals(UrlPropertyNameBytes.EncodedUtf8Bytes)) { url = reader.ReadAsString(UrlPropertyName); } - else if (reader.TextEquals(AccessTokenPropertyNameBytes)) + else if (reader.TextEquals(AccessTokenPropertyNameBytes.EncodedUtf8Bytes)) { accessToken = reader.ReadAsString(AccessTokenPropertyName); } - else if (reader.TextEquals(ConnectionIdPropertyNameBytes)) + else if (reader.TextEquals(ConnectionIdPropertyNameBytes.EncodedUtf8Bytes)) { connectionId = reader.ReadAsString(ConnectionIdPropertyName); } - else if (reader.TextEquals(AvailableTransportsPropertyNameBytes)) + else if (reader.TextEquals(AvailableTransportsPropertyNameBytes.EncodedUtf8Bytes)) { reader.CheckRead(); reader.EnsureArrayStart(); @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Http.Connections } } } - else if (reader.TextEquals(ErrorPropertyNameBytes)) + else if (reader.TextEquals(ErrorPropertyNameBytes.EncodedUtf8Bytes)) { error = reader.ReadAsString(ErrorPropertyName); } @@ -221,11 +221,11 @@ namespace Microsoft.AspNetCore.Http.Connections case JsonTokenType.PropertyName: var memberName = reader.ValueSpan; - if (memberName.SequenceEqual(TransportPropertyNameBytes)) + if (memberName.SequenceEqual(TransportPropertyNameBytes.EncodedUtf8Bytes)) { availableTransport.Transport = reader.ReadAsString(TransportPropertyName); } - else if (memberName.SequenceEqual(TransferFormatsPropertyNameBytes)) + else if (memberName.SequenceEqual(TransferFormatsPropertyNameBytes.EncodedUtf8Bytes)) { reader.CheckRead(); reader.EnsureArrayStart(); diff --git a/src/SignalR/common/Protocols.Json/src/Protocol/JsonHubProtocol.cs b/src/SignalR/common/Protocols.Json/src/Protocol/JsonHubProtocol.cs index e244479ecf..34c8764214 100644 --- a/src/SignalR/common/Protocols.Json/src/Protocol/JsonHubProtocol.cs +++ b/src/SignalR/common/Protocols.Json/src/Protocol/JsonHubProtocol.cs @@ -20,25 +20,24 @@ namespace Microsoft.AspNetCore.SignalR.Protocol /// public sealed class JsonHubProtocol : IHubProtocol { - // Use C#7.3's ReadOnlySpan optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/ private const string ResultPropertyName = "result"; - private static ReadOnlySpan ResultPropertyNameBytes => new byte[] { (byte)'r', (byte)'e', (byte)'s', (byte)'u', (byte)'l', (byte)'t' }; + private static JsonEncodedText ResultPropertyNameBytes = JsonEncodedText.Encode(ResultPropertyName); private const string ItemPropertyName = "item"; - private static ReadOnlySpan ItemPropertyNameBytes => new byte[] { (byte)'i', (byte)'t', (byte)'e', (byte)'m' }; + private static JsonEncodedText ItemPropertyNameBytes = JsonEncodedText.Encode(ItemPropertyName); private const string InvocationIdPropertyName = "invocationId"; - private static ReadOnlySpan InvocationIdPropertyNameBytes => new byte[] { (byte)'i', (byte)'n', (byte)'v', (byte)'o', (byte)'c', (byte)'a', (byte)'t', (byte)'i', (byte)'o', (byte)'n', (byte)'I', (byte)'d' }; + private static JsonEncodedText InvocationIdPropertyNameBytes = JsonEncodedText.Encode(InvocationIdPropertyName); private const string StreamIdsPropertyName = "streamIds"; - private static ReadOnlySpan StreamIdsPropertyNameBytes => new byte[] { (byte)'s', (byte)'t', (byte)'r', (byte)'e', (byte)'a', (byte)'m', (byte)'I', (byte)'d', (byte)'s' }; + private static JsonEncodedText StreamIdsPropertyNameBytes = JsonEncodedText.Encode(StreamIdsPropertyName); private const string TypePropertyName = "type"; - private static ReadOnlySpan TypePropertyNameBytes => new byte[] { (byte)'t', (byte)'y', (byte)'p', (byte)'e' }; + private static JsonEncodedText TypePropertyNameBytes = JsonEncodedText.Encode(TypePropertyName); private const string ErrorPropertyName = "error"; - private static ReadOnlySpan ErrorPropertyNameBytes => new byte[] { (byte)'e', (byte)'r', (byte)'r', (byte)'o', (byte)'r' }; + private static JsonEncodedText ErrorPropertyNameBytes = JsonEncodedText.Encode(ErrorPropertyName); private const string TargetPropertyName = "target"; - private static ReadOnlySpan TargetPropertyNameBytes => new byte[] { (byte)'t', (byte)'a', (byte)'r', (byte)'g', (byte)'e', (byte)'t' }; + private static JsonEncodedText TargetPropertyNameBytes = JsonEncodedText.Encode(TargetPropertyName); private const string ArgumentsPropertyName = "arguments"; - private static ReadOnlySpan ArgumentsPropertyNameBytes => new byte[] { (byte)'a', (byte)'r', (byte)'g', (byte)'u', (byte)'m', (byte)'e', (byte)'n', (byte)'t', (byte)'s' }; + private static JsonEncodedText ArgumentsPropertyNameBytes = JsonEncodedText.Encode(ArgumentsPropertyName); private const string HeadersPropertyName = "headers"; - private static ReadOnlySpan HeadersPropertyNameBytes => new byte[] { (byte)'h', (byte)'e', (byte)'a', (byte)'d', (byte)'e', (byte)'r', (byte)'s' }; + private static JsonEncodedText HeadersPropertyNameBytes = JsonEncodedText.Encode(HeadersPropertyName); private static readonly string ProtocolName = "json"; private static readonly int ProtocolVersion = 1; @@ -144,7 +143,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol switch (reader.TokenType) { case JsonTokenType.PropertyName: - if (reader.TextEquals(TypePropertyNameBytes)) + if (reader.TextEquals(TypePropertyNameBytes.EncodedUtf8Bytes)) { type = reader.ReadAsInt32(TypePropertyName); @@ -153,11 +152,11 @@ namespace Microsoft.AspNetCore.SignalR.Protocol throw new InvalidDataException($"Expected '{TypePropertyName}' to be of type {JsonTokenType.Number}."); } } - else if (reader.TextEquals(InvocationIdPropertyNameBytes)) + else if (reader.TextEquals(InvocationIdPropertyNameBytes.EncodedUtf8Bytes)) { invocationId = reader.ReadAsString(InvocationIdPropertyName); } - else if (reader.TextEquals(StreamIdsPropertyNameBytes)) + else if (reader.TextEquals(StreamIdsPropertyNameBytes.EncodedUtf8Bytes)) { reader.CheckRead(); @@ -177,15 +176,15 @@ namespace Microsoft.AspNetCore.SignalR.Protocol streamIds = newStreamIds.ToArray(); } - else if (reader.TextEquals(TargetPropertyNameBytes)) + else if (reader.TextEquals(TargetPropertyNameBytes.EncodedUtf8Bytes)) { target = reader.ReadAsString(TargetPropertyName); } - else if (reader.TextEquals(ErrorPropertyNameBytes)) + else if (reader.TextEquals(ErrorPropertyNameBytes.EncodedUtf8Bytes)) { error = reader.ReadAsString(ErrorPropertyName); } - else if (reader.TextEquals(ResultPropertyNameBytes)) + else if (reader.TextEquals(ResultPropertyNameBytes.EncodedUtf8Bytes)) { hasResult = true; @@ -204,7 +203,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol result = BindType(token.RootElement, returnType); } } - else if (reader.TextEquals(ItemPropertyNameBytes)) + else if (reader.TextEquals(ItemPropertyNameBytes.EncodedUtf8Bytes)) { reader.CheckRead(); @@ -233,7 +232,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol return new StreamBindingFailureMessage(id, ExceptionDispatchInfo.Capture(ex)); } } - else if (reader.TextEquals(ArgumentsPropertyNameBytes)) + else if (reader.TextEquals(ArgumentsPropertyNameBytes.EncodedUtf8Bytes)) { reader.CheckRead(); @@ -272,7 +271,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol } } } - else if (reader.TextEquals(HeadersPropertyNameBytes)) + else if (reader.TextEquals(HeadersPropertyNameBytes.EncodedUtf8Bytes)) { reader.CheckRead(); headers = ReadHeaders(ref reader); @@ -516,7 +515,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol else if (message.HasResult) { using var token = GetParsedObject(message.Result, message.Result?.GetType()); - token.RootElement.WriteAsProperty(ResultPropertyNameBytes, writer); + token.RootElement.WriteAsProperty(ResultPropertyNameBytes.EncodedUtf8Bytes, writer); } } @@ -530,7 +529,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol WriteInvocationId(message, writer); using var token = GetParsedObject(message.Item, message.Item?.GetType()); - token.RootElement.WriteAsProperty(ItemPropertyNameBytes, writer); + token.RootElement.WriteAsProperty(ItemPropertyNameBytes.EncodedUtf8Bytes, writer); } private void WriteInvocationMessage(InvocationMessage message, Utf8JsonWriter writer) diff --git a/src/SignalR/common/SignalR.Common/src/Protocol/HandshakeProtocol.cs b/src/SignalR/common/SignalR.Common/src/Protocol/HandshakeProtocol.cs index 7aa032d9e2..67c339f0eb 100644 --- a/src/SignalR/common/SignalR.Common/src/Protocol/HandshakeProtocol.cs +++ b/src/SignalR/common/SignalR.Common/src/Protocol/HandshakeProtocol.cs @@ -9,7 +9,6 @@ using System.IO; using System.Text; using System.Text.Json; using Microsoft.AspNetCore.Internal; -using Microsoft.AspNetCore.SignalR.Internal; namespace Microsoft.AspNetCore.SignalR.Protocol { @@ -18,15 +17,14 @@ namespace Microsoft.AspNetCore.SignalR.Protocol /// public static class HandshakeProtocol { - // Use C#7.3's ReadOnlySpan optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/ private const string ProtocolPropertyName = "protocol"; - private static ReadOnlySpan ProtocolPropertyNameBytes => new byte[] { (byte)'p', (byte)'r', (byte)'o', (byte)'t', (byte)'o', (byte)'c', (byte)'o', (byte)'l' }; + private static JsonEncodedText ProtocolPropertyNameBytes = JsonEncodedText.Encode(ProtocolPropertyName); private const string ProtocolVersionPropertyName = "version"; - private static ReadOnlySpan ProtocolVersionPropertyNameBytes => new byte[] { (byte)'v', (byte)'e', (byte)'r', (byte)'s', (byte)'i', (byte)'o', (byte)'n' }; + private static JsonEncodedText ProtocolVersionPropertyNameBytes = JsonEncodedText.Encode(ProtocolVersionPropertyName); private const string ErrorPropertyName = "error"; - private static ReadOnlySpan ErrorPropertyNameBytes => new byte[] { (byte)'e', (byte)'r', (byte)'r', (byte)'o', (byte)'r' }; + private static JsonEncodedText ErrorPropertyNameBytes = JsonEncodedText.Encode(ErrorPropertyName); private const string TypePropertyName = "type"; - private static ReadOnlySpan TypePropertyNameBytes => new byte[] { (byte)'t', (byte)'y', (byte)'p', (byte)'e' }; + private static JsonEncodedText TypePropertyNameBytes = JsonEncodedText.Encode(TypePropertyName); private static ConcurrentDictionary> _messageCache = new ConcurrentDictionary>(); @@ -135,13 +133,13 @@ namespace Microsoft.AspNetCore.SignalR.Protocol { if (reader.TokenType == JsonTokenType.PropertyName) { - if (reader.TextEquals(TypePropertyNameBytes)) + if (reader.TextEquals(TypePropertyNameBytes.EncodedUtf8Bytes)) { // a handshake response does not have a type // check the incoming message was not any other type of message throw new InvalidDataException("Expected a handshake response from the server."); } - else if (reader.TextEquals(ErrorPropertyNameBytes)) + else if (reader.TextEquals(ErrorPropertyNameBytes.EncodedUtf8Bytes)) { error = reader.ReadAsString(ErrorPropertyName); } @@ -190,11 +188,11 @@ namespace Microsoft.AspNetCore.SignalR.Protocol { if (reader.TokenType == JsonTokenType.PropertyName) { - if (reader.TextEquals(ProtocolPropertyNameBytes)) + if (reader.TextEquals(ProtocolPropertyNameBytes.EncodedUtf8Bytes)) { protocol = reader.ReadAsString(ProtocolPropertyName); } - else if (reader.TextEquals(ProtocolVersionPropertyNameBytes)) + else if (reader.TextEquals(ProtocolVersionPropertyNameBytes.EncodedUtf8Bytes)) { protocolVersion = reader.ReadAsInt32(ProtocolVersionPropertyName); }