|
@@ -1,20 +1,17 @@ |
|
|
using System; |
|
|
using System; |
|
|
using System.Collections.Generic; |
|
|
|
|
|
using System.Linq; |
|
|
|
|
|
|
|
|
using System.Collections.Concurrent; |
|
|
using System.Threading; |
|
|
using System.Threading; |
|
|
using System.Threading.Tasks; |
|
|
using System.Threading.Tasks; |
|
|
using MQTTnet.Core.Adapter; |
|
|
using MQTTnet.Core.Adapter; |
|
|
using MQTTnet.Core.Diagnostics; |
|
|
using MQTTnet.Core.Diagnostics; |
|
|
using MQTTnet.Core.Exceptions; |
|
|
using MQTTnet.Core.Exceptions; |
|
|
using MQTTnet.Core.Internal; |
|
|
|
|
|
using MQTTnet.Core.Packets; |
|
|
using MQTTnet.Core.Packets; |
|
|
|
|
|
|
|
|
namespace MQTTnet.Core.Server |
|
|
namespace MQTTnet.Core.Server |
|
|
{ |
|
|
{ |
|
|
public sealed class MqttClientMessageQueue |
|
|
public sealed class MqttClientMessageQueue |
|
|
{ |
|
|
{ |
|
|
private readonly List<MqttClientPublishPacketContext> _pendingPublishPackets = new List<MqttClientPublishPacketContext>(); |
|
|
|
|
|
private readonly AsyncGate _gate = new AsyncGate(); |
|
|
|
|
|
|
|
|
private readonly BlockingCollection<MqttClientPublishPacketContext> _pendingPublishPackets = new BlockingCollection<MqttClientPublishPacketContext>(); |
|
|
|
|
|
|
|
|
private readonly MqttServerOptions _options; |
|
|
private readonly MqttServerOptions _options; |
|
|
private CancellationTokenSource _cancellationTokenSource; |
|
|
private CancellationTokenSource _cancellationTokenSource; |
|
@@ -43,55 +40,38 @@ namespace MQTTnet.Core.Server |
|
|
_adapter = null; |
|
|
_adapter = null; |
|
|
_cancellationTokenSource?.Cancel(); |
|
|
_cancellationTokenSource?.Cancel(); |
|
|
_cancellationTokenSource = null; |
|
|
_cancellationTokenSource = null; |
|
|
|
|
|
_pendingPublishPackets?.Dispose(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void Enqueue(MqttPublishPacket publishPacket) |
|
|
public void Enqueue(MqttPublishPacket publishPacket) |
|
|
{ |
|
|
{ |
|
|
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket)); |
|
|
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket)); |
|
|
|
|
|
|
|
|
lock (_pendingPublishPackets) |
|
|
|
|
|
{ |
|
|
|
|
|
_pendingPublishPackets.Add(new MqttClientPublishPacketContext(publishPacket)); |
|
|
|
|
|
_gate.Set(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
_pendingPublishPackets.Add( new MqttClientPublishPacketContext( publishPacket ) ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private async Task SendPendingPublishPacketsAsync(CancellationToken cancellationToken) |
|
|
private async Task SendPendingPublishPacketsAsync(CancellationToken cancellationToken) |
|
|
{ |
|
|
{ |
|
|
while (!cancellationToken.IsCancellationRequested) |
|
|
|
|
|
|
|
|
foreach (var publishPacket in _pendingPublishPackets.GetConsumingEnumerable(cancellationToken)) |
|
|
{ |
|
|
{ |
|
|
try |
|
|
try |
|
|
{ |
|
|
{ |
|
|
await _gate.WaitOneAsync().ConfigureAwait(false); |
|
|
|
|
|
if (cancellationToken.IsCancellationRequested) |
|
|
|
|
|
|
|
|
if ( cancellationToken.IsCancellationRequested ) |
|
|
{ |
|
|
{ |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (_adapter == null) |
|
|
|
|
|
|
|
|
if ( _adapter == null ) |
|
|
{ |
|
|
{ |
|
|
continue; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
List<MqttClientPublishPacketContext> pendingPublishPackets; |
|
|
|
|
|
lock (_pendingPublishPackets) |
|
|
|
|
|
{ |
|
|
|
|
|
pendingPublishPackets = _pendingPublishPackets.ToList(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (var publishPacket in pendingPublishPackets) |
|
|
|
|
|
{ |
|
|
|
|
|
await TrySendPendingPublishPacketAsync(publishPacket).ConfigureAwait(false); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
await TrySendPendingPublishPacketAsync( publishPacket ).ConfigureAwait( false ); |
|
|
} |
|
|
} |
|
|
catch (Exception e) |
|
|
|
|
|
|
|
|
catch ( Exception e ) |
|
|
{ |
|
|
{ |
|
|
MqttTrace.Error(nameof(MqttClientMessageQueue), e, "Error while sending pending publish packets."); |
|
|
|
|
|
|
|
|
MqttTrace.Error( nameof( MqttClientMessageQueue ), e, "Error while sending pending publish packets." ); |
|
|
} |
|
|
} |
|
|
finally |
|
|
|
|
|
{ |
|
|
|
|
|
Cleanup(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -112,23 +92,17 @@ namespace MQTTnet.Core.Server |
|
|
catch (MqttCommunicationException exception) |
|
|
catch (MqttCommunicationException exception) |
|
|
{ |
|
|
{ |
|
|
MqttTrace.Warning(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed."); |
|
|
MqttTrace.Warning(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed."); |
|
|
|
|
|
_pendingPublishPackets.Add( publishPacketContext ); |
|
|
} |
|
|
} |
|
|
catch (Exception exception) |
|
|
catch (Exception exception) |
|
|
{ |
|
|
{ |
|
|
MqttTrace.Error(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed."); |
|
|
MqttTrace.Error(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed."); |
|
|
|
|
|
_pendingPublishPackets.Add( publishPacketContext ); |
|
|
} |
|
|
} |
|
|
finally |
|
|
finally |
|
|
{ |
|
|
{ |
|
|
publishPacketContext.SendTries++; |
|
|
publishPacketContext.SendTries++; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private void Cleanup() |
|
|
|
|
|
{ |
|
|
|
|
|
lock (_pendingPublishPackets) |
|
|
|
|
|
{ |
|
|
|
|
|
_pendingPublishPackets.RemoveAll(p => p.IsSent); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |