Add support for WebSocket server via ASP.NET Core 2.0

This commit is contained in:
Christian Kratky
2017-10-21 00:14:09 +02:00
parent 11ade8c3df
commit f9eb6ed85e
10 changed files with 219 additions and 9 deletions
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Frameworks\MQTTnet.Netstandard\MQTTnet.NetStandard.csproj" />
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,95 @@
using System;
using System.IO;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;
using MQTTnet.Implementations;
namespace MQTTnet.TestApp.AspNetCore2
{
public class MqttWebSocketServerAdapter : IMqttServerAdapter, IDisposable
{
private readonly MqttNetTrace _trace;
public MqttWebSocketServerAdapter(MqttNetTrace trace)
{
_trace = trace ?? throw new ArgumentNullException(nameof(trace));
}
public event EventHandler<MqttServerAdapterClientAcceptedEventArgs> ClientAccepted;
public Task StartAsync(MqttServerOptions options)
{
return Task.CompletedTask;
}
public Task StopAsync()
{
return Task.FromResult(0);
}
public Task AcceptWebSocketAsync(WebSocket webSocket)
{
if (webSocket == null) throw new ArgumentNullException(nameof(webSocket));
var channel = new MqttWebSocketServerChannel(webSocket);
var clientAdapter = new MqttChannelCommunicationAdapter(channel, new MqttPacketSerializer(), _trace);
var eventArgs = new MqttServerAdapterClientAcceptedEventArgs(clientAdapter);
ClientAccepted?.Invoke(this, eventArgs);
return eventArgs.SessionTask;
}
public void Dispose()
{
StopAsync();
}
private class MqttWebSocketServerChannel : IMqttCommunicationChannel, IDisposable
{
private readonly WebSocket _webSocket;
public MqttWebSocketServerChannel(WebSocket webSocket)
{
_webSocket = webSocket ?? throw new ArgumentNullException(nameof(webSocket));
RawReceiveStream = new WebSocketStream(_webSocket);
}
public Stream SendStream => RawReceiveStream;
public Stream ReceiveStream => RawReceiveStream;
public Stream RawReceiveStream { get; }
public Task ConnectAsync()
{
return Task.CompletedTask;
}
public Task DisconnectAsync()
{
RawReceiveStream?.Dispose();
if (_webSocket == null)
{
return Task.CompletedTask;
}
return _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
}
public void Dispose()
{
RawReceiveStream?.Dispose();
SendStream?.Dispose();
ReceiveStream?.Dispose();
_webSocket?.Dispose();
}
}
}
}
@@ -0,0 +1,18 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
namespace MQTTnet.TestApp.AspNetCore2
{
public static class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
private static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}
@@ -0,0 +1,55 @@
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Server;
namespace MQTTnet.TestApp.AspNetCore2
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public async void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(LogLevel.Debug);
MqttNetTrace.TraceMessagePublished += (s, e) =>
{
Debug.WriteLine($">> [{e.TraceMessage.Timestamp}] [{e.TraceMessage.ThreadId}] [{e.TraceMessage.Source}] [{e.TraceMessage.Level}]: {e.TraceMessage.Message}");
if (e.TraceMessage.Exception != null)
{
Debug.WriteLine(e.TraceMessage.Exception.Message);
}
};
var trace = new MqttNetTrace();
var adapter = new MqttWebSocketServerAdapter(trace);
var options = new MqttServerOptions();
var mqttServer = new MqttServer(options, new List<IMqttServerAdapter> { adapter }, new MqttNetTrace());
await mqttServer.StartAsync();
app.UseWebSockets();
app.Use(async (context, next) =>
{
if (context.WebSockets.IsWebSocketRequest)
{
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync())
{
await adapter.AcceptWebSocketAsync(webSocket);
}
}
else
{
await next();
}
});
}
}
}