mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-25 23:53:07 +08:00
Improve samples
This commit is contained in:
+18
-1
@@ -4,7 +4,13 @@
|
|||||||
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
Console.WriteLine("Welcome to MQTTnet samples!");
|
Console.BackgroundColor = ConsoleColor.White;
|
||||||
|
Console.BackgroundColor = ConsoleColor.Red;
|
||||||
|
Console.Title = "Samples - MQTTnet";
|
||||||
|
Console.WriteLine("----------------------------------------------");
|
||||||
|
Console.WriteLine("- Welcome to MQTTnet samples! -");
|
||||||
|
Console.WriteLine("----------------------------------------------");
|
||||||
|
Console.ResetColor();
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
|
|
||||||
var sampleClasses = Assembly.GetExecutingAssembly().GetExportedTypes().OrderBy(c => c.Name).ToList();
|
var sampleClasses = Assembly.GetExecutingAssembly().GetExportedTypes().OrderBy(c => c.Name).ToList();
|
||||||
@@ -16,7 +22,11 @@ foreach (var sampleClass in sampleClasses)
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
Console.Write("Please choose sample class (press Enter to continue): ");
|
Console.Write("Please choose sample class (press Enter to continue): ");
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
var input = Console.ReadLine();
|
var input = Console.ReadLine();
|
||||||
var selectedIndex = int.Parse(input ?? "0");
|
var selectedIndex = int.Parse(input ?? "0");
|
||||||
var selectedSampleClass = sampleClasses[selectedIndex];
|
var selectedSampleClass = sampleClasses[selectedIndex];
|
||||||
@@ -29,12 +39,19 @@ foreach (var sampleMethod in sampleMethods)
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
Console.Write("Please choose sample (press Enter to continue): ");
|
Console.Write("Please choose sample (press Enter to continue): ");
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
input = Console.ReadLine();
|
input = Console.ReadLine();
|
||||||
selectedIndex = int.Parse(input ?? "0");
|
selectedIndex = int.Parse(input ?? "0");
|
||||||
var selectedSampleMethod = sampleMethods[selectedIndex];
|
var selectedSampleMethod = sampleMethods[selectedIndex];
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
Console.WriteLine("Executing sample...");
|
Console.WriteLine("Executing sample...");
|
||||||
|
Console.ResetColor();
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ using MQTTnet.Server;
|
|||||||
|
|
||||||
namespace MQTTnet.Samples.Server;
|
namespace MQTTnet.Samples.Server;
|
||||||
|
|
||||||
public static class Server_Asp_Net_Samples
|
public static class Server_ASP_NET_Samples
|
||||||
{
|
{
|
||||||
public static Task Start_Server_With_WebSockets_Support()
|
public static Task Start_Server_With_WebSockets_Support()
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
using System.Net;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using MQTTnet.Server;
|
||||||
|
|
||||||
|
namespace MQTTnet.Samples.Server;
|
||||||
|
|
||||||
|
public static class Server_TLS_Samples
|
||||||
|
{
|
||||||
|
public static async Task Run_Server_With_Self_Signed_Certificate()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This sample starts a simple MQTT server which will accept any TCP connection.
|
||||||
|
* It also has an encrypted connection using a self signed TLS certificate.
|
||||||
|
*
|
||||||
|
* See sample "Run_Minimal_Server" for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
// This certificate is self signed so that
|
||||||
|
var certificate = CreateSelfSignedCertificate("1.3.6.1.5.5.7.3.1");
|
||||||
|
|
||||||
|
var mqttServerOptions = new MqttServerOptionsBuilder().WithEncryptionCertificate(certificate).WithEncryptedEndpoint().Build();
|
||||||
|
|
||||||
|
using (var mqttServer = mqttFactory.CreateMqttServer(mqttServerOptions))
|
||||||
|
{
|
||||||
|
await mqttServer.StartAsync();
|
||||||
|
|
||||||
|
Console.WriteLine("Press Enter to exit.");
|
||||||
|
Console.ReadLine();
|
||||||
|
|
||||||
|
// Stop and dispose the MQTT server if it is no longer needed!
|
||||||
|
await mqttServer.StopAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static X509Certificate2 CreateSelfSignedCertificate(string oid)
|
||||||
|
{
|
||||||
|
var sanBuilder = new SubjectAlternativeNameBuilder();
|
||||||
|
sanBuilder.AddIpAddress(IPAddress.Loopback);
|
||||||
|
sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
|
||||||
|
sanBuilder.AddDnsName("localhost");
|
||||||
|
|
||||||
|
using (var rsa = RSA.Create())
|
||||||
|
{
|
||||||
|
var certRequest = new CertificateRequest("CN=localhost", rsa, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
|
||||||
|
|
||||||
|
certRequest.CertificateExtensions.Add(
|
||||||
|
new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false));
|
||||||
|
|
||||||
|
certRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new(oid) }, false));
|
||||||
|
|
||||||
|
certRequest.CertificateExtensions.Add(sanBuilder.Build());
|
||||||
|
|
||||||
|
using (var certificate = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddMinutes(-10), DateTimeOffset.Now.AddMinutes(10)))
|
||||||
|
{
|
||||||
|
var pfxCertificate = new X509Certificate2(
|
||||||
|
certificate.Export(X509ContentType.Pfx),
|
||||||
|
(string)null!,
|
||||||
|
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
||||||
|
|
||||||
|
return pfxCertificate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,4 @@
|
|||||||
|
|
||||||
#if !WINDOWS_UWP && (NET48_OR_GREATER || NET5_0_OR_GREATER)
|
#if !WINDOWS_UWP && (NET48_OR_GREATER || NET5_0_OR_GREATER)
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using MQTTnet.Certificates;
|
|
||||||
using MQTTnet.Client;
|
|
||||||
using MQTTnet.Server;
|
|
||||||
using MQTTnet.Tests.Mockups;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -13,61 +7,52 @@ using System.Security.Cryptography;
|
|||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using MQTTnet.Certificates;
|
||||||
|
using MQTTnet.Client;
|
||||||
|
using MQTTnet.Formatter;
|
||||||
|
using MQTTnet.Server;
|
||||||
|
using MQTTnet.Tests.Mockups;
|
||||||
|
|
||||||
namespace MQTTnet.Tests.Server
|
namespace MQTTnet.Tests.Server
|
||||||
{
|
{
|
||||||
|
|
||||||
[TestClass]
|
[TestClass]
|
||||||
|
public sealed class Tls_Tests : BaseTestClass
|
||||||
public class Tls_Tests : BaseTestClass
|
|
||||||
{
|
{
|
||||||
|
static X509Certificate2 CreateCertificate(string oid)
|
||||||
public X509Certificate2 CreateCertificate(string oid)
|
|
||||||
{
|
{
|
||||||
var sanBuilder = new SubjectAlternativeNameBuilder();
|
var sanBuilder = new SubjectAlternativeNameBuilder();
|
||||||
sanBuilder.AddIpAddress(IPAddress.Loopback);
|
sanBuilder.AddIpAddress(IPAddress.Loopback);
|
||||||
sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
|
sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
|
||||||
sanBuilder.AddDnsName("localhost");
|
sanBuilder.AddDnsName("localhost");
|
||||||
var rsa = RSA.Create();
|
|
||||||
|
|
||||||
var certRequest = new CertificateRequest("CN=localhost", rsa, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
|
|
||||||
|
|
||||||
certRequest.CertificateExtensions.Add(
|
|
||||||
new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false));
|
|
||||||
|
|
||||||
certRequest.CertificateExtensions.Add(
|
|
||||||
new X509EnhancedKeyUsageExtension(
|
|
||||||
new OidCollection { new Oid(oid) }, false));
|
|
||||||
|
|
||||||
certRequest.CertificateExtensions.Add(sanBuilder.Build());
|
|
||||||
|
|
||||||
var certificate = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddMinutes(-10), DateTimeOffset.Now.AddMinutes(10));
|
|
||||||
var pfxCertificate = new X509Certificate2(certificate.Export(X509ContentType.Pfx), (string)null, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
|
||||||
|
|
||||||
return pfxCertificate;
|
using (var rsa = RSA.Create())
|
||||||
}
|
{
|
||||||
|
var certRequest = new CertificateRequest("CN=localhost", rsa, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
|
||||||
|
|
||||||
private async Task<IMqttClient> ConnectClientAsync(TestEnvironment testEnvironment, Func<MqttClientCertificateValidationEventArgs, bool> certValidator)
|
certRequest.CertificateExtensions.Add(
|
||||||
{
|
new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false));
|
||||||
var clientOptionsBuilder = testEnvironment.Factory.CreateClientOptionsBuilder();
|
|
||||||
clientOptionsBuilder
|
certRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid(oid) }, false));
|
||||||
.WithClientId(Guid.NewGuid().ToString())
|
|
||||||
.WithTcpServer("localhost", 8883)
|
certRequest.CertificateExtensions.Add(sanBuilder.Build());
|
||||||
.WithTls(tls =>
|
|
||||||
|
using (var certificate = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddMinutes(-10), DateTimeOffset.Now.AddMinutes(10)))
|
||||||
{
|
{
|
||||||
tls.UseTls = true;
|
var pfxCertificate = new X509Certificate2(
|
||||||
tls.SslProtocol = SslProtocols.Tls12;
|
certificate.Export(X509ContentType.Pfx),
|
||||||
tls.CertificateValidationHandler = certValidator;
|
(string)null,
|
||||||
});
|
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
|
||||||
|
|
||||||
var clientOptions = clientOptionsBuilder.Build();
|
return pfxCertificate;
|
||||||
return await testEnvironment.ConnectClient(clientOptions);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task Tls_Swap_Test()
|
public async Task Tls_Swap_Test()
|
||||||
{
|
{
|
||||||
var testEnvironment = CreateTestEnvironment(MQTTnet.Formatter.MqttProtocolVersion.V500);
|
var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500);
|
||||||
var serverOptionsBuilder = testEnvironment.Factory.CreateServerOptionsBuilder();
|
var serverOptionsBuilder = testEnvironment.Factory.CreateServerOptionsBuilder();
|
||||||
|
|
||||||
var firstOid = "1.3.6.1.5.5.7.3.1";
|
var firstOid = "1.3.6.1.5.5.7.3.1";
|
||||||
@@ -78,11 +63,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
CurrentCertificate = CreateCertificate(firstOid)
|
CurrentCertificate = CreateCertificate(firstOid)
|
||||||
};
|
};
|
||||||
|
|
||||||
serverOptionsBuilder
|
serverOptionsBuilder.WithoutDefaultEndpoint().WithEncryptedEndpoint().WithEncryptionSslProtocol(SslProtocols.Tls12).WithEncryptionCertificate(certificateProvider);
|
||||||
.WithoutDefaultEndpoint()
|
|
||||||
.WithEncryptedEndpoint()
|
|
||||||
.WithEncryptionSslProtocol(SslProtocols.Tls12)
|
|
||||||
.WithEncryptionCertificate(certificateProvider);
|
|
||||||
|
|
||||||
var serverOptions = serverOptionsBuilder.Build();
|
var serverOptions = serverOptionsBuilder.Build();
|
||||||
|
|
||||||
@@ -97,12 +78,14 @@ namespace MQTTnet.Tests.Server
|
|||||||
};
|
};
|
||||||
|
|
||||||
await server.StartAsync();
|
await server.StartAsync();
|
||||||
|
|
||||||
var firstClient = await ConnectClientAsync(testEnvironment, args =>
|
var firstClient = await ConnectClientAsync(
|
||||||
{
|
testEnvironment,
|
||||||
Assert.AreEqual(firstOid, ((X509Certificate2)args.Certificate).Extensions.OfType<X509EnhancedKeyUsageExtension>().First().EnhancedKeyUsages[0].Value);
|
args =>
|
||||||
return true;
|
{
|
||||||
});
|
Assert.AreEqual(firstOid, ((X509Certificate2)args.Certificate).Extensions.OfType<X509EnhancedKeyUsageExtension>().First().EnhancedKeyUsages[0].Value);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
var firstClientReceivedCount = 0;
|
var firstClientReceivedCount = 0;
|
||||||
firstClient.ApplicationMessageReceivedAsync += args =>
|
firstClient.ApplicationMessageReceivedAsync += args =>
|
||||||
@@ -114,27 +97,31 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await firstClient.SubscribeAsync("TestTopic1");
|
await firstClient.SubscribeAsync("TestTopic1");
|
||||||
|
|
||||||
await firstClient.PublishAsync(new MqttApplicationMessage
|
await firstClient.PublishAsync(
|
||||||
{
|
|
||||||
Topic = "TestTopic1",
|
|
||||||
Payload = new byte[] { 1, 2, 3, 4}
|
|
||||||
});
|
|
||||||
|
|
||||||
await testEnvironment.Server.InjectApplicationMessage(new InjectedMqttApplicationMessage(
|
|
||||||
new MqttApplicationMessage
|
new MqttApplicationMessage
|
||||||
{
|
{
|
||||||
Topic = "TestTopic1",
|
Topic = "TestTopic1",
|
||||||
Payload = new byte[] { 1, 2, 3, 4 }
|
Payload = new byte[] { 1, 2, 3, 4 }
|
||||||
}));
|
});
|
||||||
|
|
||||||
|
await testEnvironment.Server.InjectApplicationMessage(
|
||||||
|
new InjectedMqttApplicationMessage(
|
||||||
|
new MqttApplicationMessage
|
||||||
|
{
|
||||||
|
Topic = "TestTopic1",
|
||||||
|
Payload = new byte[] { 1, 2, 3, 4 }
|
||||||
|
}));
|
||||||
|
|
||||||
certificateProvider.CurrentCertificate = CreateCertificate(secondOid);
|
certificateProvider.CurrentCertificate = CreateCertificate(secondOid);
|
||||||
|
|
||||||
// Validate that the certificate was switched
|
// Validate that the certificate was switched
|
||||||
var secondClient = await ConnectClientAsync(testEnvironment, args =>
|
var secondClient = await ConnectClientAsync(
|
||||||
{
|
testEnvironment,
|
||||||
Assert.AreEqual(secondOid, ((X509Certificate2)args.Certificate).Extensions.OfType<X509EnhancedKeyUsageExtension>().First().EnhancedKeyUsages[0].Value);
|
args =>
|
||||||
return true;
|
{
|
||||||
});
|
Assert.AreEqual(secondOid, ((X509Certificate2)args.Certificate).Extensions.OfType<X509EnhancedKeyUsageExtension>().First().EnhancedKeyUsages[0].Value);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
var secondClientReceivedCount = 0;
|
var secondClientReceivedCount = 0;
|
||||||
secondClient.ApplicationMessageReceivedAsync += args =>
|
secondClient.ApplicationMessageReceivedAsync += args =>
|
||||||
@@ -146,32 +133,36 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await secondClient.SubscribeAsync("TestTopic2");
|
await secondClient.SubscribeAsync("TestTopic2");
|
||||||
|
|
||||||
await firstClient.PublishAsync(new MqttApplicationMessage
|
await firstClient.PublishAsync(
|
||||||
|
new MqttApplicationMessage
|
||||||
{
|
{
|
||||||
Topic = "TestTopic2",
|
Topic = "TestTopic2",
|
||||||
Payload = new byte[] { 1, 2, 3, 4 }
|
Payload = new byte[] { 1, 2, 3, 4 }
|
||||||
});
|
});
|
||||||
|
|
||||||
await testEnvironment.Server.InjectApplicationMessage(new InjectedMqttApplicationMessage(
|
await testEnvironment.Server.InjectApplicationMessage(
|
||||||
new MqttApplicationMessage
|
new InjectedMqttApplicationMessage(
|
||||||
{
|
new MqttApplicationMessage
|
||||||
Topic = "TestTopic2",
|
{
|
||||||
Payload = new byte[] { 1, 2, 3, 4 }
|
Topic = "TestTopic2",
|
||||||
}));
|
Payload = new byte[] { 1, 2, 3, 4 }
|
||||||
|
}));
|
||||||
|
|
||||||
// Ensure first client still works
|
// Ensure first client still works
|
||||||
await firstClient.PublishAsync(new MqttApplicationMessage
|
await firstClient.PublishAsync(
|
||||||
{
|
|
||||||
Topic = "TestTopic1",
|
|
||||||
Payload = new byte[] { 1, 2, 3, 4 }
|
|
||||||
});
|
|
||||||
|
|
||||||
await testEnvironment.Server.InjectApplicationMessage(new InjectedMqttApplicationMessage(
|
|
||||||
new MqttApplicationMessage
|
new MqttApplicationMessage
|
||||||
{
|
{
|
||||||
Topic = "TestTopic1",
|
Topic = "TestTopic1",
|
||||||
Payload = new byte[] { 1, 2, 3, 4 }
|
Payload = new byte[] { 1, 2, 3, 4 }
|
||||||
}));
|
});
|
||||||
|
|
||||||
|
await testEnvironment.Server.InjectApplicationMessage(
|
||||||
|
new InjectedMqttApplicationMessage(
|
||||||
|
new MqttApplicationMessage
|
||||||
|
{
|
||||||
|
Topic = "TestTopic1",
|
||||||
|
Payload = new byte[] { 1, 2, 3, 4 }
|
||||||
|
}));
|
||||||
|
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
|
|
||||||
@@ -182,17 +173,32 @@ namespace MQTTnet.Tests.Server
|
|||||||
await server.StopAsync();
|
await server.StopAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async Task<IMqttClient> ConnectClientAsync(TestEnvironment testEnvironment, Func<MqttClientCertificateValidationEventArgs, bool> certValidator)
|
||||||
private class CertificateProvider : ICertificateProvider
|
|
||||||
{
|
{
|
||||||
|
var clientOptionsBuilder = testEnvironment.Factory.CreateClientOptionsBuilder();
|
||||||
|
clientOptionsBuilder.WithClientId(Guid.NewGuid().ToString())
|
||||||
|
.WithTcpServer("localhost", 8883)
|
||||||
|
.WithTls(
|
||||||
|
tls =>
|
||||||
|
{
|
||||||
|
tls.UseTls = true;
|
||||||
|
tls.SslProtocol = SslProtocols.Tls12;
|
||||||
|
tls.CertificateValidationHandler = certValidator;
|
||||||
|
});
|
||||||
|
|
||||||
|
var clientOptions = clientOptionsBuilder.Build();
|
||||||
|
return await testEnvironment.ConnectClient(clientOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class CertificateProvider : ICertificateProvider
|
||||||
|
{
|
||||||
public X509Certificate2 CurrentCertificate { get; set; }
|
public X509Certificate2 CurrentCertificate { get; set; }
|
||||||
|
|
||||||
public X509Certificate2 GetCertificate()
|
public X509Certificate2 GetCertificate()
|
||||||
=> CurrentCertificate;
|
{
|
||||||
|
return CurrentCertificate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user