This commit is contained in:
Christian
2018-05-03 20:44:21 +02:00
21 changed files with 613 additions and 168 deletions
+3 -3
View File
@@ -2,7 +2,7 @@
<package > <package >
<metadata> <metadata>
<id>MQTTnet.AspNetCore</id> <id>MQTTnet.AspNetCore</id>
<version>2.7.4</version> <version>2.7.5</version>
<authors>Christian Kratky</authors> <authors>Christian Kratky</authors>
<owners>Christian Kratky</owners> <owners>Christian Kratky</owners>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
@@ -10,13 +10,13 @@
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl> <iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>This is a support library to integrate MQTTnet into AspNetCore.</description> <description>This is a support library to integrate MQTTnet into AspNetCore.</description>
<releaseNotes>* Updated to MQTTnet 2.7.4. <releaseNotes>* Updated to MQTTnet 2.7.5.
</releaseNotes> </releaseNotes>
<copyright>Copyright Christian Kratky 2016-2018</copyright> <copyright>Copyright Christian Kratky 2016-2018</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> <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>
<dependencies> <dependencies>
<group targetFramework="netstandard2.0"> <group targetFramework="netstandard2.0">
<dependency id="MQTTnet" version="2.7.4" /> <dependency id="MQTTnet" version="2.7.5" />
</group> </group>
</dependencies> </dependencies>
</metadata> </metadata>
+8 -8
View File
@@ -2,7 +2,7 @@
<package > <package >
<metadata> <metadata>
<id>MQTTnet.Extensions.Rpc</id> <id>MQTTnet.Extensions.Rpc</id>
<version>2.7.4</version> <version>2.7.5</version>
<authors>Christian Kratky</authors> <authors>Christian Kratky</authors>
<owners>Christian Kratky</owners> <owners>Christian Kratky</owners>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
@@ -10,28 +10,28 @@
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl> <iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>This is a extension library which allows executing synchronous device calls including a response using MQTTnet.</description> <description>This is a extension library which allows executing synchronous device calls including a response using MQTTnet.</description>
<releaseNotes>* Initial version. <releaseNotes>* Updated to MQTTnet 2.7.5.
</releaseNotes> </releaseNotes>
<copyright>Copyright Christian Kratky 2016-2018</copyright> <copyright>Copyright Christian Kratky 2016-2018</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> <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>
<dependencies> <dependencies>
<group targetFramework="netstandard2.0"> <group targetFramework="netstandard2.0">
<dependency id="MQTTnet" version="2.7.4" /> <dependency id="MQTTnet" version="2.7.5" />
</group> </group>
<group targetFramework="netstandard1.3"> <group targetFramework="netstandard1.3">
<dependency id="MQTTnet" version="2.7.4" /> <dependency id="MQTTnet" version="2.7.5" />
</group> </group>
<group targetFramework="netstandard2.0"> <group targetFramework="netstandard2.0">
<dependency id="MQTTnet" version="2.7.4" /> <dependency id="MQTTnet" version="2.7.5" />
</group> </group>
<group targetFramework="uap10.0"> <group targetFramework="uap10.0">
<dependency id="MQTTnet" version="2.7.4" /> <dependency id="MQTTnet" version="2.7.5" />
</group> </group>
<group targetFramework="net452"> <group targetFramework="net452">
<dependency id="MQTTnet" version="2.7.4" /> <dependency id="MQTTnet" version="2.7.5" />
</group> </group>
<group targetFramework="net461"> <group targetFramework="net461">
<dependency id="MQTTnet" version="2.7.4" /> <dependency id="MQTTnet" version="2.7.5" />
</group> </group>
</dependencies> </dependencies>
</metadata> </metadata>
+4 -7
View File
@@ -2,7 +2,7 @@
<package > <package >
<metadata> <metadata>
<id>MQTTnet</id> <id>MQTTnet</id>
<version>2.7.5</version> <version>2.8.0</version>
<authors>Christian Kratky</authors> <authors>Christian Kratky</authors>
<owners>Christian Kratky</owners> <owners>Christian Kratky</owners>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
@@ -10,12 +10,9 @@
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl> <iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <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).</description> <description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description>
<releaseNotes> * [Client] Added new overloads for the message builders. <releaseNotes> * [Client] Received messages are now processed in the worker thread by default. Added a new setting for switching back to dedicated threads.
* [Core] Performance optimizations (thanks to @ israellot) * [Server] Added support for other WebSocket sub protocol formats like mqttv-3.1.1 (thanks to @israellot).
* [Core] Fixed a memory leak which was caused by not properly stopped async tasks. * [Server] The takeover of an existing client sessions is now treated as a _clean_ disconnect of the previous client.
* [Client] Fixed a deadlock when connecting to a not reachable server.
* [Server] Fixed a deadlock when reusing the same _ClientId_ while a _will message_ is used (thanks to @william-wps).
* [Server] Fixed wrong topic filter matching for filters like 'sport/+' which should _not_ match 'sport'.
</releaseNotes> </releaseNotes>
<copyright>Copyright Christian Kratky 2016-2018</copyright> <copyright>Copyright Christian Kratky 2016-2018</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> <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>
@@ -17,12 +17,12 @@ namespace MQTTnet.AspNetCore
{ {
string subprotocol = null; string subprotocol = null;
if (context.Request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues) if (context.Request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues))
&& requestedSubProtocolValues.Count > 0
&& requestedSubProtocolValues.Any(v => v.ToLower() == "mqtt")
)
{ {
subprotocol = "mqtt"; // Order the protocols to also match "mqtt", "mqttv-3.1", "mqttv-3.11" etc.
subprotocol = requestedSubProtocolValues
.OrderByDescending(p => p.Length)
.FirstOrDefault(p => p.ToLower().StartsWith("mqtt"));
} }
var adapter = app.ApplicationServices.GetRequiredService<MqttWebSocketServerAdapter>(); var adapter = app.ApplicationServices.GetRequiredService<MqttWebSocketServerAdapter>();
@@ -6,17 +6,16 @@ namespace MQTTnet.Client
public interface IMqttClientOptions public interface IMqttClientOptions
{ {
string ClientId { get; } string ClientId { get; }
IMqttClientCredentials Credentials { get; }
bool CleanSession { get; } bool CleanSession { get; }
MqttApplicationMessage WillMessage { get; } IMqttClientCredentials Credentials { get; }
MqttProtocolVersion ProtocolVersion { get; }
IMqttClientChannelOptions ChannelOptions { get; }
TimeSpan CommunicationTimeout { get; } TimeSpan CommunicationTimeout { get; }
TimeSpan KeepAlivePeriod { get; } TimeSpan KeepAlivePeriod { get; }
TimeSpan? KeepAliveSendInterval { get; } TimeSpan? KeepAliveSendInterval { get; }
MqttReceivedApplicationMessageProcessingMode ReceivedApplicationMessageProcessingMode { get; }
MqttProtocolVersion ProtocolVersion { get; } MqttApplicationMessage WillMessage { get; }
IMqttClientChannelOptions ChannelOptions { get; }
} }
} }
@@ -63,7 +63,7 @@ namespace MQTTnet.Client
StartReceivingPackets(_cancellationTokenSource.Token); StartReceivingPackets(_cancellationTokenSource.Token);
var connectResponse = await AuthenticateAsync(options.WillMessage).ConfigureAwait(false); var connectResponse = await AuthenticateAsync(options.WillMessage, _cancellationTokenSource.Token).ConfigureAwait(false);
_logger.Verbose<MqttClient>("MQTT connection with server established."); _logger.Verbose<MqttClient>("MQTT connection with server established.");
_sendTracker.Restart(); _sendTracker.Restart();
@@ -94,7 +94,7 @@ namespace MQTTnet.Client
{ {
if (IsConnected && !_cancellationTokenSource.IsCancellationRequested) if (IsConnected && !_cancellationTokenSource.IsCancellationRequested)
{ {
await SendAsync(new MqttDisconnectPacket()).ConfigureAwait(false); await SendAsync(new MqttDisconnectPacket(), _cancellationTokenSource.Token).ConfigureAwait(false);
} }
} }
finally finally
@@ -115,7 +115,7 @@ namespace MQTTnet.Client
TopicFilters = topicFilters.ToList() TopicFilters = topicFilters.ToList()
}; };
var response = await SendAndReceiveAsync<MqttSubAckPacket>(subscribePacket).ConfigureAwait(false); var response = await SendAndReceiveAsync<MqttSubAckPacket>(subscribePacket, _cancellationTokenSource.Token).ConfigureAwait(false);
if (response.SubscribeReturnCodes.Count != subscribePacket.TopicFilters.Count) if (response.SubscribeReturnCodes.Count != subscribePacket.TopicFilters.Count)
{ {
@@ -137,7 +137,7 @@ namespace MQTTnet.Client
TopicFilters = topicFilters.ToList() TopicFilters = topicFilters.ToList()
}; };
await SendAndReceiveAsync<MqttUnsubAckPacket>(unsubscribePacket).ConfigureAwait(false); await SendAndReceiveAsync<MqttUnsubAckPacket>(unsubscribePacket, _cancellationTokenSource.Token).ConfigureAwait(false);
} }
public async Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages) public async Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages)
@@ -154,7 +154,7 @@ namespace MQTTnet.Client
case MqttQualityOfServiceLevel.AtMostOnce: case MqttQualityOfServiceLevel.AtMostOnce:
{ {
// No packet identifier is used for QoS 0 [3.3.2.2 Packet Identifier] // No packet identifier is used for QoS 0 [3.3.2.2 Packet Identifier]
await SendAsync(qosGroup.Cast<MqttBasePacket>().ToArray()).ConfigureAwait(false); await SendAsync(qosGroup, _cancellationTokenSource.Token).ConfigureAwait(false);
break; break;
} }
case MqttQualityOfServiceLevel.AtLeastOnce: case MqttQualityOfServiceLevel.AtLeastOnce:
@@ -162,7 +162,7 @@ namespace MQTTnet.Client
foreach (var publishPacket in qosGroup) foreach (var publishPacket in qosGroup)
{ {
publishPacket.PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier(); publishPacket.PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier();
await SendAndReceiveAsync<MqttPubAckPacket>(publishPacket).ConfigureAwait(false); await SendAndReceiveAsync<MqttPubAckPacket>(publishPacket, _cancellationTokenSource.Token).ConfigureAwait(false);
} }
break; break;
@@ -173,13 +173,13 @@ namespace MQTTnet.Client
{ {
publishPacket.PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier(); publishPacket.PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier();
var pubRecPacket = await SendAndReceiveAsync<MqttPubRecPacket>(publishPacket).ConfigureAwait(false); var pubRecPacket = await SendAndReceiveAsync<MqttPubRecPacket>(publishPacket, _cancellationTokenSource.Token).ConfigureAwait(false);
var pubRelPacket = new MqttPubRelPacket var pubRelPacket = new MqttPubRelPacket
{ {
PacketIdentifier = pubRecPacket.PacketIdentifier PacketIdentifier = pubRecPacket.PacketIdentifier
}; };
await SendAndReceiveAsync<MqttPubCompPacket>(pubRelPacket).ConfigureAwait(false); await SendAndReceiveAsync<MqttPubCompPacket>(pubRelPacket, _cancellationTokenSource.Token).ConfigureAwait(false);
} }
break; break;
@@ -200,7 +200,7 @@ namespace MQTTnet.Client
_adapter?.Dispose(); _adapter?.Dispose();
} }
private async Task<MqttConnAckPacket> AuthenticateAsync(MqttApplicationMessage willApplicationMessage) private async Task<MqttConnAckPacket> AuthenticateAsync(MqttApplicationMessage willApplicationMessage, CancellationToken cancellationToken)
{ {
var connectPacket = new MqttConnectPacket var connectPacket = new MqttConnectPacket
{ {
@@ -212,7 +212,7 @@ namespace MQTTnet.Client
WillMessage = willApplicationMessage WillMessage = willApplicationMessage
}; };
var response = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket).ConfigureAwait(false); var response = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket, _cancellationTokenSource.Token).ConfigureAwait(false);
if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted) if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
{ {
throw new MqttConnectingFailedException(response.ConnectReturnCode); throw new MqttConnectingFailedException(response.ConnectReturnCode);
@@ -257,14 +257,12 @@ namespace MQTTnet.Client
try try
{ {
if (_packetReceiverTask != null && _packetReceiverTask != sender) await WaitForTaskAsync(_packetReceiverTask, sender).ConfigureAwait(false);
{ await WaitForTaskAsync(_keepAliveMessageSenderTask, sender).ConfigureAwait(false);
_packetReceiverTask.Wait();
}
if (_keepAliveMessageSenderTask != null && _keepAliveMessageSenderTask != sender) if (_keepAliveMessageSenderTask != null && _keepAliveMessageSenderTask != sender)
{ {
_keepAliveMessageSenderTask.Wait(); await _keepAliveMessageSenderTask.ConfigureAwait(false);
} }
if (_adapter != null) if (_adapter != null)
@@ -290,101 +288,19 @@ namespace MQTTnet.Client
} }
} }
private async Task ProcessReceivedPacketAsync(MqttBasePacket packet) private Task SendAsync(MqttBasePacket packet, CancellationToken cancellationToken)
{
try
{
if (packet is MqttPublishPacket publishPacket)
{
await ProcessReceivedPublishPacketAsync(publishPacket).ConfigureAwait(false);
return;
}
if (packet is MqttPingReqPacket)
{
await SendAsync(new MqttPingRespPacket()).ConfigureAwait(false);
return;
}
if (packet is MqttDisconnectPacket)
{
await DisconnectAsync().ConfigureAwait(false);
return;
}
if (packet is MqttPubRelPacket pubRelPacket)
{
await ProcessReceivedPubRelPacket(pubRelPacket).ConfigureAwait(false);
return;
}
_packetDispatcher.Dispatch(packet);
}
catch (Exception exception)
{
_logger.Error<MqttClient>(exception, "Unhandled exception while processing received packet.");
}
}
private void FireApplicationMessageReceivedEvent(MqttPublishPacket publishPacket)
{
try
{
var applicationMessage = publishPacket.ToApplicationMessage();
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(_options.ClientId, applicationMessage));
}
catch (Exception exception)
{
_logger.Error<MqttClient>(exception, "Unhandled exception while handling application message.");
}
}
private Task ProcessReceivedPublishPacketAsync(MqttPublishPacket publishPacket)
{
if (_cancellationTokenSource.IsCancellationRequested)
{
return Task.FromResult(0);
}
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
{
FireApplicationMessageReceivedEvent(publishPacket);
return Task.FromResult(0);
}
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
{
FireApplicationMessageReceivedEvent(publishPacket);
return SendAsync(new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier });
}
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
{
// QoS 2 is implement as method "B" [4.3.3 QoS 2: Exactly once delivery]
FireApplicationMessageReceivedEvent(publishPacket);
return SendAsync(new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier });
}
throw new MqttCommunicationException("Received a not supported QoS level.");
}
private Task ProcessReceivedPubRelPacket(MqttPubRelPacket pubRelPacket)
{
var response = new MqttPubCompPacket
{
PacketIdentifier = pubRelPacket.PacketIdentifier
};
return SendAsync(response);
}
private Task SendAsync(params MqttBasePacket[] packets)
{ {
_sendTracker.Restart(); _sendTracker.Restart();
return _adapter.SendPacketsAsync(_options.CommunicationTimeout, packets, _cancellationTokenSource.Token); return _adapter.SendPacketsAsync(_options.CommunicationTimeout, cancellationToken, new[] { packet });
} }
private async Task<TResponsePacket> SendAndReceiveAsync<TResponsePacket>(MqttBasePacket requestPacket) where TResponsePacket : MqttBasePacket private Task SendAsync(IEnumerable<MqttBasePacket> packets, CancellationToken cancellationToken)
{
_sendTracker.Restart();
return _adapter.SendPacketsAsync(_options.CommunicationTimeout, cancellationToken, packets);
}
private async Task<TResponsePacket> SendAndReceiveAsync<TResponsePacket>(MqttBasePacket requestPacket, CancellationToken cancellationToken) where TResponsePacket : MqttBasePacket
{ {
_sendTracker.Restart(); _sendTracker.Restart();
@@ -429,7 +345,7 @@ namespace MQTTnet.Client
if (_sendTracker.Elapsed > keepAliveSendInterval) if (_sendTracker.Elapsed > keepAliveSendInterval)
{ {
await SendAndReceiveAsync<MqttPingRespPacket>(new MqttPingReqPacket()).ConfigureAwait(false); await SendAndReceiveAsync<MqttPingRespPacket>(new MqttPingReqPacket(), cancellationToken).ConfigureAwait(false);
} }
await Task.Delay(keepAliveSendInterval, cancellationToken).ConfigureAwait(false); await Task.Delay(keepAliveSendInterval, cancellationToken).ConfigureAwait(false);
@@ -472,7 +388,19 @@ namespace MQTTnet.Client
return; return;
} }
StartProcessReceivedPacket(packet, cancellationToken); if (packet == null)
{
continue;
}
if (_options.ReceivedApplicationMessageProcessingMode == MqttReceivedApplicationMessageProcessingMode.SingleThread)
{
await ProcessReceivedPacketAsync(packet, cancellationToken).ConfigureAwait(false);
}
else if (_options.ReceivedApplicationMessageProcessingMode == MqttReceivedApplicationMessageProcessingMode.DedicatedThread)
{
StartProcessReceivedPacketAsync(packet, cancellationToken);
}
} }
} }
catch (Exception exception) catch (Exception exception)
@@ -498,9 +426,74 @@ namespace MQTTnet.Client
} }
} }
private void StartProcessReceivedPacket(MqttBasePacket packet, CancellationToken cancellationToken) private async Task ProcessReceivedPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken)
{ {
Task.Run(() => ProcessReceivedPacketAsync(packet), cancellationToken); try
{
if (packet is MqttPublishPacket publishPacket)
{
await ProcessReceivedPublishPacketAsync(publishPacket, cancellationToken).ConfigureAwait(false);
return;
}
if (packet is MqttPingReqPacket)
{
await SendAsync(new MqttPingRespPacket(), cancellationToken).ConfigureAwait(false);
return;
}
if (packet is MqttDisconnectPacket)
{
await DisconnectAsync().ConfigureAwait(false);
return;
}
if (packet is MqttPubRelPacket pubRelPacket)
{
await ProcessReceivedPubRelPacket(pubRelPacket, cancellationToken).ConfigureAwait(false);
return;
}
_packetDispatcher.Dispatch(packet);
}
catch (Exception exception)
{
_logger.Error<MqttClient>(exception, "Unhandled exception while processing received packet.");
}
}
private Task ProcessReceivedPublishPacketAsync(MqttPublishPacket publishPacket, CancellationToken cancellationToken)
{
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
{
FireApplicationMessageReceivedEvent(publishPacket);
return Task.FromResult(0);
}
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
{
FireApplicationMessageReceivedEvent(publishPacket);
return SendAsync(new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier }, cancellationToken);
}
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
{
// QoS 2 is implement as method "B" [4.3.3 QoS 2: Exactly once delivery]
FireApplicationMessageReceivedEvent(publishPacket);
return SendAsync(new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier }, cancellationToken);
}
throw new MqttCommunicationException("Received a not supported QoS level.");
}
private Task ProcessReceivedPubRelPacket(MqttPubRelPacket pubRelPacket, CancellationToken cancellationToken)
{
var response = new MqttPubCompPacket
{
PacketIdentifier = pubRelPacket.PacketIdentifier
};
return SendAsync(response, cancellationToken);
} }
private void StartReceivingPackets(CancellationToken cancellationToken) private void StartReceivingPackets(CancellationToken cancellationToken)
@@ -512,5 +505,46 @@ namespace MQTTnet.Client
{ {
_keepAliveMessageSenderTask = Task.Run(() => SendKeepAliveMessagesAsync(cancellationToken), cancellationToken); _keepAliveMessageSenderTask = Task.Run(() => SendKeepAliveMessagesAsync(cancellationToken), cancellationToken);
} }
private void StartProcessReceivedPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken)
{
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(() => ProcessReceivedPacketAsync(packet, cancellationToken), cancellationToken);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
private void FireApplicationMessageReceivedEvent(MqttPublishPacket publishPacket)
{
try
{
var applicationMessage = publishPacket.ToApplicationMessage();
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(_options.ClientId, applicationMessage));
}
catch (Exception exception)
{
_logger.Error<MqttClient>(exception, "Unhandled exception while handling application message.");
}
}
private static async Task WaitForTaskAsync(Task task, Task sender)
{
if (task == sender)
{
return;
}
if (task.IsCanceled || task.IsCompleted || task.IsFaulted)
{
return;
}
try
{
await task.ConfigureAwait(false);
}
catch (TaskCanceledException)
{
}
}
} }
} }
@@ -5,22 +5,17 @@ namespace MQTTnet.Client
{ {
public class MqttClientOptions : IMqttClientOptions public class MqttClientOptions : IMqttClientOptions
{ {
public MqttApplicationMessage WillMessage { get; set; }
public string ClientId { get; set; } = Guid.NewGuid().ToString("N"); public string ClientId { get; set; } = Guid.NewGuid().ToString("N");
public bool CleanSession { get; set; } = true; public bool CleanSession { get; set; } = true;
public IMqttClientCredentials Credentials { get; set; } = new MqttClientCredentials(); public IMqttClientCredentials Credentials { get; set; } = new MqttClientCredentials();
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311;
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(15); public IMqttClientChannelOptions ChannelOptions { get; set; }
public TimeSpan? KeepAliveSendInterval { get; set; }
public TimeSpan CommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan CommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(15);
public TimeSpan? KeepAliveSendInterval { get; set; }
public MqttReceivedApplicationMessageProcessingMode ReceivedApplicationMessageProcessingMode { get; set; } = MqttReceivedApplicationMessageProcessingMode.SingleThread;
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311; public MqttApplicationMessage WillMessage { get; set; }
public IMqttClientChannelOptions ChannelOptions { get; set; }
} }
} }
@@ -114,6 +114,13 @@ namespace MQTTnet.Client
return this; return this;
} }
public MqttClientOptionsBuilder WithReceivedApplicationMessageProcessingMode(
MqttReceivedApplicationMessageProcessingMode mode)
{
_options.ReceivedApplicationMessageProcessingMode = mode;
return this;
}
public IMqttClientOptions Build() public IMqttClientOptions Build()
{ {
if (_tlsOptions != null) if (_tlsOptions != null)
@@ -0,0 +1,8 @@
namespace MQTTnet.Client
{
public enum MqttReceivedApplicationMessageProcessingMode
{
SingleThread,
DedicatedThread
}
}
@@ -0,0 +1,8 @@
namespace MQTTnet.Server
{
public enum MqttClientDisconnectType
{
Clean,
NotClean
}
}
@@ -127,7 +127,7 @@ namespace MQTTnet.Server
if (!cancellationToken.IsCancellationRequested) if (!cancellationToken.IsCancellationRequested)
{ {
await _clientSession.StopAsync().ConfigureAwait(false); await _clientSession.StopAsync(MqttClientDisconnectType.NotClean).ConfigureAwait(false);
} }
} }
} }
@@ -101,7 +101,7 @@ namespace MQTTnet.Server
return _wasCleanDisconnect; return _wasCleanDisconnect;
} }
public Task StopAsync(bool wasCleanDisconnect = false) public async Task StopAsync(MqttClientDisconnectType type)
{ {
try try
{ {
@@ -110,7 +110,7 @@ namespace MQTTnet.Server
return Task.FromResult(0); return Task.FromResult(0);
} }
_wasCleanDisconnect = wasCleanDisconnect; _wasCleanDisconnect = type == MqttClientDisconnectType.Clean;
_cancellationTokenSource?.Cancel(false); _cancellationTokenSource?.Cancel(false);
PendingMessagesQueue.WaitForCompletion(); PendingMessagesQueue.WaitForCompletion();
@@ -119,7 +119,7 @@ namespace MQTTnet.Server
var willMessage = _willMessage; var willMessage = _willMessage;
_willMessage = null; // clear willmessage so it is send just once _willMessage = null; // clear willmessage so it is send just once
if (_willMessage != null && !wasCleanDisconnect) if (willMessage != null && !_wasCleanDisconnect)
{ {
_sessionsManager.StartDispatchApplicationMessage(this, willMessage); _sessionsManager.StartDispatchApplicationMessage(this, willMessage);
} }
@@ -186,7 +186,7 @@ namespace MQTTnet.Server
private Task StopDueToKeepAliveTimeoutAsync() private Task StopDueToKeepAliveTimeoutAsync()
{ {
_logger.Info<MqttClientSession>("Client '{0}': Timeout while waiting for KeepAlive packet.", ClientId); _logger.Info<MqttClientSession>("Client '{0}': Timeout while waiting for KeepAlive packet.", ClientId);
return StopAsync(); return StopAsync(MqttClientDisconnectType.NotClean);
} }
private async Task ReceivePacketsAsync(IMqttChannelAdapter adapter, CancellationToken cancellationToken) private async Task ReceivePacketsAsync(IMqttChannelAdapter adapter, CancellationToken cancellationToken)
@@ -203,15 +203,18 @@ namespace MQTTnet.Server
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
} }
catch (MqttCommunicationException exception)
{
_logger.Warning<MqttClientSession>(exception, "Client '{0}': Communication exception while processing client packets.", ClientId);
await StopAsync().ConfigureAwait(false);
}
catch (Exception exception) catch (Exception exception)
{ {
_logger.Error<MqttClientSession>(exception, "Client '{0}': Unhandled exception while processing client packets.", ClientId); if (exception is MqttCommunicationException)
await StopAsync().ConfigureAwait(false); {
_logger.Warning<MqttClientSession>(exception, "Client '{0}': Communication exception while processing client packets.", ClientId);
}
else
{
_logger.Error<MqttClientSession>(exception, "Client '{0}': Unhandled exception while processing client packets.", ClientId);
}
await StopAsync(MqttClientDisconnectType.NotClean).ConfigureAwait(false);
} }
} }
@@ -260,16 +263,16 @@ namespace MQTTnet.Server
if (packet is MqttDisconnectPacket) if (packet is MqttDisconnectPacket)
{ {
return StopAsync(true); return StopAsync(MqttClientDisconnectType.Clean);
} }
if (packet is MqttConnectPacket) if (packet is MqttConnectPacket)
{ {
return StopAsync(); return StopAsync(MqttClientDisconnectType.NotClean);
} }
_logger.Warning<MqttClientSession>("Client '{0}': Received not supported packet ({1}). Closing connection.", ClientId, packet); _logger.Warning<MqttClientSession>("Client '{0}': Received not supported packet ({1}). Closing connection.", ClientId, packet);
return StopAsync(); return StopAsync(MqttClientDisconnectType.NotClean);
} }
private async Task EnqueueSubscribedRetainedMessagesAsync(ICollection<TopicFilter> topicFilters) private async Task EnqueueSubscribedRetainedMessagesAsync(ICollection<TopicFilter> topicFilters)
@@ -288,7 +291,7 @@ namespace MQTTnet.Server
if (subscribeResult.CloseConnection) if (subscribeResult.CloseConnection)
{ {
await StopAsync().ConfigureAwait(false); await StopAsync(MqttClientDisconnectType.NotClean).ConfigureAwait(false);
} }
await EnqueueSubscribedRetainedMessagesAsync(subscribePacket.TopicFilters).ConfigureAwait(false); await EnqueueSubscribedRetainedMessagesAsync(subscribePacket.TopicFilters).ConfigureAwait(false);
@@ -120,7 +120,7 @@ namespace MQTTnet.Server
{ {
foreach (var session in _sessions) foreach (var session in _sessions)
{ {
await session.Value.StopAsync().ConfigureAwait(false); await session.Value.StopAsync(MqttClientDisconnectType.NotClean).ConfigureAwait(false);
} }
_sessions.Clear(); _sessions.Clear();
@@ -232,7 +232,7 @@ namespace MQTTnet.Server
{ {
_sessions.Remove(connectPacket.ClientId); _sessions.Remove(connectPacket.ClientId);
await clientSession.StopAsync().ConfigureAwait(false); await clientSession.StopAsync(MqttClientDisconnectType.Clean).ConfigureAwait(false);
clientSession.Dispose(); clientSession.Dispose();
clientSession = null; clientSession = null;
+19
View File
@@ -38,6 +38,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions",
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.Rpc", "Extensions\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj", "{C444E9C8-95FA-430E-9126-274129DE16CD}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.Rpc", "Extensions\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj", "{C444E9C8-95FA-430E-9126-274129DE16CD}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Benchmarks", "Tests\MQTTnet.Benchmarks\MQTTnet.Benchmarks.csproj", "{998D04DD-7CB0-45F5-A393-E2495C16399E}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -168,6 +170,22 @@ Global
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x64.Build.0 = Release|Any CPU {C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x64.Build.0 = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.ActiveCfg = Release|Any CPU {C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.ActiveCfg = Release|Any CPU
{C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.Build.0 = Release|Any CPU {C444E9C8-95FA-430E-9126-274129DE16CD}.Release|x86.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|ARM.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x64.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x64.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x86.ActiveCfg = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Debug|x86.Build.0 = Debug|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|Any CPU.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|ARM.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|ARM.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x64.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x64.Build.0 = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x86.ActiveCfg = Release|Any CPU
{998D04DD-7CB0-45F5-A393-E2495C16399E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -180,6 +198,7 @@ Global
{C6FF8AEA-0855-41EC-A1F3-AC262225BAB9} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4} {C6FF8AEA-0855-41EC-A1F3-AC262225BAB9} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{F10C4060-F7EE-4A83-919F-FF723E72F94A} = {32A630A7-2598-41D7-B625-204CD906F5FB} {F10C4060-F7EE-4A83-919F-FF723E72F94A} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{C444E9C8-95FA-430E-9126-274129DE16CD} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587} {C444E9C8-95FA-430E-9126-274129DE16CD} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587}
{998D04DD-7CB0-45F5-A393-E2495C16399E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894} SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894}
+54
View File
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Algorithms" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{998D04DD-7CB0-45F5-A393-E2495C16399E}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>MQTTnet.Benchmarks</RootNamespace>
<AssemblyName>MQTTnet.Benchmarks</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="BenchmarkDotNet, Version=0.10.14.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\..\packages\BenchmarkDotNet.0.10.14\lib\net46\BenchmarkDotNet.dll</HintPath>
</Reference>
<Reference Include="BenchmarkDotNet.Core, Version=0.10.14.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\..\packages\BenchmarkDotNet.Core.0.10.14\lib\net46\BenchmarkDotNet.Core.dll</HintPath>
</Reference>
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.10.14.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.10.14\lib\net46\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis, Version=2.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.Common.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=2.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.CSharp.2.6.1\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.DotNet.InternalAbstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.DotNet.InternalAbstractions.1.0.0\lib\net451\Microsoft.DotNet.InternalAbstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.DotNet.PlatformAbstractions, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.DotNet.PlatformAbstractions.1.1.1\lib\net451\Microsoft.DotNet.PlatformAbstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Registry, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Win32.Registry.4.3.0\lib\net46\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.FileVersionInfo, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.StackTrace, Version=4.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Numerics" />
<Reference Include="System.Reflection, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll</HintPath>
</Reference>
<Reference Include="System.Reflection.Metadata, Version=1.4.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
</Reference>
<Reference Include="System.Runtime, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Extensions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Runtime.InteropServices.4.3.0\lib\net462\System.Runtime.InteropServices.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encoding.CodePages, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Thread, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XmlDocument, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XPath, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XPath.XDocument, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="MessageProcessingBenchmark.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
<Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Frameworks\MQTTnet.Netstandard\MQTTnet.NetStandard.csproj">
<Project>{3587E506-55A2-4EB3-99C7-DC01E42D25D2}</Project>
<Name>MQTTnet.NetStandard</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,47 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Columns;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;
using MQTTnet.Client;
using MQTTnet.Server;
namespace MQTTnet.Benchmarks
{
[ClrJob]
[RPlotExporter, RankColumn]
public class MessageProcessingBenchmark
{
private IMqttServer _mqttServer;
private IMqttClient _mqttClient;
private MqttApplicationMessage _message;
[GlobalSetup]
public void Setup()
{
var factory = new MqttFactory();
_mqttServer = factory.CreateMqttServer();
_mqttClient = factory.CreateMqttClient();
var serverOptions = new MqttServerOptionsBuilder().Build();
_mqttServer.StartAsync(serverOptions).GetAwaiter().GetResult();
var clientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("localhost").Build();
_mqttClient.ConnectAsync(clientOptions).GetAwaiter().GetResult();
_message = new MqttApplicationMessageBuilder()
.WithTopic("A")
.Build();
}
[Benchmark]
public void Send_10000_Messages()
{
for (var i = 0; i < 10000; i++)
{
_mqttClient.PublishAsync(_message).GetAwaiter().GetResult();
}
}
}
}
+14
View File
@@ -0,0 +1,14 @@
using System;
using BenchmarkDotNet.Running;
namespace MQTTnet.Benchmarks
{
public static class Program
{
public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<MessageProcessingBenchmark>();
Console.ReadLine();
}
}
}
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MQTTnet.Benchmarks")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MQTTnet.Benchmarks")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("998d04dd-7cb0-45f5-a393-e2495c16399e")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+54
View File
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BenchmarkDotNet" version="0.10.14" targetFramework="net462" />
<package id="BenchmarkDotNet.Core" version="0.10.14" targetFramework="net462" />
<package id="BenchmarkDotNet.Toolchains.Roslyn" version="0.10.14" targetFramework="net462" />
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net462" />
<package id="Microsoft.CodeAnalysis.Common" version="2.6.1" targetFramework="net462" />
<package id="Microsoft.CodeAnalysis.CSharp" version="2.6.1" targetFramework="net462" />
<package id="Microsoft.DotNet.InternalAbstractions" version="1.0.0" targetFramework="net462" />
<package id="Microsoft.DotNet.PlatformAbstractions" version="1.1.1" targetFramework="net462" />
<package id="Microsoft.Win32.Registry" version="4.3.0" targetFramework="net462" />
<package id="System.AppContext" version="4.3.0" targetFramework="net462" />
<package id="System.Collections" version="4.3.0" targetFramework="net462" />
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net462" />
<package id="System.Collections.Immutable" version="1.3.1" targetFramework="net462" />
<package id="System.Console" version="4.3.0" targetFramework="net462" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net462" />
<package id="System.Diagnostics.FileVersionInfo" version="4.3.0" targetFramework="net462" />
<package id="System.Diagnostics.StackTrace" version="4.3.0" targetFramework="net462" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net462" />
<package id="System.Dynamic.Runtime" version="4.3.0" targetFramework="net462" />
<package id="System.Globalization" version="4.3.0" targetFramework="net462" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net462" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net462" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net462" />
<package id="System.Linq" version="4.3.0" targetFramework="net462" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net462" />
<package id="System.Reflection" version="4.3.0" targetFramework="net462" />
<package id="System.Reflection.Metadata" version="1.4.2" targetFramework="net462" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net462" />
<package id="System.Runtime" version="4.3.0" targetFramework="net462" />
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net462" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net462" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net462" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net462" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net462" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net462" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net462" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net462" />
<package id="System.Text.Encoding.CodePages" version="4.3.0" targetFramework="net462" />
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net462" />
<package id="System.Threading" version="4.3.0" targetFramework="net462" />
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net462" />
<package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net462" />
<package id="System.Threading.Tasks.Parallel" version="4.3.0" targetFramework="net462" />
<package id="System.Threading.Thread" version="4.3.0" targetFramework="net462" />
<package id="System.ValueTuple" version="4.3.0" targetFramework="net462" />
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net462" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net462" />
<package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="net462" />
<package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="net462" />
<package id="System.Xml.XPath" version="4.3.0" targetFramework="net462" />
<package id="System.Xml.XPath.XDocument" version="4.3.0" targetFramework="net462" />
</packages>
@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using MQTTnet;
using MQTTnet.AspNetCore; using MQTTnet.AspNetCore;
using MQTTnet.Server; using MQTTnet.Server;