├── spelling.dic ├── .dockerignore ├── microsoft.png ├── docs ├── images │ ├── arch.png │ ├── echo.png │ ├── broadcast.png │ ├── tls_throws.png │ ├── sendtoclient.png │ ├── sendtogroup.png │ ├── service-mode.png │ ├── chrome_network.gif │ ├── cross_geo_infra.png │ ├── serverless-arch.png │ ├── failover_negotiate.png │ ├── normal_negotiate.png │ ├── fiddler_view_network.png │ ├── throw_clr_exceptions.png │ ├── uncheck_just_my_code.png │ ├── diagnostic-logs │ │ ├── message-path.png │ │ ├── add-diagnostic-setting.png │ │ ├── log-analytics-menu-item.png │ │ ├── diagnostics-settings-pane.png │ │ ├── query-log-in-log-analytics.png │ │ ├── diagnostic-settings-menu-item.png │ │ └── azure-signalr-diagnostic-settings.png │ └── client_connection_increasing_constantly.jpg ├── faq.md ├── emulator.md ├── tsg.md ├── use-signalr-service.md ├── advanced-topics │ ├── negotiate.md │ ├── json-object-serializer.md │ └── transport-configuration.md ├── internal.md ├── diagnostic-logs.md ├── rest-api.md ├── run-asp-net.md ├── management-sdk-guide.md ├── run-asp-net-core.md ├── sharding.md ├── swagger │ ├── v1.md │ ├── v1-preview.md │ └── Readme.md ├── howto-tsg.md └── performance-guide.md ├── .gitattributes ├── samples ├── ChatSample.Cli │ ├── chat.txt │ ├── Extensions.cs │ └── ChatSample.Cli.csproj ├── BlazorAppSample │ ├── Pages │ │ ├── Index.razor │ │ ├── Counter.razor │ │ ├── _Host.cshtml │ │ └── Error.razor │ ├── wwwroot │ │ ├── favicon.ico │ │ └── css │ │ │ └── open-iconic │ │ │ └── font │ │ │ └── fonts │ │ │ ├── open-iconic.eot │ │ │ ├── open-iconic.otf │ │ │ ├── open-iconic.ttf │ │ │ └── open-iconic.woff │ ├── appsettings.Development.json │ ├── BlazorAppSample.csproj │ ├── appsettings.json │ ├── Shared │ │ └── MainLayout.razor │ ├── _Imports.razor │ ├── App.razor │ ├── Data │ │ ├── WeatherForecast.cs │ │ └── WeatherForecastService.cs │ ├── Program.cs │ └── Properties │ │ └── launchSettings.json ├── ChatSample │ ├── ChatSample.RazorPages │ │ ├── Pages │ │ │ ├── _ViewStart.cshtml │ │ │ ├── _ViewImports.cshtml │ │ │ ├── Privacy.cshtml │ │ │ ├── Shared │ │ │ │ ├── _ValidationScriptsPartial.cshtml │ │ │ │ └── _Layout.cshtml.css │ │ │ ├── Index.cshtml.cs │ │ │ ├── Privacy.cshtml.cs │ │ │ ├── Index.cshtml │ │ │ ├── Chats.cshtml.cs │ │ │ ├── Error.cshtml.cs │ │ │ └── Error.cshtml │ │ ├── wwwroot │ │ │ ├── favicon.ico │ │ │ ├── js │ │ │ │ └── site.js │ │ │ └── css │ │ │ │ └── site.css │ │ ├── appsettings.Development.json │ │ ├── libman.json │ │ ├── appsettings.json │ │ ├── ChatSample.RazorPages.csproj │ │ └── Properties │ │ │ └── launchSettings.json │ ├── ChatSample │ │ ├── wwwroot │ │ │ └── favicon.ico │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ ├── ChatSample.csproj │ │ ├── Program.cs │ │ └── Dockerfile │ ├── ChatSample.ManagementPublisher │ │ └── ManagementPublisher.csproj │ └── ChatSample.CSharpClient │ │ └── ChatSample.CSharpClient.csproj ├── AspNet.ChatSample │ ├── AspNet.ChatSample.JavaScriptClient │ │ ├── AspNet.ChatSample.JavaScriptClient.csproj │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ └── Startup.cs │ ├── AspNet.ChatSample.CSharpClient │ │ └── AspNet.ChatSample.CSharpClient.csproj │ └── AspNet.ChatSample.SelfHostServer │ │ ├── Startup.cs │ │ ├── Program.cs │ │ └── app.config └── Directory.Build.props ├── specs └── images │ └── client-invocation │ ├── multi-instances.png │ ├── single-instance.png │ ├── serverless-persistent.png │ └── serverless-transient.png ├── .github ├── pull_request_template.md └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── .gitmodules ├── src ├── Microsoft.Azure.SignalR.Protocols │ ├── .editorconfig │ ├── IHasTtl.cs │ ├── IHasProtocol.cs │ ├── IPartializable.cs │ ├── IHasSubscriberFilter.cs │ ├── IHasDataMessageType.cs │ ├── IMessageWithTracingId.cs │ ├── MessagePackPitfalls.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── Models │ │ ├── IMessagePackSerializable.cs │ │ └── GroupMember.cs ├── Microsoft.Azure.SignalR.Emulator │ ├── appsettings.Development.json │ ├── settings.json │ ├── appsettings.json │ ├── Upstreams │ │ ├── UpstreamContext.cs │ │ ├── UpstreamOptionsExtension.cs │ │ ├── IHttpUpstreamPropertiesFeature.cs │ │ ├── IHttpUpstreamTrigger.cs │ │ ├── UpstreamOptions.cs │ │ └── InvokeUpstreamParameters.cs │ ├── HubEmulator │ │ ├── IHubLifetimeManager.cs │ │ ├── IDynamicHubContextStore.cs │ │ └── IUpstreamMessageHandler.cs │ ├── Dockerfile │ ├── Common │ │ ├── ParameterValidator.cs │ │ └── PayloadMessage.cs │ ├── Properties │ │ ├── launchSettings.json │ │ └── AssemblyInfo.cs │ ├── Extensions │ │ └── HttpResponseExtensions.cs │ └── Directory.Build.props ├── Microsoft.Azure.SignalR.Common │ ├── Endpoints │ │ ├── EndpointType.cs │ │ ├── ScaleOperation.cs │ │ ├── UriExtensions.cs │ │ ├── IServiceEndpointOptions.cs │ │ ├── ServiceEndpointUtility.cs │ │ ├── IConfigurationExtension.cs │ │ └── EndpointMetrics.cs │ ├── Interfaces │ │ ├── IServerNameProvider.cs │ │ ├── IBlazorDetector.cs │ │ ├── IServiceConnectionContainerFactory.cs │ │ ├── IAccessTokenProvider.cs │ │ ├── IServiceEventHandler.cs │ │ ├── IServiceMessageHandler.cs │ │ ├── IServiceConnectionFactory.cs │ │ ├── IClientConnectionFactory.cs │ │ ├── IServiceConnectionManager.cs │ │ ├── IServiceConnectionContainer.cs │ │ ├── IServiceEndpointManager.cs │ │ ├── IClientConnectionManager.cs │ │ ├── IServiceEndpointProvider.cs │ │ ├── ICultureFeatureManager.cs │ │ ├── IServiceMessageWriter.cs │ │ ├── IClientConnection.cs │ │ ├── IServiceConnection.cs │ │ └── IConnectionFactory.cs │ ├── AccessTokenAlgorithm.cs │ ├── Auth │ │ ├── MicrosoftEntra │ │ │ ├── ClientTokenResponse.cs │ │ │ ├── AccessKeyResponse.cs │ │ │ └── MicrosoftEntraTokenProvider.cs │ │ └── IAccessKey.cs │ ├── ServiceConnections │ │ ├── ServiceDiagnosticLogsContext.cs │ │ ├── AckStatus.cs │ │ ├── ServiceConnectionStatus.cs │ │ ├── StatusChange.cs │ │ └── ServerConnectionType.cs │ ├── Utilities │ │ ├── Rest │ │ │ ├── PayloadMessage.cs │ │ │ ├── IPayloadContentBuilder.cs │ │ │ ├── BinaryPayloadContentBuilder.cs │ │ │ └── JsonPayloadContentBuilder.cs │ │ ├── RestApiEndpoint.cs │ │ ├── IsExternalInit.cs │ │ ├── HttpClientFactory.cs │ │ ├── ParsedConnectionString.cs │ │ ├── ScopePropertiesAccessor.cs │ │ ├── StaticRandom.cs │ │ ├── TaskExtenstions.cs │ │ └── ProductInfo.cs │ ├── ClientInvocation │ │ ├── IRoutedClientResultsManager.cs │ │ ├── IClientInvocationManager.cs │ │ ├── IClientResultsManager.cs │ │ └── DummyClientInvocationManager.cs │ ├── DefaultServerNameProvider.cs │ ├── Models │ │ └── SignalRGroupConnection.cs │ ├── ServiceMessages │ │ ├── IMessageWithTracingIdExtensions.cs │ │ └── MessageWithTracingIdHelper.cs │ ├── DefaultBlazorDetector.cs │ └── Exceptions │ │ ├── AzureSignalRNoPrimaryEndpointException.cs │ │ ├── AzureSignalRNoEndpointAvailableException.cs │ │ ├── AzureSignalRConfigurationNoEndpointException.cs │ │ ├── AzureSignalRInvalidServiceOptionsException.cs │ │ ├── ExceptionExtensions.cs │ │ └── AzureSignalRInvalidArgumentException.cs ├── Microsoft.Azure.SignalR │ ├── Internals │ │ └── AzureSignalRMarkerService.cs │ ├── ServerConnections │ │ ├── IConnectionMigrationFeature.cs │ │ ├── IConnectionStatFeature.cs │ │ ├── IServiceConnectionManager.cs │ │ ├── ConnectionMigrationFeature.cs │ │ └── ConnectionFactory.cs │ ├── EndpointProvider │ │ └── IServiceEndpointGenerator.cs │ ├── EndpointRouters │ │ └── IEndpointRouter.cs │ └── Startup │ │ ├── AzureSignalRConnectionBuilderExtensions.cs │ │ ├── AzureSignalRStartupFilter.cs │ │ └── AzureSignalRHostingStartup.cs ├── Microsoft.Azure.SignalR.Serverless.Protocols │ ├── MessagePackPitfalls.cs │ ├── Internal │ │ └── Constants.cs │ ├── ServerlessMessage.cs │ └── IServerlessProtocol.cs ├── Microsoft.Azure.SignalR.Management │ ├── IServiceHubLifetimeManager`T.cs │ ├── Resilient │ │ ├── IBackoffPolicy.cs │ │ └── DummyBackoffPolicy.cs │ ├── IStreamingHubLifetimeManager.cs │ ├── HubInstanceFactories │ │ └── HealthCheckOptions.cs │ ├── HubContext │ │ ├── StreamingManager.cs │ │ └── UserGroupManager.cs │ ├── ServiceTransportType.cs │ ├── Negotiation │ │ ├── AutoHealthCheckRouter.cs │ │ └── FixedEndpointRouter.cs │ ├── Configuration │ │ ├── ServiceManagerRetryMode.cs │ │ └── CascadeServiceOptionsSetup.cs │ ├── Serialization │ │ ├── NewtonsoftServiceHubProtocolOptions.cs │ │ └── SerializationDependencyInjectionExtensions.cs │ ├── IServiceManagerBuilder.cs │ ├── IServiceHubContext.cs │ ├── ManagementConnectionFactory.cs │ ├── IUserGroupHubLifetimeManager.cs │ └── IServiceHubLifetimeManager.cs ├── Microsoft.Azure.SignalR.AspNet │ ├── HubHost │ │ ├── IServiceTransport.cs │ │ ├── IMessageParser.cs │ │ ├── HubMessage.cs │ │ └── AppMessage.cs │ ├── ServerConnections │ │ ├── IServiceConnectionManager.cs │ │ └── ConnectionFactory.cs │ ├── ClientConnections │ │ └── IClientConnectionManagerAspNet.cs │ ├── AspNetConstants.cs │ ├── Internals │ │ └── ListHelper.cs │ ├── EndpointRouters │ │ └── IEndpointRouter.cs │ ├── EndpointProvider │ │ └── ServiceEndpointManager.cs │ ├── ProductInfo.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── Transports │ │ └── AzureTransportManager.cs └── Common │ ├── TextMessageFormatter.cs │ └── TextMessageParser.cs ├── test ├── appsettings.Test.json ├── Microsoft.Azure.SignalR.Tests │ ├── Infrastructure │ │ ├── TestHub.cs │ │ ├── TestRequestIdProvider.cs │ │ └── TestClientConnectionFactory.cs │ ├── ProductInfoFacts.cs │ ├── testappsettings.json │ ├── TestClasses │ │ ├── TestHubContext.cs │ │ └── TestServiceConnectionForCloseAsync.cs │ ├── TestHubs │ │ ├── SimpleHub.cs │ │ └── ConnectedHub.cs │ └── Utils.cs ├── Directory.Build.props ├── Microsoft.Azure.SignalR.Tests.Common │ ├── E2ETest │ │ ├── ITestServerFactory.cs │ │ ├── ITestClientSetFactory.cs │ │ ├── ITestServer.cs │ │ └── ITestClientSet.cs │ ├── Retry │ │ ├── IRetryableTestCase.cs │ │ ├── Skip.cs │ │ └── EnumerableExtensions.cs │ ├── ReloadableMemoryProvider.cs │ ├── IVerifiableLog.cs │ ├── LogRecord.cs │ ├── TestClasses │ │ ├── TestHubServiceEndpoint.cs │ │ ├── TestServiceMessageHandler.cs │ │ ├── TestServiceEndpoint.cs │ │ ├── TestBaseServiceConnectionContainer.cs │ │ └── TestServiceConnectionContainerFactory.cs │ ├── Utils │ │ ├── ClientEndpointUtils.cs │ │ └── FakeEndpointUtils.cs │ ├── ReloadableMemorySource.cs │ ├── SkipIfConnectionStringNotPresentAttribute.cs │ └── SkipIfMultiEndpointsAbsentFactAttribute.cs ├── Microsoft.Azure.SignalR.AspNet.Tests │ ├── TestHubs │ │ └── AuthorizedChatHub.cs │ ├── ProductInfoFacts.cs │ └── TestClasses │ │ ├── TestAppBuilder.cs │ │ └── TestEndpointRouter.cs ├── Microsoft.Azure.SignalR.AspNet.E2ETests │ ├── TestServerFactory.cs │ ├── TestClientSetFactory.cs │ └── AspNetSignalRServiceE2EFacts.cs ├── Microsoft.Azure.SignalR.E2ETests │ └── SignalR │ │ ├── TestServerFactory.cs │ │ └── TestClientSetFactory.cs ├── Microsoft.Azure.SignalR.IntegrationTests │ └── Infrastructure │ │ ├── IHotReloadIntegrationTestStartupParameters.cs │ │ ├── IIntegrationTestStartupParameters.cs │ │ ├── MessageOrderTests │ │ ├── UseSameServiceConnectionHub.cs │ │ ├── TestHubBroadcastNCallsInvocationBinder.cs │ │ └── HotReloadTestHub.cs │ │ └── MockServiceSideConnectionEndpointComparer.cs ├── Microsoft.Azure.SignalR.Emulator.Tests │ └── Microsoft.Azure.SignalR.Emulator.Tests.csproj ├── Microsoft.Azure.SignalR.Management.Tests │ └── AutoHealthCheckRouterFacts.cs ├── Microsoft.Azure.SignalR.Protocols.Tests │ └── Models │ │ └── GroupMemberTests.cs └── Microsoft.Azure.SignalR.Common.Tests │ └── Auth │ └── AccessKeyTests.cs ├── NuGet.config ├── client-generation.ps1 └── eng ├── Export-API.ps1 └── ApiListing.targets /spelling.dic: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | .git/ 3 | -------------------------------------------------------------------------------- /microsoft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/microsoft.png -------------------------------------------------------------------------------- /docs/images/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/arch.png -------------------------------------------------------------------------------- /docs/images/echo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/echo.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | -------------------------------------------------------------------------------- /docs/images/broadcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/broadcast.png -------------------------------------------------------------------------------- /docs/images/tls_throws.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/tls_throws.png -------------------------------------------------------------------------------- /samples/ChatSample.Cli/chat.txt: -------------------------------------------------------------------------------- 1 | define broadcastMessage(string,string) 2 | define echo(string,string) 3 | -------------------------------------------------------------------------------- /docs/images/sendtoclient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/sendtoclient.png -------------------------------------------------------------------------------- /docs/images/sendtogroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/sendtogroup.png -------------------------------------------------------------------------------- /docs/images/service-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/service-mode.png -------------------------------------------------------------------------------- /docs/images/chrome_network.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/chrome_network.gif -------------------------------------------------------------------------------- /docs/images/cross_geo_infra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/cross_geo_infra.png -------------------------------------------------------------------------------- /docs/images/serverless-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/serverless-arch.png -------------------------------------------------------------------------------- /docs/images/failover_negotiate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/failover_negotiate.png -------------------------------------------------------------------------------- /docs/images/normal_negotiate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/normal_negotiate.png -------------------------------------------------------------------------------- /samples/BlazorAppSample/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 |

Hello, world!

4 | 5 | Welcome to your new app. 6 | -------------------------------------------------------------------------------- /docs/images/fiddler_view_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/fiddler_view_network.png -------------------------------------------------------------------------------- /docs/images/throw_clr_exceptions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/throw_clr_exceptions.png -------------------------------------------------------------------------------- /docs/images/uncheck_just_my_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/uncheck_just_my_code.png -------------------------------------------------------------------------------- /docs/images/diagnostic-logs/message-path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/diagnostic-logs/message-path.png -------------------------------------------------------------------------------- /samples/BlazorAppSample/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/samples/BlazorAppSample/wwwroot/favicon.ico -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = (Context.Request.Path.Value == "/") ? "_Layout" : null; 3 | } 4 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/samples/ChatSample/ChatSample/wwwroot/favicon.ico -------------------------------------------------------------------------------- /specs/images/client-invocation/multi-instances.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/specs/images/client-invocation/multi-instances.png -------------------------------------------------------------------------------- /specs/images/client-invocation/single-instance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/specs/images/client-invocation/single-instance.png -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions 2 | 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/signalr-resource-faq). 4 | -------------------------------------------------------------------------------- /docs/images/diagnostic-logs/add-diagnostic-setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/diagnostic-logs/add-diagnostic-setting.png -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Summary of the changes (Less than 80 chars) 2 | - Detail 1 3 | - Detail 2 4 | 5 | Fixes #bugnumber (in this specific format) 6 | -------------------------------------------------------------------------------- /docs/emulator.md: -------------------------------------------------------------------------------- 1 | # Azure SignalR Local Emulator 2 | 3 | This article has been moved to [here](https://learn.microsoft.com/azure/azure-signalr/signalr-howto-emulator). -------------------------------------------------------------------------------- /docs/images/client_connection_increasing_constantly.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/client_connection_increasing_constantly.jpg -------------------------------------------------------------------------------- /docs/images/diagnostic-logs/log-analytics-menu-item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/diagnostic-logs/log-analytics-menu-item.png -------------------------------------------------------------------------------- /docs/tsg.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting Guide 2 | 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/signalr-howto-troubleshoot-guide). 4 | -------------------------------------------------------------------------------- /specs/images/client-invocation/serverless-persistent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/specs/images/client-invocation/serverless-persistent.png -------------------------------------------------------------------------------- /specs/images/client-invocation/serverless-transient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/specs/images/client-invocation/serverless-transient.png -------------------------------------------------------------------------------- /docs/images/diagnostic-logs/diagnostics-settings-pane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/diagnostic-logs/diagnostics-settings-pane.png -------------------------------------------------------------------------------- /docs/images/diagnostic-logs/query-log-in-log-analytics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/diagnostic-logs/query-log-in-log-analytics.png -------------------------------------------------------------------------------- /docs/use-signalr-service.md: -------------------------------------------------------------------------------- 1 | # Use Azure SignalR Service 2 | 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/signalr-howto-use). 4 | -------------------------------------------------------------------------------- /docs/images/diagnostic-logs/diagnostic-settings-menu-item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/diagnostic-logs/diagnostic-settings-menu-item.png -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/samples/ChatSample/ChatSample.RazorPages/wwwroot/favicon.ico -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/submodules/MessagePack-CSharp"] 2 | path = src/submodules/MessagePack-CSharp 3 | url = https://github.com/neuecc/MessagePack-CSharp 4 | branch = v2.1.115 -------------------------------------------------------------------------------- /docs/advanced-topics/negotiate.md: -------------------------------------------------------------------------------- 1 | # Negotiate 2 | 3 | This article has been moved to [here](https://learn.microsoft.com/azure/azure-signalr/signalr-concept-client-negotiation). 4 | -------------------------------------------------------------------------------- /docs/internal.md: -------------------------------------------------------------------------------- 1 | # Internals of Azure SignalR Service 2 | 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/signalr-concept-internals). 4 | -------------------------------------------------------------------------------- /docs/images/diagnostic-logs/azure-signalr-diagnostic-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/docs/images/diagnostic-logs/azure-signalr-diagnostic-settings.png -------------------------------------------------------------------------------- /docs/diagnostic-logs.md: -------------------------------------------------------------------------------- 1 | # Diagnostic Logs for Azure SignalR Service 2 | 3 | This article has been moved to [HERE](https://docs.microsoft.com/azure/azure-signalr/signalr-howto-diagnostic-logs) -------------------------------------------------------------------------------- /docs/rest-api.md: -------------------------------------------------------------------------------- 1 | # REST API in Azure SignalR Service 2 | 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/signalr-reference-data-plane-rest-api). 4 | -------------------------------------------------------------------------------- /docs/run-asp-net.md: -------------------------------------------------------------------------------- 1 | # Run ASP.NET SignalR 2 | 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/signalr-howto-use#for-the-legacy-aspnet-signalr). 4 | -------------------------------------------------------------------------------- /docs/management-sdk-guide.md: -------------------------------------------------------------------------------- 1 | # Azure SignalR Service Management SDK 2 | 3 | This article has been moved to [here](https://learn.microsoft.com/azure/azure-signalr/signalr-howto-use-management-sdk). -------------------------------------------------------------------------------- /docs/run-asp-net-core.md: -------------------------------------------------------------------------------- 1 | # Run ASP.NET Core SignalR 2 | 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/signalr-howto-use#for-aspnet-core-signalr). 4 | -------------------------------------------------------------------------------- /docs/sharding.md: -------------------------------------------------------------------------------- 1 | # Multiple SignalR service endpoint support 2 | 3 | This article has been moved to [HERE](https://docs.microsoft.com/azure/azure-signalr/signalr-howto-scale-multi-instances) 4 | -------------------------------------------------------------------------------- /docs/swagger/v1.md: -------------------------------------------------------------------------------- 1 | # Azure SignalR Service REST API 2 | ## Version: v1 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/swagger/signalr-data-plane-rest-v1) 4 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/samples/BlazorAppSample/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /samples/BlazorAppSample/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/samples/BlazorAppSample/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /samples/BlazorAppSample/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/samples/BlazorAppSample/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using ChatSample.RazorPages 2 | @namespace ChatSample.RazorPages.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/azure-signalr/HEAD/samples/BlazorAppSample/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | [*.{cs,vb}] 3 | 4 | # IDE0060: Remove unused parameter 5 | # Disable for protocol project for now 6 | dotnet_diagnostic.IDE0060.severity = silent 7 | -------------------------------------------------------------------------------- /docs/howto-tsg.md: -------------------------------------------------------------------------------- 1 | # How to troubleshoot connectivity and message delivery issues 2 | 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/signalr-howto-troubleshoot-method). 4 | -------------------------------------------------------------------------------- /docs/swagger/v1-preview.md: -------------------------------------------------------------------------------- 1 | # Azure SignalR Service REST API 2 | ## Version: v1-preview 3 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/swagger/signalr-data-plane-rest-v1-preview) 4 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /docs/performance-guide.md: -------------------------------------------------------------------------------- 1 | Azure SignalR Service Performance Guide 2 | =========================================== 3 | 4 | This article has been moved to [here](https://docs.microsoft.com/azure/azure-signalr/signalr-concept-performance). 5 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /docs/advanced-topics/json-object-serializer.md: -------------------------------------------------------------------------------- 1 | # Customizing Json Serialization in Management SDK 2 | 3 | This article has been moved to [here](https://learn.microsoft.com/azure/azure-signalr/signalr-howto-use-management-sdk#json-serialization). 4 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model PrivacyModel 3 | @{ 4 | ViewData["Title"] = "Privacy Policy"; 5 | } 6 |

@ViewData["Title"]

7 | 8 |

Use this page to detail your site's privacy policy.

9 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft.AspNetCore": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/swagger/Readme.md: -------------------------------------------------------------------------------- 1 | Generate Markdown from Swagger 2 | -------------------------------- 3 | 4 | Steps 5 | ========= 6 | 1. Step1 7 | `npm install -g https://github.com/vicancy/swagger-markdown.git` 8 | 9 | 2. Run 10 | `swagger-markdown -i v1.json` 11 | 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/appsettings.Test.json: -------------------------------------------------------------------------------- 1 | { 2 | "ReadMe": "Recommend external contributors fill in `ConnectionString`, change service mode to `Classic` and then run E2E test before create a pull request.", 3 | "Azure": { 4 | "SignalR": { 5 | "ConnectionString": "" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://www.myget.org/F/azure-signalr-dev/api/v3/index.json; 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "UpstreamSettings": { 3 | "Templates": [ 4 | { 5 | "UrlTemplate": "http://localhost:7071/runtime/webhooks/signalr", 6 | "EventPattern": "*", 7 | "HubPattern": "*", 8 | "CategoryPattern": "*" 9 | } 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/AspNet.ChatSample/AspNet.ChatSample.JavaScriptClient/AspNet.ChatSample.JavaScriptClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Warning" 7 | } 8 | }, 9 | "AllowedHosts": "*", 10 | "AccessKey": "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGH" 11 | } 12 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/libman.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "3.0", 3 | "defaultProvider": "unpkg", 4 | "libraries": [ 5 | { 6 | "library": "@microsoft/signalr@8.0.7", 7 | "destination": "wwwroot/js/signalr/8.0.7", 8 | "files": [ 9 | "dist/browser/signalr.min.js" 10 | ] 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Azure": { 3 | "SignalR": { 4 | "Enabled": true, 5 | "ConnectionString": "" 6 | } 7 | }, 8 | "Logging": { 9 | "LogLevel": { 10 | "Default": "Warning", 11 | "Microsoft.Hosting.Lifetime": "Information" 12 | } 13 | }, 14 | "AllowedHosts": "*" 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Endpoints/EndpointType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | public enum EndpointType 7 | { 8 | Primary, 9 | 10 | Secondary 11 | } 12 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/BlazorAppSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServerNameProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | public interface IServerNameProvider 7 | { 8 | string GetName(); 9 | } 10 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/Pages/Counter.razor: -------------------------------------------------------------------------------- 1 | @page "/counter" 2 | 3 |

Counter

4 | 5 |

Current count: @currentCount

6 | 7 | 8 | 9 | @code { 10 | int currentCount = 0; 11 | 12 | void IncrementCount() 13 | { 14 | currentCount++; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Azure": { 3 | "SignalR": { 4 | "Enabled": true, 5 | "ConnectionString": "" 6 | } 7 | }, 8 | "Logging": { 9 | "LogLevel": { 10 | "Default": "Warning", 11 | "Microsoft.Hosting.Lifetime": "Information" 12 | } 13 | }, 14 | "AllowedHosts": "*" 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/AccessTokenAlgorithm.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR 5 | { 6 | public enum AccessTokenAlgorithm 7 | { 8 | HS256, 9 | HS512 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Endpoints/ScaleOperation.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR 5 | { 6 | internal enum ScaleOperation 7 | { 8 | Add, 9 | Remove 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/IHasTtl.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | #nullable enable 4 | 5 | namespace Microsoft.Azure.SignalR.Protocol 6 | { 7 | public interface IHasTtl 8 | { 9 | int? Ttl { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Azure": { 3 | "SignalR": { 4 | "Enabled": true, 5 | "ConnectionString": "" 6 | } 7 | }, 8 | "Logging": { 9 | "LogLevel": { 10 | "Default": "Information", 11 | "Microsoft": "Warning", 12 | "Microsoft.Hosting.Lifetime": "Information" 13 | } 14 | }, 15 | "AllowedHosts": "*" 16 | } 17 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Auth/MicrosoftEntra/ClientTokenResponse.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.Common; 5 | 6 | internal class ClientTokenResponse 7 | { 8 | public string Token { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/Infrastructure/TestHub.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.SignalR; 5 | 6 | namespace Microsoft.Azure.SignalR.Tests 7 | { 8 | internal sealed class TestHub : Hub 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 6 | 7 |
8 |
9 | About 10 |
11 | 12 |
13 | @Body 14 |
15 |
16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/IHasProtocol.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | #nullable enable 4 | 5 | namespace Microsoft.Azure.SignalR.Protocol 6 | { 7 | public interface IHasProtocol 8 | { 9 | string? Protocol { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/IPartializable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | #nullable enable 4 | 5 | namespace Microsoft.Azure.SignalR.Protocol 6 | { 7 | public interface IPartializable 8 | { 9 | bool IsPartial { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/Internals/AzureSignalRMarkerService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR 5 | { 6 | internal class AzureSignalRMarkerService 7 | { 8 | internal bool IsConfigured { set; get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NU1902; 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using BlazorAppSample 9 | @using BlazorAppSample.Shared 10 | -------------------------------------------------------------------------------- /samples/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NU1902 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ServiceConnections/ServiceDiagnosticLogsContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | internal class ServiceDiagnosticLogsContext 7 | { 8 | public bool EnableMessageLog { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/IHasSubscriberFilter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | #nullable enable 4 | 5 | namespace Microsoft.Azure.SignalR.Protocol 6 | { 7 | public interface IHasSubscriberFilter 8 | { 9 | string? Filter { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 14px; 3 | } 4 | 5 | @media (min-width: 768px) { 6 | html { 7 | font-size: 16px; 8 | } 9 | } 10 | 11 | html { 12 | position: relative; 13 | min-height: 100%; 14 | } 15 | 16 | body { 17 | margin-bottom: 60px; 18 | } 19 | 20 | iframe { 21 | height: 1024px; 22 | width: 100%; 23 | } 24 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Upstreams/UpstreamContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR.Emulator 7 | { 8 | internal class UpstreamContext 9 | { 10 | public Uri Uri { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/IHasDataMessageType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | #nullable enable 4 | 5 | namespace Microsoft.Azure.SignalR.Protocol 6 | { 7 | public interface IHasDataMessageType 8 | { 9 | DataMessageType Type { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/IMessageWithTracingId.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | #nullable enable 4 | 5 | namespace Microsoft.Azure.SignalR.Protocol 6 | { 7 | public interface IMessageWithTracingId 8 | { 9 | ulong? TracingId { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/MessagePackPitfalls.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace System.Diagnostics.CodeAnalysis; 5 | 6 | [AttributeUsage(AttributeTargets.Method, Inherited = false)] 7 | internal sealed class DoesNotReturnAttribute : Attribute 8 | { 9 | } 10 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/App.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Sorry, there's nothing at this address.

8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/ServerConnections/IConnectionMigrationFeature.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | public interface IConnectionMigrationFeature 7 | { 8 | string MigrateFrom { get; } 9 | 10 | string MigrateTo { get; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ServiceConnections/AckStatus.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | internal enum AckStatus 7 | { 8 | Ok = 1, 9 | 10 | NotFound = 2, 11 | 12 | Timeout = 3, 13 | 14 | InternalServerError = 4, 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Serverless.Protocols/MessagePackPitfalls.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace System.Diagnostics.CodeAnalysis; 5 | 6 | [AttributeUsage(AttributeTargets.Method, Inherited = false)] 7 | internal sealed class DoesNotReturnAttribute : Attribute 8 | { 9 | } 10 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Mvc.RazorPages; 5 | 6 | namespace ChatSample.RazorPages.Pages; 7 | public class IndexModel : PageModel 8 | { 9 | public void OnGet() 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IBlazorDetector.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | internal interface IBlazorDetector 7 | { 8 | public bool IsBlazor(string hubName); 9 | 10 | public bool TrySetBlazor(string hubName, bool isBlazor); 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ServiceConnections/ServiceConnectionStatus.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | internal enum ServiceConnectionStatus 7 | { 8 | Inited, 9 | 10 | Disconnected, 11 | 12 | Connecting, 13 | 14 | Connected, 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/Rest/PayloadMessage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR 5 | { 6 | internal class PayloadMessage 7 | { 8 | public string Target { get; set; } 9 | 10 | public object[] Arguments { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/E2ETest/ITestServerFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit.Abstractions; 5 | 6 | namespace Microsoft.Azure.SignalR.Tests.Common 7 | { 8 | public interface ITestServerFactory 9 | { 10 | ITestServer Create(ITestOutputHelper output); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/IServiceHubLifetimeManager`T.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.SignalR; 5 | 6 | namespace Microsoft.Azure.SignalR.Management 7 | { 8 | internal interface IServiceHubLifetimeManager : IServiceHubLifetimeManager where THub : Hub 9 | { 10 | } 11 | } -------------------------------------------------------------------------------- /samples/ChatSample.Cli/Extensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace ChatSample.Cli; 5 | 6 | internal static class Extensions 7 | { 8 | public static TBuilder When(this TBuilder self, bool condition, Func func) 9 | { 10 | return condition ? func(self) : self; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/HubEmulator/IHubLifetimeManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.SignalR; 5 | 6 | namespace Microsoft.Azure.SignalR.Emulator.HubEmulator 7 | { 8 | internal interface IHubLifetimeManager 9 | { 10 | HubConnectionStore Connections { get; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/Resilient/IBackoffPolicy.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.Azure.SignalR.Management; 8 | 9 | #nullable enable 10 | 11 | internal interface IBackOffPolicy 12 | { 13 | IEnumerable GetDelays(); 14 | } 15 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.AspNet.Tests/TestHubs/AuthorizedChatHub.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNet.SignalR; 5 | using Microsoft.AspNet.SignalR.Hubs; 6 | 7 | namespace Microsoft.Azure.SignalR.AspNet.Tests.TestHubs; 8 | 9 | [Authorize, HubName("authchat")] 10 | public class AuthorizedChatHub : Hub 11 | { 12 | } 13 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceConnectionContainerFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR; 7 | 8 | internal interface IServiceConnectionContainerFactory 9 | { 10 | IServiceConnectionContainer Create(string hub, TimeSpan? serviceScaleTimeout = null); 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IAccessTokenProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.Azure.SignalR; 8 | 9 | internal interface IAccessTokenProvider 10 | { 11 | Task ProvideAsync(CancellationToken cancellationToken = default); 12 | } 13 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.ManagementPublisher/ManagementPublisher.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Make sure to check the SDK version required to build the latest version 2 | # of Emulator here: https://www.nuget.org/packages/Microsoft.Azure.SignalR.Emulator 3 | FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build 4 | 5 | WORKDIR /emulator 6 | 7 | RUN dotnet tool install -g Microsoft.Azure.SignalR.Emulator 8 | 9 | COPY . . 10 | 11 | ENV PATH="/root/.dotnet/tools:${PATH}" 12 | 13 | ENTRYPOINT ["asrs-emulator", "start", "-i", "0.0.0.0"] 14 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/E2ETest/ITestClientSetFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit.Abstractions; 5 | 6 | namespace Microsoft.Azure.SignalR.Tests.Common 7 | { 8 | public interface ITestClientSetFactory 9 | { 10 | ITestClientSet Create(string serverUrl, int count, ITestOutputHelper output); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/HubHost/IServiceTransport.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNet.SignalR.Transports; 5 | 6 | namespace Microsoft.Azure.SignalR.AspNet 7 | { 8 | internal interface IServiceTransport : ITransport 9 | { 10 | void OnReceived(string value); 11 | 12 | void OnDisconnected(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceEventHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading.Tasks; 5 | 6 | using Microsoft.Azure.SignalR.Protocol; 7 | 8 | namespace Microsoft.Azure.SignalR; 9 | 10 | public interface IServiceEventHandler 11 | { 12 | Task HandleAsync(string connectionId, ServiceEventMessage message); 13 | } 14 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/ServerConnections/IConnectionStatFeature.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR; 7 | 8 | public interface IConnectionStatFeature 9 | { 10 | DateTime StartedAtUtc { get; } 11 | 12 | DateTime LastMessageReceivedAtUtc { get; } 13 | 14 | long ReceivedBytes { get; } 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/HubHost/IMessageParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.AspNet.SignalR.Messaging; 7 | 8 | namespace Microsoft.Azure.SignalR.AspNet 9 | { 10 | internal interface IMessageParser 11 | { 12 | IEnumerable GetMessages(Message message); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Common/ParameterValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.Controllers.Common 5 | { 6 | public class ParameterValidator 7 | { 8 | public const string HubNamePattern = "^[A-Za-z][A-Za-z0-9_`,.[\\]]{0,127}$"; 9 | public const string NotWhitespacePattern = "^(?!\\s+$).+$"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/ServerConnections/IServiceConnectionManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.SignalR; 5 | 6 | namespace Microsoft.Azure.SignalR; 7 | 8 | internal interface IServiceConnectionManager : IServiceConnectionManager where THub : Hub 9 | { 10 | void SetServiceConnection(IServiceConnectionContainer serviceConnection); 11 | } 12 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/Retry/IRetryableTestCase.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit.Sdk; 5 | 6 | namespace Microsoft.Azure.SignalR.Tests; 7 | 8 | public interface IRetryableTestCase : IXunitTestCase 9 | { 10 | int MaxRetries { get; } 11 | 12 | int DelayBetweenRetriesMs { get; } 13 | 14 | string[] SkipOnExceptionFullNames { get; } 15 | } 16 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/ProductInfoFacts.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | 6 | namespace Microsoft.Azure.SignalR.Tests; 7 | 8 | public class ProductInfoFacts 9 | { 10 | [Fact] 11 | public void GetProductInfo() 12 | { 13 | var productInfo = ProductInfo.GetProductInfo(); 14 | 15 | Assert.NotNull(productInfo); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/ServerConnections/IServiceConnectionManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.AspNet; 5 | 6 | internal interface IServiceConnectionManager : IServiceConnectionContainer 7 | { 8 | void Initialize(IServiceConnectionContainerFactory connectionFactory); 9 | 10 | IServiceConnectionContainer WithHub(string hubName); 11 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/HubEmulator/IDynamicHubContextStore.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.Emulator.HubEmulator 5 | { 6 | internal interface IDynamicHubContextStore 7 | { 8 | bool TryGetLifetimeContext(string hub, out DynamicHubContext context); 9 | 10 | public DynamicHubContext GetOrAdd(string hub); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/Resilient/DummyBackoffPolicy.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace Microsoft.Azure.SignalR.Management; 9 | 10 | internal class DummyBackOffPolicy : IBackOffPolicy 11 | { 12 | public IEnumerable GetDelays() => Enumerable.Empty(); 13 | } 14 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/ChatSample.RazorPages.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | chatsample.razorpages 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceMessageHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading.Tasks; 5 | 6 | using Microsoft.Azure.SignalR.Protocol; 7 | 8 | namespace Microsoft.Azure.SignalR; 9 | 10 | internal interface IServiceMessageHandler 11 | { 12 | Task HandlePingAsync(PingMessage pingMessage); 13 | 14 | void HandleAck(AckMessage ackMessage); 15 | } 16 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.AspNet.Tests/ProductInfoFacts.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | 6 | namespace Microsoft.Azure.SignalR.AspNet.Tests; 7 | 8 | public class ProductInfoFacts 9 | { 10 | [Fact] 11 | public void GetProductInfo() 12 | { 13 | var productInfo = ProductInfo.GetProductInfo(); 14 | 15 | Assert.NotNull(productInfo); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Common/PayloadMessage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace Microsoft.Azure.SignalR.Controllers.Common 7 | { 8 | internal class PayloadMessage 9 | { 10 | [Required] 11 | public string Target { get; set; } 12 | 13 | public object[] Arguments { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/Rest/IPayloadContentBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Net.Http; 6 | 7 | using Microsoft.AspNetCore.SignalR.Protocol; 8 | 9 | #nullable enable 10 | 11 | namespace Microsoft.Azure.SignalR.Common; 12 | 13 | internal interface IPayloadContentBuilder 14 | { 15 | HttpContent? Build(HubMessage? payload, Type? typeHint); 16 | } 17 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ClientInvocation/IRoutedClientResultsManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading; 5 | 6 | namespace Microsoft.Azure.SignalR 7 | { 8 | internal interface IRoutedClientResultsManager : IClientResultsManager 9 | { 10 | void AddInvocation(string connectionId, string invocationId, string callerServerId, CancellationToken cancellationToken); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/ClientConnections/IClientConnectionManagerAspNet.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading.Tasks; 5 | 6 | using Microsoft.Azure.SignalR.Protocol; 7 | 8 | namespace Microsoft.Azure.SignalR.AspNet; 9 | 10 | internal interface IClientConnectionManagerAspNet : IClientConnectionManager 11 | { 12 | Task CreateConnection(OpenConnectionMessage message); 13 | } 14 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Upstreams/UpstreamOptionsExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR.Emulator 7 | { 8 | internal static class UpstreamOptionsExtension 9 | { 10 | public static void Print(this UpstreamOptions options) 11 | { 12 | Console.WriteLine($"Current Upstream Settings:\n{options}"); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/testappsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Azure": { 3 | "SignalR": { 4 | "ConnectionString": [ 5 | { 6 | "EP1:Primary": "Endpoint=https://primaryconnectionstring;AccessKey=1" 7 | }, 8 | { 9 | "EP2:Secondary": "Endpoint=https://secondaryconnectionstring;AccessKey=1" 10 | } 11 | ] 12 | } 13 | }, 14 | "Logging": { 15 | "LogLevel": { 16 | "Default": "Warning", 17 | "Microsoft.Hosting.Lifetime": "Information" 18 | } 19 | }, 20 | "AllowedHosts": "*" 21 | } -------------------------------------------------------------------------------- /samples/BlazorAppSample/Data/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace BlazorAppSample.Data 7 | { 8 | public class WeatherForecast 9 | { 10 | public DateTime Date { get; set; } 11 | 12 | public int TemperatureC { get; set; } 13 | 14 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 15 | 16 | public string Summary { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/DefaultServerNameProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR; 7 | 8 | #nullable enable 9 | 10 | internal class DefaultServerNameProvider : IServerNameProvider 11 | { 12 | private readonly string _name = $"{Environment.MachineName}_{Guid.NewGuid():N}"; 13 | 14 | public string GetName() 15 | { 16 | return _name; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💡 Feature request 3 | about: Suggest an idea for this project 4 | --- 5 | 6 | ### Is your feature request related to a problem? Please describe. 7 | A clear and concise description of what the problem is. 8 | Example: I am trying to do [...] but [...] 9 | 10 | ### Describe the solution you'd like 11 | A clear and concise description of what you want to happen. Include any alternative solutions you've considered. 12 | 13 | ### Additional context 14 | Add any other context or screenshots about the feature request here. 15 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Endpoints/UriExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Linq; 6 | 7 | namespace Microsoft.Azure.SignalR; 8 | 9 | internal static class UriExtensions 10 | { 11 | public static Uri Append(this Uri uri, params string[] paths) 12 | { 13 | return new Uri(paths.Aggregate(uri.AbsoluteUri, (current, path) => $"{current.TrimEnd('/')}/{path.TrimStart('/')}")); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/ReloadableMemoryProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Extensions.Configuration; 5 | 6 | namespace Microsoft.Azure.SignalR.Tests.Common 7 | { 8 | public class ReloadableMemoryProvider : ConfigurationProvider 9 | { 10 | public override void Set(string key, string value) 11 | { 12 | base.Set(key, value); 13 | OnReload(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/AspNetConstants.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.AspNet; 5 | 6 | internal static class AspNetConstants 7 | { 8 | public static class QueryString 9 | { 10 | public const string ConnectionToken = "connectionToken"; 11 | } 12 | 13 | public static class Context 14 | { 15 | public const string AzureSignalRTransportKey = "signalr.transport"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-generation.ps1: -------------------------------------------------------------------------------- 1 | node -v 2 | if (! $? ) { 3 | throw "To use Autorest to generate REST client, Node.js is required. Version 10.15.x LTS is preferred. " 4 | } 5 | autorest --info | Out-Null 6 | if (-not $? ) { 7 | npm install -g autorest 8 | } 9 | if (Test-Path .\src\Microsoft.Azure.SignalR.Common\RestClients\Generated ) { 10 | Remove-Item .\src\Microsoft.Azure.SignalR.Common\RestClients\Generated -Force -Recurse 11 | } 12 | autorest --csharp --v3 src\Microsoft.Azure.SignalR.Common\RestClients\readme.md 13 | Remove-Item .\src\Microsoft.Azure.SignalR.Common\RestClients\Generated\code-model-v1 -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/E2ETest/ITestServer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.Azure.SignalR.Tests.Common 8 | { 9 | public interface ITestServer 10 | { 11 | TestHubConnectionManager HubConnectionManager { get; } 12 | Task StartAsync(Dictionary configuration = null); 13 | Task StopAsync(); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Endpoints/IServiceEndpointOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR 5 | { 6 | internal interface IServiceEndpointOptions 7 | { 8 | ServiceEndpoint[] Endpoints { get; } 9 | string ApplicationName { get; } 10 | string ConnectionString { get; } 11 | int InitialHubServerConnectionCount { get; } 12 | int? MaxHubServerConnectionCount { get; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | internal interface IServiceConnectionFactory 7 | { 8 | IServiceConnection Create(HubServiceEndpoint endpoint, 9 | IServiceMessageHandler serviceMessageHandler, 10 | AckHandler ackHandler, 11 | ServiceConnectionType type); 12 | } 13 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.AspNet.E2ETests/TestServerFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Azure.SignalR.Tests.Common; 5 | 6 | using Xunit.Abstractions; 7 | 8 | namespace Microsoft.Azure.SignalR.AspNet.Tests 9 | { 10 | internal class TestServerFactory : ITestServerFactory 11 | { 12 | public ITestServer Create(ITestOutputHelper output) 13 | { 14 | return new TestServer(output); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.E2ETests/SignalR/TestServerFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Azure.SignalR.Tests.Common; 5 | 6 | using Xunit.Abstractions; 7 | 8 | namespace Microsoft.Azure.SignalR.Tests 9 | { 10 | internal sealed class TestServerFactory : ITestServerFactory 11 | { 12 | public ITestServer Create(ITestOutputHelper output) 13 | { 14 | return new TestServer(output); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/Privacy.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Mvc.RazorPages; 5 | 6 | namespace ChatSample.RazorPages.Pages; 7 | public class PrivacyModel : PageModel 8 | { 9 | private readonly ILogger _logger; 10 | 11 | public PrivacyModel(ILogger logger) 12 | { 13 | _logger = logger; 14 | } 15 | 16 | public void OnGet() 17 | { 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/Infrastructure/TestRequestIdProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.Tests; 5 | 6 | public class TestRequestIdProvider : IConnectionRequestIdProvider 7 | { 8 | private readonly string _id; 9 | 10 | public TestRequestIdProvider(string id) 11 | { 12 | _id = id; 13 | } 14 | 15 | public string GetRequestId(string clientRequestId) 16 | { 17 | return _id; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 |
3 |
4 |
5 |

Connection 1

6 |
7 | 8 |
9 |
10 |
11 |

Connection 2

12 |
13 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ServiceConnections/StatusChange.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | internal class StatusChange 7 | { 8 | public ServiceConnectionStatus OldStatus { get; } 9 | 10 | public ServiceConnectionStatus NewStatus { get; } 11 | 12 | public StatusChange(ServiceConnectionStatus oldStatus, ServiceConnectionStatus newStatus) 13 | { 14 | OldStatus = oldStatus; 15 | NewStatus = newStatus; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Microsoft.Azure.SignalR.Emulator": { 4 | "commandName": "Project", 5 | "commandLineArgs": "start -p 8111", 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | } 9 | } 10 | }, 11 | "$schema": "http://json.schemastore.org/launchsettings.json", 12 | "iisSettings": { 13 | "windowsAuthentication": false, 14 | "anonymousAuthentication": true, 15 | "iisExpress": { 16 | "applicationUrl": "http://localhost:54115", 17 | "sslPort": 44304 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/ServerConnections/ConnectionMigrationFeature.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | internal class ConnectionMigrationFeature : IConnectionMigrationFeature 7 | { 8 | public string MigrateTo { get; private set; } 9 | 10 | public string MigrateFrom { get; private set; } 11 | 12 | public ConnectionMigrationFeature(string from, string to) 13 | { 14 | MigrateFrom = from; 15 | MigrateTo = to; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/Chats.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Mvc.RazorPages; 5 | 6 | namespace ClientResultSample.Pages 7 | { 8 | public class ChatsModel : PageModel 9 | { 10 | private readonly ILogger _logger; 11 | 12 | public ChatsModel(ILogger logger) 13 | { 14 | _logger = logger; 15 | } 16 | 17 | public void OnGet() 18 | { 19 | 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IClientConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | #if NETFRAMEWORK 7 | using System.Web; 8 | 9 | #else 10 | using Microsoft.AspNetCore.Http; 11 | #endif 12 | using Microsoft.Azure.SignalR.Protocol; 13 | 14 | namespace Microsoft.Azure.SignalR; 15 | 16 | internal interface IClientConnectionFactory 17 | { 18 | IClientConnection CreateConnection(OpenConnectionMessage message, Action configureContext = null); 19 | } 20 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceConnectionManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.Azure.SignalR; 8 | 9 | internal interface IServiceConnectionManager : IServiceMessageWriter 10 | { 11 | Task StartAsync(); 12 | 13 | Task StopAsync(); 14 | 15 | Task OfflineAsync(GracefulShutdownMode mode, CancellationToken token); 16 | 17 | Task CloseClientConnections(CancellationToken token); 18 | } 19 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/IVerifiableLog.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.Azure.SignalR.Tests.Common; 8 | 9 | public interface IVerifiableLog : IDisposable 10 | { 11 | LogRecord Expects(Func predicate); 12 | LogRecord Expects(string logEventName); 13 | IReadOnlyList ExpectsMany(string logEventName); 14 | IReadOnlyList ExpectsMany(Func predicate); 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Azure.SignalR.Common, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/HubHost/HubMessage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNet.SignalR.Messaging; 5 | using Microsoft.Azure.SignalR.Protocol; 6 | 7 | namespace Microsoft.Azure.SignalR.AspNet 8 | { 9 | internal class HubMessage : AppMessage 10 | { 11 | public string HubName { get; } 12 | 13 | public HubMessage(string name, ServiceMessage message, Message rawMessage) : base(message, rawMessage) 14 | { 15 | HubName = name; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ClientInvocation/IClientInvocationManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR 7 | { 8 | internal interface IClientInvocationManager 9 | { 10 | ICallerClientResultsManager Caller { get; } 11 | IRoutedClientResultsManager Router { get; } 12 | 13 | bool TryGetInvocationReturnType(string invocationId, out Type type); 14 | 15 | void CleanupInvocationsByConnection(string connectionId); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/RestApiEndpoint.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.Extensions.Primitives; 7 | 8 | #nullable enable 9 | 10 | namespace Microsoft.Azure.SignalR; 11 | 12 | internal class RestApiEndpoint 13 | { 14 | public string Audience { get; } 15 | 16 | public IDictionary? Query { get; set; } 17 | 18 | public RestApiEndpoint(string endpoint) 19 | { 20 | Audience = endpoint; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.AspNet.E2ETests/TestClientSetFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Azure.SignalR.Tests.Common; 5 | 6 | using Xunit.Abstractions; 7 | 8 | namespace Microsoft.Azure.SignalR.AspNet.Tests 9 | { 10 | internal class TestClientSetFactory : ITestClientSetFactory 11 | { 12 | public ITestClientSet Create(string serverUrl, int count, ITestOutputHelper output) 13 | { 14 | return new TestClientSet(serverUrl, count, output); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.E2ETests/SignalR/TestClientSetFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Azure.SignalR.Tests.Common; 5 | 6 | using Xunit.Abstractions; 7 | 8 | namespace Microsoft.Azure.SignalR.Tests 9 | { 10 | internal sealed class TestClientSetFactory : ITestClientSetFactory 11 | { 12 | public ITestClientSet Create(string serverUrl, int count, ITestOutputHelper output) 13 | { 14 | return new TestClientSet(serverUrl, count, output); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.IntegrationTests/Infrastructure/IHotReloadIntegrationTestStartupParameters.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | using System.Collections.Generic; 4 | 5 | namespace Microsoft.Azure.SignalR.IntegrationTests.Infrastructure; 6 | 7 | // Specialized startup for hot reload config tests 8 | internal interface IHotReloadIntegrationTestStartupParameters : IIntegrationTestStartupParameters 9 | { 10 | public KeyValuePair[] Endpoints(int versionIndex); 11 | public int EndpointsCount { get; } 12 | } 13 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/Retry/Skip.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.Tests; 5 | 6 | #nullable enable 7 | 8 | public static class Skip 9 | { 10 | /// 11 | /// Throws an exception that results in a "Skipped" result for the test. 12 | /// 13 | /// Reason for the test needing to be skipped 14 | public static void Always(string? reason = null) 15 | { 16 | throw new SkipTestException(reason); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ClientInvocation/IClientResultsManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Microsoft.AspNetCore.SignalR.Protocol; 7 | 8 | namespace Microsoft.Azure.SignalR 9 | { 10 | internal interface IClientResultsManager 11 | { 12 | bool TryCompleteResult(string connectionId, CompletionMessage message); 13 | 14 | bool TryGetInvocationReturnType(string invocationId, out Type type); 15 | 16 | void CleanupInvocationsByConnection(string connectionId); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/EndpointProvider/IServiceEndpointGenerator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | internal interface IServiceEndpointGenerator 7 | { 8 | string GetClientAudience(string hubName, string applicationName); 9 | 10 | string GetClientEndpoint(string hubName, string applicationName, string originalPath, string queryString); 11 | 12 | string GetServerAudience(string hubName, string applicationName); 13 | 14 | string GetServerEndpoint(string hubName, string applicationName); 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/Internals/ListHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | 7 | namespace Microsoft.AspNet.SignalR.Infrastructure 8 | { 9 | /// 10 | /// Copied from https://github.com/SignalR/SignalR/blob/dev/src/Microsoft.AspNet.SignalR.Core/Infrastructure/ListHelper.cs 11 | /// 12 | internal class ListHelper 13 | { 14 | public static readonly IList Empty = new ReadOnlyCollection(new List()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/IStreamingHubLifetimeManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.Azure.SignalR.Management; 8 | 9 | internal interface IStreamingHubLifetimeManager 10 | { 11 | Task SendStreamItemAsync(string connectionId, string streamId, TItem item, CancellationToken cancellationToken = default); 12 | 13 | Task SendStreamCompletionAsync(string connectionId, string streamId, string error, CancellationToken cancellationToken = default); 14 | } 15 | -------------------------------------------------------------------------------- /samples/AspNet.ChatSample/AspNet.ChatSample.CSharpClient/AspNet.ChatSample.CSharpClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.IntegrationTests/Infrastructure/IIntegrationTestStartupParameters.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.IntegrationTests.Infrastructure; 5 | 6 | // The only reason for having this interface is to overcome the lack 7 | // of static properties support in generic type system 8 | internal interface IIntegrationTestStartupParameters 9 | { 10 | public int ConnectionCount { get; } 11 | 12 | public ServiceEndpoint[] ServiceEndpoints { get; } 13 | 14 | public GracefulShutdownMode ShutdownMode { get; } 15 | } 16 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample/ChatSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | chatsample 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceConnectionContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.Azure.SignalR; 8 | 9 | internal interface IServiceConnectionContainer : IServiceConnectionManager, IDisposable 10 | { 11 | ServiceConnectionStatus Status { get; } 12 | 13 | Task ConnectionInitializedTask { get; } 14 | 15 | string ServersTag { get; } 16 | 17 | bool HasClients { get; } 18 | 19 | Task StartGetServersPing(); 20 | 21 | Task StopGetServersPing(); 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/HubHost/AppMessage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNet.SignalR.Messaging; 5 | using Microsoft.Azure.SignalR.Protocol; 6 | 7 | namespace Microsoft.Azure.SignalR.AspNet 8 | { 9 | internal class AppMessage 10 | { 11 | public ServiceMessage Message { get; } 12 | 13 | public Message RawMessage { get; } 14 | 15 | public AppMessage(ServiceMessage message, Message rawMessage) 16 | { 17 | Message = message; 18 | RawMessage = rawMessage; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/HubInstanceFactories/HealthCheckOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR.Management; 7 | 8 | #nullable enable 9 | 10 | //used to reduce test time 11 | internal class HealthCheckOption 12 | { 13 | public TimeSpan CheckInterval { get; set; } = TimeSpan.FromMinutes(2); 14 | public TimeSpan RetryInterval { get; set; } = TimeSpan.FromSeconds(3); 15 | public TimeSpan HttpTimeout { get; set; } = TimeSpan.FromSeconds(2); 16 | public bool EnabledForSingleEndpoint { get; set; } 17 | } -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/TestClasses/TestHubContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Microsoft.AspNetCore.SignalR; 7 | 8 | namespace Microsoft.Azure.SignalR.Tests; 9 | 10 | internal sealed class TestHubContext : IHubContext where THub : Hub 11 | { 12 | public IHubClients Clients => throw new NotImplementedException(); 13 | 14 | public IGroupManager Groups => throw new NotImplementedException(); 15 | 16 | public static TestHubContext GetInstance() 17 | { 18 | return new TestHubContext(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/LogRecord.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Microsoft.Extensions.Logging.Testing; 7 | 8 | namespace Microsoft.Azure.SignalR.Tests.Common 9 | { 10 | // WriteContext, but with a timestamp... 11 | public class LogRecord 12 | { 13 | public DateTime Timestamp { get; } 14 | 15 | public WriteContext Write { get; } 16 | 17 | public LogRecord(DateTime timestamp, WriteContext write) 18 | { 19 | Timestamp = timestamp; 20 | Write = write; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/AspNet.ChatSample/AspNet.ChatSample.SelfHostServer/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Owin; 5 | using Microsoft.Owin.Cors; 6 | 7 | using Owin; 8 | 9 | [assembly: OwinStartup(typeof(AspNet.ChatSample.SelfHostServer.Startup))] 10 | 11 | namespace AspNet.ChatSample.SelfHostServer 12 | { 13 | public class Startup 14 | { 15 | public void Configuration(IAppBuilder app) 16 | { 17 | // app.MapSignalR(); 18 | app.UseCors(CorsOptions.AllowAll); 19 | app.MapAzureSignalR(GetType().FullName); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /samples/AspNet.ChatSample/AspNet.ChatSample.JavaScriptClient/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore; 5 | using Microsoft.AspNetCore.Hosting; 6 | 7 | namespace AspNet.ChatSample.JavaScriptClient 8 | { 9 | public class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | CreateWebHostBuilder(args).Build().Run(); 14 | } 15 | 16 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 17 | WebHost.CreateDefaultBuilder(args) 18 | .UseStartup(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace BlazorAppSample.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | 5 | 6 | 7 | 8 | 9 | 10 | BlazorAppSample 11 | 12 | 13 | 14 | 15 | 16 | 17 | @(await Html.RenderComponentAsync(RenderMode.ServerPrerendered)) 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Upstreams/IHttpUpstreamPropertiesFeature.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.Azure.SignalR.Emulator 7 | { 8 | internal interface IHttpUpstreamPropertiesFeature 9 | { 10 | string QueryString { get; } 11 | 12 | IReadOnlyList ClaimStrings { get; } 13 | 14 | IReadOnlyList GetSignatures(IReadOnlyList keys); 15 | 16 | string Hub { get; } 17 | 18 | string UserIdentifier { get; } 19 | 20 | string ConnectionId { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Hosting; 6 | 7 | namespace ChatSample; 8 | 9 | public class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | CreateHostBuilder(args).Build().Run(); 14 | } 15 | 16 | public static IHostBuilder CreateHostBuilder(string[] args) => 17 | Host.CreateDefaultBuilder(args) 18 | .ConfigureWebHostDefaults(webBuilder => 19 | { 20 | webBuilder.UseStartup(); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/IsExternalInit.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | using System.ComponentModel; 4 | 5 | namespace System.Runtime.CompilerServices 6 | { 7 | /// 8 | /// Reserved to be used by the compiler for tracking metadata. 9 | /// This class should not be used by developers in source code. 10 | /// 11 | /// A class originally defined in .NET 5. Copy here to use "init" accessor on target frameworks below .NET 5. 12 | [EditorBrowsable(EditorBrowsableState.Never)] 13 | internal static class IsExternalInit 14 | { 15 | } 16 | } -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample/Dockerfile: -------------------------------------------------------------------------------- 1 | ################################################## 2 | # Build stage 3 | ################################################## 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0 6 | 7 | COPY ./ /home/signalr-src 8 | 9 | WORKDIR /home/signalr-src/samples/ChatSample/ChatSample 10 | RUN dotnet build && \ 11 | dotnet publish -r linux-x64 -c Release -o /home/build/ 12 | 13 | ################################################## 14 | # Final stage 15 | ################################################## 16 | 17 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 18 | 19 | COPY --from=0 /home/build/ /home/SignalR 20 | 21 | WORKDIR /home/SignalR 22 | 23 | EXPOSE 5050 24 | 25 | CMD ["./ChatSample", "--urls", "http://0.0.0.0:5050"] 26 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.CSharpClient/ChatSample.CSharpClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/HttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Net.Http; 5 | 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | namespace Microsoft.Azure.SignalR 9 | { 10 | internal static class HttpClientFactory 11 | { 12 | public static IHttpClientFactory Instance { get; } = new ServiceCollection().AddHttpClient() 13 | .BuildServiceProvider() 14 | .GetRequiredService(); 15 | } 16 | } -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/TestClasses/TestHubServiceEndpoint.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | namespace Microsoft.Azure.SignalR.Tests.Common; 4 | 5 | internal class TestHubServiceEndpoint(string name = null, 6 | IServiceEndpointProvider provider = null, 7 | ServiceEndpoint endpoint = null) : HubServiceEndpoint( 8 | name ?? "foo", 9 | provider ?? new TestServiceEndpointProvider(), 10 | endpoint ?? new TestServiceEndpoint()) 11 | { 12 | } -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "http": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "applicationUrl": "http://localhost:5212", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development" 11 | } 12 | }, 13 | "https": { 14 | "commandName": "Project", 15 | "dotnetRunMessages": true, 16 | "launchBrowser": true, 17 | "applicationUrl": "https://localhost:7113;http://localhost:5212", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/Utils/ClientEndpointUtils.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.Tests.Common; 5 | 6 | public static class ClientEndpointUtils 7 | { 8 | private const string Endpoint = "https://abc"; 9 | 10 | public static string GetExpectedClientEndpoint(string hubName, string appName = null, string endpoint = Endpoint) 11 | { 12 | if (string.IsNullOrEmpty(appName)) 13 | { 14 | return $"{endpoint}/client/?hub={hubName.ToLower()}"; 15 | } 16 | 17 | return $"{endpoint}/client/?hub={appName.ToLower()}_{hubName.ToLower()}"; 18 | } 19 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Auth/MicrosoftEntra/AccessKeyResponse.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.Common; 5 | 6 | /// 7 | /// The response object containing the dynamic access key for signing client tokens. 8 | /// 9 | public class AccessKeyResponse 10 | { 11 | /// 12 | /// The string value of the access key for SignalR app server to sign client tokens. 13 | /// 14 | public string AccessKey { get; set; } 15 | 16 | /// 17 | /// The ID of the access key. 18 | /// 19 | public string KeyId { get; set; } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/ReloadableMemorySource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Extensions.Configuration; 5 | 6 | namespace Microsoft.Azure.SignalR.Tests.Common 7 | { 8 | public class ReloadableMemorySource : IConfigurationSource 9 | { 10 | private readonly ReloadableMemoryProvider _provider; 11 | 12 | public ReloadableMemorySource(ReloadableMemoryProvider provider) 13 | { 14 | _provider = provider; 15 | } 16 | 17 | public IConfigurationProvider Build(IConfigurationBuilder builder) 18 | { 19 | return _provider; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /samples/BlazorAppSample/Pages/Error.razor: -------------------------------------------------------------------------------- 1 | @page "/error" 2 | 3 | 4 |

Error.

5 |

An error occurred while processing your request.

6 | 7 |

Development Mode

8 |

9 | Swapping to Development environment will display more detailed information about the error that occurred. 10 |

11 |

12 | The Development environment shouldn't be enabled for deployed applications. 13 | It can result in displaying sensitive information from exceptions to end users. 14 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 15 | and restarting the app. 16 |

-------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceEndpointManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.Azure.SignalR; 7 | 8 | internal delegate void EndpointEventHandler(HubServiceEndpoint endpoint); 9 | 10 | internal interface IServiceEndpointManager 11 | { 12 | IReadOnlyDictionary Endpoints { get; } 13 | 14 | event EndpointEventHandler OnAdd; 15 | 16 | event EndpointEventHandler OnRemove; 17 | 18 | IServiceEndpointProvider GetEndpointProvider(ServiceEndpoint endpoint); 19 | 20 | IReadOnlyList GetEndpoints(string hub); 21 | } 22 | -------------------------------------------------------------------------------- /samples/BlazorAppSample/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Hosting; 6 | 7 | namespace BlazorAppSample 8 | { 9 | public class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | CreateHostBuilder(args).Build().Run(); 14 | } 15 | 16 | public static IHostBuilder CreateHostBuilder(string[] args) => 17 | Host.CreateDefaultBuilder(args) 18 | .ConfigureWebHostDefaults(webBuilder => 19 | { 20 | webBuilder.UseStartup(); 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.IntegrationTests/Infrastructure/MessageOrderTests/UseSameServiceConnectionHub.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading.Tasks; 5 | 6 | using Microsoft.AspNetCore.SignalR; 7 | 8 | namespace Microsoft.Azure.SignalR.IntegrationTests.Infrastructure.MessageOrderTests 9 | { 10 | public class UseSameServiceConnectionHub : Hub 11 | { 12 | public async Task BroadcastNumCalls(int numCalls) 13 | { 14 | for (int i = 0; i < numCalls;) 15 | { 16 | await Clients.All.SendAsync("Callback", ++i); 17 | } 18 | return true; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/TestClasses/TestServiceConnectionForCloseAsync.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading.Tasks; 5 | 6 | using Microsoft.Azure.SignalR.Protocol; 7 | using Microsoft.Azure.SignalR.Tests.Common; 8 | 9 | namespace Microsoft.Azure.SignalR.Tests; 10 | 11 | internal sealed class TestServiceConnectionForCloseAsync : TestServiceConnection 12 | { 13 | public TestServiceConnectionForCloseAsync() : base(ServiceConnectionStatus.Connected, false) 14 | { 15 | } 16 | 17 | protected override Task OnClientConnectedAsync(OpenConnectionMessage openConnectionMessage) 18 | { 19 | return Task.CompletedTask; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Models/SignalRGroupConnection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Text.Json.Serialization; 5 | 6 | namespace Microsoft.Azure.SignalR; 7 | 8 | #nullable enable 9 | 10 | // TODO: make public later 11 | internal sealed record SignalRGroupConnection 12 | { 13 | [JsonPropertyName("connectionId")] 14 | public string ConnectionId { internal set; get; } 15 | 16 | [JsonPropertyName("userId")] 17 | public string? UserId { get; internal set; } 18 | 19 | public SignalRGroupConnection(string connectionId, string? userId = default) 20 | { 21 | ConnectionId = connectionId; 22 | UserId = userId; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/HubContext/StreamingManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Channels; 7 | using System.Threading.Tasks; 8 | 9 | namespace Microsoft.Azure.SignalR.Management; 10 | 11 | public abstract class StreamingManager : IStreamingManager 12 | { 13 | public abstract Task SendStreamAsync(string connectionId, string streamId, IAsyncEnumerable items, CancellationToken cancellationToken); 14 | 15 | public abstract Task SendStreamAsync(string connectionId, string streamId, ChannelReader items, CancellationToken cancellationToken); 16 | } 17 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/EndpointRouters/IEndpointRouter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.Owin; 7 | 8 | namespace Microsoft.Azure.SignalR.AspNet; 9 | 10 | public interface IEndpointRouter: IMessageRouter 11 | { 12 | /// 13 | /// Get the service endpoint for the client to connect to 14 | /// 15 | /// The incoming owin http context 16 | /// All the available endpoints 17 | /// 18 | ServiceEndpoint GetNegotiateEndpoint(IOwinContext owinContext, IEnumerable endpoints); 19 | } 20 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/EndpointRouters/IEndpointRouter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.AspNetCore.Http; 7 | 8 | namespace Microsoft.Azure.SignalR; 9 | 10 | public interface IEndpointRouter : IMessageRouter 11 | { 12 | /// 13 | /// Get the service endpoint for the client to connect to 14 | /// 15 | /// The http context of the incoming request 16 | /// All the available endpoints 17 | /// 18 | ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable endpoints); 19 | } 20 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/TestClasses/TestServiceMessageHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | using Microsoft.Azure.SignalR.Protocol; 8 | 9 | namespace Microsoft.Azure.SignalR.Tests.Common; 10 | 11 | internal sealed class TestServiceMessageHandler : IServiceMessageHandler 12 | { 13 | public TestServiceMessageHandler() 14 | { 15 | } 16 | 17 | public Task HandlePingAsync(PingMessage pingMessage) 18 | { 19 | return Task.CompletedTask; 20 | } 21 | 22 | public void HandleAck(AckMessage serviceMessage) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ServiceMessages/IMessageWithTracingIdExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Azure.SignalR.Protocol; 5 | 6 | namespace Microsoft.Azure.SignalR 7 | { 8 | internal static class IMessageWithTracingIdExtensions 9 | { 10 | public static T WithTracingId(this T message) where T : IMessageWithTracingId 11 | { 12 | if (ServiceConnectionContainerScope.EnableMessageLog || ClientConnectionScope.IsDiagnosticClient) 13 | { 14 | var id = MessageWithTracingIdHelper.Generate(); 15 | message.TracingId = id; 16 | } 17 | return message; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Upstreams/IHttpUpstreamTrigger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Net.Http; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace Microsoft.Azure.SignalR.Emulator 10 | { 11 | internal interface IHttpUpstreamTrigger 12 | { 13 | Task TriggerAsync(UpstreamContext context, IHttpUpstreamPropertiesFeature upstreamProperties, InvokeUpstreamParameters parameters, Action configureRequest = null, CancellationToken token = default); 14 | bool TryGetMatchedUpstreamContext(InvokeUpstreamParameters parameters, out UpstreamContext upstreamContext); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/AspNet.ChatSample/AspNet.ChatSample.JavaScriptClient/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54338", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "AspNet.ChatSample.JavaScriptClient": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/ServiceTransportType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.Management 5 | { 6 | /// 7 | /// Transport type to the Azure SignalR Service. 8 | /// 9 | public enum ServiceTransportType 10 | { 11 | /// 12 | /// The SDK will call REST API to send each message to Azure SignalR Service. 13 | /// 14 | Transient, 15 | 16 | /// 17 | /// The SDK will establish one or more Websockets connection(s) to send all messages in the connection(s) to Azure SignalR Service. 18 | /// 19 | Persistent 20 | } 21 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ServiceConnections/ServerConnectionType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR; 5 | 6 | internal enum ServiceConnectionType 7 | { 8 | /// 9 | /// 0, Default, it can carry clients, service runtime should always accept this kind of connection 10 | /// 11 | Default = 0, 12 | /// 13 | /// 1, OnDemand, creating when service requested more connections, it can carry clients, but it may be rejected by service runtime. 14 | /// 15 | OnDemand = 1, 16 | /// 17 | /// 2, Weak, it can not carry clients, but it can send message 18 | /// 19 | Weak = 2, 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/Negotiation/AutoHealthCheckRouter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | using Microsoft.AspNetCore.Http; 8 | 9 | namespace Microsoft.Azure.SignalR.Management; 10 | 11 | /// 12 | /// An endpoint router that only checks health when there are multiple endpoints. 13 | /// 14 | internal class AutoHealthCheckRouter : EndpointRouterDecorator 15 | { 16 | public override ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable endpoints) 17 | { 18 | return endpoints.Count() == 1 ? endpoints.Single() : base.GetNegotiateEndpoint(context, endpoints); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IClientConnectionManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | 7 | namespace Microsoft.Azure.SignalR; 8 | 9 | #nullable enable 10 | 11 | internal interface IClientConnectionManager 12 | { 13 | IEnumerable ClientConnections { get; } 14 | 15 | int Count { get; } 16 | 17 | bool TryAddClientConnection(IClientConnection connection); 18 | 19 | bool TryRemoveClientConnection(string connectionId, out IClientConnection? connection); 20 | 21 | bool TryGetClientConnection(string connectionId, out IClientConnection? connection); 22 | 23 | Task WhenAllCompleted(); 24 | } 25 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Auth/MicrosoftEntra/MicrosoftEntraTokenProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace Microsoft.Azure.SignalR; 9 | 10 | internal class MicrosoftEntraTokenProvider : IAccessTokenProvider 11 | { 12 | private readonly MicrosoftEntraAccessKey _accessKey; 13 | 14 | public MicrosoftEntraTokenProvider(MicrosoftEntraAccessKey accessKey) 15 | { 16 | _accessKey = accessKey ?? throw new ArgumentNullException(nameof(accessKey)); 17 | } 18 | 19 | public Task ProvideAsync(CancellationToken cancellationToken) => _accessKey.GetMicrosoftEntraTokenAsync(cancellationToken); 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/DefaultBlazorDetector.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Concurrent; 5 | 6 | namespace Microsoft.Azure.SignalR 7 | { 8 | internal class DefaultBlazorDetector: IBlazorDetector 9 | { 10 | private readonly ConcurrentDictionary _blazor = new ConcurrentDictionary(); 11 | 12 | public bool IsBlazor(string hubName) 13 | { 14 | _blazor.TryGetValue(hubName, out var isBlazor); 15 | return isBlazor; 16 | } 17 | 18 | public bool TrySetBlazor(string hubName, bool isBlazor) 19 | { 20 | return _blazor.TryAdd(hubName, isBlazor); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Emulator.Tests/Microsoft.Azure.SignalR.Emulator.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/TestHubs/SimpleHub.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | using Microsoft.AspNetCore.SignalR; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Microsoft.Azure.SignalR.Tests.TestHubs; 11 | 12 | internal sealed class SimpleHub : Hub 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public SimpleHub(ILogger logger) 17 | { 18 | _logger = logger; 19 | } 20 | 21 | public override Task OnDisconnectedAsync(Exception exception) 22 | { 23 | _logger.LogInformation($"{Context.ConnectionId} disconnected: {exception}."); 24 | return Task.CompletedTask; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Exceptions/AzureSignalRNoPrimaryEndpointException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Runtime.Serialization; 6 | 7 | namespace Microsoft.Azure.SignalR.Common 8 | { 9 | [Serializable] 10 | public class AzureSignalRNoPrimaryEndpointException : AzureSignalRException 11 | { 12 | public AzureSignalRNoPrimaryEndpointException() : base("No primary endpoint defined.") 13 | { 14 | } 15 | 16 | #if NET8_0_OR_GREATER 17 | [Obsolete] 18 | #endif 19 | protected AzureSignalRNoPrimaryEndpointException(SerializationInfo info, StreamingContext context) 20 | : base(info, context) 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /samples/AspNet.ChatSample/AspNet.ChatSample.SelfHostServer/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Microsoft.Owin.Hosting; 7 | 8 | namespace AspNet.ChatSample.SelfHostServer 9 | { 10 | class Program 11 | { 12 | static void Main(string[] args) 13 | { 14 | if (!(args.Length > 0 && int.TryParse(args[0], out var port))) 15 | { 16 | port = 8009; 17 | } 18 | 19 | var url = $"http://localhost:{port}"; 20 | using (WebApp.Start(url)) 21 | { 22 | Console.WriteLine($"Server running at {url}"); 23 | Console.ReadLine(); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Endpoints/ServiceEndpointUtility.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.Azure.SignalR; 7 | 8 | internal static class ServiceEndpointUtility 9 | { 10 | public static IEnumerable Merge(string connectionString, IEnumerable endpoints) 11 | { 12 | if (!string.IsNullOrEmpty(connectionString)) 13 | { 14 | yield return new ServiceEndpoint(connectionString); 15 | } 16 | 17 | if (endpoints != null) 18 | { 19 | foreach (var endpoint in endpoints) 20 | { 21 | yield return endpoint; 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/Configuration/ServiceManagerRetryMode.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR.Management; 5 | 6 | #nullable enable 7 | 8 | /// 9 | /// The type of approach to apply when calculating the delay between retry attempts. 10 | /// 11 | public enum ServiceManagerRetryMode 12 | { 13 | /// 14 | /// Retry attempts happen at fixed intervals; each delay is a consistent duration. 15 | /// 16 | Fixed, 17 | /// 18 | /// Retry attempts will delay based on a backoff strategy, where each attempt will 19 | /// increase the duration that it waits before retrying. 20 | /// 21 | Exponential 22 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/ParsedConnectionString.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Azure.Core; 7 | 8 | namespace Microsoft.Azure.SignalR; 9 | 10 | #nullable enable 11 | 12 | internal class ParsedConnectionString 13 | { 14 | internal Uri Endpoint { get; } 15 | 16 | internal string? AccessKey { get; init; } 17 | 18 | internal TokenCredential TokenCredential { get; } 19 | 20 | internal Uri? ClientEndpoint { get; init; } 21 | 22 | internal Uri? ServerEndpoint { get; init; } 23 | 24 | public ParsedConnectionString(Uri endpoint, TokenCredential tokenCredential) 25 | { 26 | Endpoint = endpoint; 27 | TokenCredential = tokenCredential; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Management.Tests/AutoHealthCheckRouterFacts.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Linq; 5 | 6 | using Microsoft.Azure.SignalR.Tests.Common; 7 | 8 | using Xunit; 9 | 10 | namespace Microsoft.Azure.SignalR.Management.Tests 11 | { 12 | public class AutoHealthCheckRouterFacts 13 | { 14 | [Fact] 15 | public void TestAutoHealthCheckRouterWithSingleEndpoint() 16 | { 17 | var router = new AutoHealthCheckRouter(); 18 | var endpoints = new ServiceEndpoint[] { new(FakeEndpointUtils.GetFakeConnectionString(1).First()) { Online = false } }; 19 | Assert.Equal(endpoints[0], router.GetNegotiateEndpoint(null, endpoints)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Exceptions/AzureSignalRNoEndpointAvailableException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Runtime.Serialization; 6 | 7 | namespace Microsoft.Azure.SignalR.Common 8 | { 9 | [Serializable] 10 | public class AzureSignalRNoEndpointAvailableException : AzureSignalRException 11 | { 12 | public AzureSignalRNoEndpointAvailableException() : base("No Azure Service endpoint available.") 13 | { 14 | } 15 | 16 | #if NET8_0_OR_GREATER 17 | [Obsolete] 18 | #endif 19 | protected AzureSignalRNoEndpointAvailableException(SerializationInfo info, StreamingContext context) 20 | : base(info, context) 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/E2ETest/ITestClientSet.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | 8 | namespace Microsoft.Azure.SignalR.Tests.Common 9 | { 10 | public interface ITestClientSet 11 | { 12 | Task StartAsync(); 13 | Task StopAsync(); 14 | int Count { get; } 15 | void AddListener(string methodName, Action handler); 16 | Task SendAsync(string methodName, int sendCount = -1, params string[] messages); 17 | Task SendAsync(string methodName, int[] sendInds, params string[] messages); 18 | Task ManageGroupAsync(string methodName, IDictionary connectionGroupMap); 19 | } 20 | } -------------------------------------------------------------------------------- /samples/BlazorAppSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:2023", 7 | "sslPort": 44367 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "BlazorAppSample": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development", 24 | "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.Azure.SignalR" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Exceptions/AzureSignalRConfigurationNoEndpointException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Runtime.Serialization; 6 | 7 | namespace Microsoft.Azure.SignalR.Common 8 | { 9 | [Serializable] 10 | public class AzureSignalRConfigurationNoEndpointException : AzureSignalRException 11 | { 12 | public AzureSignalRConfigurationNoEndpointException() : base("No connection string was specified.") 13 | { 14 | } 15 | 16 | #if NET8_0_OR_GREATER 17 | [Obsolete] 18 | #endif 19 | protected AzureSignalRConfigurationNoEndpointException(SerializationInfo info, StreamingContext context) 20 | : base(info, context) 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceEndpointProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Net; 7 | using System.Security.Claims; 8 | using System.Threading.Tasks; 9 | 10 | namespace Microsoft.Azure.SignalR; 11 | 12 | internal interface IServiceEndpointProvider 13 | { 14 | Task GenerateClientAccessTokenAsync(string hubName, IEnumerable claims = null, TimeSpan? lifetime = null); 15 | 16 | string GetClientEndpoint(string hubName, string originalPath, string queryString); 17 | 18 | IAccessTokenProvider GetServerAccessTokenProvider(string hubName, string serverId); 19 | 20 | string GetServerEndpoint(string hubName); 21 | 22 | IWebProxy Proxy { get; } 23 | } 24 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/ICultureFeatureManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | // IRequestCultureFeature is unavailable in net462. See https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.localization.irequestculturefeature#applies-to 5 | #if NETSTANDARD2_0 || NET6_0_OR_GREATER 6 | using Microsoft.AspNetCore.Localization; 7 | 8 | namespace Microsoft.Azure.SignalR; 9 | 10 | internal interface ICultureFeatureManager 11 | { 12 | bool TryAddCultureFeature(string clientRequestId, IRequestCultureFeature cultureFeature); 13 | 14 | bool TryRemoveCultureFeature(string clientRequestId, out IRequestCultureFeature feature); 15 | 16 | bool IsDefaultFeature(IRequestCultureFeature feature); 17 | 18 | public void Cleanup(); 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/ScopePropertiesAccessor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading; 5 | 6 | namespace Microsoft.Azure.SignalR.Common.Utilities 7 | { 8 | internal class ScopePropertiesAccessor 9 | { 10 | // Use async local with indirect reference to TProps to allow for deep cleanup 11 | private static readonly AsyncLocal> s_currentAccessor = new AsyncLocal>(); 12 | 13 | protected internal static ScopePropertiesAccessor Current 14 | { 15 | get => s_currentAccessor.Value; 16 | set => s_currentAccessor.Value = value; 17 | } 18 | 19 | internal TProps Properties { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/Negotiation/FixedEndpointRouter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | using Microsoft.AspNetCore.Http; 8 | 9 | namespace Microsoft.Azure.SignalR.Management; 10 | 11 | /// 12 | /// An endpoint router that always return a fixed collection of endpoints. 13 | /// 14 | internal class FixedEndpointRouter(IEnumerable serviceEndpoints) : EndpointRouterDecorator 15 | { 16 | private readonly IEnumerable _serviceEndpoints = serviceEndpoints; 17 | 18 | public override ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable endpoints) 19 | { 20 | return _serviceEndpoints.First(); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Serverless.Protocols/Internal/Constants.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | #nullable enable 4 | 5 | namespace Microsoft.Azure.SignalR.Serverless.Protocols; 6 | 7 | internal static class ServerlessProtocolConstants 8 | { 9 | /// 10 | /// Represents the invocation message type. 11 | /// 12 | public const int InvocationMessageType = 1; 13 | 14 | // Reserve number in HubProtocolConstants 15 | 16 | /// 17 | /// Represents the open connection message type. 18 | /// 19 | public const int OpenConnectionMessageType = 10; 20 | 21 | /// 22 | /// Represents the close connection message type. 23 | /// 24 | public const int CloseConnectionMessageType = 11; 25 | } -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/SkipIfConnectionStringNotPresentAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Microsoft.AspNetCore.Testing.xunit; 7 | 8 | namespace Microsoft.Azure.SignalR.Tests.Common 9 | { 10 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] 11 | public class SkipIfConnectionStringNotPresentAttribute : Attribute, ITestCondition 12 | { 13 | public bool IsMet => IsConnectionStringAvailable(); 14 | 15 | public string SkipReason => "Connection string is not available."; 16 | 17 | private static bool IsConnectionStringAvailable() 18 | { 19 | return !string.IsNullOrEmpty(TestConfiguration.Instance.ConnectionString); 20 | } 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ClientInvocation/DummyClientInvocationManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR 7 | { 8 | internal sealed class DummyClientInvocationManager : IClientInvocationManager 9 | { 10 | public ICallerClientResultsManager Caller => throw new NotSupportedException(); 11 | public IRoutedClientResultsManager Router => throw new NotSupportedException(); 12 | 13 | public DummyClientInvocationManager() 14 | { 15 | } 16 | 17 | public void CleanupInvocationsByConnection(string connectionId) => throw new NotSupportedException(); 18 | 19 | public bool TryGetInvocationReturnType(string invocationId, out Type type) => throw new NotSupportedException(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Auth/IAccessKey.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Security.Claims; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace Microsoft.Azure.SignalR; 11 | 12 | internal interface IAccessKey 13 | { 14 | public string Kid { get; } 15 | 16 | public byte[] KeyBytes { get; } 17 | 18 | public Task GenerateAccessTokenAsync(string audience, 19 | IEnumerable claims, 20 | TimeSpan lifetime, 21 | AccessTokenAlgorithm algorithm, 22 | CancellationToken ctoken = default); 23 | } 24 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.AspNet.Tests/TestClasses/TestAppBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | using Owin; 8 | 9 | namespace Microsoft.Azure.SignalR.AspNet.Tests; 10 | 11 | internal sealed class TestAppBuilder : IAppBuilder 12 | { 13 | public IDictionary Properties { get; } = new Dictionary() 14 | { 15 | ["builder.AddSignatureConversion"] = new Action(e => { }) 16 | }; 17 | 18 | public object Build(Type returnType) 19 | { 20 | return null; 21 | } 22 | 23 | public IAppBuilder New() 24 | { 25 | return null; 26 | } 27 | 28 | public IAppBuilder Use(object middleware, params object[] args) 29 | { 30 | return this; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Exceptions/AzureSignalRInvalidServiceOptionsException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Runtime.Serialization; 6 | 7 | namespace Microsoft.Azure.SignalR.Common 8 | { 9 | [Serializable] 10 | public class AzureSignalRInvalidServiceOptionsException : AzureSignalRException 11 | { 12 | public AzureSignalRInvalidServiceOptionsException(string propertyName, string validScope) 13 | : base($"Property '{propertyName}' value should be {validScope}.") 14 | { 15 | } 16 | 17 | #if NET8_0_OR_GREATER 18 | [Obsolete] 19 | #endif 20 | protected AzureSignalRInvalidServiceOptionsException(SerializationInfo info, StreamingContext context) : base(info, context) 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Exceptions/ExceptionExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Net.WebSockets; 6 | 7 | namespace Microsoft.Azure.SignalR.Common; 8 | 9 | #nullable enable 10 | 11 | internal static class ExceptionExtensions 12 | { 13 | internal static Exception WrapAsAzureSignalRException(this Exception e, string? jwtToken) 14 | { 15 | switch (e) 16 | { 17 | case WebSocketException webSocketException: 18 | if (e.Message.StartsWith("The server returned status code \"401\"")) 19 | { 20 | return new AzureSignalRUnauthorizedException(null, webSocketException, jwtToken); 21 | } 22 | return e; 23 | default: return e; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Upstreams/UpstreamOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Globalization; 5 | using System.Text; 6 | 7 | namespace Microsoft.Azure.SignalR.Emulator; 8 | 9 | internal class UpstreamOptions 10 | { 11 | public UpstreamTemplateItem[] Templates { get; set; } 12 | 13 | public override string ToString() 14 | { 15 | if (Templates?.Length > 0) 16 | { 17 | var sb = new StringBuilder(); 18 | for (var i = 0; i < Templates.Length; i++) 19 | { 20 | sb.AppendLine(CultureInfo.InvariantCulture, $"\t[{i}]{Templates[i]}"); 21 | } 22 | return sb.ToString(); 23 | } 24 | 25 | return "No upstream is set yet. Use 'upstream init' to create default upstreams."; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/Serialization/NewtonsoftServiceHubProtocolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Serialization; 6 | 7 | namespace Microsoft.Azure.SignalR.Management 8 | { 9 | /// 10 | /// Options to configure the hub serialization behaviours with Newtonsoft.Json hub protocol. 11 | /// 12 | public class NewtonsoftServiceHubProtocolOptions 13 | { 14 | /// 15 | /// Gets or sets the settings used to serialize invocation arguments and return values. 16 | /// 17 | public JsonSerializerSettings PayloadSerializerSettings { get; set; } = new() 18 | { 19 | ContractResolver = new CamelCasePropertyNamesContractResolver() 20 | }; 21 | } 22 | } -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.IntegrationTests/Infrastructure/MockServiceSideConnectionEndpointComparer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Diagnostics.CodeAnalysis; 6 | 7 | using Microsoft.Azure.SignalR.IntegrationTests.MockService; 8 | 9 | namespace Microsoft.Azure.SignalR.IntegrationTests.Infrastructure; 10 | 11 | internal sealed class MockServiceSideConnectionEndpointComparer : IEqualityComparer 12 | { 13 | public bool Equals(MockServiceSideConnection x, MockServiceSideConnection y) 14 | { 15 | return x.Endpoint.Endpoint == y.Endpoint.Endpoint && x.Endpoint.EndpointType == y.Endpoint.EndpointType; 16 | } 17 | 18 | public int GetHashCode([DisallowNull] MockServiceSideConnection obj) => obj.Endpoint.GetHashCode(); 19 | } 20 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceMessageWriter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | using Azure; 9 | 10 | using Microsoft.Azure.SignalR.Protocol; 11 | 12 | namespace Microsoft.Azure.SignalR; 13 | 14 | #nullable enable 15 | 16 | internal interface IServiceMessageWriter 17 | { 18 | Task WriteAsync(ServiceMessage serviceMessage); 19 | 20 | Task WriteAckableMessageAsync(ServiceMessage serviceMessage, CancellationToken cancellationToken = default); 21 | 22 | IAsyncEnumerable> ListConnectionsInGroupAsync(string groupName, int? top = null, int? maxPageSize = null, string? continuationToken = null, ulong? tracingId = null, CancellationToken token = default); 23 | } 24 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/IServiceManagerBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR.Management 7 | { 8 | /// 9 | /// A builder abstraction for configuring instances. 10 | /// 11 | [Obsolete("Use ServiceManagerBuilder.BuildServiceManager() to build an abstract class of ServiceManager instead.")] 12 | public interface IServiceManagerBuilder 13 | { 14 | /// 15 | /// Builds instances. 16 | /// 17 | /// The instance of the . 18 | [Obsolete("Use ServiceManagerBuilder.BuildServiceManager() instead.")] 19 | IServiceManager Build(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/Utils/FakeEndpointUtils.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Microsoft.Azure.SignalR.Tests.Common; 8 | 9 | public static class FakeEndpointUtils 10 | { 11 | public const string FakeAccessKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 12 | 13 | public static IEnumerable GetFakeConnectionString(int count) 14 | { 15 | return Enumerable.Range(StaticRandom.Next(9999), count).Select(i => $"Endpoint=http://localhost{i};AccessKey={FakeAccessKey};Version=1.0;"); 16 | } 17 | 18 | public static IEnumerable GetFakeEndpoint(int count) 19 | { 20 | return GetFakeConnectionString(count).Select(connectionString => new ServiceEndpoint(connectionString)); 21 | } 22 | } -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/Infrastructure/TestClientConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.Azure.SignalR.Protocol; 9 | 10 | namespace Microsoft.Azure.SignalR.Tests; 11 | 12 | internal sealed class TestClientConnectionFactory : IClientConnectionFactory 13 | { 14 | public IList Connections = new List(); 15 | 16 | public IClientConnection CreateConnection(OpenConnectionMessage message, Action configureContext = null) 17 | { 18 | var context = new ClientConnectionContext(message, configureContext, closeTimeOutMilliseconds: 10000); 19 | Connections.Add(context); 20 | return context; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/TestClasses/TestServiceEndpoint.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Azure.Core; 7 | 8 | namespace Microsoft.Azure.SignalR.Tests.Common; 9 | 10 | #nullable enable 11 | 12 | internal class TestServiceEndpoint : ServiceEndpoint 13 | { 14 | private static readonly Uri DefaultEndpoint = new("https://localhost"); 15 | 16 | private const string DefaultConnectionString = "Endpoint=https://localhost;AccessKey=ABCDEFGHIJKLMNOPQRSTUVWXYZ;Version=1.0"; 17 | 18 | public TestServiceEndpoint(string name = "", string? connectionString = null) : base(connectionString ?? DefaultConnectionString, name: name) 19 | { 20 | } 21 | 22 | public TestServiceEndpoint(TokenCredential tokenCredential) : base(DefaultEndpoint, tokenCredential) 23 | { 24 | } 25 | } -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Protocols.Tests/Models/GroupMemberTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Buffers; 5 | 6 | using Microsoft.Azure.SignalR.Protocol; 7 | 8 | using Xunit; 9 | 10 | namespace Microsoft.Azure.SignalR.Protocols.Tests.Models; 11 | public class GroupMemberTests 12 | { 13 | [Fact] 14 | public void TestMessagePackSerialization() 15 | { 16 | var groupMember = new GroupMember() { ConnectionId = "conn", UserId = "userId" }; 17 | var buffer = new ArrayBufferWriter(); 18 | var protocol = new ServiceProtocol(); 19 | protocol.WriteMessagePayload(groupMember, buffer); 20 | var deserialized = protocol.ParseMessagePayload(new ReadOnlySequence(buffer.WrittenMemory)); 21 | Assert.Equal(groupMember, deserialized); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/TestClasses/TestBaseServiceConnectionContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | 7 | using Microsoft.Azure.SignalR.Protocol; 8 | using Microsoft.Extensions.Logging; 9 | using Microsoft.Extensions.Logging.Abstractions; 10 | 11 | namespace Microsoft.Azure.SignalR.Tests.Common; 12 | 13 | internal sealed class TestBaseServiceConnectionContainer( 14 | List serviceConnections, 15 | HubServiceEndpoint endpoint = null, 16 | ILogger logger = null) : ServiceConnectionContainerBase(null, 0, endpoint, serviceConnections, logger: logger ?? NullLogger.Instance) 17 | { 18 | public override Task HandlePingAsync(PingMessage pingMessage) 19 | { 20 | return Task.CompletedTask; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/Rest/BinaryPayloadContentBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Net.Http; 7 | 8 | using Microsoft.AspNetCore.SignalR.Protocol; 9 | 10 | #nullable enable 11 | 12 | namespace Microsoft.Azure.SignalR.Common; 13 | 14 | internal class BinaryPayloadContentBuilder : IPayloadContentBuilder 15 | { 16 | private readonly IReadOnlyList _hubProtocols; 17 | 18 | public BinaryPayloadContentBuilder(IReadOnlyList hubProtocols) 19 | { 20 | _hubProtocols = hubProtocols; 21 | } 22 | 23 | public HttpContent? Build(HubMessage? payload, Type? typeHint) 24 | { 25 | return payload == null ? null : (HttpContent)new BinaryPayloadMessageContent(payload, _hubProtocols); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/StaticRandom.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.Azure.SignalR 7 | { 8 | internal sealed class StaticRandom 9 | { 10 | private static readonly object RandomLock = new object(); 11 | private static readonly Random RandomInterval = new Random((int)DateTime.UtcNow.Ticks); 12 | 13 | public static int Next(int maxValue) 14 | { 15 | lock (RandomLock) 16 | { 17 | return RandomInterval.Next(maxValue); 18 | } 19 | } 20 | 21 | public static int Next(int minValue, int maxValue) 22 | { 23 | lock (RandomLock) 24 | { 25 | return RandomInterval.Next(minValue, maxValue); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/Rest/JsonPayloadContentBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Net.Http; 6 | 7 | using Azure.Core.Serialization; 8 | 9 | using Microsoft.AspNetCore.SignalR.Protocol; 10 | 11 | #nullable enable 12 | namespace Microsoft.Azure.SignalR.Common; 13 | 14 | internal class JsonPayloadContentBuilder : IPayloadContentBuilder 15 | { 16 | private readonly ObjectSerializer _jsonObjectSerializer; 17 | 18 | public JsonPayloadContentBuilder(ObjectSerializer jsonObjectSerializer) 19 | { 20 | _jsonObjectSerializer = jsonObjectSerializer; 21 | } 22 | 23 | public HttpContent? Build(HubMessage? payload, Type? typeHint) 24 | { 25 | return payload == null ? null : new JsonPayloadMessageContent(payload, _jsonObjectSerializer, typeHint); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Diagnostics; 5 | 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | 9 | namespace ChatSample.RazorPages.Pages; 10 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 11 | [IgnoreAntiforgeryToken] 12 | public class ErrorModel : PageModel 13 | { 14 | public string? RequestId { get; set; } 15 | 16 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 17 | 18 | private readonly ILogger _logger; 19 | 20 | public ErrorModel(ILogger logger) 21 | { 22 | _logger = logger; 23 | } 24 | 25 | public void OnGet() 26 | { 27 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/Startup/AzureSignalRConnectionBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Reflection; 6 | 7 | using Microsoft.AspNetCore.Connections; 8 | using Microsoft.AspNetCore.SignalR; 9 | 10 | namespace Microsoft.Azure.SignalR 11 | { 12 | internal static class AzureSignalRConnectionBuilderExtensions 13 | { 14 | private static readonly MethodInfo _useHubMethod = typeof(SignalRConnectionBuilderExtensions).GetMethod(nameof(SignalRConnectionBuilderExtensions.UseHub)); 15 | 16 | // A late bound version of UseHub 17 | public static IConnectionBuilder UseHub(this IConnectionBuilder builder, Type hubType) 18 | { 19 | return (IConnectionBuilder)_useHubMethod.MakeGenericMethod(hubType).Invoke(null, new object[] { builder }); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/ServerConnections/ConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace Microsoft.Azure.SignalR.AspNet; 9 | 10 | #nullable enable 11 | 12 | internal class ConnectionFactory : ConnectionFactoryBase 13 | { 14 | public ConnectionFactory(IServerNameProvider nameProvider, ILoggerFactory loggerFactory) : base(nameProvider, loggerFactory) 15 | { 16 | } 17 | 18 | protected override void SetInternalUserAgent(IDictionary headers) 19 | { 20 | // Fix issue: https://github.com/Azure/azure-signalr/issues/198 21 | // .NET Framework has restriction about reserved string as the header name like "User-Agent" 22 | headers[Constants.AsrsUserAgent] = ProductInfo.GetProductInfo(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/HubEmulator/IUpstreamMessageHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Buffers; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | using Microsoft.AspNetCore.SignalR; 9 | using Microsoft.Azure.SignalR.Serverless.Common; 10 | 11 | namespace Microsoft.Azure.SignalR.Emulator.HubEmulator 12 | { 13 | internal interface IUpstreamMessageHandler 14 | { 15 | Task AddClientConnectionAsync(HubConnectionContext connection, CancellationToken token = default); 16 | 17 | Task RemoveClientConnectionAsync(HubConnectionContext connection, string error, CancellationToken token = default); 18 | 19 | Task> WriteMessageAsync(HubConnectionContext connection, ServerlessProtocol.InvocationMessage message, CancellationToken token = default); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Common.Tests/Auth/AccessKeyTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | using Xunit; 8 | 9 | namespace Microsoft.Azure.SignalR.Common.Tests.Auth; 10 | 11 | public class AccessKeyTests 12 | { 13 | private const string Audience = "https://localhost/aspnetclient?hub=testhub"; 14 | 15 | private const string SigningKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 16 | 17 | [Fact] 18 | public async Task TestGenerateAccessToken() 19 | { 20 | var accessKey = new AccessKey(SigningKey); 21 | var token = await accessKey.GenerateAccessTokenAsync(Audience, [], TimeSpan.FromHours(1), AccessTokenAlgorithm.HS256); 22 | Assert.True(TokenUtilities.TryParseIssuer(token, out var iss)); 23 | Assert.Equal(Constants.AsrsTokenIssuer, iss); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /eng/Export-API.ps1: -------------------------------------------------------------------------------- 1 | # Path to the root directory containing the src folder 2 | $srcPath = Resolve-Path "$PSScriptRoot/../src" 3 | 4 | # Enumerate all .csproj files under src/**/ directory, excluding any in the src/submodules folder 5 | $csprojFiles = Get-ChildItem -Path $srcPath -Recurse -Filter "*.csproj" | Where-Object { 6 | $projectDir = $_.DirectoryName 7 | # Exclude files in the src/submodules folder 8 | -not ($projectDir -like "$srcPath\submodules\*") 9 | } 10 | if ($csprojFiles.Count -gt 0) { 11 | # Iterate over each found .csproj file 12 | foreach ($csproj in $csprojFiles) { 13 | # Log which project will be built 14 | Write-Host "Building project: $($csproj.FullName)" 15 | 16 | # Run dotnet build with the necessary parameters for each project 17 | dotnet build -v diag $csproj.FullName /p:GenerateApiListingOnBuild=true /p:Configuration=Release /restore 18 | } 19 | } else { 20 | Write-Host "No .csproj files found in the src directory." 21 | } -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ErrorModel 3 | @{ 4 | ViewData["Title"] = "Error"; 5 | } 6 | 7 |

Error.

8 |

An error occurred while processing your request.

9 | 10 | @if (Model.ShowRequestId) 11 | { 12 |

13 | Request ID: @Model.RequestId 14 |

15 | } 16 | 17 |

Development Mode

18 |

19 | Swapping to the Development environment displays detailed information about the error that occurred. 20 |

21 |

22 | The Development environment shouldn't be enabled for deployed applications. 23 | It can result in displaying sensitive information from exceptions to end users. 24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 25 | and restarting the app. 26 |

27 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Endpoints/IConfigurationExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | using Microsoft.Extensions.Configuration; 8 | 9 | namespace Microsoft.Azure.SignalR 10 | { 11 | internal static class IConfigurationExtension 12 | { 13 | /// 14 | /// 15 | public static IEnumerable GetEndpoints(this IConfiguration configuration, string sectionName) 16 | { 17 | var section = configuration.GetSection(sectionName); 18 | return section.AsEnumerable(true) 19 | .Where(entry => !string.IsNullOrEmpty(entry.Value)) 20 | .Select(entry => new ServiceEndpoint(entry.Key, entry.Value)); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/TaskExtenstions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace System.Threading.Tasks; 5 | 6 | #nullable enable 7 | 8 | internal static class TaskExtenstions 9 | { 10 | public static async Task OrCancelAsync(this Task task, CancellationToken token, string? message = null) 11 | { 12 | var tcs = new TaskCompletionSource(); 13 | token.Register(() => tcs.TrySetResult(null)); 14 | 15 | var anyTask = await Task.WhenAny(task, tcs.Task); 16 | 17 | if (anyTask == task) 18 | { 19 | // make sure the task throws exception if any 20 | await anyTask; 21 | tcs.TrySetCanceled(); 22 | } 23 | else 24 | { 25 | throw message == null ? new TaskCanceledException() : new TaskCanceledException(message); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/Models/IMessagePackSerializable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using MessagePack; 5 | 6 | namespace Microsoft.Azure.SignalR.Protocol; 7 | internal interface IMessagePackSerializable 8 | { 9 | void Serialize(ref MessagePackWriter writer); 10 | 11 | //.NET Standard 2.0 dones't support static abstract members. 12 | //As a workaround, we have to new an instance, and then load members from reader. 13 | void Load(ref MessagePackReader reader, string fieldName); 14 | } 15 | 16 | internal static class IMessagePackSerializableExtensions 17 | { 18 | public static TSelf Deserialize(ref this MessagePackReader reader, string fieldName) where TSelf : IMessagePackSerializable, new() 19 | { 20 | var result = new TSelf(); 21 | result.Load(ref reader, fieldName); 22 | return result; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/Startup/AzureSignalRStartupFilter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #if !NETSTANDARD2_0 5 | using System; 6 | 7 | using Microsoft.AspNetCore.Builder; 8 | using Microsoft.AspNetCore.Hosting; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | namespace Microsoft.Azure.SignalR 12 | { 13 | internal class AzureSignalRStartupFilter : IStartupFilter 14 | { 15 | public Action Configure(Action build) 16 | { 17 | return app => 18 | { 19 | build(app); 20 | 21 | // This can't be a hosted service because it needs to run after startup 22 | var service = app.ApplicationServices.GetRequiredService(); 23 | service.Start(); 24 | }; 25 | } 26 | } 27 | } 28 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/IServiceHubContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading.Tasks; 5 | 6 | using Microsoft.AspNetCore.SignalR; 7 | 8 | namespace Microsoft.Azure.SignalR.Management 9 | { 10 | /// 11 | /// A context abstraction for a hub. 12 | /// 13 | public interface IServiceHubContext : IHubContext 14 | { 15 | /// 16 | /// Gets a user group manager instance which implements that can be used to add and remove users to named groups. 17 | /// 18 | IUserGroupManager UserGroups { get; } 19 | 20 | /// 21 | /// Dispose instances of asynchronously. 22 | /// 23 | /// 24 | Task DisposeAsync(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/ServerConnections/ConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace Microsoft.Azure.SignalR; 9 | 10 | #nullable enable 11 | 12 | internal class ConnectionFactory : ConnectionFactoryBase 13 | { 14 | public ConnectionFactory(IServerNameProvider nameProvider, 15 | ILoggerFactory loggerFactory) : base(nameProvider, loggerFactory) 16 | { 17 | } 18 | 19 | protected override void SetInternalUserAgent(IDictionary headers) 20 | { 21 | // Fix issue: https://github.com/Azure/azure-signalr/issues/198 22 | // .NET Framework has restriction about reserved string as the header name like "User-Agent" 23 | headers[Constants.AsrsUserAgent] = ProductInfo.GetProductInfo(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/TestClasses/TestServiceConnectionContainerFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | using Microsoft.Azure.SignalR.Protocol; 8 | 9 | namespace Microsoft.Azure.SignalR.Tests.Common; 10 | 11 | internal class TestServiceConnectionContainerFactory(SortedList output) : IServiceConnectionContainerFactory 12 | { 13 | private readonly SortedList _messages = output; 14 | 15 | public IServiceConnectionContainer Create(string hub, TimeSpan? serviceScaleTimeout = null) 16 | { 17 | return new TestServiceConnectionContainer(hub, 18 | m => 19 | { 20 | lock (_messages) 21 | { 22 | _messages.Add(hub, m.Item1); 23 | } 24 | }); 25 | } 26 | } -------------------------------------------------------------------------------- /docs/advanced-topics/transport-configuration.md: -------------------------------------------------------------------------------- 1 | # Transport configuration 2 | 3 | Currently, Azure SignalR Service supports configuring the transport type between clients and service. You can specify the transport type for each client by setting `ServiceOptions.TransportTypeDetector`. 4 | The `TransportTypeDetector` is a function which takes the `HttpContext` during negotiation as parameter and returns a bit mask combining one or more transport type values. 5 | 6 | For example, if you want to disable Server-Sent Event (enable only WebSocket and Long Polling) for all clients, you can set a transport type detector when you add Azure SignalR Service as a dependency: 7 | 8 | ```cs 9 | public void ConfigureServices(IServiceCollection services) 10 | { 11 | services.AddSignalR().AddAzureSignalR(o => 12 | { 13 | o.TransportTypeDetector = (httpContext) => Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets | Microsoft.AspNetCore.Http.Connections.HttpTransportType.LongPolling; 14 | }); 15 | } 16 | ``` 17 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Extensions/HttpResponseExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.Extensions.Primitives; 6 | 7 | namespace Microsoft.Azure.SignalR; 8 | 9 | #nullable enable 10 | 11 | internal static class HttpResponseExtensions 12 | { 13 | public static bool IsSuccessStatusCode(this HttpResponse response) => 14 | response.StatusCode >= 200 && response.StatusCode <= 299; 15 | 16 | public static void SetMsErrorCodeHeader(this HttpResponse response, string code) 17 | { 18 | if (!string.IsNullOrEmpty(code)) 19 | { 20 | const string MSErrorCodeKey = "x-ms-error-code"; 21 | if (!response.Headers.ContainsKey(MSErrorCodeKey)) 22 | { 23 | response.Headers[MSErrorCodeKey] = new StringValues(code); 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/Serialization/SerializationDependencyInjectionExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Azure.Core.Serialization; 7 | 8 | using Microsoft.AspNetCore.SignalR.Protocol; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | namespace Microsoft.Azure.SignalR.Management; 12 | 13 | internal static class SerializationDependencyInjectionExtensions 14 | { 15 | public static IServiceCollection AddNewtonsoftHubProtocol(this IServiceCollection services, Action configure) 16 | { 17 | var options = new NewtonsoftServiceHubProtocolOptions(); 18 | configure?.Invoke(options); 19 | services.AddSingleton(new JsonObjectSerializerHubProtocol(new NewtonsoftJsonObjectSerializer(options.PayloadSerializerSettings))); 20 | return services; 21 | } 22 | } -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.IntegrationTests/Infrastructure/MessageOrderTests/TestHubBroadcastNCallsInvocationBinder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | using Microsoft.AspNetCore.SignalR; 8 | 9 | namespace Microsoft.Azure.SignalR.IntegrationTests.Infrastructure.MessageOrderTests 10 | { 11 | internal sealed class TestHubBroadcastNCallsInvocationBinder : IInvocationBinder 12 | { 13 | public IReadOnlyList GetParameterTypes(string methodName) 14 | { 15 | return new List(new Type[] { typeof(int) }); 16 | } 17 | 18 | public Type GetReturnType(string invocationId) 19 | { 20 | return typeof(bool); 21 | } 22 | 23 | public Type GetStreamItemType(string streamId) 24 | { 25 | return typeof(object); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/SkipIfMultiEndpointsAbsentFactAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Linq; 5 | 6 | using Xunit; 7 | 8 | namespace Microsoft.Azure.SignalR.Tests.Common 9 | { 10 | public class SkipIfMultiEndpointsAbsentFactAttribute : FactAttribute 11 | { 12 | private const string SkipReason = $"There are no multiple connection-string-based named endpoints under '{Constants.Keys.AzureSignalREndpointsKey}'."; 13 | 14 | public SkipIfMultiEndpointsAbsentFactAttribute() 15 | { 16 | Skip = MultiEndpointsExist() ? null : SkipReason; 17 | } 18 | 19 | private static bool MultiEndpointsExist() 20 | { 21 | var config = TestConfiguration.Instance.Configuration; 22 | return config.GetEndpoints(Constants.Keys.AzureSignalREndpointsKey).Count() > 1; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/EndpointProvider/ServiceEndpointManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Microsoft.Azure.SignalR.AspNet; 7 | 8 | internal class ServiceEndpointManager : ServiceEndpointManagerBase 9 | { 10 | private readonly ServiceOptions _options; 11 | 12 | public ServiceEndpointManager(ServiceOptions options, 13 | ILoggerFactory loggerFactory) : 14 | base(options, 15 | loggerFactory?.CreateLogger()) 16 | { 17 | _options = options; 18 | } 19 | 20 | public override IServiceEndpointProvider GetEndpointProvider(ServiceEndpoint endpoint) 21 | { 22 | if (endpoint == null) 23 | { 24 | return null; 25 | } 26 | return new ServiceEndpointProvider(endpoint, _options); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests.Common/Retry/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace Microsoft.Azure.SignalR.Tests; 9 | 10 | #nullable enable 11 | 12 | public static class EnumerableExtensions 13 | { 14 | public static bool ContainsAny(this IEnumerable values, T[] searchFor, IEqualityComparer? comparer = null) 15 | { 16 | #if NET6_0_OR_GREATER 17 | ArgumentNullException.ThrowIfNull(searchFor); 18 | #else 19 | if (searchFor == null) 20 | { 21 | throw new ArgumentNullException(nameof(searchFor)); 22 | } 23 | #endif 24 | 25 | comparer ??= EqualityComparer.Default; 26 | 27 | return searchFor.Length != 0 && 28 | values.Any(val => searchFor.Any(search => comparer.Equals(val, search))); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Endpoints/EndpointMetrics.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.Azure.SignalR 5 | { 6 | public class EndpointMetrics 7 | { 8 | /// 9 | /// total concurrent connected client connection count on all hubs. 10 | /// 11 | public int ClientConnectionCount { get; internal set; } 12 | 13 | /// 14 | /// total concurrent connected server connection count on all hubs. 15 | /// 16 | public int ServerConnectionCount { get; internal set; } 17 | 18 | /// 19 | /// connection quota for this instance, including client and server connections. 20 | /// 21 | public int ConnectionCapacity { get; internal set; } 22 | } 23 | } -------------------------------------------------------------------------------- /samples/ChatSample.Cli/ChatSample.Cli.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | true 9 | 10 | 11 | 12 | 13 | PreserveNewest 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Common/TextMessageFormatter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Buffers; 5 | 6 | namespace Microsoft.Azure.SignalR 7 | { 8 | /// 9 | /// Copied from https://github.com/dotnet/aspnetcore/blob/d9660d157627af710b71c636fa8cb139616cadba/src/SignalR/common/Shared/TextMessageFormatter.cs 10 | /// 11 | internal static class TextMessageFormatter 12 | { 13 | // This record separator is supposed to be used only for JSON payloads where 0x1e character 14 | // will not occur (is not a valid character) and therefore it is safe to not escape it 15 | public const byte RecordSeparator = 0x1e; 16 | 17 | public static void WriteRecordSeparator(IBufferWriter output) 18 | { 19 | var buffer = output.GetSpan(1); 20 | buffer[0] = RecordSeparator; 21 | output.Advance(1); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.AspNet.Tests/TestClasses/TestEndpointRouter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | using Microsoft.Owin; 8 | 9 | namespace Microsoft.Azure.SignalR.AspNet.Tests; 10 | 11 | internal class TestEndpointRouter : EndpointRouterDecorator 12 | { 13 | public TestEndpointRouter() : base() 14 | { 15 | } 16 | 17 | public override ServiceEndpoint GetNegotiateEndpoint(IOwinContext context, IEnumerable endpoints) 18 | { 19 | var endpointName = context.Request.Query["endpoint"]; 20 | if (string.IsNullOrEmpty(endpointName)) 21 | { 22 | context.Response.StatusCode = 400; 23 | context.Response.Write("Invalid request."); 24 | return null; 25 | } 26 | 27 | return endpoints.First(s => s.Name == endpointName && s.Online); 28 | } 29 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Utilities/ProductInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace Microsoft.Azure.SignalR; 8 | 9 | internal static class ProductInfo 10 | { 11 | public static string GetProductInfo(Assembly assembly = null) 12 | { 13 | assembly ??= Assembly.GetCallingAssembly(); 14 | var packageId = assembly.GetName().Name; 15 | var version = assembly.GetCustomAttribute().InformationalVersion; 16 | var runtime = RuntimeInformation.FrameworkDescription?.Trim(); 17 | var operatingSystem = RuntimeInformation.OSDescription?.Trim(); 18 | var processorArchitecture = RuntimeInformation.ProcessArchitecture.ToString().Trim(); 19 | return $"{packageId}/{version} ({runtime}; {operatingSystem}; {processorArchitecture})"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Azure.SignalR.Emulator.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] 8 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/ManagementConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.Extensions.Options; 8 | 9 | namespace Microsoft.Azure.SignalR.Management; 10 | 11 | #nullable enable 12 | 13 | internal class ManagementConnectionFactory(IOptions context, 14 | IServerNameProvider serverNameProvider, 15 | ILoggerFactory loggerFactory) 16 | : ConnectionFactoryBase(serverNameProvider, loggerFactory) 17 | { 18 | private readonly string? _productInfo = context.Value.ProductInfo; 19 | 20 | protected override void SetInternalUserAgent(IDictionary headers) 21 | { 22 | headers[Constants.AsrsUserAgent] = _productInfo ?? ProductInfo.GetProductInfo(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/Utils.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | using Xunit; 8 | 9 | namespace Microsoft.Azure.SignalR.Tests 10 | { 11 | internal sealed class Utils 12 | { 13 | public static async Task PollWait(Func pollFunc, int count = 5) 14 | { 15 | var result = false; 16 | var times = 0; 17 | while (!result) 18 | { 19 | times++; 20 | result = pollFunc(); 21 | if (result) 22 | { 23 | return; 24 | } 25 | else if (times > count) 26 | { 27 | break; 28 | } 29 | 30 | await Task.Delay(1000); 31 | } 32 | 33 | Assert.Fail("Poll wait failed"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/ProductInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Reflection; 5 | 6 | namespace Microsoft.Azure.SignalR.AspNet; 7 | 8 | #nullable enable 9 | 10 | internal static class ProductInfo 11 | { 12 | /// 13 | /// For .NET framework below netframework462, there are assembly binding issues when referencing netstandard assemblies, https://github.com/Azure/azure-signalr/issues/452 14 | /// For now, disable usage of System.Runtime.InteropServices.RuntimeInformation 15 | /// 16 | /// 17 | public static string GetProductInfo() 18 | { 19 | var assembly = Assembly.GetCallingAssembly(); 20 | var packageId = assembly.GetName().Name; 21 | var version = assembly.GetCustomAttribute().InformationalVersion; 22 | 23 | return $"{packageId}/{version}"; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.IntegrationTests/Infrastructure/MessageOrderTests/HotReloadTestHub.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | using Microsoft.AspNetCore.SignalR; 8 | 9 | namespace Microsoft.Azure.SignalR.IntegrationTests.Infrastructure.MessageOrderTests 10 | { 11 | public class HotReloadTestHub : Hub 12 | { 13 | public bool BroadcastNumCalls(int numCalls) 14 | { 15 | var all = Clients.All; 16 | Task.Run(async () => { 17 | for (int i = 0; i < numCalls;) 18 | { 19 | await all.SendAsync("Callback", ++i); 20 | } 21 | 22 | // hang the task so its execution context (and stuff it carries) is "leaked" 23 | await Task.Delay(TimeSpan.FromHours(1)); 24 | }); 25 | return true; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐞 Bug report 3 | about: Create a report about something that is not working 4 | --- 5 | 6 | 7 | ### Describe the bug 8 | A clear and concise description of what the bug is. 9 | 10 | ### To Reproduce 11 | 19 | 20 | ### Exceptions (if any) 21 | 24 | 25 | ### Further technical details 26 | - Your Azure SignalR SDK version 27 | - Your Server ASPNETCORE version or Assembly version of `Microsoft.AspNetCore.SignalR` 28 | - Your SignalR Client SDK version 29 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.Azure.SignalR.AspNet.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | [assembly: InternalsVisibleTo("Microsoft.Azure.SignalR.AspNet.E2ETests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 8 | 9 | -------------------------------------------------------------------------------- /samples/AspNet.ChatSample/AspNet.ChatSample.JavaScriptClient/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | namespace AspNet.ChatSample.JavaScriptClient 9 | { 10 | public class Startup 11 | { 12 | // This method gets called by the runtime. Use this method to add services to the container. 13 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 14 | public void ConfigureServices(IServiceCollection services) 15 | { 16 | } 17 | 18 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 19 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 20 | { 21 | app.UseFileServer(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IClientConnection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading.Tasks; 5 | 6 | namespace Microsoft.Azure.SignalR; 7 | 8 | #nullable enable 9 | 10 | internal interface IClientConnection 11 | { 12 | /// 13 | /// The connection id. 14 | /// 15 | string ConnectionId { get; } 16 | 17 | /// 18 | /// The instance id. 19 | /// 20 | string InstanceId { get; } 21 | 22 | /// 23 | /// The connection protocol being used. 24 | /// JSON / MesssagePack 25 | /// 26 | string HubProtocol { get; } 27 | 28 | /// 29 | /// The server connection associated with this client connection. 30 | /// 31 | IServiceConnection? ServiceConnection { get; set; } 32 | 33 | Task PauseAsync(); 34 | 35 | Task PauseAckAsync(); 36 | 37 | Task ResumeAsync(); 38 | } 39 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IServiceConnection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | using Microsoft.Azure.SignalR.Protocol; 9 | 10 | namespace Microsoft.Azure.SignalR; 11 | 12 | #nullable enable 13 | 14 | internal interface IServiceConnection 15 | { 16 | string ConnectionId { get; } 17 | 18 | string ServerId { get; } 19 | 20 | ServiceConnectionStatus Status { get; } 21 | 22 | Task ConnectionInitializedTask { get; } 23 | 24 | Task ConnectionOfflineTask { get; } 25 | 26 | Task CloseClientConnections(CancellationToken token); 27 | 28 | event Action ConnectionStatusChanged; 29 | 30 | Task StartAsync(string? target = null); 31 | 32 | Task StopAsync(); 33 | 34 | Task WriteAsync(ServiceMessage serviceMessage); 35 | 36 | Task SafeWriteAsync(ServiceMessage serviceMessage); 37 | } 38 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/IUserGroupHubLifetimeManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace Microsoft.Azure.SignalR.Management 9 | { 10 | internal interface IUserGroupHubLifetimeManager 11 | { 12 | Task UserAddToGroupAsync(string userId, string groupName, CancellationToken cancellationToken = default); 13 | 14 | Task UserAddToGroupAsync(string userId, string groupName, TimeSpan ttl, CancellationToken cancellationToken = default); 15 | 16 | Task UserRemoveFromGroupAsync(string userId, string groupName, CancellationToken cancellationToken = default); 17 | 18 | Task UserRemoveFromAllGroupsAsync(string userId, CancellationToken cancellationToken = default); 19 | 20 | Task IsUserInGroup(string userId, string groupName, CancellationToken cancellationToken = default); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Upstreams/InvokeUpstreamParameters.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Text; 5 | 6 | namespace Microsoft.Azure.SignalR.Emulator; 7 | 8 | internal class InvokeUpstreamParameters 9 | { 10 | public InvokeUpstreamParameters(string hub, string category, string @event) 11 | { 12 | Hub = hub; 13 | Category = category; 14 | Event = @event; 15 | } 16 | 17 | public string Hub { get; } 18 | public string Category { get; } 19 | public string Event { get; } 20 | 21 | public override string ToString() 22 | { 23 | var sb = new StringBuilder(); 24 | sb.Append("{hub}="); 25 | sb.Append(Hub); 26 | sb.Append(','); 27 | sb.Append("{event}="); 28 | sb.Append(Event); 29 | sb.Append(','); 30 | sb.Append("{category}="); 31 | sb.Append(Category); 32 | return sb.ToString(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/ServiceMessages/MessageWithTracingIdHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading; 6 | 7 | namespace Microsoft.Azure.SignalR 8 | { 9 | internal static class MessageWithTracingIdHelper 10 | { 11 | internal static ulong Prefix { get; set; } = (ulong)(Guid.NewGuid().GetHashCode() & 0x0FFF_FFFF) << 32; 12 | private static int _index = -1; 13 | 14 | // message tracing id is constructed in the format: 15 | // from most significant digit to least significant digit: 16 | // 8 hex digits: prefix of the server 17 | // 8 hex digits: message index 18 | // Usage: 19 | // - Messaging log category is enabled 20 | // - EnableMessageTracing is true for Management SDK 21 | public static ulong Generate() 22 | { 23 | return Prefix + (uint)Interlocked.Increment(ref _index); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /samples/BlazorAppSample/Data/WeatherForecastService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace BlazorAppSample.Data 9 | { 10 | public class WeatherForecastService 11 | { 12 | private static readonly string[] Summaries = new[] 13 | { 14 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 15 | }; 16 | 17 | public Task GetForecastAsync(DateTime startDate) 18 | { 19 | var rng = new Random(); 20 | return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast 21 | { 22 | Date = startDate.AddDays(index), 23 | TemperatureC = rng.Next(-20, 55), 24 | Summary = Summaries[rng.Next(Summaries.Length)] 25 | }).ToArray()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Emulator/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $(NoWarn);CS1591 6 | true 7 | aspnetcore;azure;signalr 8 | false 9 | false 10 | 11 | 12 | 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | all 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/AspNet.ChatSample/AspNet.ChatSample.SelfHostServer/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.AspNet/Transports/AzureTransportManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNet.SignalR; 5 | using Microsoft.AspNet.SignalR.Hosting; 6 | using Microsoft.AspNet.SignalR.Transports; 7 | 8 | namespace Microsoft.Azure.SignalR.AspNet 9 | { 10 | internal class AzureTransportManager : ITransportManager 11 | { 12 | private readonly IDependencyResolver _resolver; 13 | 14 | public AzureTransportManager(IDependencyResolver resolver) 15 | { 16 | _resolver = resolver; 17 | } 18 | 19 | public ITransport GetTransport(HostContext hostContext) 20 | { 21 | return new AzureTransport(hostContext, _resolver); 22 | } 23 | 24 | public bool SupportsTransport(string transportName) 25 | { 26 | // This is only called for websockets, and should never be called in this flow 27 | return false; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Serverless.Protocols/ServerlessMessage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | #nullable enable 4 | 5 | using Newtonsoft.Json; 6 | 7 | namespace Microsoft.Azure.SignalR.Serverless.Protocols; 8 | 9 | public abstract class ServerlessMessage 10 | { 11 | [JsonProperty(PropertyName = "type")] 12 | public int Type { get; set; } 13 | } 14 | 15 | public class InvocationMessage : ServerlessMessage 16 | { 17 | [JsonProperty(PropertyName = "invocationId")] 18 | public string? InvocationId { get; set; } 19 | 20 | [JsonProperty(PropertyName = "target")] 21 | public string? Target { get; set; } 22 | 23 | [JsonProperty(PropertyName = "arguments")] 24 | public object?[]? Arguments { get; set; } 25 | } 26 | 27 | public class OpenConnectionMessage : ServerlessMessage 28 | { 29 | } 30 | 31 | public class CloseConnectionMessage : ServerlessMessage 32 | { 33 | [JsonProperty(PropertyName = "error")] 34 | public string? Error { get; set; } 35 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Exceptions/AzureSignalRInvalidArgumentException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Runtime.Serialization; 6 | 7 | namespace Microsoft.Azure.SignalR.Common 8 | { 9 | [Serializable] 10 | public class AzureSignalRInvalidArgumentException : AzureSignalRException 11 | { 12 | private const string ErrorMessage = "Invalid argument. Caused by one or more of the following reasons:"; 13 | 14 | public AzureSignalRInvalidArgumentException(string requestUri, Exception innerException, string detail) : base(string.IsNullOrEmpty(requestUri) ? $"{ErrorMessage} {detail}" : $"{ErrorMessage} {detail} Request Uri: {requestUri}", innerException) 15 | { 16 | } 17 | 18 | #if NET8_0_OR_GREATER 19 | [Obsolete] 20 | #endif 21 | protected AzureSignalRInvalidArgumentException(SerializationInfo info, StreamingContext context) : base(info, context) 22 | { 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/Configuration/CascadeServiceOptionsSetup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Azure.SignalR.Management.Configuration; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Microsoft.Azure.SignalR.Management 8 | { 9 | internal class CascadeServiceOptionsSetup : CascadeOptionsSetup 10 | { 11 | public CascadeServiceOptionsSetup(IOptionsMonitor sourceMonitor) : base(sourceMonitor) 12 | { 13 | } 14 | 15 | protected override void Convert(ServiceOptions target, ServiceManagerOptions source) 16 | { 17 | target.ConnectionString = source.ConnectionString; 18 | target.ApplicationName = source.ApplicationName; 19 | target.Endpoints = source.ServiceEndpoints; 20 | target.Proxy = source.Proxy; 21 | target.InitialHubServerConnectionCount = source.ConnectionCount; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /eng/ApiListing.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <_SupportsApiListing Condition="'$(GenerateApiListingOnBuild)' == 'true' AND '$(GenerateAPIListing)' == 'true'">true 5 | true 6 | 7 | 8 | 12 | 13 | 14 | <_RefSourceOutputPath>$(MSBuildThisFileDirectory)../api 15 | $(_RefSourceOutputPath)/$(AssemblyName).$(TargetFramework).cs 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Common/TextMessageParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Buffers; 5 | 6 | namespace Microsoft.Azure.SignalR 7 | { 8 | /// 9 | /// The same as https://github.com/aspnet/SignalR/blob/release/2.2/src/Common/TextMessageParser.cs 10 | /// 11 | internal static class TextMessageParser 12 | { 13 | public const byte RecordSeparator = 0x1e; 14 | 15 | public static bool TryParseMessage(ref ReadOnlySequence buffer, out ReadOnlySequence payload) 16 | { 17 | var position = buffer.PositionOf(RecordSeparator); 18 | if (position == null) 19 | { 20 | payload = default; 21 | return false; 22 | } 23 | 24 | payload = buffer.Slice(0, position.Value); 25 | 26 | // Skip record separator 27 | buffer = buffer.Slice(buffer.GetPosition(1, position.Value)); 28 | 29 | return true; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Common/Interfaces/IConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | using Microsoft.AspNetCore.Connections; 8 | 9 | namespace Microsoft.Azure.SignalR; 10 | 11 | #nullable enable 12 | 13 | internal interface IConnectionFactory 14 | { 15 | Task ConnectAsync(HubServiceEndpoint endpoint, 16 | TransferFormat transferFormat, 17 | string connectionId, 18 | string target, 19 | CancellationToken cancellationToken = default); 20 | 21 | // Current plan for IAsyncDisposable is that DisposeAsync will NOT take a CancellationToken 22 | // https://github.com/dotnet/csharplang/blob/195efa07806284d7b57550e7447dc8bd39c156bf/proposals/async-streams.md#iasyncdisposable 23 | Task DisposeAsync(ConnectionContext connection); 24 | } 25 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/HubContext/UserGroupManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace Microsoft.Azure.SignalR.Management 9 | { 10 | public abstract class UserGroupManager : IUserGroupManager 11 | { 12 | public abstract Task AddToGroupAsync(string userId, string groupName, CancellationToken cancellationToken = default); 13 | 14 | public abstract Task AddToGroupAsync(string userId, string groupName, TimeSpan ttl, CancellationToken cancellationToken = default); 15 | 16 | public abstract Task IsUserInGroup(string userId, string groupName, CancellationToken cancellationToken = default); 17 | 18 | public abstract Task RemoveFromAllGroupsAsync(string userId, CancellationToken cancellationToken = default); 19 | 20 | public abstract Task RemoveFromGroupAsync(string userId, string groupName, CancellationToken cancellationToken = default); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Management/IServiceHubLifetimeManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | using Azure; 8 | 9 | using Microsoft.Azure.SignalR.Protocol; 10 | 11 | namespace Microsoft.Azure.SignalR.Management; 12 | 13 | #nullable enable 14 | 15 | internal interface IServiceHubLifetimeManager : IHubLifetimeManager, IUserGroupHubLifetimeManager, IStreamingHubLifetimeManager 16 | { 17 | Task CloseConnectionAsync(string connectionId, string reason, CancellationToken cancellationToken); 18 | 19 | Task ConnectionExistsAsync(string connectionId, CancellationToken cancellationToken); 20 | 21 | Task UserExistsAsync(string userId, CancellationToken cancellationToken); 22 | 23 | Task GroupExistsAsync(string groupName, CancellationToken cancellationToken); 24 | 25 | AsyncPageable ListConnectionsInGroup(string groupName, int? top = null, CancellationToken token = default); 26 | } 27 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Protocols/Models/GroupMember.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using MessagePack; 5 | 6 | using static Microsoft.Azure.SignalR.Protocol.MessagePackUtils; 7 | 8 | namespace Microsoft.Azure.SignalR.Protocol; 9 | 10 | /// 11 | /// Represents a connection in a group. 12 | /// 13 | public record GroupMember : IMessagePackSerializable 14 | { 15 | public string ConnectionId { get; set; } = string.Empty; 16 | 17 | public string? UserId { get; set; } 18 | 19 | void IMessagePackSerializable.Serialize(ref MessagePackWriter writer) 20 | { 21 | writer.WriteArrayHeader(2); 22 | writer.Write(ConnectionId); 23 | writer.Write(UserId); 24 | } 25 | 26 | void IMessagePackSerializable.Load(ref MessagePackReader reader, string fieldName) 27 | { 28 | _ = reader.ReadArrayHeader(); 29 | ConnectionId = ReadStringNotNull(ref reader, nameof(ConnectionId)); 30 | UserId = reader.ReadString(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR/Startup/AzureSignalRHostingStartup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #if !NETSTANDARD2_0 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Azure.SignalR; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Hosting; 10 | 11 | [assembly: HostingStartup(typeof(AzureSignalRHostingStartup))] 12 | 13 | namespace Microsoft.Azure.SignalR 14 | { 15 | internal class AzureSignalRHostingStartup : IHostingStartup 16 | { 17 | public void Configure(IWebHostBuilder builder) 18 | { 19 | builder.ConfigureServices((context, services) => 20 | { 21 | if (!context.HostingEnvironment.IsDevelopment() || context.Configuration.GetSection(Constants.Keys.AzureSignalREnabledKey).Get()) 22 | { 23 | services.AddSignalR().AddAzureSignalR(); 24 | } 25 | }); 26 | } 27 | } 28 | } 29 | #endif -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.AspNet.E2ETests/AspNetSignalRServiceE2EFacts.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | using Microsoft.AspNetCore.Testing.xunit; 8 | using Microsoft.Azure.SignalR.Tests.Common; 9 | 10 | using Xunit; 11 | using Xunit.Abstractions; 12 | 13 | namespace Microsoft.Azure.SignalR.AspNet.Tests 14 | { 15 | public class AspNetSignalRServiceE2EFacts : ServiceE2EFactsBase 16 | { 17 | public AspNetSignalRServiceE2EFacts(ITestOutputHelper output) 18 | : base(new TestServerFactory(), new TestClientSetFactory(), output) 19 | { 20 | } 21 | 22 | [ConditionalTheory] 23 | [SkipIfConnectionStringNotPresent] 24 | [MemberData(nameof(TestDataBase))] 25 | public Task RunE2ETests(string methodName, int expectedMessageCount, Func coreTask) 26 | { 27 | return RunE2ETestsBase(methodName, expectedMessageCount, coreTask); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /samples/ChatSample/ChatSample.RazorPages/Pages/Shared/_Layout.cshtml.css: -------------------------------------------------------------------------------- 1 | /* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | for details on configuring this project to bundle and minify static web assets. */ 3 | 4 | a.navbar-brand { 5 | white-space: normal; 6 | text-align: center; 7 | word-break: break-all; 8 | } 9 | 10 | a { 11 | color: #0077cc; 12 | } 13 | 14 | .btn-primary { 15 | color: #fff; 16 | background-color: #1b6ec2; 17 | border-color: #1861ac; 18 | } 19 | 20 | .nav-pills .nav-link.active, .nav-pills .show > .nav-link { 21 | color: #fff; 22 | background-color: #1b6ec2; 23 | border-color: #1861ac; 24 | } 25 | 26 | .border-top { 27 | border-top: 1px solid #e5e5e5; 28 | } 29 | .border-bottom { 30 | border-bottom: 1px solid #e5e5e5; 31 | } 32 | 33 | .box-shadow { 34 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 35 | } 36 | 37 | button.accept-policy { 38 | font-size: 1rem; 39 | line-height: inherit; 40 | } 41 | 42 | .footer { 43 | position: absolute; 44 | bottom: 0; 45 | width: 100%; 46 | white-space: nowrap; 47 | line-height: 60px; 48 | } 49 | -------------------------------------------------------------------------------- /test/Microsoft.Azure.SignalR.Tests/TestHubs/ConnectedHub.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | using Microsoft.AspNetCore.SignalR; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Microsoft.Azure.SignalR.Tests.TestHubs; 11 | 12 | internal sealed class ConnectedHub : Hub 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public ConnectedHub(ILogger logger) 17 | { 18 | _logger = logger; 19 | } 20 | public override async Task OnConnectedAsync() 21 | { 22 | while (!Context.ConnectionAborted.IsCancellationRequested) 23 | { 24 | await Clients.Clients(Context.ConnectionId).SendAsync("hello"); 25 | await Task.Delay(100); 26 | } 27 | } 28 | 29 | public override Task OnDisconnectedAsync(Exception exception) 30 | { 31 | _logger.LogInformation($"{Context.ConnectionId} disconnected: {exception}."); 32 | return Task.CompletedTask; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Microsoft.Azure.SignalR.Serverless.Protocols/IServerlessProtocol.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #nullable enable 5 | using System.Buffers; 6 | 7 | namespace Microsoft.Azure.SignalR.Serverless.Protocols; 8 | 9 | public interface IServerlessProtocol 10 | { 11 | // TODO: Have a discussion about how to handle version change. 12 | /// 13 | /// Gets the version of the protocol. 14 | /// 15 | int Version { get; } 16 | 17 | /// 18 | /// Creates a new from the specified serialized representation. 19 | /// 20 | /// The serialized representation of the message. 21 | /// When this method returns true, contains the parsed message. 22 | /// A value that is true if the was successfully parsed; otherwise, false. 23 | bool TryParseMessage(ref ReadOnlySequence input, out ServerlessMessage? message); 24 | } --------------------------------------------------------------------------------