Skip to content

Commit ae84aa4

Browse files
authored
1846 server mqttserverstopasync doesnt indicate correct reason (#1872)
1 parent b431a5d commit ae84aa4

25 files changed

+521
-147
lines changed

.github/workflows/ReleaseNotes.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
* [Server] Fixed not working _UpdateRetainedMessageAsync_ public api (#1858, thanks to @kimdiego2098).
1+
* [Client] Added support for custom CA chain validation (#1851, thanks to @rido-min).
22
* [Client] Added support for custom CA chain validation (#1851, thanks to @rido-min).
33
* [Client] Fixed handling of unobserved tasks exceptions (#1871).
4-
* [Client] Fixed not specified ReasonCode when using _SendExtendedAuthenticationExchangeDataAsync_ (#1882, thanks to @rido-min).
4+
* [Client] Fixed not specified ReasonCode when using _SendExtendedAuthenticationExchangeDataAsync_ (#1882, thanks to @rido-min).
5+
* [Server] Fixed not working _UpdateRetainedMessageAsync_ public api (#1858, thanks to @kimdiego2098).
6+
* [Server] Added support for custom DISCONNECT packets when stopping the server or disconnect a client (BREAKING CHANGE!, #1846).
7+
* [Server] Added new property to stop the server from accepting new connections even if it is running (#1846).

Source/MQTTnet.AspnetCore/MqttHostedServer.cs

+14-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System;
56
using System.Collections.Generic;
67
using System.Threading;
78
using System.Threading.Tasks;
@@ -14,20 +15,27 @@ namespace MQTTnet.AspNetCore
1415
{
1516
public sealed class MqttHostedServer : MqttServer, IHostedService
1617
{
17-
public MqttHostedServer(MqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
18-
: base(options, adapters, logger)
18+
readonly MqttFactory _mqttFactory;
19+
20+
public MqttHostedServer(MqttFactory mqttFactory, MqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger) : base(
21+
options,
22+
adapters,
23+
logger)
1924
{
25+
_mqttFactory = mqttFactory ?? throw new ArgumentNullException(nameof(mqttFactory));
2026
}
2127

22-
public Task StartAsync(CancellationToken cancellationToken)
28+
public async Task StartAsync(CancellationToken cancellationToken)
2329
{
24-
_ = StartAsync();
25-
return Task.CompletedTask;
30+
// The yield makes sure that the hosted service is considered up and running.
31+
await Task.Yield();
32+
33+
_ = StartAsync();
2634
}
2735

2836
public Task StopAsync(CancellationToken cancellationToken)
2937
{
30-
return StopAsync();
38+
return StopAsync(_mqttFactory.CreateMqttServerStopOptionsBuilder().Build());
3139
}
3240
}
3341
}

Source/MQTTnet.AspnetCore/ServiceCollectionExtensions.cs

+68-42
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
using System;
66
using Microsoft.Extensions.DependencyInjection;
7-
using Microsoft.Extensions.Hosting;
7+
using Microsoft.Extensions.DependencyInjection.Extensions;
88
using MQTTnet.Adapter;
99
using MQTTnet.Diagnostics;
1010
using MQTTnet.Implementations;
@@ -14,76 +14,102 @@ namespace MQTTnet.AspNetCore
1414
{
1515
public static class ServiceCollectionExtensions
1616
{
17-
public static IServiceCollection AddMqttServer(this IServiceCollection serviceCollection, Action<MqttServerOptionsBuilder> configure = null)
17+
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, MqttServerOptions options)
1818
{
19-
if (serviceCollection is null)
19+
if (services == null)
2020
{
21-
throw new ArgumentNullException(nameof(serviceCollection));
21+
throw new ArgumentNullException(nameof(services));
2222
}
2323

24-
serviceCollection.AddMqttConnectionHandler();
25-
serviceCollection.AddHostedMqttServer(configure);
26-
27-
return serviceCollection;
28-
}
29-
30-
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, MqttServerOptions options)
31-
{
32-
if (options == null) throw new ArgumentNullException(nameof(options));
24+
if (options == null)
25+
{
26+
throw new ArgumentNullException(nameof(options));
27+
}
3328

3429
services.AddSingleton(options);
35-
3630
services.AddHostedMqttServer();
3731

3832
return services;
3933
}
4034

41-
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, Action<MqttServerOptionsBuilder> configure = null)
35+
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, Action<MqttServerOptionsBuilder> configure)
4236
{
43-
services.AddSingleton(s =>
37+
if (services == null)
4438
{
45-
var serverOptionsBuilder = new MqttServerOptionsBuilder();
46-
configure?.Invoke(serverOptionsBuilder);
47-
return serverOptionsBuilder.Build();
48-
});
39+
throw new ArgumentNullException(nameof(services));
40+
}
4941

50-
services.AddHostedMqttServer();
42+
if (configure == null)
43+
{
44+
throw new ArgumentNullException(nameof(configure));
45+
}
5146

52-
return services;
47+
var serverOptionsBuilder = new MqttServerOptionsBuilder();
48+
configure.Invoke(serverOptionsBuilder);
49+
var options = serverOptionsBuilder.Build();
50+
51+
return AddHostedMqttServer(services, options);
52+
}
53+
54+
public static void AddHostedMqttServer(this IServiceCollection services)
55+
{
56+
// The user may have these services already registered.
57+
services.TryAddSingleton<IMqttNetLogger>(MqttNetNullLogger.Instance);
58+
services.TryAddSingleton(new MqttFactory());
59+
60+
services.AddSingleton<MqttHostedServer>();
61+
services.AddHostedService<MqttHostedServer>();
5362
}
5463

5564
public static IServiceCollection AddHostedMqttServerWithServices(this IServiceCollection services, Action<AspNetMqttServerOptionsBuilder> configure)
5665
{
57-
services.AddSingleton(s =>
66+
if (services == null)
5867
{
59-
var builder = new AspNetMqttServerOptionsBuilder(s);
60-
configure(builder);
61-
return builder.Build();
62-
});
68+
throw new ArgumentNullException(nameof(services));
69+
}
70+
71+
services.AddSingleton(
72+
s =>
73+
{
74+
var builder = new AspNetMqttServerOptionsBuilder(s);
75+
configure(builder);
76+
return builder.Build();
77+
});
6378

6479
services.AddHostedMqttServer();
6580

6681
return services;
6782
}
6883

69-
static IServiceCollection AddHostedMqttServer(this IServiceCollection services)
84+
public static IServiceCollection AddMqttConnectionHandler(this IServiceCollection services)
7085
{
71-
var logger = new MqttNetEventLogger();
72-
73-
services.AddSingleton<IMqttNetLogger>(logger);
74-
services.AddSingleton<MqttHostedServer>();
75-
services.AddSingleton<IHostedService>(s => s.GetService<MqttHostedServer>());
76-
services.AddSingleton<MqttServer>(s => s.GetService<MqttHostedServer>());
86+
services.AddSingleton<MqttConnectionHandler>();
87+
services.AddSingleton<IMqttServerAdapter>(s => s.GetService<MqttConnectionHandler>());
7788

7889
return services;
7990
}
8091

81-
public static IServiceCollection AddMqttWebSocketServerAdapter(this IServiceCollection services)
92+
public static void AddMqttLogger(this IServiceCollection services, IMqttNetLogger logger)
8293
{
83-
services.AddSingleton<MqttWebSocketServerAdapter>();
84-
services.AddSingleton<IMqttServerAdapter>(s => s.GetService<MqttWebSocketServerAdapter>());
94+
if (services == null)
95+
{
96+
throw new ArgumentNullException(nameof(services));
97+
}
8598

86-
return services;
99+
services.AddSingleton(logger);
100+
}
101+
102+
public static IServiceCollection AddMqttServer(this IServiceCollection serviceCollection, Action<MqttServerOptionsBuilder> configure = null)
103+
{
104+
if (serviceCollection is null)
105+
{
106+
throw new ArgumentNullException(nameof(serviceCollection));
107+
}
108+
109+
serviceCollection.AddMqttConnectionHandler();
110+
serviceCollection.AddHostedMqttServer(configure);
111+
112+
return serviceCollection;
87113
}
88114

89115
public static IServiceCollection AddMqttTcpServerAdapter(this IServiceCollection services)
@@ -94,12 +120,12 @@ public static IServiceCollection AddMqttTcpServerAdapter(this IServiceCollection
94120
return services;
95121
}
96122

97-
public static IServiceCollection AddMqttConnectionHandler(this IServiceCollection services)
123+
public static IServiceCollection AddMqttWebSocketServerAdapter(this IServiceCollection services)
98124
{
99-
services.AddSingleton<MqttConnectionHandler>();
100-
services.AddSingleton<IMqttServerAdapter>(s => s.GetService<MqttConnectionHandler>());
125+
services.AddSingleton<MqttWebSocketServerAdapter>();
126+
services.AddSingleton<IMqttServerAdapter>(s => s.GetService<MqttWebSocketServerAdapter>());
101127

102128
return services;
103129
}
104130
}
105-
}
131+
}

Source/MQTTnet.Tests/Clients/LowLevelMqttClient/LowLevelMqttClient_Tests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using MQTTnet.LowLevelClient;
1414
using MQTTnet.Packets;
1515
using MQTTnet.Protocol;
16+
using MQTTnet.Server;
1617

1718
namespace MQTTnet.Tests.Clients.LowLevelMqttClient
1819
{

Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Tests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using MQTTnet.Internal;
1818
using MQTTnet.Packets;
1919
using MQTTnet.Protocol;
20+
using MQTTnet.Server;
2021
using MQTTnet.Tests.Mockups;
2122

2223
// ReSharper disable InconsistentNaming

Source/MQTTnet.Tests/MQTTv5/Server_Tests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Threading.Tasks;
1111
using MQTTnet.Internal;
1212
using MQTTnet.Protocol;
13+
using MQTTnet.Server;
1314

1415
namespace MQTTnet.Tests.MQTTv5
1516
{

Source/MQTTnet.Tests/Server/General.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ public async Task Intercept_Message()
303303
var server = await testEnvironment.StartServer();
304304
server.InterceptingPublishAsync += e =>
305305
{
306-
e.ApplicationMessage.Payload = Encoding.ASCII.GetBytes("extended");
306+
e.ApplicationMessage.PayloadSegment = new ArraySegment<byte>(Encoding.ASCII.GetBytes("extended"));
307307
return CompletedTask.Instance;
308308
};
309309

@@ -314,7 +314,7 @@ public async Task Intercept_Message()
314314
var isIntercepted = false;
315315
c2.ApplicationMessageReceivedAsync += e =>
316316
{
317-
isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(e.ApplicationMessage.Payload), StringComparison.Ordinal) == 0;
317+
isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment.ToArray()), StringComparison.Ordinal) == 0;
318318
return CompletedTask.Instance;
319319
};
320320

@@ -425,7 +425,7 @@ await server.InjectApplicationMessage(
425425
new MqttApplicationMessage
426426
{
427427
Topic = "/test/1",
428-
Payload = Encoding.UTF8.GetBytes("true"),
428+
PayloadSegment = new ArraySegment<byte>(Encoding.UTF8.GetBytes("true")),
429429
QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce
430430
})
431431
{
@@ -780,7 +780,7 @@ public async Task Send_Long_Body()
780780
var client1 = await testEnvironment.ConnectClient();
781781
client1.ApplicationMessageReceivedAsync += e =>
782782
{
783-
receivedBody = e.ApplicationMessage.Payload;
783+
receivedBody = e.ApplicationMessage.PayloadSegment.ToArray();
784784
return CompletedTask.Instance;
785785
};
786786

Source/MQTTnet.Tests/Server/Publishing_Tests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using MQTTnet.Formatter;
99
using MQTTnet.Internal;
1010
using MQTTnet.Protocol;
11+
using MQTTnet.Server;
1112

1213
namespace MQTTnet.Tests.Server
1314
{

Source/MQTTnet.Tests/Server/Session_Tests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public async Task Set_Session_Item()
283283

284284
server.InterceptingPublishAsync += e =>
285285
{
286-
e.ApplicationMessage.Payload = Encoding.UTF8.GetBytes(e.SessionItems["default_payload"] as string ?? string.Empty);
286+
e.ApplicationMessage.PayloadSegment = new ArraySegment<byte>(Encoding.UTF8.GetBytes(e.SessionItems["default_payload"] as string ?? string.Empty));
287287
return CompletedTask.Instance;
288288
};
289289

Source/MQTTnet.Tests/Server/Tls_Tests.cs

+9-11
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,15 @@ await firstClient.PublishAsync(
101101
new MqttApplicationMessage
102102
{
103103
Topic = "TestTopic1",
104-
Payload = new byte[] { 1, 2, 3, 4 }
104+
PayloadSegment = new ArraySegment<byte>(new byte[] { 1, 2, 3, 4 })
105105
});
106106

107107
await testEnvironment.Server.InjectApplicationMessage(
108108
new InjectedMqttApplicationMessage(
109109
new MqttApplicationMessage
110110
{
111111
Topic = "TestTopic1",
112-
Payload = new byte[] { 1, 2, 3, 4 }
112+
PayloadSegment = new ArraySegment<byte>(new byte[] { 1, 2, 3, 4 })
113113
}));
114114

115115
certificateProvider.CurrentCertificate = CreateCertificate(secondOid);
@@ -137,31 +137,31 @@ await firstClient.PublishAsync(
137137
new MqttApplicationMessage
138138
{
139139
Topic = "TestTopic2",
140-
Payload = new byte[] { 1, 2, 3, 4 }
140+
PayloadSegment = new ArraySegment<byte>(new byte[] { 1, 2, 3, 4 })
141141
});
142142

143143
await testEnvironment.Server.InjectApplicationMessage(
144144
new InjectedMqttApplicationMessage(
145145
new MqttApplicationMessage
146146
{
147147
Topic = "TestTopic2",
148-
Payload = new byte[] { 1, 2, 3, 4 }
148+
PayloadSegment = new ArraySegment<byte>(new byte[] { 1, 2, 3, 4 })
149149
}));
150150

151151
// Ensure first client still works
152152
await firstClient.PublishAsync(
153153
new MqttApplicationMessage
154154
{
155155
Topic = "TestTopic1",
156-
Payload = new byte[] { 1, 2, 3, 4 }
156+
PayloadSegment = new ArraySegment<byte>(new byte[] { 1, 2, 3, 4 })
157157
});
158158

159159
await testEnvironment.Server.InjectApplicationMessage(
160160
new InjectedMqttApplicationMessage(
161161
new MqttApplicationMessage
162162
{
163163
Topic = "TestTopic1",
164-
Payload = new byte[] { 1, 2, 3, 4 }
164+
PayloadSegment = new ArraySegment<byte>(new byte[] { 1, 2, 3, 4 })
165165
}));
166166

167167
await Task.Delay(1000);
@@ -178,12 +178,10 @@ static async Task<IMqttClient> ConnectClientAsync(TestEnvironment testEnvironmen
178178
var clientOptionsBuilder = testEnvironment.Factory.CreateClientOptionsBuilder();
179179
clientOptionsBuilder.WithClientId(Guid.NewGuid().ToString())
180180
.WithTcpServer("localhost", 8883)
181-
.WithTls(
182-
tls =>
181+
.WithTlsOptions(
182+
o =>
183183
{
184-
tls.UseTls = true;
185-
tls.SslProtocol = SslProtocols.Tls12;
186-
tls.CertificateValidationHandler = certValidator;
184+
o.WithSslProtocols(SslProtocols.Tls12).WithCertificateValidationHandler(certValidator);
187185
});
188186

189187
var clientOptions = clientOptionsBuilder.Build();

0 commit comments

Comments
 (0)