Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
xingsy97 committed Oct 31, 2024
1 parent 87f1a66 commit d0e4d1d
Show file tree
Hide file tree
Showing 19 changed files with 87 additions and 89 deletions.
4 changes: 2 additions & 2 deletions src/Microsoft.Azure.SignalR.Common/Auth/AuthUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ public static string GenerateAccessToken(
return jwtToken;
}

public static string GenerateRequestId()
public static string GenerateRequestId(string traceIdentifier)
{
return Convert.ToBase64String(BitConverter.GetBytes(Stopwatch.GetTimestamp()));
return $"{traceIdentifier}-{Convert.ToBase64String(BitConverter.GetBytes(Stopwatch.GetTimestamp()))}";
}
}
}
4 changes: 0 additions & 4 deletions src/Microsoft.Azure.SignalR.Common/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,6 @@ public static class QueryParameter
public const string OriginalPath = "asrs.op";

public const string ConnectionRequestId = "asrs_request_id";

public const string RequestCulture = "asrs_lang";

public const string RequestUICulture = "asrs_ui_lang";
}

public static class CustomizedPingTimer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;

namespace Microsoft.Azure.SignalR;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ namespace Microsoft.Azure.SignalR;

internal interface IConnectionRequestIdProvider
{
string GetRequestId();
string GetRequestId(string traceIdentifier);
}

internal class DefaultConnectionRequestIdProvider : IConnectionRequestIdProvider
{
public string GetRequestId()
public string GetRequestId(string traceIdentifier)
{
return AuthUtility.GenerateRequestId();
return AuthUtility.GenerateRequestId(traceIdentifier);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ public bool AbortOnClose

private CancellationToken OutgoingAborted => _abortOutgoingCts.Token;

public string RequestId { get; set; }

public ClientConnectionContext(OpenConnectionMessage serviceMessage,
Action<HttpContext> configureContext = null,
PipeOptions transportPipeOptions = null,
Expand Down Expand Up @@ -492,22 +494,17 @@ internal void ClearBufferedMessages()
_bufferedMessages.Clear();
}

private static void ProcessQuery(string queryString, out string originalPath)
private void ProcessQuery(string queryString, out string originalPath)
{
originalPath = string.Empty;
var query = QueryHelpers.ParseNullableQuery(queryString);
if (query == null)
{
return;
}

if (query.TryGetValue(Constants.QueryParameter.RequestCulture, out var culture))
{
SetCurrentThreadCulture(culture.FirstOrDefault());
}
if (query.TryGetValue(Constants.QueryParameter.RequestUICulture, out var uiCulture))
if (query.TryGetValue(Constants.QueryParameter.ConnectionRequestId, out var connectionRequestId))
{
SetCurrentThreadUiCulture(uiCulture.FirstOrDefault());
RequestId = connectionRequestId;
}
if (query.TryGetValue(Constants.QueryParameter.OriginalPath, out var path))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ private static ISignalRServerBuilder AddAzureSignalRCore(this ISignalRServerBuil
.AddSingleton(typeof(IServiceEndpointManager), typeof(ServiceEndpointManager))
.AddSingleton(typeof(IServerNameProvider), typeof(DefaultServerNameProvider))
.AddSingleton(typeof(IBlazorDetector), typeof(DefaultBlazorDetector))
.AddSingleton(typeof(ICultureInfoManager), typeof(DefaultCultureInfoManager))
.AddSingleton(typeof(ServiceHubDispatcher<>))
.AddSingleton(typeof(ServerLifetimeManager))
.AddSingleton(typeof(AzureSignalRMarkerService))
Expand Down
5 changes: 4 additions & 1 deletion src/Microsoft.Azure.SignalR/HubHost/HeartBeat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ internal class HeartBeat : BackgroundService
private static readonly TimeSpan HeartbeatTickRate = TimeSpan.FromSeconds(1);

private readonly IClientConnectionManager _connectionManager;
private readonly ICultureInfoManager _cultureInfoManager;

private readonly TimerAwaitable _nextHeartbeat;

public HeartBeat(IClientConnectionManager connectionManager)
public HeartBeat(IClientConnectionManager connectionManager, ICultureInfoManager cultureInfoManager)
{
_connectionManager = connectionManager;
_cultureInfoManager = cultureInfoManager;
_nextHeartbeat = new TimerAwaitable(HeartbeatTickRate, HeartbeatTickRate);
}

Expand Down Expand Up @@ -50,6 +52,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
(connection as ClientConnectionContext).TickHeartbeat();
}
_cultureInfoManager.Cleanup();
}
}
}
Expand Down
27 changes: 11 additions & 16 deletions src/Microsoft.Azure.SignalR/HubHost/NegotiateHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ internal class NegotiateHandler<THub> where THub : Hub
#if NET6_0_OR_GREATER
private readonly HttpConnectionDispatcherOptions _dispatcherOptions;
#endif
private readonly ICultureInfoManager _cultureInfoManager;

public NegotiateHandler(
IOptions<HubOptions> globalHubOptions,
Expand All @@ -52,7 +53,8 @@ public NegotiateHandler(
#if NET6_0_OR_GREATER
EndpointDataSource endpointDataSource,
#endif
ILogger<NegotiateHandler<THub>> logger)
ILogger<NegotiateHandler<THub>> logger,
ICultureInfoManager cultureInfoManager)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_endpointManager = endpointManager ?? throw new ArgumentNullException(nameof(endpointManager));
Expand All @@ -73,14 +75,15 @@ public NegotiateHandler(
#if NET6_0_OR_GREATER
_dispatcherOptions = GetDispatcherOptions(endpointDataSource, typeof(THub));
#endif
cultureInfoManager = _cultureInfoManager ?? throw new ArgumentNullException(nameof(cultureInfoManager));
}

public async Task<NegotiationResponse> Process(HttpContext context)
{
var claims = BuildClaims(context);
var request = context.Request;
var cultureName = context.Features.Get<IRequestCultureFeature>()?.RequestCulture.Culture.Name;
var uiCultureName = context.Features.Get<IRequestCultureFeature>()?.RequestCulture.UICulture.Name;
var culture = context.Features.Get<IRequestCultureFeature>()?.RequestCulture.Culture;
var uiCulture = context.Features.Get<IRequestCultureFeature>()?.RequestCulture.UICulture;
var originalPath = GetOriginalPath(request.Path);
var provider = _endpointManager.GetEndpointProvider(_router.GetNegotiateEndpoint(context, _endpointManager.GetEndpoints(_hubName)));

Expand All @@ -89,12 +92,14 @@ public async Task<NegotiationResponse> Process(HttpContext context)
return null;
}

var clientRequestId = _connectionRequestIdProvider.GetRequestId(context.TraceIdentifier);
var queryString = GetQueryString(
request.QueryString.HasValue ? request.QueryString.Value.Substring(1) : null,
cultureName,
uiCultureName
clientRequestId
);

_cultureInfoManager.TryAddCulture(clientRequestId, culture, uiCulture);

return new NegotiationResponse
{
Url = provider.GetClientEndpoint(_hubName, originalPath, queryString),
Expand All @@ -104,24 +109,14 @@ public async Task<NegotiationResponse> Process(HttpContext context)
};
}

private string GetQueryString(string originalQueryString, string cultureName, string uiCultureName)
private string GetQueryString(string originalQueryString, string clientRequestId)
{
var clientRequestId = _connectionRequestIdProvider.GetRequestId();
if (clientRequestId != null)
{
clientRequestId = WebUtility.UrlEncode(clientRequestId);
}

var queryString = $"{Constants.QueryParameter.ConnectionRequestId}={clientRequestId}";
if (!string.IsNullOrEmpty(cultureName))
{
queryString += $"&{Constants.QueryParameter.RequestCulture}={cultureName}";
}
if (!string.IsNullOrEmpty(uiCultureName))
{
queryString += $"&{Constants.QueryParameter.RequestUICulture}={uiCultureName}";
}

return originalQueryString != null
? $"{originalQueryString}&{queryString}"
: queryString;
Expand Down
4 changes: 3 additions & 1 deletion src/Microsoft.Azure.SignalR/HubHost/ServiceHubDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ internal class ServiceHubDispatcher<THub> where THub : Hub
private readonly IServiceEndpointManager _serviceEndpointManager;
private readonly IServiceConnectionManager<THub> _serviceConnectionManager;
private readonly IClientConnectionManager _clientConnectionManager;
private readonly ICultureInfoManager _cultureInfoManager;
private readonly IServiceProtocol _serviceProtocol;
private readonly IClientConnectionFactory _clientConnectionFactory;
private readonly IEndpointRouter _router;
Expand Down Expand Up @@ -198,7 +199,8 @@ internal virtual ServiceConnectionFactory GetServiceConnectionFactory(
_nameProvider,
_serviceEventHandler,
_clientInvocationManager,
_hubProtocolResolver)
_hubProtocolResolver,
_cultureInfoManager)
{
ConfigureContext = contextConfig,
ShutdownMode = _options.GracefulShutdown.Mode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ private static class Log
private static readonly Action<ILogger, int, string, Exception> _closingClientConnections =
LoggerMessage.Define<int, string>(LogLevel.Information, new EventId(25, "ClosingClientConnections"), "Closing {ClientCount} client connection(s) for server connection {ServerConnectionId}.");

private static readonly Action<ILogger, string, Exception> _applyCultureInfoFailed =
LoggerMessage.Define<string>(LogLevel.Information, new EventId(26, "ApplyCultureInfoFailed"), "Error applying culture info for connection request id {requestId}.");

public static void WaitingForTransport(ILogger logger)
{
_waitingForTransport(logger, null);
Expand Down Expand Up @@ -93,6 +96,11 @@ public static void ClosingClientConnections(ILogger logger, int clientCount, str
_closingClientConnections(logger, clientCount, serverConnectionId, null);
}

public static void FailedToApplyCultureInfo(ILogger logger, string requestId)
{
_applyCultureInfoFailed(logger, requestId, null);
}

public static void FailedToCleanupConnections(ILogger logger, Exception exception)
{
_failedToCleanupConnections(logger, exception);
Expand Down
11 changes: 11 additions & 0 deletions src/Microsoft.Azure.SignalR/ServerConnections/ServiceConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
Expand Down Expand Up @@ -45,6 +46,8 @@ internal partial class ServiceConnection : ServiceConnectionBase

private readonly IHubProtocolResolver _hubProtocolResolver;

private readonly ICultureInfoManager _cultureInfoManager;

public Action<HttpContext> ConfigureContext { get; set; }

public ServiceConnection(IServiceProtocol serviceProtocol,
Expand All @@ -60,6 +63,7 @@ public ServiceConnection(IServiceProtocol serviceProtocol,
IServiceEventHandler serviceEventHandler,
IClientInvocationManager clientInvocationManager,
IHubProtocolResolver hubProtocolResolver,
ICultureInfoManager cultureInfoManager,
ServiceConnectionType connectionType = ServiceConnectionType.Default,
GracefulShutdownMode mode = GracefulShutdownMode.Off,
bool allowStatefulReconnects = false)
Expand All @@ -81,6 +85,7 @@ public ServiceConnection(IServiceProtocol serviceProtocol,
_clientConnectionFactory = clientConnectionFactory;
_clientInvocationManager = clientInvocationManager;
_hubProtocolResolver = hubProtocolResolver;
_cultureInfoManager = cultureInfoManager;
}

public override bool TryAddClientConnection(IClientConnection connection)
Expand Down Expand Up @@ -149,6 +154,12 @@ protected override Task OnClientConnectedAsync(OpenConnectionMessage message)
connection.ServiceConnection = this;

connection.Features.Set<IConnectionMigrationFeature>(null);

if (!_cultureInfoManager.TryApplyCulture(connection.RequestId))
{
Log.FailedToApplyCultureInfo(Logger, connection.RequestId);
}

if (message.Headers.TryGetValue(Constants.AsrsMigrateFrom, out var from))
{
connection.Features.Set<IConnectionMigrationFeature>(new ConnectionMigrationFeature(from, ServerId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ internal class ServiceConnectionFactory : IServiceConnectionFactory

private readonly IHubProtocolResolver _hubProtocolResolver;

private readonly ICultureInfoManager _cultureInfoManager;

public GracefulShutdownMode ShutdownMode { get; set; } = GracefulShutdownMode.Off;

public bool AllowStatefulReconnects { get; set; }
Expand All @@ -45,7 +47,8 @@ public ServiceConnectionFactory(
IServerNameProvider nameProvider,
IServiceEventHandler serviceEventHandler,
IClientInvocationManager clientInvocationManager,
IHubProtocolResolver hubProtocolResolver)
IHubProtocolResolver hubProtocolResolver,
ICultureInfoManager cultureInfoManager)
{
_serviceProtocol = serviceProtocol;
_clientConnectionManager = clientConnectionManager;
Expand All @@ -57,6 +60,7 @@ public ServiceConnectionFactory(
_serviceEventHandler = serviceEventHandler;
_clientInvocationManager = clientInvocationManager;
_hubProtocolResolver = hubProtocolResolver;
_cultureInfoManager = cultureInfoManager;
}

public virtual IServiceConnection Create(HubServiceEndpoint endpoint, IServiceMessageHandler serviceMessageHandler, AckHandler ackHandler, ServiceConnectionType type)
Expand All @@ -75,6 +79,7 @@ public virtual IServiceConnection Create(HubServiceEndpoint endpoint, IServiceMe
_serviceEventHandler,
_clientInvocationManager,
_hubProtocolResolver,
_cultureInfoManager,
type,
ShutdownMode,
allowStatefulReconnects: AllowStatefulReconnects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public MockServiceConnectionFactory(
nameProvider,
null,
clientInvocationManager,
hubProtocolResolver)
hubProtocolResolver,
null)
{
_mockService = mockService;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public IServiceConnection Create(HubServiceEndpoint endpoint,
null,
ClientInvocationManager,
new DefaultHubProtocolResolver(new[] { new JsonHubProtocol() }, NullLogger<DefaultHubProtocolResolver>.Instance),
null,
type,
allowStatefulReconnects: AllowStatefulReconnects);
ServiceConnections.TryAdd(connectionId, connection);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public TestRequestIdProvider(string id)
_id = id;
}

public string GetRequestId()
public string GetRequestId(string clientRequestId)
{
return _id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1656,7 +1656,8 @@ public async Task ServiceConnectionContainerScopeWithPingUpdateTest()
endpoints[0].ConnectionContainer as IServiceMessageHandler,
null,
clientInvocationManager,
hubProtocolResolver);
hubProtocolResolver,
null);

var connection2 = new ServiceConnection(protocol,
ccm,
Expand All @@ -1670,7 +1671,8 @@ public async Task ServiceConnectionContainerScopeWithPingUpdateTest()
endpoints[1].ConnectionContainer as IServiceMessageHandler,
null,
clientInvocationManager,
hubProtocolResolver);
hubProtocolResolver,
null);

var connection22 = new ServiceConnection(protocol,
ccm,
Expand All @@ -1684,7 +1686,8 @@ public async Task ServiceConnectionContainerScopeWithPingUpdateTest()
endpoints[1].ConnectionContainer as IServiceMessageHandler,
null,
clientInvocationManager,
hubProtocolResolver);
hubProtocolResolver,
null);

var router = new TestEndpointRouter();

Expand Down
Loading

0 comments on commit d0e4d1d

Please sign in to comment.