Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
chkr1011 committed Aug 18, 2019
2 parents f54598c + cf6f0ec commit 9302e80
Show file tree
Hide file tree
Showing 32 changed files with 313 additions and 135 deletions.
18 changes: 8 additions & 10 deletions Build/MQTTnet.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description>
<releaseNotes>
* [Core] Nuget packages with symbols are now also published to improve debugging.
* [Core] Improve task handling (thanks to @mwinterb)
* [ManagedClient] Fix a race condition in the message storage (thanks to @PaulFake).
* [Server] Added items dictionary to client session in order to share data across interceptors as along as the session exists.
* [Server] Exposed CONNECT packet properties in Application Message and Subscription interceptor.
* [Server] Fixed: Sending Large packets with AspnetCore based connection throws System.ArgumentException.
* [Server] Fixed wrong usage of socket option _NoDelay_.
* [Server] Added remote certificate validation callback (thanks to @rudacs).
* [Server] Add support for certificate passwords (thanks to @cslutgen).
* [MQTTnet.Server] Added REST API for publishing basic messages.
* [Core] Converted all pending methods to use async/await.
* [Core] Fixed an issue when serializing a PubRec (QoS 2) packet for MQTTv5.
* [Client] Fixed an issue when checking for revoked SSL certificates (thanks to @cslutgen).
* [RpcClient] Added support for custom topic generation strategies.
* [Server] Refactoring of server certificate password classes (BREAKING CHANGE!).
* [Server] Fixed an issue with empty server certificate passwords (thanks to @SeppPenner).
* [MQTTnet.Server] Added support for certificate passwords (BREAKING CHANGE IN CONFIG!)
* [MQTTnet.AspNetCore] Fixed an issue with MQTTv5 package serialization (#743, thanks to @JanEggers, @pcbing).
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2019</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
Expand Down
8 changes: 7 additions & 1 deletion Build/build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,14 @@ Write-Host
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx"

# Create NuGet packages.
# Build and execute tests
&$msbuild ..\Tests\MQTTnet.Core.Tests\MQTTnet.Tests.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp2.1" /verbosity:m
&$msbuild ..\Tests\MQTTnet.AspNetCore.Tests\MQTTnet.AspNetCore.Tests.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp2.1" /verbosity:m

vstest.console.exe ..\Tests\MQTTnet.Core.Tests\bin\Release\netcoreapp2.1\MQTTnet.Tests.dll
vstest.console.exe ..\Tests\MQTTnet.AspNetCore.Tests\bin\Release\netcoreapp2.1\MQTTnet.AspNetCore.Tests.dll

# Create NuGet packages.
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile "nuget.exe"

Remove-Item .\NuGet -Force -Recurse -ErrorAction SilentlyContinue
Expand Down
1 change: 0 additions & 1 deletion Source/MQTTnet.AspnetCore/SpanBasedMqttPacketWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ public void Write(IMqttPacketWriter propertyWriter)

GrowIfNeeded(propertyWriter.Length);
Write(propertyWriter.GetBuffer(), 0, propertyWriter.Length);
Commit(propertyWriter.Length);
}

public void Write(byte[] payload, int start, int length)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ public void Dispose()
_maintainConnectionTask = null;
}

_messageQueueLock.Dispose();
_mqttClient.Dispose();
}

Expand Down
33 changes: 30 additions & 3 deletions Source/MQTTnet.Extensions.Rpc/MqttRpcClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Threading.Tasks;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Extensions.Rpc.Options;
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
using MQTTnet.Protocol;

namespace MQTTnet.Extensions.Rpc
Expand All @@ -13,11 +15,18 @@ public class MqttRpcClient : IDisposable
{
private readonly ConcurrentDictionary<string, TaskCompletionSource<byte[]>> _waitingCalls = new ConcurrentDictionary<string, TaskCompletionSource<byte[]>>();
private readonly IMqttClient _mqttClient;
private readonly IMqttRpcClientOptions _options;
private readonly RpcAwareApplicationMessageReceivedHandler _applicationMessageReceivedHandler;

public MqttRpcClient(IMqttClient mqttClient)
[Obsolete("Use MqttRpcClient(IMqttClient mqttClient, IMqttRpcClientOptions options).")]
public MqttRpcClient(IMqttClient mqttClient) : this(mqttClient, new MqttRpcClientOptions())
{
}

public MqttRpcClient(IMqttClient mqttClient, IMqttRpcClientOptions options)
{
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
_options = options ?? throw new ArgumentNullException(nameof(options));

_applicationMessageReceivedHandler = new RpcAwareApplicationMessageReceivedHandler(
mqttClient.ApplicationMessageReceivedHandler,
Expand Down Expand Up @@ -55,8 +64,26 @@ public async Task<byte[]> ExecuteAsync(TimeSpan timeout, string methodName, byte
throw new InvalidOperationException("The application message received handler was modified.");
}

var requestTopic = $"MQTTnet.RPC/{Guid.NewGuid():N}/{methodName}";
var responseTopic = requestTopic + "/response";
var topicNames = _options.TopicGenerationStrategy.CreateRpcTopics(new TopicGenerationContext
{
MethodName = methodName,
QualityOfServiceLevel = qualityOfServiceLevel,
MqttClient = _mqttClient,
Options = _options
});

var requestTopic = topicNames.RequestTopic;
var responseTopic = topicNames.ResponseTopic;

if (string.IsNullOrWhiteSpace(requestTopic))
{
throw new MqttProtocolViolationException("RPC request topic is empty.");
}

if (string.IsNullOrWhiteSpace(responseTopic))
{
throw new MqttProtocolViolationException("RPC response topic is empty.");
}

var requestMessage = new MqttApplicationMessageBuilder()
.WithTopic(requestTopic)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;

namespace MQTTnet.Extensions.Rpc.Options
{
public interface IMqttRpcClientOptions
{
IMqttRpcClientTopicGenerationStrategy TopicGenerationStrategy { get; set; }
}
}
9 changes: 9 additions & 0 deletions Source/MQTTnet.Extensions.Rpc/Options/MqttRpcClientOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;

namespace MQTTnet.Extensions.Rpc.Options
{
public class MqttRpcClientOptions : IMqttRpcClientOptions
{
public IMqttRpcClientTopicGenerationStrategy TopicGenerationStrategy { get; set; } = new DefaultMqttRpcClientTopicGenerationStrategy();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
using System;

namespace MQTTnet.Extensions.Rpc.Options
{
public class MqttRpcClientOptionsBuilder
{
IMqttRpcClientTopicGenerationStrategy _topicGenerationStrategy = new DefaultMqttRpcClientTopicGenerationStrategy();

public MqttRpcClientOptionsBuilder WithTopicGenerationStrategy(IMqttRpcClientTopicGenerationStrategy value)
{
_topicGenerationStrategy = value ?? throw new ArgumentNullException(nameof(value));

return this;
}

public IMqttRpcClientOptions Build()
{
return new MqttRpcClientOptions
{
TopicGenerationStrategy = _topicGenerationStrategy
};
}
}
}
9 changes: 9 additions & 0 deletions Source/MQTTnet.Extensions.Rpc/Options/MqttRpcTopicPair.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace MQTTnet.Extensions.Rpc.Options
{
public class MqttRpcTopicPair
{
public string RequestTopic { get; set; }

public string ResponseTopic { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using MQTTnet.Extensions.Rpc.Options.TopicGeneration;
using System;

namespace MQTTnet.Extensions.Rpc.Options
{
public class DefaultMqttRpcClientTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy
{
public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context)
{
var requestTopic = $"MQTTnet.RPC/{Guid.NewGuid():N}/{context.MethodName}";
var responseTopic = requestTopic + "/response";

return new MqttRpcTopicPair
{
RequestTopic = requestTopic,
ResponseTopic = responseTopic
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
{
public interface IMqttRpcClientTopicGenerationStrategy
{
MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using MQTTnet.Client;
using MQTTnet.Protocol;

namespace MQTTnet.Extensions.Rpc.Options.TopicGeneration
{
public class TopicGenerationContext
{
public string MethodName { get; set; }

public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }

public IMqttClient MqttClient { get; set; }

public IMqttRpcClientOptions Options { get; set; }
}
}
35 changes: 35 additions & 0 deletions Source/MQTTnet.Server/Configuration/CertificateSettingsModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.IO;

namespace MQTTnet.Server.Configuration
{
public class CertificateSettingsModel
{
/// <summary>
/// Path to certificate.
/// </summary>
public string Path { get; set; }

/// <summary>
/// Password of certificate.
/// </summary>
public string Password { get; set; }

/// <summary>
/// Read certificate file.
/// </summary>
public byte[] ReadCertificate()
{
if (string.IsNullOrEmpty(Path) || string.IsNullOrWhiteSpace(Path))
{
throw new FileNotFoundException("No path set");
}

if (!File.Exists(Path))
{
throw new FileNotFoundException($"Could not find Certificate in path: {Path}");
}

return File.ReadAllBytes(Path);
}
}
}
23 changes: 2 additions & 21 deletions Source/MQTTnet.Server/Configuration/TcpEndpointModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace MQTTnet.Server.Configuration
public class TcpEndPointModel
{
/// <summary>
/// Path to Certificate
/// Certificate settings.
/// </summary>
public string CertificatePath { get; set; }
public CertificateSettingsModel Certificate { get; set; }

/// <summary>
/// Enabled / Disable
Expand All @@ -33,25 +33,6 @@ public class TcpEndPointModel
/// </summary>
public int Port { get; set; } = 1883;

/// <summary>
/// Read Certificate file
/// </summary>
/// <returns></returns>
public byte[] ReadCertificate()
{
if (string.IsNullOrEmpty(CertificatePath) || string.IsNullOrWhiteSpace(CertificatePath))
{
throw new FileNotFoundException("No path set");
}

if (!File.Exists(CertificatePath))
{
throw new FileNotFoundException($"Could not find Certificate in path: {CertificatePath}");
}

return File.ReadAllBytes(CertificatePath);
}

/// <summary>
/// Read IPv4
/// </summary>
Expand Down
22 changes: 18 additions & 4 deletions Source/MQTTnet.Server/Mqtt/MqttServerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class MqttServerService
MqttSubscriptionInterceptor mqttSubscriptionInterceptor,
MqttApplicationMessageInterceptor mqttApplicationMessageInterceptor,
MqttServerStorage mqttServerStorage,
PythonScriptHostService pythonScriptHostService,
PythonScriptHostService pythonScriptHostService,
ILogger<MqttServerService> logger)
{
_settings = mqttSettings ?? throw new ArgumentNullException(nameof(mqttSettings));
Expand Down Expand Up @@ -179,7 +179,7 @@ private IMqttServerOptions CreateMqttServerOptions()
.WithApplicationMessageInterceptor(_mqttApplicationMessageInterceptor)
.WithSubscriptionInterceptor(_mqttSubscriptionInterceptor)
.WithStorage(_mqttServerStorage);

// Configure unencrypted connections
if (_settings.TcpEndPoint.Enabled)
{
Expand Down Expand Up @@ -210,9 +210,23 @@ private IMqttServerOptions CreateMqttServerOptions()
{
options
.WithEncryptedEndpoint()
.WithEncryptionSslProtocol(SslProtocols.Tls12)
.WithEncryptionCertificate(_settings.EncryptedTcpEndPoint.ReadCertificate());
.WithEncryptionSslProtocol(SslProtocols.Tls12);

if (!string.IsNullOrEmpty(_settings.EncryptedTcpEndPoint?.Certificate?.Path))
{
IMqttServerCertificateCredentials certificateCredentials = null;

if (!string.IsNullOrEmpty(_settings.EncryptedTcpEndPoint?.Certificate?.Password))
{
certificateCredentials = new MqttServerCertificateCredentials
{
Password = _settings.EncryptedTcpEndPoint.Certificate.Password
};
}

options.WithEncryptionCertificate(_settings.EncryptedTcpEndPoint.Certificate.ReadCertificate(), certificateCredentials);
}

if (_settings.EncryptedTcpEndPoint.TryReadIPv4(out var address4))
{
options.WithEncryptedEndpointBoundIPAddress(address4);
Expand Down
7 changes: 5 additions & 2 deletions Source/MQTTnet.Server/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
"IPv4": "*",
"IPv6": "*",
"Port": 8883,
"CertificatePath": "/absolute/path/to/pfx"
"Certificate": {
"Path": "/absolute/path/to/pfx",
"Password": ""
}
},
"WebSocketEndPoint": {
"Enabled": true,
Expand Down Expand Up @@ -63,4 +66,4 @@
}
},
"AllowedHosts": "*"
}
}
26 changes: 18 additions & 8 deletions Source/MQTTnet/Formatter/IMqttPacketWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,25 @@ public interface IMqttPacketWriter
int Length { get; }

void WriteWithLengthPrefix(string value);
void Write(byte returnCode);
void WriteWithLengthPrefix(byte[] payload);
void Write(ushort keepAlivePeriod);
void Write(IMqttPacketWriter propertyWriter);
void WriteVariableLengthInteger(uint length);
void Write(byte[] payload, int v, int length);
void Reset(int v);
void Seek(int v);

void Write(byte value);

void WriteWithLengthPrefix(byte[] value);

void Write(ushort value);

void Write(IMqttPacketWriter value);

void WriteVariableLengthInteger(uint value);

void Write(byte[] value, int offset, int length);

void Reset(int length);

void Seek(int offset);

void FreeBuffer();

byte[] GetBuffer();
}
}
Loading

0 comments on commit 9302e80

Please sign in to comment.