-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Support for hosting extensions #1653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
YAJeff
wants to merge
21
commits into
dotnet:master
Choose a base branch
from
YAJeff:hosting/hosting-extensions
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 8 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
8888a36
Hosting extensions initial check-in.
YAJeff 392bd39
Added hosting extensions capability.
YAJeff 2055653
Added simple server example.
YAJeff 5c9df71
Added single line example.
YAJeff 10fbb2c
Fixed solution changes and a whitespace mistake.
JeffDrives e4ecc7a
Merge branch 'dotnet:master' into hosting/hosting-extensions
YAJeff 0f22d8b
Renamed to extensions hosting and added support for websockets.
YAJeff 5742b3f
Merge branch 'dotnet:master' into hosting/hosting-extensions
YAJeff 1d0a6ad
Fix broken project reference
chkr1011 2005da0
Merge remote-tracking branch 'upstream/master' into HEAD
02f825c
Completes the ReleaseNotes sentence.
a3bca6a
Build error
9614bb4
Merge branch 'master' into hosting/hosting-extensions
kallayj 5cad983
Update ReleaseNotes.md
chkr1011 db37cfb
Apply code style
chkr1011 3f2e563
Apply code style
chkr1011 9f99d40
Move projects
chkr1011 7605d10
Fixes nullability of method parameters.
kallayj 13c7db3
Merge branch 'master' into pr/1653
chkr1011 d6b4b29
Fix breaking changes
chkr1011 2e45174
Removes unused properties.
kallayj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
// ReSharper disable UnusedType.Global | ||
// ReSharper disable UnusedMember.Global | ||
// ReSharper disable InconsistentNaming | ||
// ReSharper disable EmptyConstructor | ||
// ReSharper disable MemberCanBeMadeStatic.Local | ||
|
||
using Microsoft.Extensions.Hosting; | ||
//using MQTTnet.AspNetCore; | ||
using MQTTnet.Server; | ||
|
||
namespace MQTTnet.Samples.Server; | ||
|
||
public static class Server_Hosting_Extensions_Samples | ||
{ | ||
|
||
// This could be called as a top-level statement in a Program.cs file | ||
public static Task Start_Single_Line_Server() | ||
=> new HostBuilder().UseMqttServer().Build().RunAsync(); | ||
|
||
public static Task Start_Simple_Server() | ||
{ | ||
var host = new HostBuilder() | ||
.UseMqttServer() | ||
.Build(); | ||
|
||
return host.RunAsync(); | ||
} | ||
|
||
public static Task Start_Server() | ||
{ | ||
var builder = new HostBuilder(); | ||
|
||
builder | ||
.UseMqttServer(mqtt => | ||
{ | ||
mqtt.WithDefaultEndpoint(); | ||
}); | ||
|
||
var host = builder.Build(); | ||
return host.RunAsync(); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
Source/MQTTnet.Extensions.Hosting/Events/HttpWebSocketClientAuthenticationCallback.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace MQTTnet.Extensions.Hosting.Events | ||
{ | ||
public delegate Task<bool> HttpWebSocketClientAuthenticationCallback(); | ||
|
||
} |
61 changes: 61 additions & 0 deletions
61
Source/MQTTnet.Extensions.Hosting/Extensions/HostBuilderExtensions.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using MQTTnet.Adapter; | ||
using MQTTnet.Diagnostics; | ||
using MQTTnet.Extensions.Hosting; | ||
using MQTTnet.Extensions.Hosting.Implementations; | ||
using MQTTnet.Extensions.Hosting.Options; | ||
using MQTTnet.Implementations; | ||
using MQTTnet.Server; | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace Microsoft.Extensions.Hosting | ||
{ | ||
public static class HostBuilderExtensions | ||
{ | ||
|
||
public static IHostBuilder UseMqttServer(this IHostBuilder hostBuilder) | ||
=> hostBuilder.UseMqttServer(builder => | ||
{ | ||
builder.WithDefaultEndpoint(); | ||
}); | ||
|
||
|
||
public static IHostBuilder UseMqttServer(this IHostBuilder hostBuilder, Action<MqttServerHostingBuilder> configure) | ||
{ | ||
var startActions = new List<Action<MqttServer>>(); | ||
var stopActions = new List<Action<MqttServer>>(); | ||
hostBuilder.ConfigureServices((context, services) => | ||
{ | ||
services.AddSingleton(s => | ||
{ | ||
var builder = new MqttServerHostingBuilder(s, startActions, stopActions); | ||
configure(builder); | ||
return builder.Build(); | ||
}); | ||
|
||
var logger = new MqttNetEventLogger(); | ||
|
||
services | ||
.AddSingleton<IMqttNetLogger>(logger) | ||
.AddSingleton<MqttHostedServer>() | ||
.AddSingleton<MqttServerHostingOptions>() | ||
.AddSingleton<IHostedService>(s => s.GetRequiredService<MqttHostedServer>()) | ||
.AddSingleton<IHostedService>(s => new MqttServerConfigurationHostedService(s, startActions, stopActions)) | ||
.AddSingleton<MqttServer>(s => s.GetRequiredService<MqttHostedServer>()) | ||
|
||
.AddSingleton<MqttTcpServerAdapter>() | ||
.AddSingleton<IMqttServerAdapter>(s => s.GetRequiredService<MqttTcpServerAdapter>()) | ||
|
||
.AddSingleton<MqttServerWebSocketConnectionHandler>() | ||
|
||
.AddSingleton<MqttWebSocketServerAdapter>() | ||
.AddSingleton<IMqttServerAdapter>(s => s.GetRequiredService<MqttWebSocketServerAdapter>()); | ||
|
||
}); | ||
return hostBuilder; | ||
} | ||
|
||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
Source/MQTTnet.Extensions.Hosting/Extensions/HostingMqttServerExtensions.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using MQTTnet.Extensions.Hosting; | ||
using MQTTnet.Extensions.Hosting.Implementations; | ||
using MQTTnet.Server; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net; | ||
using System.Net.WebSockets; | ||
using System.Text; | ||
|
||
namespace MQTTnet.Server | ||
{ | ||
public static class HostingMqttServerExtensions | ||
{ | ||
|
||
public static void HandleWebSocketConnection(this MqttServer server, HttpListenerWebSocketContext webSocketContext, HttpListenerContext httpListenerContext) | ||
{ | ||
if (!(server is MqttHostedServer mqttHostedServer)) | ||
throw new InvalidOperationException("The server must be started through hosting extensions."); | ||
|
||
mqttHostedServer.ServiceProvider.GetRequiredService<MqttServerWebSocketConnectionHandler>().HandleWebSocketConnection(webSocketContext, httpListenerContext); | ||
} | ||
|
||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
Source/MQTTnet.Extensions.Hosting/Implementations/MqttServerWebSocketConnectionHandler.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
using Microsoft.Extensions.Hosting; | ||
using MQTTnet.Adapter; | ||
using MQTTnet.Diagnostics; | ||
using MQTTnet.Formatter; | ||
using MQTTnet.Implementations; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net; | ||
using System.Net.WebSockets; | ||
using System.Security.Cryptography.X509Certificates; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace MQTTnet.Extensions.Hosting.Implementations | ||
{ | ||
public class MqttServerWebSocketConnectionHandler : IHostedService, IDisposable | ||
{ | ||
readonly CancellationTokenSource _cts = new CancellationTokenSource(); | ||
readonly MqttWebSocketServerAdapter _adapter; | ||
readonly IMqttNetLogger _logger; | ||
|
||
public MqttServerWebSocketConnectionHandler(MqttWebSocketServerAdapter adapter, IMqttNetLogger logger) | ||
{ | ||
_adapter = adapter; | ||
_logger = logger; | ||
} | ||
|
||
public Task StartAsync(CancellationToken cancellationToken) | ||
{ | ||
return Task.CompletedTask; | ||
} | ||
|
||
public Task StopAsync(CancellationToken cancellationToken) | ||
{ | ||
_cts.Cancel(); | ||
|
||
return Task.CompletedTask; | ||
} | ||
|
||
public void HandleWebSocketConnection(HttpListenerWebSocketContext webSocketContext, HttpListenerContext httpListenerContext, X509Certificate2 clientCertificate = null) | ||
{ | ||
_ = Task.Factory.StartNew(() => TryHandleWebSocketConnectionAsync(webSocketContext, httpListenerContext, clientCertificate)); | ||
} | ||
|
||
async Task TryHandleWebSocketConnectionAsync(HttpListenerWebSocketContext webSocketContext, HttpListenerContext httpListenerContext, X509Certificate2 clientCertificate) | ||
{ | ||
if (webSocketContext == null) throw new ArgumentNullException(nameof(webSocketContext)); | ||
var endpoint = $"{httpListenerContext.Request.RemoteEndPoint.Address}:{httpListenerContext.Request.RemoteEndPoint.Port}"; | ||
|
||
try | ||
{ | ||
var clientHandler = _adapter.ClientHandler; | ||
if (clientHandler != null) | ||
{ | ||
var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535)); | ||
var channel = new MqttWebSocketChannel(webSocketContext.WebSocket, endpoint, webSocketContext.IsSecureConnection, clientCertificate); | ||
using (var channelAdapter = new MqttChannelAdapter(channel, formatter, null, _logger)) | ||
{ | ||
await clientHandler(channelAdapter).ConfigureAwait(false); | ||
} | ||
} | ||
} | ||
finally | ||
{ | ||
clientCertificate?.Dispose(); | ||
} | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
_cts.Dispose(); | ||
} | ||
} | ||
} |
83 changes: 83 additions & 0 deletions
83
Source/MQTTnet.Extensions.Hosting/Implementations/MqttWebSocketServerAdapter.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
using MQTTnet.Adapter; | ||
using MQTTnet.Diagnostics; | ||
using MQTTnet.Internal; | ||
using MQTTnet.Server; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net.Sockets; | ||
using System.Net; | ||
using System.Security.Cryptography.X509Certificates; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using System.Net.WebSockets; | ||
using System.Net.Http; | ||
using MQTTnet.Formatter; | ||
using MQTTnet.Extensions.Hosting; | ||
using MQTTnet.Extensions.Hosting.Options; | ||
using MQTTnet.Extensions.Hosting.Implementations; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace MQTTnet.Implementations | ||
{ | ||
public class MqttWebSocketServerAdapter : IMqttServerAdapter | ||
{ | ||
readonly List<MqttWebSocketServerListener> _listeners = new List<MqttWebSocketServerListener>(); | ||
readonly IServiceProvider _services; | ||
readonly MqttServerHostingOptions _hostingOptions; | ||
MqttServerOptions _serverOptions; | ||
IMqttNetLogger _logger; | ||
|
||
public MqttWebSocketServerAdapter(IServiceProvider services, MqttServerHostingOptions hostingOptions) | ||
{ | ||
_services = services; | ||
_hostingOptions = hostingOptions; | ||
} | ||
|
||
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; } | ||
|
||
public Task StartAsync(MqttServerOptions options, IMqttNetLogger logger) | ||
{ | ||
_serverOptions = options; | ||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); | ||
|
||
if (_hostingOptions.DefaultWebSocketEndpointOptions.IsEnabled) | ||
{ | ||
_listeners.Add(ActivatorUtilities.CreateInstance<MqttWebSocketServerListener>(_services, options, _hostingOptions.DefaultWebSocketEndpointOptions)); | ||
} | ||
|
||
if (_hostingOptions.DefaultTlsWebSocketEndpointOptions.IsEnabled) | ||
{ | ||
_listeners.Add(ActivatorUtilities.CreateInstance<MqttWebSocketServerListener>(_services, options, _hostingOptions.DefaultTlsWebSocketEndpointOptions)); | ||
} | ||
|
||
foreach (var listener in _listeners) | ||
{ | ||
listener.Start(CancellationToken.None); | ||
} | ||
|
||
return CompletedTask.Instance; | ||
} | ||
|
||
public Task StopAsync() | ||
{ | ||
foreach (var listener in _listeners) | ||
{ | ||
listener.Dispose(); | ||
} | ||
|
||
_listeners.Clear(); | ||
|
||
return CompletedTask.Instance; | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
foreach (var listener in _listeners) | ||
{ | ||
listener.Dispose(); | ||
} | ||
} | ||
|
||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.