Ver a proveniência

Merge pull request #2 from chkr1011/develop

Develop
release/3.x.x
cslutgen há 5 anos
committed by GitHub
ascendente
cometimento
4cefa1dfa9
Não foi encontrada uma chave conhecida para esta assinatura, na base de dados ID da chave GPG: 4AEE18F83AFDEB23
17 ficheiros alterados com 173 adições e 121 eliminações
  1. +9
    -6
      .github/ISSUE_TEMPLATE/bug_report.md
  2. +8
    -7
      .github/ISSUE_TEMPLATE/custom.md
  3. +7
    -6
      .github/ISSUE_TEMPLATE/feature_request.md
  4. +1
    -0
      Build/MQTTnet.nuspec
  5. +35
    -0
      Source/MQTTnet.Server/Configuration/CertificateSettingsModel.cs
  6. +2
    -21
      Source/MQTTnet.Server/Configuration/TcpEndpointModel.cs
  7. +18
    -4
      Source/MQTTnet.Server/Mqtt/MqttServerService.cs
  8. +5
    -2
      Source/MQTTnet.Server/appsettings.json
  9. +7
    -0
      Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs
  10. +0
    -55
      Source/MQTTnet/Formatter/MqttPacketReader.cs
  11. +1
    -1
      Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs
  12. +2
    -2
      Source/MQTTnet/MQTTnet.csproj
  13. +4
    -0
      Source/MQTTnet/Server/IMqttServerCertificateCredentials.cs
  14. +7
    -0
      Source/MQTTnet/Server/MqttServerCertificateCredentials.cs
  15. +13
    -2
      Source/MQTTnet/Server/MqttServerOptionsBuilder.cs
  16. +2
    -0
      Source/MQTTnet/Server/MqttServerTlsTcpEndpointOptions.cs
  17. +52
    -15
      Tests/MQTTnet.Core.Tests/RPC_Tests.cs

+ 9
- 6
.github/ISSUE_TEMPLATE/bug_report.md Ver ficheiro

@@ -1,6 +1,6 @@
---
name: Bug report
about: Create a report to help us improve
about: Create a report to help us improve.
title: ''
labels: ''
assignees: ''
@@ -11,11 +11,12 @@ assignees: ''
A clear and concise description of what the bug is.

### Which project is your bug related to?
- [x] Client
- [ ] ManagedClient
- [ ] MQTTnet.Server standalone
- [ ] Server
- [ ] Generic
<!-- Remove the items which don't apply from the following list -->
- Client
- ManagedClient
- MQTTnet.Server standalone
- Server
- Generic

### To Reproduce
Steps to reproduce the behavior:
@@ -35,9 +36,11 @@ Add any other context about the problem here.
Include debugging or logging information here:

```batch
\\ Put your logging output here.
```
### Code example
Please provide full code examples below where possible to make it easier for the developers to check your issues.
```csharp
\\ Put your code here.
```

+ 8
- 7
.github/ISSUE_TEMPLATE/custom.md Ver ficheiro

@@ -1,6 +1,6 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
about: Do you have a question related to the project? Use this template.
title: ''
labels: ''
assignees: ''
@@ -10,9 +10,10 @@ assignees: ''
### Describe your question
A clear and concise description of what you want to know.

### Which project is your bug related to?
- [x] Client
- [ ] ManagedClient
- [ ] MQTTnet.Server standalone
- [ ] Server
- [ ] Generic
### Which project is your question related to?
<!-- Remove the items which don't apply from the following list -->
- Client
- ManagedClient
- MQTTnet.Server standalone
- Server
- Generic

+ 7
- 6
.github/ISSUE_TEMPLATE/feature_request.md Ver ficheiro

@@ -1,6 +1,6 @@
---
name: Feature request
about: Suggest an idea for this project
about: Suggest an idea for this project.
title: ''
labels: ''
assignees: ''
@@ -12,11 +12,12 @@ Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Example. I'm am trying to do [...] but [...]

### Which project is your feature request related to?
- [x] Client
- [ ] ManagedClient
- [ ] MQTTnet.Server standalone
- [ ] Server
- [ ] Generic
<!-- Remove the items which don't apply from the following list -->
- Client
- ManagedClient
- MQTTnet.Server standalone
- Server
- Generic

### Describe the solution you'd like
A clear and concise description of what you want to happen.


+ 1
- 0
Build/MQTTnet.nuspec Ver ficheiro

@@ -19,6 +19,7 @@
* [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.
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2019</copyright>


+ 35
- 0
Source/MQTTnet.Server/Configuration/CertificateSettingsModel.cs Ver ficheiro

@@ -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);
}
}
}

+ 2
- 21
Source/MQTTnet.Server/Configuration/TcpEndpointModel.cs Ver ficheiro

@@ -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
@@ -33,25 +33,6 @@ namespace MQTTnet.Server.Configuration
/// </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>


+ 18
- 4
Source/MQTTnet.Server/Mqtt/MqttServerService.cs Ver ficheiro

@@ -47,7 +47,7 @@ namespace MQTTnet.Server.Mqtt
MqttSubscriptionInterceptor mqttSubscriptionInterceptor,
MqttApplicationMessageInterceptor mqttApplicationMessageInterceptor,
MqttServerStorage mqttServerStorage,
PythonScriptHostService pythonScriptHostService,
PythonScriptHostService pythonScriptHostService,
ILogger<MqttServerService> logger)
{
_settings = mqttSettings ?? throw new ArgumentNullException(nameof(mqttSettings));
@@ -179,7 +179,7 @@ namespace MQTTnet.Server.Mqtt
.WithApplicationMessageInterceptor(_mqttApplicationMessageInterceptor)
.WithSubscriptionInterceptor(_mqttSubscriptionInterceptor)
.WithStorage(_mqttServerStorage);
// Configure unencrypted connections
if (_settings.TcpEndPoint.Enabled)
{
@@ -210,9 +210,23 @@ namespace MQTTnet.Server.Mqtt
{
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);


+ 5
- 2
Source/MQTTnet.Server/appsettings.json Ver ficheiro

@@ -27,7 +27,10 @@
"IPv4": "*",
"IPv6": "*",
"Port": 8883,
"CertificatePath": "/absolute/path/to/pfx"
"Certificate": {
"Path": "/absolute/path/to/pfx",
"Password": ""
}
},
"WebSocketEndPoint": {
"Enabled": true,
@@ -63,4 +66,4 @@
}
},
"AllowedHosts": "*"
}
}

+ 7
- 0
Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs Ver ficheiro

@@ -139,6 +139,13 @@ namespace MQTTnet.Client.Options
return this;
}

public MqttClientOptionsBuilder WithCredentials(IMqttClientCredentials credentials)
{
_options.Credentials = credentials;

return this;
}

public MqttClientOptionsBuilder WithExtendedAuthenticationExchangeHandler(IMqttExtendedAuthenticationExchangeHandler handler)
{
_options.ExtendedAuthenticationExchangeHandler = handler;


+ 0
- 55
Source/MQTTnet/Formatter/MqttPacketReader.cs Ver ficheiro

@@ -21,8 +21,6 @@ namespace MQTTnet.Formatter
{
// The MQTT fixed header contains 1 byte of flags and at least 1 byte for the remaining data length.
// So in all cases at least 2 bytes must be read for a complete MQTT packet.
// async/await is used here because the next packet is received in a couple of minutes so the performance
// impact is acceptable according to a useless waiting thread.
var buffer = fixedHeaderBuffer;
var totalBytesRead = 0;

@@ -55,16 +53,7 @@ namespace MQTTnet.Formatter
};
}

#if WINDOWS_UWP
// UWP will have a dead lock when calling this not async.
var bodyLength = await ReadBodyLengthAsync(buffer[1], cancellationToken).ConfigureAwait(false);
#else
// Here the async/await pattern is not used because the overhead of context switches
// is too big for reading 1 byte in a row. We expect that the remaining data was sent
// directly after the initial bytes. If the client disconnects just in this moment we
// will get an exception anyway.
var bodyLength = ReadBodyLength(buffer[1], cancellationToken);
#endif

if (!bodyLength.HasValue)
{
@@ -81,49 +70,6 @@ namespace MQTTnet.Formatter
};
}

#if !WINDOWS_UWP
private int? ReadBodyLength(byte initialEncodedByte, CancellationToken cancellationToken)
{
var offset = 0;
var multiplier = 128;
var value = initialEncodedByte & 127;
int encodedByte = initialEncodedByte;

while ((encodedByte & 128) != 0)
{
offset++;
if (offset > 3)
{
throw new MqttProtocolViolationException("Remaining length is invalid.");
}

if (cancellationToken.IsCancellationRequested)
{
return null;
}

var readCount = _channel.ReadAsync(_singleByteBuffer, 0, 1, cancellationToken).GetAwaiter().GetResult();

if (cancellationToken.IsCancellationRequested)
{
return null;
}

if (readCount == 0)
{
return null;
}

encodedByte = _singleByteBuffer[0];

value += (encodedByte & 127) * multiplier;
multiplier *= 128;
}

return value;
}
#else

private async Task<int?> ReadBodyLengthAsync(byte initialEncodedByte, CancellationToken cancellationToken)
{
var offset = 0;
@@ -164,6 +110,5 @@ namespace MQTTnet.Formatter

return value;
}
#endif
}
}

+ 1
- 1
Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs Ver ficheiro

@@ -48,7 +48,7 @@ namespace MQTTnet.Implementations
throw new ArgumentException("TLS certificate is not set.");
}

var tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate);
var tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate, options.TlsEndpointOptions.CertificateCredentials.Password);
if (!tlsCertificate.HasPrivateKey)
{
throw new InvalidOperationException("The certificate for TLS encryption must contain the private key.");


+ 2
- 2
Source/MQTTnet/MQTTnet.csproj Ver ficheiro

@@ -41,13 +41,13 @@
<DefineConstants>RELEASE;NETSTANDARD1_3</DefineConstants>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.3'">
<PackageReference Include="System.Net.Security" Version="4.3.2" />
<PackageReference Include="System.Net.WebSockets" Version="4.3.0" />
<PackageReference Include="System.Net.WebSockets.Client" Version="4.3.2" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.3'">
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<PackageReference Include="System.Net.Security" Version="4.3.2" />
<PackageReference Include="System.Net.WebSockets" Version="4.3.0" />
<PackageReference Include="System.Net.WebSockets.Client" Version="4.3.2" />


+ 4
- 0
Source/MQTTnet/Server/IMqttServerCertificateCredentials.cs Ver ficheiro

@@ -0,0 +1,4 @@
public interface IMqttServerCertificateCredentials
{
string Password { get; }
}

+ 7
- 0
Source/MQTTnet/Server/MqttServerCertificateCredentials.cs Ver ficheiro

@@ -0,0 +1,7 @@
namespace MQTTnet.Server
{
public class MqttServerCertificateCredentials : IMqttServerCertificateCredentials
{
public string Password { get; set; }
}
}

+ 13
- 2
Source/MQTTnet/Server/MqttServerOptionsBuilder.cs Ver ficheiro

@@ -82,9 +82,10 @@ namespace MQTTnet.Server
return this;
}

public MqttServerOptionsBuilder WithEncryptionCertificate(byte[] value)
public MqttServerOptionsBuilder WithEncryptionCertificate(byte[] value, IMqttServerCertificateCredentials credentials = null)
{
_options.TlsEndpointOptions.Certificate = value;
_options.TlsEndpointOptions.CertificateCredentials = credentials;
return this;
}

@@ -94,6 +95,16 @@ namespace MQTTnet.Server
return this;
}

#if !WINDOWS_UWP
public MqttServerOptionsBuilder WithClientCertificate(RemoteCertificateValidationCallback validationCallback = null, bool checkCertificateRevocation = false)
{
_options.TlsEndpointOptions.ClientCertificateRequired = true;
_options.TlsEndpointOptions.CheckCertificateRevocation = checkCertificateRevocation;
_options.TlsEndpointOptions.RemoteCertificateValidationCallback = validationCallback;
return this;
}
#endif

public MqttServerOptionsBuilder WithoutEncryptedEndpoint()
{
_options.TlsEndpointOptions.IsEnabled = false;
@@ -107,7 +118,7 @@ namespace MQTTnet.Server
return this;
}
#endif
public MqttServerOptionsBuilder WithStorage(IMqttServerStorage value)
{
_options.Storage = value;


+ 2
- 0
Source/MQTTnet/Server/MqttServerTlsTcpEndpointOptions.cs Ver ficheiro

@@ -12,6 +12,8 @@ namespace MQTTnet.Server

public byte[] Certificate { get; set; }

public IMqttServerCertificateCredentials CertificateCredentials { get; set; }

public bool ClientCertificateRequired { get; set; }

public bool CheckCertificateRevocation { get; set; }


+ 52
- 15
Tests/MQTTnet.Core.Tests/RPC_Tests.cs Ver ficheiro

@@ -8,6 +8,8 @@ using MQTTnet.Client.Receiving;
using MQTTnet.Exceptions;
using MQTTnet.Extensions.Rpc;
using MQTTnet.Protocol;
using MQTTnet.Client.Options;
using MQTTnet.Formatter;

namespace MQTTnet.Tests
{
@@ -15,26 +17,39 @@ namespace MQTTnet.Tests
public class RPC_Tests
{
[TestMethod]
public async Task Execute_Success()
public Task Execute_Success_With_QoS_0()
{
using (var testEnvironment = new TestEnvironment())
{
await testEnvironment.StartServerAsync();
var responseSender = await testEnvironment.ConnectClientAsync();
await responseSender.SubscribeAsync("MQTTnet.RPC/+/ping");
return Execute_Success(MqttQualityOfServiceLevel.AtMostOnce, MqttProtocolVersion.V311);
}

responseSender.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(async e =>
{
await responseSender.PublishAsync(e.ApplicationMessage.Topic + "/response", "pong");
});
[TestMethod]
public Task Execute_Success_With_QoS_1()
{
return Execute_Success(MqttQualityOfServiceLevel.AtLeastOnce, MqttProtocolVersion.V311);
}

var requestSender = await testEnvironment.ConnectClientAsync();
[TestMethod]
public Task Execute_Success_With_QoS_2()
{
return Execute_Success(MqttQualityOfServiceLevel.ExactlyOnce, MqttProtocolVersion.V311);
}

var rpcClient = new MqttRpcClient(requestSender);
var response = await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(5), "ping", "", MqttQualityOfServiceLevel.AtMostOnce);
[TestMethod]
public Task Execute_Success_With_QoS_0_MQTT_V5()
{
return Execute_Success(MqttQualityOfServiceLevel.AtMostOnce, MqttProtocolVersion.V500);
}

Assert.AreEqual("pong", Encoding.UTF8.GetString(response));
}
[TestMethod]
public Task Execute_Success_With_QoS_1_MQTT_V5()
{
return Execute_Success(MqttQualityOfServiceLevel.AtLeastOnce, MqttProtocolVersion.V500);
}

[TestMethod]
public Task Execute_Success_With_QoS_2_MQTT_V5()
{
return Execute_Success(MqttQualityOfServiceLevel.ExactlyOnce, MqttProtocolVersion.V500);
}

[TestMethod]
@@ -51,5 +66,27 @@ namespace MQTTnet.Tests
await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(2), "ping", "", MqttQualityOfServiceLevel.AtMostOnce);
}
}

private async Task Execute_Success(MqttQualityOfServiceLevel qosLevel, MqttProtocolVersion protocolVersion)
{
using (var testEnvironment = new TestEnvironment())
{
await testEnvironment.StartServerAsync();
var responseSender = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithProtocolVersion(protocolVersion));
await responseSender.SubscribeAsync("MQTTnet.RPC/+/ping");

responseSender.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(async e =>
{
await responseSender.PublishAsync(e.ApplicationMessage.Topic + "/response", "pong");
});

var requestSender = await testEnvironment.ConnectClientAsync();

var rpcClient = new MqttRpcClient(requestSender);
var response = await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(5), "ping", "", qosLevel);

Assert.AreEqual("pong", Encoding.UTF8.GetString(response));
}
}
}
}

Carregando…
Cancelar
Guardar