From 94155b0e89888298d2abc62a00a424d604599211 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 10 Feb 2018 18:10:09 -0800 Subject: [PATCH] Use protocol.abstractions primitives instead of socket abstractions (#1432) --- build/dependencies.props | 91 ++++++++++--------- client-ts/FunctionalTests/EchoEndPoint.cs | 1 + .../PersistentConnectionLifeTimeManager.cs | 11 ++- .../SocialWeather/SocialWeatherEndPoint.cs | 4 +- .../EndPoints/MessagesEndPoint.cs | 6 +- samples/SocketsSample/Program.cs | 15 ++- .../HubConnectionContext.cs | 3 +- .../HubEndPoint.cs | 2 +- .../SignalRSocketBuilderExtensions.cs | 3 +- ...{SocketBuilder.cs => ConnectionBuilder.cs} | 13 +-- .../ConnectionContext.cs | 20 ---- .../DuplexPipe.cs | 49 ---------- .../ISocketBuilder.cs | 18 ---- ...oft.AspNetCore.Sockets.Abstractions.csproj | 1 + .../SocketBuilderExtensions.cs | 5 +- .../SocketDelegate.cs | 12 --- .../HttpConnectionContextExtensions.cs | 4 +- .../HttpConnectionDispatcher.cs | 25 ++--- .../SocketRouteBuilder.cs | 9 +- .../ConnectionList.cs | 1 + .../DefaultConnectionContext.cs | 4 +- src/Microsoft.AspNetCore.Sockets/EndPoint.cs | 1 + .../SocketBuilderExtensions.cs | 3 +- .../TestClient.cs | 2 +- .../EchoEndPoint.cs | 1 + .../DefaultHubProtocolResolverTests.cs | 1 + .../HttpConnectionDispatcherTests.cs | 55 +++++------ .../MapEndPointTests.cs | 1 + 28 files changed, 148 insertions(+), 213 deletions(-) rename src/Microsoft.AspNetCore.Sockets.Abstractions/{SocketBuilder.cs => ConnectionBuilder.cs} (61%) delete mode 100644 src/Microsoft.AspNetCore.Sockets.Abstractions/ConnectionContext.cs delete mode 100644 src/Microsoft.AspNetCore.Sockets.Abstractions/DuplexPipe.cs delete mode 100644 src/Microsoft.AspNetCore.Sockets.Abstractions/ISocketBuilder.cs delete mode 100644 src/Microsoft.AspNetCore.Sockets.Abstractions/SocketDelegate.cs diff --git a/build/dependencies.props b/build/dependencies.props index eea44544e8ff..aa84705921ef 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -7,51 +7,52 @@ 2.4.337 3.1.0 2.1.0-preview2-15698 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 0.5.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 0.5.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 4.5.0-preview2-26130-01 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 + 2.1.0-preview2-30073 2.0.0 2.1.0-preview2-26130-04 15.3.0 @@ -70,7 +71,7 @@ 4.5.0-preview2-26130-01 4.5.0-preview2-26130-01 2.3.1 - 2.3.1 + 2.4.0-beta.1.build3945 \ No newline at end of file diff --git a/client-ts/FunctionalTests/EchoEndPoint.cs b/client-ts/FunctionalTests/EchoEndPoint.cs index 0680acc8ca35..27460590ebf6 100644 --- a/client-ts/FunctionalTests/EchoEndPoint.cs +++ b/client-ts/FunctionalTests/EchoEndPoint.cs @@ -3,6 +3,7 @@ using System.IO.Pipelines; using System.Threading.Tasks; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets; namespace FunctionalTests diff --git a/samples/SocialWeather/PersistentConnectionLifeTimeManager.cs b/samples/SocialWeather/PersistentConnectionLifeTimeManager.cs index 01093214a685..577254ae1576 100644 --- a/samples/SocialWeather/PersistentConnectionLifeTimeManager.cs +++ b/samples/SocialWeather/PersistentConnectionLifeTimeManager.cs @@ -6,6 +6,7 @@ using System.IO; using System.IO.Pipelines; using System.Threading.Tasks; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets; using Microsoft.AspNetCore.Sockets.Features; @@ -23,9 +24,9 @@ public PersistentConnectionLifeTimeManager(FormatterResolver formatterResolver) public void OnConnectedAsync(ConnectionContext connection) { - connection.Metadata["groups"] = new HashSet(); + connection.Features.Get().Metadata["groups"] = new HashSet(); var format = connection.GetHttpContext().Request.Query["formatType"].ToString(); - connection.Metadata["format"] = format; + connection.Features.Get().Metadata["format"] = format; if (string.Equals(format, "protobuf", StringComparison.OrdinalIgnoreCase)) { var transferModeFeature = connection.Features.Get(); @@ -47,7 +48,7 @@ public async Task SendToAllAsync(T data) foreach (var connection in _connectionList) { var context = connection.GetHttpContext(); - var formatter = _formatterResolver.GetFormatter((string)connection.Metadata["format"]); + var formatter = _formatterResolver.GetFormatter((string)connection.Features.Get().Metadata["format"]); var ms = new MemoryStream(); await formatter.WriteAsync(data, ms); @@ -72,7 +73,7 @@ public Task InvokeUserAsync(string userId, object data) public void AddGroupAsync(ConnectionContext connection, string groupName) { - var groups = (HashSet)connection.Metadata["groups"]; + var groups = (HashSet)connection.Features.Get().Metadata["groups"]; lock (groups) { groups.Add(groupName); @@ -81,7 +82,7 @@ public void AddGroupAsync(ConnectionContext connection, string groupName) public void RemoveGroupAsync(ConnectionContext connection, string groupName) { - var groups = (HashSet)connection.Metadata["groups"]; + var groups = (HashSet)connection.Features.Get().Metadata["groups"]; if (groups != null) { lock (groups) diff --git a/samples/SocialWeather/SocialWeatherEndPoint.cs b/samples/SocialWeather/SocialWeatherEndPoint.cs index 84dd03d919ac..38eaf60752dd 100644 --- a/samples/SocialWeather/SocialWeatherEndPoint.cs +++ b/samples/SocialWeather/SocialWeatherEndPoint.cs @@ -3,7 +3,9 @@ using System.IO; using System.Threading.Tasks; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets; +using Microsoft.AspNetCore.Sockets.Features; using Microsoft.Extensions.Logging; namespace SocialWeather @@ -32,7 +34,7 @@ public async override Task OnConnectedAsync(ConnectionContext connection) public async Task ProcessRequests(ConnectionContext connection) { var formatter = _formatterResolver.GetFormatter( - (string)connection.Metadata["format"]); + (string)connection.Features.Get().Metadata["format"]); while (true) { diff --git a/samples/SocketsSample/EndPoints/MessagesEndPoint.cs b/samples/SocketsSample/EndPoints/MessagesEndPoint.cs index 0fd837f8bf36..933e50fd7371 100644 --- a/samples/SocketsSample/EndPoints/MessagesEndPoint.cs +++ b/samples/SocketsSample/EndPoints/MessagesEndPoint.cs @@ -5,7 +5,9 @@ using System.IO.Pipelines; using System.Text; using System.Threading.Tasks; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets; +using Microsoft.AspNetCore.Sockets.Features; namespace SocketsSample.EndPoints { @@ -17,7 +19,7 @@ public override async Task OnConnectedAsync(ConnectionContext connection) { Connections.Add(connection); - await Broadcast($"{connection.ConnectionId} connected ({connection.Metadata[ConnectionMetadataNames.Transport]})"); + await Broadcast($"{connection.ConnectionId} connected ({connection.Features.Get().Metadata[ConnectionMetadataNames.Transport]})"); try { @@ -50,7 +52,7 @@ public override async Task OnConnectedAsync(ConnectionContext connection) { Connections.Remove(connection); - await Broadcast($"{connection.ConnectionId} disconnected ({connection.Metadata[ConnectionMetadataNames.Transport]})"); + await Broadcast($"{connection.ConnectionId} disconnected ({connection.Features.Get().Metadata[ConnectionMetadataNames.Transport]})"); } } diff --git a/samples/SocketsSample/Program.cs b/samples/SocketsSample/Program.cs index aa6c67a8fe14..3aea9e847282 100644 --- a/samples/SocketsSample/Program.cs +++ b/samples/SocketsSample/Program.cs @@ -3,8 +3,10 @@ using System.IO; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using SocketsSample.Hubs; namespace SocketsSample { @@ -23,7 +25,18 @@ public static void Main(string[] args) { factory.AddConsole(); }) - .UseKestrel() + .UseKestrel(options => + { + // Default port + options.ListenLocalhost(5000); + + // Hub bound to TCP end point + options.ListenLocalhost(9001, builder => + { + // Run the hub on this port (this won't work properly until streaming parsing is implemented) + builder.UseHub(); + }); + }) .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup() diff --git a/src/Microsoft.AspNetCore.SignalR.Core/HubConnectionContext.cs b/src/Microsoft.AspNetCore.SignalR.Core/HubConnectionContext.cs index 2913578a422b..6cfb3bcc58d1 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/HubConnectionContext.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/HubConnectionContext.cs @@ -13,6 +13,7 @@ using System.Threading.Channels; using System.Threading.Tasks; using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.SignalR.Core; using Microsoft.AspNetCore.SignalR.Internal; using Microsoft.AspNetCore.SignalR.Internal.Encoders; @@ -64,7 +65,7 @@ public class HubConnectionContext public virtual IFeatureCollection Features => _connectionContext.Features; - public virtual IDictionary Metadata => _connectionContext.Metadata; + public virtual IDictionary Metadata => Features.Get().Metadata; public virtual PipeReader Input => _connectionContext.Transport.Input; diff --git a/src/Microsoft.AspNetCore.SignalR.Core/HubEndPoint.cs b/src/Microsoft.AspNetCore.SignalR.Core/HubEndPoint.cs index 8c87c0abeddf..535c52e3f55e 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/HubEndPoint.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/HubEndPoint.cs @@ -11,10 +11,10 @@ using System.Threading.Channels; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.SignalR.Core; using Microsoft.AspNetCore.SignalR.Internal; using Microsoft.AspNetCore.SignalR.Internal.Protocol; -using Microsoft.AspNetCore.Sockets; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Internal; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.AspNetCore.SignalR.Core/SignalRSocketBuilderExtensions.cs b/src/Microsoft.AspNetCore.SignalR.Core/SignalRSocketBuilderExtensions.cs index eee93cc206fb..a1e0e5f5e6c2 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/SignalRSocketBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/SignalRSocketBuilderExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets; using Microsoft.Extensions.DependencyInjection; @@ -8,7 +9,7 @@ namespace Microsoft.AspNetCore.SignalR { public static class SignalRSocketBuilderExtensions { - public static ISocketBuilder UseHub(this ISocketBuilder socketBuilder) where THub : Hub + public static IConnectionBuilder UseHub(this IConnectionBuilder socketBuilder) where THub : Hub { var endpoint = socketBuilder.ApplicationServices.GetRequiredService>(); return socketBuilder.Run(connection => endpoint.OnConnectedAsync(connection)); diff --git a/src/Microsoft.AspNetCore.Sockets.Abstractions/SocketBuilder.cs b/src/Microsoft.AspNetCore.Sockets.Abstractions/ConnectionBuilder.cs similarity index 61% rename from src/Microsoft.AspNetCore.Sockets.Abstractions/SocketBuilder.cs rename to src/Microsoft.AspNetCore.Sockets.Abstractions/ConnectionBuilder.cs index 8dfc21b84815..b11ffc03cb62 100644 --- a/src/Microsoft.AspNetCore.Sockets.Abstractions/SocketBuilder.cs +++ b/src/Microsoft.AspNetCore.Sockets.Abstractions/ConnectionBuilder.cs @@ -6,29 +6,30 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Microsoft.AspNetCore.Protocols; namespace Microsoft.AspNetCore.Sockets { - public class SocketBuilder : ISocketBuilder + public class ConnectionBuilder : IConnectionBuilder { - private readonly IList> _components = new List>(); + private readonly IList> _components = new List>(); public IServiceProvider ApplicationServices { get; } - public SocketBuilder(IServiceProvider applicationServices) + public ConnectionBuilder(IServiceProvider applicationServices) { ApplicationServices = applicationServices; } - public ISocketBuilder Use(Func middleware) + public IConnectionBuilder Use(Func middleware) { _components.Add(middleware); return this; } - public SocketDelegate Build() + public ConnectionDelegate Build() { - SocketDelegate app = features => + ConnectionDelegate app = features => { return Task.CompletedTask; }; diff --git a/src/Microsoft.AspNetCore.Sockets.Abstractions/ConnectionContext.cs b/src/Microsoft.AspNetCore.Sockets.Abstractions/ConnectionContext.cs deleted file mode 100644 index 53779be11dcb..000000000000 --- a/src/Microsoft.AspNetCore.Sockets.Abstractions/ConnectionContext.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.IO.Pipelines; -using Microsoft.AspNetCore.Http.Features; - -namespace Microsoft.AspNetCore.Sockets -{ - public abstract class ConnectionContext - { - public abstract string ConnectionId { get; set; } - - public abstract IFeatureCollection Features { get; } - - public abstract IDictionary Metadata { get; set; } - - public abstract IDuplexPipe Transport { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.Sockets.Abstractions/DuplexPipe.cs b/src/Microsoft.AspNetCore.Sockets.Abstractions/DuplexPipe.cs deleted file mode 100644 index 8cb25722f099..000000000000 --- a/src/Microsoft.AspNetCore.Sockets.Abstractions/DuplexPipe.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO.Pipelines; - -namespace Microsoft.AspNetCore.Sockets -{ - public class DuplexPipe : IDuplexPipe - { - public DuplexPipe(PipeReader reader, PipeWriter writer) - { - Input = reader; - Output = writer; - } - - public PipeReader Input { get; } - - public PipeWriter Output { get; } - - public void Dispose() - { - - } - - public static DuplexPipePair CreateConnectionPair(PipeOptions inputOptions, PipeOptions outputOptions) - { - var input = new Pipe(inputOptions); - var output = new Pipe(outputOptions); - - var transportToApplication = new DuplexPipe(output.Reader, input.Writer); - var applicationToTransport = new DuplexPipe(input.Reader, output.Writer); - - return new DuplexPipePair(applicationToTransport, transportToApplication); - } - - // This class exists to work around issues with value tuple on .NET Framework - public struct DuplexPipePair - { - public IDuplexPipe Transport { get; private set; } - public IDuplexPipe Application { get; private set; } - - public DuplexPipePair(IDuplexPipe transport, IDuplexPipe application) - { - Transport = transport; - Application = application; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.Sockets.Abstractions/ISocketBuilder.cs b/src/Microsoft.AspNetCore.Sockets.Abstractions/ISocketBuilder.cs deleted file mode 100644 index f7d2f985131d..000000000000 --- a/src/Microsoft.AspNetCore.Sockets.Abstractions/ISocketBuilder.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Microsoft.AspNetCore.Sockets -{ - public interface ISocketBuilder - { - IServiceProvider ApplicationServices { get; } - - ISocketBuilder Use(Func middleware); - - SocketDelegate Build(); - } -} diff --git a/src/Microsoft.AspNetCore.Sockets.Abstractions/Microsoft.AspNetCore.Sockets.Abstractions.csproj b/src/Microsoft.AspNetCore.Sockets.Abstractions/Microsoft.AspNetCore.Sockets.Abstractions.csproj index 4ad4e73092b5..86f2e2045415 100644 --- a/src/Microsoft.AspNetCore.Sockets.Abstractions/Microsoft.AspNetCore.Sockets.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Sockets.Abstractions/Microsoft.AspNetCore.Sockets.Abstractions.csproj @@ -8,6 +8,7 @@ + diff --git a/src/Microsoft.AspNetCore.Sockets.Abstractions/SocketBuilderExtensions.cs b/src/Microsoft.AspNetCore.Sockets.Abstractions/SocketBuilderExtensions.cs index e8fe0db5194a..69dc9712d4ba 100644 --- a/src/Microsoft.AspNetCore.Sockets.Abstractions/SocketBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Sockets.Abstractions/SocketBuilderExtensions.cs @@ -3,12 +3,13 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Protocols; namespace Microsoft.AspNetCore.Sockets { public static class SocketBuilderExtensions { - public static ISocketBuilder Use(this ISocketBuilder socketBuilder, Func, Task> middleware) + public static IConnectionBuilder Use(this IConnectionBuilder socketBuilder, Func, Task> middleware) { return socketBuilder.Use(next => { @@ -20,7 +21,7 @@ public static ISocketBuilder Use(this ISocketBuilder socketBuilder, Func middleware) + public static IConnectionBuilder Run(this IConnectionBuilder socketBuilder, Func middleware) { return socketBuilder.Use(next => { diff --git a/src/Microsoft.AspNetCore.Sockets.Abstractions/SocketDelegate.cs b/src/Microsoft.AspNetCore.Sockets.Abstractions/SocketDelegate.cs deleted file mode 100644 index 45af07cd77bf..000000000000 --- a/src/Microsoft.AspNetCore.Sockets.Abstractions/SocketDelegate.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Sockets -{ - public delegate Task SocketDelegate(ConnectionContext connection); -} diff --git a/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionContextExtensions.cs b/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionContextExtensions.cs index 74ce92ccd1a6..8e538d47bf94 100644 --- a/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionContextExtensions.cs +++ b/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionContextExtensions.cs @@ -1,10 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; -using System.Collections.Generic; -using System.Text; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets.Http.Features; namespace Microsoft.AspNetCore.Sockets diff --git a/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionDispatcher.cs b/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionDispatcher.cs index 9ea7aaf9b58f..72766cc7889b 100644 --- a/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionDispatcher.cs +++ b/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionDispatcher.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets.Features; using Microsoft.AspNetCore.Sockets.Internal; using Microsoft.AspNetCore.Sockets.Internal.Transports; @@ -32,7 +33,7 @@ public HttpConnectionDispatcher(ConnectionManager manager, ILoggerFactory logger _logger = _loggerFactory.CreateLogger(); } - public async Task ExecuteAsync(HttpContext context, HttpSocketOptions options, SocketDelegate socketDelegate) + public async Task ExecuteAsync(HttpContext context, HttpSocketOptions options, ConnectionDelegate ConnectionDelegate) { // Create the log scope and attempt to pass the Connection ID to it so as many logs as possible contain // the Connection ID metadata. If this is the negotiate request then the Connection ID for the scope will @@ -53,7 +54,7 @@ public async Task ExecuteAsync(HttpContext context, HttpSocketOptions options, S else if (HttpMethods.IsGet(context.Request.Method)) { // GET /{path} - await ExecuteEndpointAsync(context, socketDelegate, options, logScope); + await ExecuteEndpointAsync(context, ConnectionDelegate, options, logScope); } else { @@ -87,7 +88,7 @@ public async Task ExecuteNegotiateAsync(HttpContext context, HttpSocketOptions o } } - private async Task ExecuteEndpointAsync(HttpContext context, SocketDelegate socketDelegate, HttpSocketOptions options, ConnectionLogScope logScope) + private async Task ExecuteEndpointAsync(HttpContext context, ConnectionDelegate ConnectionDelegate, HttpSocketOptions options, ConnectionLogScope logScope) { var supportedTransports = options.Transports; @@ -119,7 +120,7 @@ private async Task ExecuteEndpointAsync(HttpContext context, SocketDelegate sock // We only need to provide the Input channel since writing to the application is handled through /send. var sse = new ServerSentEventsTransport(connection.Application.Input, connection.ConnectionId, _loggerFactory); - await DoPersistentConnection(socketDelegate, sse, context, connection); + await DoPersistentConnection(ConnectionDelegate, sse, context, connection); } else if (context.WebSockets.IsWebSocketRequest) { @@ -141,7 +142,7 @@ private async Task ExecuteEndpointAsync(HttpContext context, SocketDelegate sock var ws = new WebSocketsTransport(options.WebSockets, connection.Application, connection, _loggerFactory); - await DoPersistentConnection(socketDelegate, ws, context, connection); + await DoPersistentConnection(ConnectionDelegate, ws, context, connection); } else { @@ -202,7 +203,7 @@ private async Task ExecuteEndpointAsync(HttpContext context, SocketDelegate sock connection.Metadata[ConnectionMetadataNames.Transport] = TransportType.LongPolling; - connection.ApplicationTask = ExecuteApplication(socketDelegate, connection); + connection.ApplicationTask = ExecuteApplication(ConnectionDelegate, connection); } else { @@ -291,7 +292,7 @@ private async Task ExecuteEndpointAsync(HttpContext context, SocketDelegate sock } } - private async Task DoPersistentConnection(SocketDelegate socketDelegate, + private async Task DoPersistentConnection(ConnectionDelegate ConnectionDelegate, IHttpTransport transport, HttpContext context, DefaultConnectionContext connection) @@ -323,7 +324,7 @@ private async Task ExecuteEndpointAsync(HttpContext context, SocketDelegate sock connection.Status = DefaultConnectionContext.ConnectionStatus.Active; // Call into the end point passing the connection - connection.ApplicationTask = ExecuteApplication(socketDelegate, connection); + connection.ApplicationTask = ExecuteApplication(ConnectionDelegate, connection); // Start the transport connection.TransportTask = transport.ProcessRequestAsync(context, context.RequestAborted); @@ -339,12 +340,12 @@ private async Task ExecuteEndpointAsync(HttpContext context, SocketDelegate sock await _manager.DisposeAndRemoveAsync(connection); } - private async Task ExecuteApplication(SocketDelegate socketDelegate, ConnectionContext connection) + private async Task ExecuteApplication(ConnectionDelegate ConnectionDelegate, ConnectionContext connection) { // Verify some initialization invariants // We want to be positive that the IConnectionInherentKeepAliveFeature is initialized before invoking the application, if the long polling transport is in use. - Debug.Assert(connection.Metadata[ConnectionMetadataNames.Transport] != null, "Transport has not been initialized yet"); - Debug.Assert((TransportType?)connection.Metadata[ConnectionMetadataNames.Transport] != TransportType.LongPolling || + Debug.Assert(connection.Features.Get().Metadata[ConnectionMetadataNames.Transport] != null, "Transport has not been initialized yet"); + Debug.Assert((TransportType?)connection.Features.Get().Metadata[ConnectionMetadataNames.Transport] != TransportType.LongPolling || connection.Features.Get() != null, "Long-polling transport is in use but IConnectionInherentKeepAliveFeature as not configured"); // Jump onto the thread pool thread so blocking user code doesn't block the setup of the @@ -352,7 +353,7 @@ private async Task ExecuteApplication(SocketDelegate socketDelegate, ConnectionC await AwaitableThreadPool.Yield(); // Running this in an async method turns sync exceptions into async ones - await socketDelegate(connection); + await ConnectionDelegate(connection); } private Task ProcessNegotiate(HttpContext context, HttpSocketOptions options, ConnectionLogScope logScope) diff --git a/src/Microsoft.AspNetCore.Sockets.Http/SocketRouteBuilder.cs b/src/Microsoft.AspNetCore.Sockets.Http/SocketRouteBuilder.cs index 99b92af5d508..96df652cc572 100644 --- a/src/Microsoft.AspNetCore.Sockets.Http/SocketRouteBuilder.cs +++ b/src/Microsoft.AspNetCore.Sockets.Http/SocketRouteBuilder.cs @@ -5,6 +5,7 @@ using System.Reflection; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Routing; namespace Microsoft.AspNetCore.Sockets @@ -20,15 +21,15 @@ public SocketRouteBuilder(RouteBuilder routes, HttpConnectionDispatcher dispatch _dispatcher = dispatcher; } - public void MapSocket(string path, Action socketConfig) => + public void MapSocket(string path, Action socketConfig) => MapSocket(new PathString(path), new HttpSocketOptions(), socketConfig); - public void MapSocket(PathString path, Action socketConfig) => + public void MapSocket(PathString path, Action socketConfig) => MapSocket(path, new HttpSocketOptions(), socketConfig); - public void MapSocket(PathString path, HttpSocketOptions options, Action socketConfig) + public void MapSocket(PathString path, HttpSocketOptions options, Action socketConfig) { - var socketBuilder = new SocketBuilder(_routes.ServiceProvider); + var socketBuilder = new ConnectionBuilder(_routes.ServiceProvider); socketConfig(socketBuilder); var socket = socketBuilder.Build(); _routes.MapRoute(path, c => _dispatcher.ExecuteAsync(c, options, socket)); diff --git a/src/Microsoft.AspNetCore.Sockets/ConnectionList.cs b/src/Microsoft.AspNetCore.Sockets/ConnectionList.cs index 0b9b7994067f..ea3e201c95cb 100644 --- a/src/Microsoft.AspNetCore.Sockets/ConnectionList.cs +++ b/src/Microsoft.AspNetCore.Sockets/ConnectionList.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; +using Microsoft.AspNetCore.Protocols; namespace Microsoft.AspNetCore.Sockets { diff --git a/src/Microsoft.AspNetCore.Sockets/DefaultConnectionContext.cs b/src/Microsoft.AspNetCore.Sockets/DefaultConnectionContext.cs index eb7b72767335..d523335e9ebc 100644 --- a/src/Microsoft.AspNetCore.Sockets/DefaultConnectionContext.cs +++ b/src/Microsoft.AspNetCore.Sockets/DefaultConnectionContext.cs @@ -2,12 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Buffers; using System.Collections.Generic; using System.IO.Pipelines; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets.Features; using Microsoft.Extensions.Internal; @@ -63,7 +65,7 @@ public DefaultConnectionContext(string id, IDuplexPipe transport, IDuplexPipe ap public ClaimsPrincipal User { get; set; } - public override IDictionary Metadata { get; set; } = new ConnectionMetadata(); + public IDictionary Metadata { get; set; } = new ConnectionMetadata(); public IDuplexPipe Application { get; } diff --git a/src/Microsoft.AspNetCore.Sockets/EndPoint.cs b/src/Microsoft.AspNetCore.Sockets/EndPoint.cs index d23fbeddf42f..89de4b79fa7a 100644 --- a/src/Microsoft.AspNetCore.Sockets/EndPoint.cs +++ b/src/Microsoft.AspNetCore.Sockets/EndPoint.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.AspNetCore.Protocols; namespace Microsoft.AspNetCore.Sockets { diff --git a/src/Microsoft.AspNetCore.Sockets/SocketBuilderExtensions.cs b/src/Microsoft.AspNetCore.Sockets/SocketBuilderExtensions.cs index f0d6d3387b8e..1e4d5cd68880 100644 --- a/src/Microsoft.AspNetCore.Sockets/SocketBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Sockets/SocketBuilderExtensions.cs @@ -1,13 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.AspNetCore.Protocols; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Sockets { public static class SocketBuilderExtensions { - public static ISocketBuilder UseEndPoint(this ISocketBuilder socketBuilder) where TEndPoint : EndPoint + public static IConnectionBuilder UseEndPoint(this IConnectionBuilder socketBuilder) where TEndPoint : EndPoint { var endpoint = socketBuilder.ApplicationServices.GetRequiredService(); // This is a terminal middleware, so there's no need to use the 'next' parameter diff --git a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs index c6a2578506ee..f602324733d5 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests.Utils/TestClient.cs @@ -30,7 +30,7 @@ public class TestClient : IDisposable public TestClient(bool synchronousCallbacks = false, IHubProtocol protocol = null, IInvocationBinder invocationBinder = null, bool addClaimId = false) { var options = new PipeOptions(readerScheduler: synchronousCallbacks ? PipeScheduler.Inline : null); - var pair = Microsoft.AspNetCore.Sockets.DuplexPipe.CreateConnectionPair(options, options); + var pair = DuplexPipe.CreateConnectionPair(options, options); Connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Transport, pair.Application); var claimValue = Interlocked.Increment(ref _id).ToString(); diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/EchoEndPoint.cs b/test/Microsoft.AspNetCore.SignalR.Tests/EchoEndPoint.cs index 839e98088b85..b31f85c7ddab 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/EchoEndPoint.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/EchoEndPoint.cs @@ -3,6 +3,7 @@ using System.IO.Pipelines; using System.Threading.Tasks; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets; namespace Microsoft.AspNetCore.SignalR.Tests diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs index ea571661a8e7..61910660a327 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.SignalR.Internal; using Microsoft.AspNetCore.SignalR.Internal.Protocol; using Microsoft.AspNetCore.Sockets; diff --git a/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs b/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs index aac60adee800..11998ab2983c 100644 --- a/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs +++ b/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs @@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Internal; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Sockets.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -116,7 +117,7 @@ public async Task EndpointsThatAcceptConnectionId404WhenUnknownConnectionIdProvi context.Request.Query = qs; SetTransport(context, transportType); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); await dispatcher.ExecuteAsync(context, new HttpSocketOptions(), app); @@ -151,7 +152,7 @@ public async Task EndpointsThatAcceptConnectionId404WhenUnknownConnectionIdProvi var qs = new QueryCollection(values); context.Request.Query = qs; - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); await dispatcher.ExecuteAsync(context, new HttpSocketOptions(), app); @@ -188,7 +189,7 @@ public async Task PostNotAllowedForWebSocketConnections() var qs = new QueryCollection(values); context.Request.Query = qs; - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); await dispatcher.ExecuteAsync(context, new HttpSocketOptions(), app); @@ -233,7 +234,7 @@ public async Task PostSendsToConnection(TransportType transportType) var qs = new QueryCollection(values); context.Request.Query = qs; - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); @@ -268,7 +269,7 @@ public async Task EndpointsThatRequireConnectionId400WhenNoConnectionIdProvided( SetTransport(context, transportType); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); await dispatcher.ExecuteAsync(context, new HttpSocketOptions(), app); @@ -297,7 +298,7 @@ public async Task EndpointsThatRequireConnectionId400WhenNoConnectionIdProvidedF context.Request.Path = "/foo"; context.Request.Method = "POST"; - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); await dispatcher.ExecuteAsync(context, new HttpSocketOptions(), app); @@ -370,7 +371,7 @@ public async Task CompletedEndPointEndsConnection() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); await dispatcher.ExecuteAsync(context, new HttpSocketOptions(), app); @@ -396,7 +397,7 @@ public async Task SynchronusExceptionEndsConnection() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); await dispatcher.ExecuteAsync(context, new HttpSocketOptions(), app); @@ -422,7 +423,7 @@ public async Task CompletedEndPointEndsLongPollingConnection() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); await dispatcher.ExecuteAsync(context, new HttpSocketOptions(), app); @@ -448,7 +449,7 @@ public async Task LongPollingTimeoutSets200StatusCode() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -474,7 +475,7 @@ public async Task WebSocketTransportTimesOutWhenCloseFrameNotReceived() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -506,7 +507,7 @@ public async Task RequestToActiveConnectionId409ForStreamingTransports(Transport var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -545,7 +546,7 @@ public async Task RequestToActiveConnectionIdKillsPreviousConnectionLongPolling( var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -583,7 +584,7 @@ public async Task RequestToDisposedConnectionIdReturns404(TransportType transpor var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -608,7 +609,7 @@ public async Task ConnectionStateSetToInactiveAfterPoll() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -643,7 +644,7 @@ public async Task BlockingConnectionWorksWithStreamingConnections() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -676,7 +677,7 @@ public async Task BlockingConnectionWorksWithLongPollingConnection() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -707,7 +708,7 @@ public async Task AttemptingToPollWhileAlreadyPollingReplacesTheCurrentPoll() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -751,7 +752,7 @@ public async Task TransportCapabilitiesSet(TransportType transportType, Transfer var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); @@ -795,7 +796,7 @@ public async Task UnauthorizedConnectionFailsToStartEndPoint() var qs = new QueryCollection(values); context.Request.Query = qs; - var builder = new SocketBuilder(sp); + var builder = new ConnectionBuilder(sp); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -840,7 +841,7 @@ public async Task AuthenticatedUserWithoutPermissionCausesForbidden() var qs = new QueryCollection(values); context.Request.Query = qs; - var builder = new SocketBuilder(sp); + var builder = new ConnectionBuilder(sp); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -892,7 +893,7 @@ public async Task AuthorizedConnectionCanConnectToEndPoint() context.Request.Query = qs; context.Response.Body = new MemoryStream(); - var builder = new SocketBuilder(sp); + var builder = new ConnectionBuilder(sp); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -952,7 +953,7 @@ public async Task AllPoliciesRequiredForAuthorizedEndPoint() context.Request.Query = qs; context.Response.Body = new MemoryStream(); - var builder = new SocketBuilder(sp); + var builder = new ConnectionBuilder(sp); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -1030,7 +1031,7 @@ public async Task AuthorizedConnectionWithAcceptedSchemesCanConnectToEndPoint() context.Request.Query = qs; context.Response.Body = new MemoryStream(); - var builder = new SocketBuilder(sp); + var builder = new ConnectionBuilder(sp); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -1086,7 +1087,7 @@ public async Task AuthorizedConnectionWithRejectedSchemesFailsToConnectToEndPoin context.Request.Query = qs; context.Response.Body = new MemoryStream(); - var builder = new SocketBuilder(sp); + var builder = new ConnectionBuilder(sp); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -1116,7 +1117,7 @@ public async Task SetsInherentKeepAliveFeatureOnFirstLongPollingRequest() var services = new ServiceCollection(); services.AddEndPoint(); - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); @@ -1196,7 +1197,7 @@ private static async Task CheckTransportSupported(TransportType supportedTranspo var qs = new QueryCollection(values); context.Request.Query = qs; - var builder = new SocketBuilder(services.BuildServiceProvider()); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseEndPoint(); var app = builder.Build(); var options = new HttpSocketOptions(); diff --git a/test/Microsoft.AspNetCore.Sockets.Tests/MapEndPointTests.cs b/test/Microsoft.AspNetCore.Sockets.Tests/MapEndPointTests.cs index 1ab370512ae0..0854c338ffff 100644 --- a/test/Microsoft.AspNetCore.Sockets.Tests/MapEndPointTests.cs +++ b/test/Microsoft.AspNetCore.Sockets.Tests/MapEndPointTests.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Testing.xunit; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging;