mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-21 12:16:02 +08:00
Fix broken unit tests.
This commit is contained in:
@@ -1,25 +1,24 @@
|
|||||||
#if !WINDOWS_UWP
|
#if !WINDOWS_UWP
|
||||||
using System;
|
|
||||||
using System.Net.Security;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.ExceptionServices;
|
|
||||||
using System.Threading;
|
|
||||||
using MQTTnet.Channel;
|
using MQTTnet.Channel;
|
||||||
using MQTTnet.Client.Options;
|
using MQTTnet.Client.Options;
|
||||||
using MQTTnet.Internal;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Security;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.ExceptionServices;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.Implementations
|
namespace MQTTnet.Implementations
|
||||||
{
|
{
|
||||||
public class MqttTcpChannel : Disposable, IMqttChannel
|
public sealed class MqttTcpChannel : IDisposable, IMqttChannel
|
||||||
{
|
{
|
||||||
private readonly IMqttClientOptions _clientOptions;
|
readonly IMqttClientOptions _clientOptions;
|
||||||
private readonly MqttClientTcpOptions _options;
|
readonly MqttClientTcpOptions _options;
|
||||||
|
|
||||||
private Stream _stream;
|
Stream _stream;
|
||||||
|
|
||||||
public MqttTcpChannel(IMqttClientOptions clientOptions)
|
public MqttTcpChannel(IMqttClientOptions clientOptions)
|
||||||
{
|
{
|
||||||
@@ -69,7 +68,7 @@ namespace MQTTnet.Implementations
|
|||||||
// of the actual value.
|
// of the actual value.
|
||||||
socket.DualMode = _options.DualMode.Value;
|
socket.DualMode = _options.DualMode.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround for: workaround for https://github.com/dotnet/corefx/issues/24430
|
// Workaround for: workaround for https://github.com/dotnet/corefx/issues/24430
|
||||||
using (cancellationToken.Register(() => socket.Dispose()))
|
using (cancellationToken.Register(() => socket.Dispose()))
|
||||||
{
|
{
|
||||||
@@ -83,7 +82,7 @@ namespace MQTTnet.Implementations
|
|||||||
var sslStream = new SslStream(networkStream, false, InternalUserCertificateValidationCallback);
|
var sslStream = new SslStream(networkStream, false, InternalUserCertificateValidationCallback);
|
||||||
_stream = sslStream;
|
_stream = sslStream;
|
||||||
|
|
||||||
await sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(), _options.TlsOptions.SslProtocol, !_options.TlsOptions.IgnoreCertificateRevocationErrors).ConfigureAwait(false);
|
await sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(), _options.TlsOptions.SslProtocol, !_options.TlsOptions.IgnoreCertificateRevocationErrors).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -95,12 +94,14 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public Task DisconnectAsync(CancellationToken cancellationToken)
|
public Task DisconnectAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Cleanup();
|
Dispose();
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
if (buffer is null) throw new ArgumentNullException(nameof(buffer));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Workaround for: https://github.com/dotnet/corefx/issues/24430
|
// Workaround for: https://github.com/dotnet/corefx/issues/24430
|
||||||
@@ -131,6 +132,8 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
public async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
if (buffer is null) throw new ArgumentNullException(nameof(buffer));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Workaround for: https://github.com/dotnet/corefx/issues/24430
|
// Workaround for: https://github.com/dotnet/corefx/issues/24430
|
||||||
@@ -159,7 +162,7 @@ namespace MQTTnet.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Cleanup()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
// When the stream is disposed it will also close the socket and this will also dispose it.
|
// When the stream is disposed it will also close the socket and this will also dispose it.
|
||||||
// So there is no need to dispose the socket again.
|
// So there is no need to dispose the socket again.
|
||||||
@@ -178,16 +181,7 @@ namespace MQTTnet.Implementations
|
|||||||
_stream = null;
|
_stream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
Cleanup();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
|
||||||
{
|
{
|
||||||
if (_options.TlsOptions.CertificateValidationCallback != null)
|
if (_options.TlsOptions.CertificateValidationCallback != null)
|
||||||
{
|
{
|
||||||
@@ -218,7 +212,7 @@ namespace MQTTnet.Implementations
|
|||||||
return _options.TlsOptions.AllowUntrustedCertificates;
|
return _options.TlsOptions.AllowUntrustedCertificates;
|
||||||
}
|
}
|
||||||
|
|
||||||
private X509CertificateCollection LoadCertificates()
|
X509CertificateCollection LoadCertificates()
|
||||||
{
|
{
|
||||||
var certificates = new X509CertificateCollection();
|
var certificates = new X509CertificateCollection();
|
||||||
if (_options.TlsOptions.Certificates == null)
|
if (_options.TlsOptions.Certificates == null)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public static class PlatformAbstractionLayer
|
public static class PlatformAbstractionLayer
|
||||||
{
|
{
|
||||||
|
// TODO: Consider creating primitives like "MqttNetSocket" which will wrap all required methods and do the platform stuff.
|
||||||
public static async Task<Socket> AcceptAsync(Socket socket)
|
public static async Task<Socket> AcceptAsync(Socket socket)
|
||||||
{
|
{
|
||||||
#if NET452 || NET461
|
#if NET452 || NET461
|
||||||
@@ -90,7 +91,7 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public static Task CompletedTask
|
public static Task CompletedTask
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
#if NET452
|
#if NET452
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
|
|||||||
@@ -2,32 +2,20 @@
|
|||||||
|
|
||||||
namespace MQTTnet.Internal
|
namespace MQTTnet.Internal
|
||||||
{
|
{
|
||||||
public class Disposable : IDisposable
|
public abstract class Disposable : IDisposable
|
||||||
{
|
{
|
||||||
protected bool IsDisposed => _isDisposed;
|
protected bool IsDisposed { get; private set; } = false;
|
||||||
|
|
||||||
protected void ThrowIfDisposed()
|
protected void ThrowIfDisposed()
|
||||||
{
|
{
|
||||||
if (_isDisposed)
|
if (IsDisposed)
|
||||||
{
|
{
|
||||||
throw new ObjectDisposedException(GetType().Name);
|
throw new ObjectDisposedException(GetType().Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region IDisposable Support
|
|
||||||
|
|
||||||
private bool _isDisposed = false; // To detect redundant calls
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
// TODO: dispose managed state (managed objects).
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
|
|
||||||
// TODO: set large fields to null.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
|
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
|
||||||
@@ -40,18 +28,17 @@ namespace MQTTnet.Internal
|
|||||||
// This code added to correctly implement the disposable pattern.
|
// This code added to correctly implement the disposable pattern.
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (_isDisposed)
|
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||||
|
|
||||||
|
if (IsDisposed)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isDisposed = true;
|
IsDisposed = true;
|
||||||
|
|
||||||
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
// TODO: uncomment the following line if the finalizer is overridden above.
|
GC.SuppressFinalize(this);
|
||||||
// GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
using System;
|
using MQTTnet.Adapter;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Adapter;
|
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Internal;
|
using MQTTnet.Internal;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using MQTTnet.Server.Status;
|
using MQTTnet.Server.Status;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
@@ -236,12 +237,23 @@ namespace MQTTnet.Server
|
|||||||
string clientId = null;
|
string clientId = null;
|
||||||
var clientWasConnected = true;
|
var clientWasConnected = true;
|
||||||
|
|
||||||
|
MqttConnectPacket connectPacket = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var firstPacket = await channelAdapter.ReceivePacketAsync(_options.DefaultCommunicationTimeout, cancellationToken).ConfigureAwait(false);
|
try
|
||||||
if (!(firstPacket is MqttConnectPacket connectPacket))
|
|
||||||
{
|
{
|
||||||
_logger.Warning(null, "The first packet from client '{0}' was no 'CONNECT' packet [MQTT-3.1.0-1].", channelAdapter.Endpoint);
|
var firstPacket = await channelAdapter.ReceivePacketAsync(_options.DefaultCommunicationTimeout, cancellationToken).ConfigureAwait(false);
|
||||||
|
connectPacket = firstPacket as MqttConnectPacket;
|
||||||
|
if (connectPacket == null)
|
||||||
|
{
|
||||||
|
_logger.Warning(null, "The first packet from client '{0}' was no 'CONNECT' packet [MQTT-3.1.0-1].", channelAdapter.Endpoint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MqttCommunicationTimedOutException)
|
||||||
|
{
|
||||||
|
_logger.Warning(null, "Client '{0}' connected but did not sent a CONNECT packet.", channelAdapter.Endpoint);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
using System;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Client;
|
using MQTTnet.Client;
|
||||||
using MQTTnet.Client.Connecting;
|
using MQTTnet.Client.Connecting;
|
||||||
@@ -17,6 +10,13 @@ using MQTTnet.Implementations;
|
|||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
using MQTTnet.Tests.Mockups;
|
using MQTTnet.Tests.Mockups;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.Tests
|
namespace MQTTnet.Tests
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ namespace MQTTnet.Tests
|
|||||||
MqttQualityOfServiceLevel.AtMostOnce,
|
MqttQualityOfServiceLevel.AtMostOnce,
|
||||||
"A/B/C",
|
"A/B/C",
|
||||||
MqttQualityOfServiceLevel.AtMostOnce,
|
MqttQualityOfServiceLevel.AtMostOnce,
|
||||||
1,
|
1,
|
||||||
TestContext);
|
TestContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1050,6 +1050,7 @@ namespace MQTTnet.Tests
|
|||||||
Assert.AreEqual("c", flow);
|
Assert.AreEqual("c", flow);
|
||||||
|
|
||||||
// dc
|
// dc
|
||||||
|
// Connect client with same client ID. Should disconnect existing client.
|
||||||
var c2 = await testEnvironment.ConnectClientAsync(clientOptions);
|
var c2 = await testEnvironment.ConnectClientAsync(clientOptions);
|
||||||
|
|
||||||
c2.UseApplicationMessageReceivedHandler(_ =>
|
c2.UseApplicationMessageReceivedHandler(_ =>
|
||||||
@@ -1058,8 +1059,8 @@ namespace MQTTnet.Tests
|
|||||||
{
|
{
|
||||||
events.Add("r");
|
events.Add("r");
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
c2.SubscribeAsync("topic").Wait();
|
c2.SubscribeAsync("topic").Wait();
|
||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
@@ -1075,12 +1076,11 @@ namespace MQTTnet.Tests
|
|||||||
flow = string.Join(string.Empty, events);
|
flow = string.Join(string.Empty, events);
|
||||||
Assert.AreEqual("cdcr", flow);
|
Assert.AreEqual("cdcr", flow);
|
||||||
|
|
||||||
|
|
||||||
// nothing
|
// nothing
|
||||||
|
|
||||||
Assert.AreEqual(false, c1.IsConnected);
|
Assert.AreEqual(false, c1.IsConnected);
|
||||||
await c1.DisconnectAsync();
|
await c1.DisconnectAsync();
|
||||||
Assert.AreEqual (false, c1.IsConnected);
|
Assert.AreEqual(false, c1.IsConnected);
|
||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
@@ -1141,7 +1141,7 @@ namespace MQTTnet.Tests
|
|||||||
await testEnvironment.ConnectClientAsync();
|
await testEnvironment.ConnectClientAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task Close_Idle_Connection()
|
public async Task Close_Idle_Connection()
|
||||||
{
|
{
|
||||||
@@ -1182,7 +1182,7 @@ namespace MQTTnet.Tests
|
|||||||
// forever. This is security related.
|
// forever. This is security related.
|
||||||
var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
await PlatformAbstractionLayer.ConnectAsync(client, "localhost", testEnvironment.ServerPort);
|
await PlatformAbstractionLayer.ConnectAsync(client, "localhost", testEnvironment.ServerPort);
|
||||||
|
|
||||||
var buffer = Encoding.UTF8.GetBytes("Garbage");
|
var buffer = Encoding.UTF8.GetBytes("Garbage");
|
||||||
client.Send(buffer, buffer.Length, SocketFlags.None);
|
client.Send(buffer, buffer.Length, SocketFlags.None);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user