Compare commits

...
18 Commits
Author SHA1 Message Date
Christian Kratky 2ed8e55394 Fix upload script. 2019-06-23 21:46:06 +02:00
Christian Kratky c5b6ca204d Merge branch 'develop' 2019-06-23 21:37:35 +02:00
Christian Kratky 7a767c7d2f Improve logging and exception handling when stopping the server. 2019-06-23 15:58:21 +02:00
Christian Kratky dd96cf98a8 Make storage update for managed client async. 2019-06-23 15:57:48 +02:00
Christian Kratky 6ee3d1640f Improve logging. 2019-06-23 15:57:12 +02:00
Christian Kratky 6f8272210c Fix MQTTnet.Server app settings to allow external connections. 2019-06-23 15:39:50 +02:00
Christian Kratky ce05cc9936 Fix MQTTnet.Server connection validation. 2019-06-23 15:39:07 +02:00
Christian Kratky 985c3084a8 Performance refactoring. 2019-06-23 12:37:55 +02:00
Christian Kratky 7b3be3a64f Update docs. 2019-06-23 12:37:41 +02:00
Christian Kratky c50fb740fc Add UnitTests. 2019-06-23 12:37:33 +02:00
Christian Kratky 5895a73f85 Merge remote-tracking branch 'origin/develop' into develop 2019-06-23 11:32:11 +02:00
Christian Kratky 961a497798 Performance refactoring. 2019-06-23 11:32:09 +02:00
Christian 6a90864c44 Merge pull request #666 from vbBerni/develop
fix Managed Client removes failed messages from message queue but not from storage manager
2019-06-23 11:30:31 +02:00
vbBerni a9017b8795 handle storage manager null 2019-06-22 22:31:48 +02:00
vbBerni f76e130283 fix for failed publishing messages get removed from the message queue but not from the storage manager 2019-06-19 16:33:54 +02:00
Christian Kratky 5a48b146b4 Merge branch 'master' into develop 2019-06-14 20:53:24 +02:00
Christian Kratky 1d1def3275 Remove nuget binary from repo. 2019-06-14 20:52:56 +02:00
Christian Kratky bd75a2440e Merge branch 'master' into develop 2019-06-14 20:43:33 +02:00
20 changed files with 233 additions and 128 deletions
+1
View File
@@ -15,6 +15,7 @@
* [Core] Added extension method to allow usage of _WebSocket4Net_ in clients to fix issues with AWS and Xamarin.
* [Core] Fixed usage of wrong data type for passwords (string -> byte[]).
* [Core] Fixed an _ObjectDisposedException_ when sending data using a WebSocket channel.
* [Core] Performance optimizations.
* [Client] Added support for extended authentication exchange.
* [Client] Exposed MQTTv5 CONNACK values to client.
* [Client] Added _MqttClientSubscribeOptionsBuilder_.
+6 -1
View File
@@ -90,6 +90,9 @@ If(Test-path $destination) {Remove-item $destination}
####################################################################
# 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
Copy-Item MQTTnet.AspNetCore.nuspec -Destination MQTTnet.AspNetCore.nuspec.old -Force
@@ -112,4 +115,6 @@ New-Item -ItemType Directory -Force -Path .\NuGet
Move-Item MQTTnet.AspNetCore.nuspec.old -Destination MQTTnet.AspNetCore.nuspec -Force
Move-Item MQTTnet.Extensions.Rpc.nuspec.old -Destination MQTTnet.Extensions.Rpc.nuspec -Force
Move-Item MQTTnet.Extensions.ManagedClient.nuspec.old -Destination MQTTnet.Extensions.ManagedClient.nuspec -Force
Move-Item MQTTnet.Extensions.WebSocket4Net.nuspec.old -Destination MQTTnet.Extensions.WebSocket4Net.nuspec -Force
Move-Item MQTTnet.Extensions.WebSocket4Net.nuspec.old -Destination MQTTnet.Extensions.WebSocket4Net.nuspec -Force
Remove-Item "nuget.exe" -Force -Recurse -ErrorAction SilentlyContinue
BIN
View File
Binary file not shown.
+5 -1
View File
@@ -1,9 +1,13 @@
param([string]$apiKey)
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile "nuget.exe"
$files = Get-ChildItem -Path ".\NuGet" -Filter "*.nupkg"
foreach ($file in $files)
{
Write-Host "Uploading: " $file
.\nuget.exe push $file.Fullname $apiKey -NoSymbols -Source https://api.nuget.org/v3/index.json
}
}
Remove-Item "nuget.exe" -Force -Recurse -ErrorAction SilentlyContinue
@@ -9,6 +9,7 @@ namespace MQTTnet.AspNetCore
public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
{
private ReadOnlyMemory<byte> _buffer;
private int _offset;
public void SetBuffer(ReadOnlyMemory<byte> buffer)
@@ -17,11 +18,11 @@ namespace MQTTnet.AspNetCore
_offset = 0;
}
public ulong Length => (ulong)_buffer.Length;
public int Length => _buffer.Length;
public bool EndOfStream => _buffer.Length.Equals(_offset);
public ulong Offset => (ulong)_offset;
public int Offset => _offset;
public byte ReadByte()
{
@@ -116,9 +117,9 @@ namespace MQTTnet.AspNetCore
throw new MqttProtocolViolationException("Boolean values can be 0 or 1 only.");
}
public void Seek(ulong position)
public void Seek(int position)
{
_offset = (int)position;
_offset = position;
}
}
}
@@ -31,7 +31,7 @@ namespace MQTTnet.Extensions.ManagedClient
private ManagedMqttClientStorageManager _storageManager;
private bool _disposed = false;
private bool _disposed;
private bool _subscriptionsNotPushed;
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetChildLogger logger)
@@ -102,9 +102,8 @@ namespace MQTTnet.Extensions.ManagedClient
_connectionCancellationToken = new CancellationTokenSource();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
_maintainConnectionTask = Task.Run(() => MaintainConnectionAsync(_connectionCancellationToken.Token), _connectionCancellationToken.Token);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
_maintainConnectionTask.Forget(_logger);
_logger.Info("Started");
}
@@ -333,20 +332,20 @@ namespace MQTTnet.Extensions.ManagedClient
}
}
private void PublishQueuedMessages(CancellationToken cancellationToken)
private async Task PublishQueuedMessagesAsync(CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested && _mqttClient.IsConnected)
{
//Peek at the message without dequeueing in order to prevent the
//possibility of the queue growing beyond the configured cap.
//Previously, messages could be re-enqueued if there was an
//exception, and this re-enqueueing did not honor the cap.
//Furthermore, because re-enqueueing would shuffle the order
//of the messages, the DropOldestQueuedMessage strategy would
//be unable to know which message is actually the oldest and would
//instead drop the first item in the queue.
// Peek at the message without dequeueing in order to prevent the
// possibility of the queue growing beyond the configured cap.
// Previously, messages could be re-enqueued if there was an
// exception, and this re-enqueueing did not honor the cap.
// Furthermore, because re-enqueueing would shuffle the order
// of the messages, the DropOldestQueuedMessage strategy would
// be unable to know which message is actually the oldest and would
// instead drop the first item in the queue.
var message = _messageQueue.PeekAndWait();
if (message == null)
{
@@ -355,7 +354,7 @@ namespace MQTTnet.Extensions.ManagedClient
cancellationToken.ThrowIfCancellationRequested();
TryPublishQueuedMessage(message);
await TryPublishQueuedMessageAsync(message).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
@@ -371,23 +370,28 @@ namespace MQTTnet.Extensions.ManagedClient
}
}
private void TryPublishQueuedMessage(ManagedMqttApplicationMessage message)
private async Task TryPublishQueuedMessageAsync(ManagedMqttApplicationMessage message)
{
Exception transmitException = null;
try
{
_mqttClient.PublishAsync(message.ApplicationMessage).GetAwaiter().GetResult();
await _mqttClient.PublishAsync(message.ApplicationMessage).ConfigureAwait(false);
lock (_messageQueue) //lock to avoid conflict with this.PublishAsync
{
//While publishing this message, this.PublishAsync could have booted this
//message off the queue to make room for another (when using a cap
//with the DropOldestQueuedMessage strategy). If the first item
//in the queue is equal to this message, then it's safe to remove
//it from the queue. If not, that means this.PublishAsync has already
//removed it, in which case we don't want to do anything.
// While publishing this message, this.PublishAsync could have booted this
// message off the queue to make room for another (when using a cap
// with the DropOldestQueuedMessage strategy). If the first item
// in the queue is equal to this message, then it's safe to remove
// it from the queue. If not, that means this.PublishAsync has already
// removed it, in which case we don't want to do anything.
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
}
_storageManager?.RemoveAsync(message).GetAwaiter().GetResult();
if (_storageManager != null)
{
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
}
}
catch (MqttCommunicationException exception)
{
@@ -408,6 +412,11 @@ namespace MQTTnet.Extensions.ManagedClient
{
_messageQueue.RemoveFirst(i => i.Id.Equals(message.Id));
}
if (_storageManager != null)
{
await _storageManager.RemoveAsync(message).ConfigureAwait(false);
}
}
}
catch (Exception exception)
@@ -417,7 +426,12 @@ namespace MQTTnet.Extensions.ManagedClient
}
finally
{
ApplicationMessageProcessedHandler?.HandleApplicationMessageProcessedAsync(new ApplicationMessageProcessedEventArgs(message, transmitException)).GetAwaiter().GetResult();
var eventHandler = ApplicationMessageProcessedHandler;
if (eventHandler != null)
{
var eventArguments = new ApplicationMessageProcessedEventArgs(message, transmitException);
await eventHandler.HandleApplicationMessageProcessedAsync(eventArguments).ConfigureAwait(false);
}
}
}
@@ -502,7 +516,7 @@ namespace MQTTnet.Extensions.ManagedClient
var cts = new CancellationTokenSource();
_publishingCancellationToken = cts;
Task.Factory.StartNew(() => PublishQueuedMessages(cts.Token), cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Task.Run(() => PublishQueuedMessagesAsync(cts.Token), cts.Token).Forget(_logger);
}
private void StopPublishing()
@@ -29,10 +29,10 @@ namespace MQTTnet.Server.Mqtt
{ "client_id", context.ClientId },
{ "username", context.Username },
{ "password", context.Password },
{ "raw_password", new Bytes(context.RawPassword) },
{ "raw_password", new Bytes(context.RawPassword ?? new byte[0]) },
{ "clean_session", context.CleanSession},
{ "authentication_method", context.AuthenticationMethod},
{ "authentication_data", new Bytes(context.AuthenticationData)},
{ "authentication_data", new Bytes(context.AuthenticationData ?? new byte[0]) },
{ "result", PythonConvert.Pythonfy(context.ReasonCode) }
};
@@ -44,6 +44,8 @@ namespace MQTTnet.Server.Mqtt
catch (Exception exception)
{
_logger.LogError(exception, "Error while validating client connection.");
context.ReasonCode = MqttConnectReasonCode.UnspecifiedError;
}
return Task.CompletedTask;
@@ -66,7 +66,10 @@ namespace MQTTnet.Server.Mqtt
var adapters = new List<IMqttServerAdapter>
{
new MqttTcpServerAdapter(mqttFactory.Logger.CreateChildLogger()),
new MqttTcpServerAdapter(mqttFactory.Logger.CreateChildLogger())
{
TreatSocketOpeningErrorAsWarning = true // Opening other ports than for HTTP is not allows in Azure App Services.
},
_webSocketServerAdapter
};
+2 -2
View File
@@ -2,10 +2,10 @@
"Kestrel": {
"EndPoints": {
"Http": {
"Url": "http://localhost:80"
"Url": "http://*:80"
},
"Https": {
"Url": "http://localhost:443"
"Url": "http://*:443"
}
}
},
@@ -4,9 +4,9 @@ namespace MQTTnet.Formatter
{
public interface IMqttPacketBodyReader
{
ulong Length { get; }
int Length { get; }
ulong Offset { get; }
int Offset { get; }
bool EndOfStream { get; }
@@ -26,6 +26,6 @@ namespace MQTTnet.Formatter
bool ReadBoolean();
void Seek(ulong position);
void Seek(int position);
}
}
@@ -9,52 +9,42 @@ namespace MQTTnet.Formatter
public class MqttPacketBodyReader : IMqttPacketBodyReader
{
private readonly byte[] _buffer;
private readonly ulong _initialOffset;
private readonly ulong _length;
private readonly int _initialOffset;
private readonly int _length;
private int _offset;
public MqttPacketBodyReader(byte[] buffer, int offset, int length)
: this(buffer, (ulong)offset, (ulong)length)
{
}
public MqttPacketBodyReader(byte[] buffer, ulong offset, ulong length)
{
_buffer = buffer;
_initialOffset = offset;
Offset = offset;
_offset = offset;
_length = length;
}
public ulong Offset { get; private set; }
public int Offset => _offset;
public ulong Length => _length - Offset;
public int Length => _length - _offset;
public bool EndOfStream => Offset == _length;
public bool EndOfStream => _offset == _length;
public void Seek(ulong position)
public void Seek(int position)
{
Offset = _initialOffset + position;
}
public ArraySegment<byte> Read(uint length)
{
ValidateReceiveBuffer(length);
var buffer = new ArraySegment<byte>(_buffer, (int)Offset, (int)length);
Offset += length;
return buffer;
_offset = _initialOffset + position;
}
public byte ReadByte()
{
ValidateReceiveBuffer(1);
return _buffer[Offset++];
}
return _buffer[_offset++];
}
public bool ReadBoolean()
{
ValidateReceiveBuffer(1);
var buffer = _buffer[Offset++];
var buffer = _buffer[_offset++];
if (buffer == 0)
{
@@ -71,15 +61,19 @@ namespace MQTTnet.Formatter
public byte[] ReadRemainingData()
{
return new ArraySegment<byte>(_buffer, (int)Offset, (int)(_length - Offset)).ToArray();
var bufferLength = _length - _offset;
var buffer = new byte[bufferLength];
Array.Copy(_buffer, _offset, buffer, 0, bufferLength);
return buffer;
}
public ushort ReadTwoByteInteger()
{
ValidateReceiveBuffer(2);
var msb = _buffer[Offset++];
var lsb = _buffer[Offset++];
var msb = _buffer[_offset++];
var lsb = _buffer[_offset++];
return (ushort)(msb << 8 | lsb);
}
@@ -88,31 +82,14 @@ namespace MQTTnet.Formatter
{
ValidateReceiveBuffer(4);
var byte0 = _buffer[Offset++];
var byte1 = _buffer[Offset++];
var byte2 = _buffer[Offset++];
var byte3 = _buffer[Offset++];
var byte0 = _buffer[_offset++];
var byte1 = _buffer[_offset++];
var byte2 = _buffer[_offset++];
var byte3 = _buffer[_offset++];
return (uint)(byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3);
}
public byte[] ReadWithLengthPrefix()
{
return ReadSegmentWithLengthPrefix().ToArray();
}
private ArraySegment<byte> ReadSegmentWithLengthPrefix()
{
var length = ReadTwoByteInteger();
ValidateReceiveBuffer(length);
var result = new ArraySegment<byte>(_buffer, (int)Offset, length);
Offset += length;
return result;
}
public uint ReadVariableLengthInteger()
{
var multiplier = 1;
@@ -134,13 +111,30 @@ namespace MQTTnet.Formatter
return value;
}
public byte[] ReadWithLengthPrefix()
{
return ReadSegmentWithLengthPrefix().ToArray();
}
private ArraySegment<byte> ReadSegmentWithLengthPrefix()
{
var length = ReadTwoByteInteger();
ValidateReceiveBuffer(length);
var result = new ArraySegment<byte>(_buffer, _offset, length);
_offset += length;
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ValidateReceiveBuffer(uint length)
private void ValidateReceiveBuffer(int length)
{
if (_length < Offset + length)
if (_length < _offset + length)
{
throw new ArgumentOutOfRangeException(nameof(_buffer), $"Expected at least {Offset + length} bytes but there are only {_length} bytes");
throw new ArgumentOutOfRangeException(nameof(_buffer), $"Expected at least {_offset + length} bytes but there are only {_length} bytes");
}
}
@@ -9,8 +9,8 @@ namespace MQTTnet.Formatter.V5
public class MqttV500PropertiesReader
{
private readonly IMqttPacketBodyReader _body;
private readonly uint _length;
private readonly ulong _targetOffset;
private readonly int _length;
private readonly int _targetOffset;
public MqttV500PropertiesReader(IMqttPacketBodyReader body)
{
@@ -18,7 +18,7 @@ namespace MQTTnet.Formatter.V5
if (!body.EndOfStream)
{
_length = body.ReadVariableLengthInteger();
_length = (int)body.ReadVariableLengthInteger();
}
_targetOffset = body.Offset + _length;
@@ -28,6 +28,8 @@ namespace MQTTnet.Implementations
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
public bool TreatSocketOpeningErrorAsWarning { get; set; }
public Task StartAsync(IMqttServerOptions options)
{
if (_cancellationTokenSource != null) throw new InvalidOperationException("Server is already started.");
@@ -36,7 +38,7 @@ namespace MQTTnet.Implementations
if (options.DefaultEndpointOptions.IsEnabled)
{
RegisterListeners(options.DefaultEndpointOptions, null);
RegisterListeners(options.DefaultEndpointOptions, null, _cancellationTokenSource.Token);
}
if (options.TlsEndpointOptions.IsEnabled)
@@ -52,7 +54,7 @@ namespace MQTTnet.Implementations
throw new InvalidOperationException("The certificate for TLS encryption must contain the private key.");
}
RegisterListeners(options.TlsEndpointOptions, tlsCertificate);
RegisterListeners(options.TlsEndpointOptions, tlsCertificate, _cancellationTokenSource.Token);
}
return Task.FromResult(0);
@@ -78,7 +80,7 @@ namespace MQTTnet.Implementations
_listeners.Clear();
}
private void RegisterListeners(MqttServerTcpEndpointBaseOptions options, X509Certificate2 tlsCertificate)
private void RegisterListeners(MqttServerTcpEndpointBaseOptions options, X509Certificate2 tlsCertificate, CancellationToken cancellationToken)
{
if (!options.BoundInterNetworkAddress.Equals(IPAddress.None))
{
@@ -86,14 +88,15 @@ namespace MQTTnet.Implementations
AddressFamily.InterNetwork,
options,
tlsCertificate,
_cancellationTokenSource.Token,
_logger)
{
ClientHandler = OnClientAcceptedAsync
};
listenerV4.Start();
_listeners.Add(listenerV4);
if (listenerV4.Start(TreatSocketOpeningErrorAsWarning, cancellationToken))
{
_listeners.Add(listenerV4);
}
}
if (!options.BoundInterNetworkV6Address.Equals(IPAddress.None))
@@ -102,14 +105,15 @@ namespace MQTTnet.Implementations
AddressFamily.InterNetworkV6,
options,
tlsCertificate,
_cancellationTokenSource.Token,
_logger)
{
ClientHandler = OnClientAcceptedAsync
};
listenerV6.Start();
_listeners.Add(listenerV6);
if (listenerV6.Start(TreatSocketOpeningErrorAsWarning, cancellationToken))
{
_listeners.Add(listenerV6);
}
}
}
@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Server;
namespace MQTTnet.Implementations
@@ -17,24 +18,23 @@ namespace MQTTnet.Implementations
public class MqttTcpServerListener : IDisposable
{
private readonly IMqttNetChildLogger _logger;
private readonly CancellationToken _cancellationToken;
private readonly AddressFamily _addressFamily;
private readonly MqttServerTcpEndpointBaseOptions _options;
private readonly MqttServerTlsTcpEndpointOptions _tlsOptions;
private readonly X509Certificate2 _tlsCertificate;
private Socket _socket;
private IPEndPoint _localEndPoint;
public MqttTcpServerListener(
AddressFamily addressFamily,
MqttServerTcpEndpointBaseOptions options,
X509Certificate2 tlsCertificate,
CancellationToken cancellationToken,
IMqttNetChildLogger logger)
{
_addressFamily = addressFamily;
_options = options;
_tlsCertificate = tlsCertificate;
_cancellationToken = cancellationToken;
_logger = logger.CreateChildLogger(nameof(MqttTcpServerListener));
if (_options is MqttServerTlsTcpEndpointOptions tlsOptions)
@@ -45,21 +45,38 @@ namespace MQTTnet.Implementations
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
public void Start()
public bool Start(bool treatErrorsAsWarning, CancellationToken cancellationToken)
{
var boundIp = _options.BoundInterNetworkAddress;
if (_addressFamily == AddressFamily.InterNetworkV6)
try
{
boundIp = _options.BoundInterNetworkV6Address;
var boundIp = _options.BoundInterNetworkAddress;
if (_addressFamily == AddressFamily.InterNetworkV6)
{
boundIp = _options.BoundInterNetworkV6Address;
}
_localEndPoint = new IPEndPoint(boundIp, _options.Port);
_logger.Info($"Starting TCP listener for {_localEndPoint} TLS={_tlsCertificate != null}.");
_socket = new Socket(_addressFamily, SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(_localEndPoint);
_socket.Listen(_options.ConnectionBacklog);
Task.Run(() => AcceptClientConnectionsAsync(cancellationToken), cancellationToken).Forget(_logger);
return true;
}
catch (Exception exception)
{
if (!treatErrorsAsWarning)
{
throw;
}
_socket = new Socket(_addressFamily, SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(new IPEndPoint(boundIp, _options.Port));
_logger.Info($"Starting TCP listener for {_socket.LocalEndPoint} TLS={_tlsCertificate != null}.");
_socket.Listen(_options.ConnectionBacklog);
Task.Run(() => AcceptClientConnectionsAsync(_cancellationToken), _cancellationToken);
_logger.Warning(exception,"Error while creating listener socket for local end point '{0}'.", _localEndPoint);
return false;
}
}
public void Dispose()
@@ -82,13 +99,29 @@ namespace MQTTnet.Implementations
#else
var clientSocket = await _socket.AcceptAsync().ConfigureAwait(false);
#endif
#pragma warning disable 4014
Task.Run(() => TryHandleClientConnectionAsync(clientSocket), cancellationToken);
#pragma warning restore 4014
if (clientSocket == null)
{
continue;
}
Task.Run(() => TryHandleClientConnectionAsync(clientSocket), cancellationToken).Forget(_logger);
}
catch (OperationCanceledException)
{
}
catch (Exception exception)
{
_logger.Error(exception, $"Error while accepting connection at TCP listener {_socket.LocalEndPoint} TLS={_tlsCertificate != null}.");
if (exception is SocketException socketException)
{
if (socketException.SocketErrorCode == SocketError.ConnectionAborted ||
socketException.SocketErrorCode == SocketError.OperationAborted)
{
continue;
}
}
_logger.Error(exception, $"Error while accepting connection at TCP listener {_localEndPoint} TLS={_tlsCertificate != null}.");
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
}
}
@@ -105,7 +138,7 @@ namespace MQTTnet.Implementations
_logger.Verbose("Client '{0}' accepted by TCP listener '{1}, {2}'.",
remoteEndPoint,
_socket.LocalEndPoint,
_localEndPoint,
_addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6");
clientSocket.NoDelay = _options.NoDelay;
@@ -163,7 +196,7 @@ namespace MQTTnet.Implementations
_logger.Verbose("Client '{0}' disconnected at TCP listener '{1}, {2}'.",
remoteEndPoint,
_socket.LocalEndPoint,
_localEndPoint,
_addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6");
}
catch (Exception disposeException)
@@ -7,6 +7,7 @@ using MQTTnet.Client;
using MQTTnet.Diagnostics;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.PacketDispatcher;
using MQTTnet.Packets;
using MQTTnet.Protocol;
@@ -134,9 +135,7 @@ namespace MQTTnet.Server
Session.WillMessage = _connectPacket.WillMessage;
#pragma warning disable 4014
Task.Run(() => SendPendingPacketsAsync(_cancellationToken.Token), _cancellationToken.Token);
#pragma warning restore 4014
Task.Run(() => SendPendingPacketsAsync(_cancellationToken.Token), _cancellationToken.Token).Forget(_logger);
// TODO: Change to single thread in SessionManager. Or use SessionManager and stats from KeepAliveMonitor.
_keepAliveMonitor.Start(_connectPacket.KeepAlivePeriod, _cancellationToken.Token);
@@ -3,6 +3,7 @@ using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Diagnostics;
using MQTTnet.Internal;
namespace MQTTnet.Server
{
@@ -32,7 +33,7 @@ namespace MQTTnet.Server
return;
}
Task.Run(() => RunAsync(keepAlivePeriod, cancellationToken), cancellationToken).ConfigureAwait(false);
Task.Run(() => RunAsync(keepAlivePeriod, cancellationToken), cancellationToken).Forget(_logger);
}
public void Pause()
@@ -47,7 +47,7 @@ namespace MQTTnet.Server
public void Start()
{
Task.Run(() => TryProcessQueuedApplicationMessagesAsync(_cancellationToken), _cancellationToken);
Task.Run(() => TryProcessQueuedApplicationMessagesAsync(_cancellationToken), _cancellationToken).Forget(_logger);
}
public async Task StopAsync()
@@ -57,7 +57,7 @@ namespace MQTTnet.Benchmarks
var receivedPacket = new ReceivedMqttPacket(
header.Flags,
new MqttPacketBodyReader(_serializedPacket.Array, (ulong)(_serializedPacket.Count - header.RemainingLength), (ulong)_serializedPacket.Array.Length), 0);
new MqttPacketBodyReader(_serializedPacket.Array, _serializedPacket.Count - header.RemainingLength, _serializedPacket.Array.Length), 0);
_serializer.Decode(receivedPacket);
}
@@ -0,0 +1,23 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Formatter;
namespace MQTTnet.Tests
{
[TestClass]
public class Protocol_Tests
{
[TestMethod]
public void Encode_Four_Byte_Integer()
{
for (uint i = 0; i < 268435455; i++)
{
var buffer = MqttPacketWriter.EncodeVariableLengthInteger(i);
var reader = new MqttPacketBodyReader(buffer.Array, buffer.Offset, buffer.Count);
var checkValue = reader.ReadVariableLengthInteger();
Assert.AreEqual(i, checkValue);
}
}
}
}
+21
View File
@@ -22,6 +22,27 @@ namespace MQTTnet.Tests
[TestClass]
public class Server_Tests
{
[TestMethod]
public async Task Use_Empty_Client_ID()
{
using (var testEnvironment = new TestEnvironment())
{
await testEnvironment.StartServerAsync();
var client = testEnvironment.CreateClient();
var clientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("localhost", testEnvironment.ServerPort)
.WithClientId(string.Empty)
.Build();
var connectResult = await client.ConnectAsync(clientOptions);
Assert.IsFalse(connectResult.IsSessionPresent);
Assert.IsTrue(client.IsConnected);
}
}
[TestMethod]
public async Task Publish_At_Most_Once_0x00()
{