Compare commits

..
4 Commits
Author SHA1 Message Date
Christian Kratky 105abeba06 * [Server] Added support for complex client IDs.
* [Server] Fixed an issue with not correctly removed old client sessions.
* [Server] Several minor performance improvements.
* [Server] An existing client session is no longer closed if a new client connection is invalid.
* [Client] Added support for sending "CleanSession" flag.
2017-05-05 21:34:37 +02:00
Christian Kratky b3a6919ea0 Add support for complex device IDs. 2017-04-30 19:32:52 +02:00
Christian Kratky 9816f12df6 Performance optimizations 2017-04-09 15:10:35 +02:00
Christian Kratky 8bfad437cf Add nuget support 2017-04-01 21:51:36 +02:00
39 changed files with 946 additions and 592 deletions
+2 -1
View File
@@ -242,4 +242,5 @@ ModelManifest.xml
.paket/paket.exe
# FAKE - F# Make
.fake/
.fake/
nuget.exe
@@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<Authors>Christian Kratky</Authors>
<Company>Christian Kratky</Company>
<Product>MQTTnet</Product>
<Description>MQTTnet for .NET Core</Description>
<Copyright>Copyright © Christian Kratky 2016-2017</Copyright>
<Version>2.0.4.0</Version>
<AssemblyVersion>2.0.4.0</AssemblyVersion>
<FileVersion>2.0.4.0</FileVersion>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<AssemblyName>MQTTnet</AssemblyName>
<RootNamespace>MQTTnet</RootNamespace>
<PackageId>MQTTnet</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<Authors>Christian Kratky</Authors>
<Company>Christian Kratky</Company>
<Product>MQTTnet</Product>
<Description>MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</Description>
<Copyright>Copyright © Christian Kratky 2016-2017</Copyright>
<Version>2.1.1.0</Version>
<AssemblyVersion>2.1.1.0</AssemblyVersion>
<FileVersion>2.1.1.0</FileVersion>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<AssemblyName>MQTTnet</AssemblyName>
<RootNamespace>MQTTnet</RootNamespace>
<PackageId>MQTTnet.NetCore</PackageId>
<PackageProjectUrl>https://github.com/chkr1011/MQTTnet</PackageProjectUrl>
<RepositoryUrl>https://github.com/chkr1011/MQTTnet</RepositoryUrl>
<PackageTags>MQTT MQTTClient MQTTServer MQTTBroker Broker</PackageTags>
<PackageIconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</PackageIconUrl>
<PackageLicenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</PackageLicenseUrl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x64'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x86'" />
<ItemGroup>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj" />
</ItemGroup>
</Project>
@@ -32,6 +32,69 @@
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|AnyCPU'">
<OutputPath>bin\Any CPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x86'">
<OutputPath>bin\x86\Any CPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x64'">
<OutputPath>bin\x64\Any CPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -45,7 +108,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
<Project>{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}</Project>
<Project>{2ecb99e4-72d0-4c23-99ba-93d511d3967d}</Project>
<Name>MQTTnet.Core</Name>
</ProjectReference>
</ItemGroup>
@@ -11,5 +11,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("a480ef90-0eaa-4d9a-b271-47a9c47f6f7d")]
[assembly: AssemblyVersion("2.1.0.4")]
[assembly: AssemblyFileVersion("2.1.0.4")]
[assembly: AssemblyVersion("2.1.1.0")]
[assembly: AssemblyFileVersion("2.1.1.0")]
@@ -57,6 +57,7 @@
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<DocumentationFile>bin\x86\Release\MQTTnet.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<PlatformTarget>ARM</PlatformTarget>
@@ -79,6 +80,7 @@
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<DocumentationFile>bin\ARM\Release\MQTTnet.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
@@ -101,6 +103,8 @@
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<GenerateLibraryLayout>false</GenerateLibraryLayout>
<DocumentationFile>bin\x64\Release\MQTTnet.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
@@ -116,13 +120,63 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
<Project>{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}</Project>
<Project>{2ecb99e4-72d0-4c23-99ba-93d511d3967d}</Project>
<Name>MQTTnet.Core</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|AnyCPU'">
<OutputPath>bin\Any CPU\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoStdLib>true</NoStdLib>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x86'">
<OutputPath>bin\x86\Any CPU\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DocumentationFile>bin\x86\Release\MQTTnet.XML</DocumentationFile>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<NoStdLib>true</NoStdLib>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|ARM'">
<OutputPath>bin\ARM\Any CPU\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DocumentationFile>bin\ARM\Release\MQTTnet.XML</DocumentationFile>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<NoStdLib>true</NoStdLib>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x64'">
<OutputPath>bin\x64\Any CPU\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<DocumentationFile>bin\x64\Release\MQTTnet.XML</DocumentationFile>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<NoStdLib>true</NoStdLib>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
@@ -10,5 +10,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("2.1.0.4")]
[assembly: AssemblyFileVersion("2.1.0.4")]
[assembly: AssemblyVersion("2.1.1.0")]
[assembly: AssemblyFileVersion("2.1.1.0")]
@@ -1,33 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains Runtime Directives, specifications about types your application accesses
through reflection and other dynamic code patterns. Runtime Directives are used to control the
.NET Native optimizer and ensure that it does not remove code accessed by your library. If your
library does not do any reflection, then you generally do not need to edit this file. However,
if your library reflects over types, especially types passed to it or derived from its types,
then you should write Runtime Directives.
The most common use of reflection in libraries is to discover information about types passed
to the library. Runtime Directives have three ways to express requirements on types passed to
your library.
1. Parameter, GenericParameter, TypeParameter, TypeEnumerableParameter
Use these directives to reflect over types passed as a parameter.
2. SubTypes
Use a SubTypes directive to reflect over types derived from another type.
3. AttributeImplies
Use an AttributeImplies directive to indicate that your library needs to reflect over
types or methods decorated with an attribute.
For more information on writing Runtime Directives for libraries, please visit
http://go.microsoft.com/fwlink/?LinkID=391919
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="MQTTnet.Universal">
<!-- add directives for your library here -->
</Library>
</Directives>
@@ -3,7 +3,8 @@
"Microsoft.NETCore.UniversalWindowsPlatform": "5.1.0"
},
"frameworks": {
"uap10.0": {}
"uap10.0": {},
"netstandard1.1": {}
},
"runtimes": {
"win10-arm": {},
+17 -20
View File
@@ -53,6 +53,7 @@ namespace MQTTnet.Core.Client
ClientId = _options.ClientId,
Username = _options.UserName,
Password = _options.Password,
CleanSession = _options.CleanSession,
KeepAlivePeriod = (ushort)_options.KeepAlivePeriod.TotalSeconds,
WillMessage = willApplicationMessage
};
@@ -66,7 +67,7 @@ namespace MQTTnet.Core.Client
_packetDispatcher.Reset();
IsConnected = true;
Task.Run(async () => await ReceivePackets(_cancellationTokenSource.Token), _cancellationTokenSource.Token).Forget();
Task.Run(() => ReceivePackets(_cancellationTokenSource.Token), _cancellationTokenSource.Token).Forget();
var response = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket);
if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
@@ -76,7 +77,7 @@ namespace MQTTnet.Core.Client
if (_options.KeepAlivePeriod != TimeSpan.Zero)
{
Task.Run(async () => await SendKeepAliveMessagesAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token).Forget();
Task.Run(() => SendKeepAliveMessagesAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token).Forget();
}
Connected?.Invoke(this, EventArgs.Empty);
@@ -88,11 +89,11 @@ namespace MQTTnet.Core.Client
await DisconnectInternalAsync();
}
public async Task<IList<MqttSubscribeResult>> SubscribeAsync(params TopicFilter[] topicFilters)
public Task<IList<MqttSubscribeResult>> SubscribeAsync(params TopicFilter[] topicFilters)
{
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
return await SubscribeAsync(topicFilters.ToList());
return SubscribeAsync(topicFilters.ToList());
}
public async Task<IList<MqttSubscribeResult>> SubscribeAsync(IList<TopicFilter> topicFilters)
@@ -114,20 +115,14 @@ namespace MQTTnet.Core.Client
throw new MqttProtocolViolationException("The return codes are not matching the topic filters [MQTT-3.9.3-1].");
}
var result = new List<MqttSubscribeResult>();
for (var i = 0; i < topicFilters.Count; i++)
{
result.Add(new MqttSubscribeResult(topicFilters[i], response.SubscribeReturnCodes[i]));
}
return result;
return topicFilters.Select((t, i) => new MqttSubscribeResult(t, response.SubscribeReturnCodes[i])).ToList();
}
public async Task Unsubscribe(params string[] topicFilters)
public Task Unsubscribe(params string[] topicFilters)
{
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
await Unsubscribe(topicFilters.ToList());
return Unsubscribe(topicFilters.ToList());
}
public async Task Unsubscribe(IList<string> topicFilters)
@@ -280,14 +275,14 @@ namespace MQTTnet.Core.Client
FireApplicationMessageReceivedEvent(originalPublishPacket);
}
private async Task SendAsync(MqttBasePacket packet)
private Task SendAsync(MqttBasePacket packet)
{
await _adapter.SendPacketAsync(packet, _options.DefaultCommunicationTimeout);
return _adapter.SendPacketAsync(packet, _options.DefaultCommunicationTimeout);
}
private async Task<TResponsePacket> SendAndReceiveAsync<TResponsePacket>(MqttBasePacket requestPacket) where TResponsePacket : MqttBasePacket
{
Func<MqttBasePacket, bool> responsePacketSelector = p =>
bool ResponsePacketSelector(MqttBasePacket p)
{
var p1 = p as TResponsePacket;
if (p1 == null)
@@ -307,10 +302,10 @@ namespace MQTTnet.Core.Client
}
return true;
};
}
await _adapter.SendPacketAsync(requestPacket, _options.DefaultCommunicationTimeout);
return (TResponsePacket)await _packetDispatcher.WaitForPacketAsync(responsePacketSelector, _options.DefaultCommunicationTimeout);
return (TResponsePacket)await _packetDispatcher.WaitForPacketAsync(ResponsePacketSelector, _options.DefaultCommunicationTimeout);
}
private ushort GetNewPacketIdentifier()
@@ -330,8 +325,9 @@ namespace MQTTnet.Core.Client
await SendAndReceiveAsync<MqttPingRespPacket>(new MqttPingReqPacket());
}
}
catch (MqttCommunicationException)
catch (MqttCommunicationException exception)
{
MqttTrace.Warning(nameof(MqttClient), exception, "MQTT communication error while receiving packets.");
}
catch (Exception exception)
{
@@ -357,8 +353,9 @@ namespace MQTTnet.Core.Client
Task.Run(() => ProcessReceivedPacket(mqttPacket), cancellationToken).Forget();
}
}
catch (MqttCommunicationException)
catch (MqttCommunicationException exception)
{
MqttTrace.Warning(nameof(MqttClient), exception, "MQTT communication error while receiving packets.");
}
catch (Exception exception)
{
+2
View File
@@ -14,6 +14,8 @@ namespace MQTTnet.Core.Client
public string ClientId { get; set; } = Guid.NewGuid().ToString().Replace("-", string.Empty);
public bool CleanSession { get; set; } = true;
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(5);
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MQTTnet.Core.Internal
{
public class AsyncGate
{
private readonly Queue<TaskCompletionSource<bool>> _waitingTasks = new Queue<TaskCompletionSource<bool>>();
public Task WaitOneAsync()
{
var tcs = new TaskCompletionSource<bool>();
lock (_waitingTasks)
{
_waitingTasks.Enqueue(tcs);
}
return tcs.Task;
}
public void Set()
{
lock (_waitingTasks)
{
if (_waitingTasks.Count > 0)
{
_waitingTasks.Dequeue().SetResult(true);
}
}
}
}
}
+30 -103
View File
@@ -1,107 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MQTTnet.Core</RootNamespace>
<TargetFramework>netstandard1.1</TargetFramework>
<AssemblyName>MQTTnet.Core</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Profile111</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<RootNamespace>MQTTnet.Core</RootNamespace>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<Description>MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</Description>
<Product>MQTTnet</Product>
<Company>Christian Kratky</Company>
<Authors>Christian Kratky</Authors>
<Version>2.1.2.0</Version>
<PackageId>MQTTnet.Core</PackageId>
<Copyright>Copyright © Christian Kratky 2016-2017</Copyright>
<PackageProjectUrl>https://github.com/chkr1011/MQTTnet</PackageProjectUrl>
<PackageIconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</PackageIconUrl>
<RepositoryUrl>https://github.com/chkr1011/MQTTnet</RepositoryUrl>
<PackageTags>MQTT MQTTClient MQTTServer MQTTBroker Broker</PackageTags>
<FileVersion>2.1.2.0</FileVersion>
<AssemblyVersion>2.1.2.0</AssemblyVersion>
<PackageLicenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</PackageLicenseUrl>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<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' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
</ItemGroup>
<ItemGroup>
<Compile Include="Adapter\IMqttCommunicationAdapter.cs" />
<Compile Include="Adapter\IMqttServerAdapter.cs" />
<Compile Include="Adapter\MqttClientConnectedEventArgs.cs" />
<Compile Include="Adapter\MqttConnectingFailedException.cs" />
<Compile Include="Adapter\MqttChannelCommunicationAdapter.cs" />
<Compile Include="Channel\IMqttCommunicationChannel.cs" />
<Compile Include="Client\MqttPacketDispatcher.cs" />
<Compile Include="Client\MqttSubscribeResult.cs" />
<Compile Include="Client\MqttPacketAwaiter.cs" />
<Compile Include="Diagnostics\MqttTrace.cs" />
<Compile Include="Diagnostics\MqttTraceLevel.cs" />
<Compile Include="Diagnostics\MqttTraceMessagePublishedEventArgs.cs" />
<Compile Include="Exceptions\MqttCommunicationException.cs" />
<Compile Include="Exceptions\MqttCommunicationTimedOutException.cs" />
<Compile Include="Exceptions\MqttProtocolViolationException.cs" />
<Compile Include="Internal\MqttApplicationMessageExtensions.cs" />
<Compile Include="MqttApplicationMessageReceivedEventArgs.cs" />
<Compile Include="Packets\IPacketWithPacketIdentifier.cs" />
<Compile Include="Packets\MqttConnAckPacket.cs" />
<Compile Include="Packets\MqttBasePacket.cs" />
<Compile Include="Packets\MqttConnectPacket.cs" />
<Compile Include="Packets\MqttDisconnectPacket.cs" />
<Compile Include="MqttApplicationMessage.cs" />
<Compile Include="Client\MqttClient.cs" />
<Compile Include="Client\MqttClientOptions.cs" />
<Compile Include="Packets\MqttPingReqPacket.cs" />
<Compile Include="Packets\MqttPubCompPacket.cs" />
<Compile Include="Packets\MqttBasePublishPacket.cs" />
<Compile Include="Packets\MqttUnsubAckPacket.cs" />
<Compile Include="Packets\MqttSubAckPacket.cs" />
<Compile Include="Packets\MqttPubRelPacket.cs" />
<Compile Include="Packets\MqttPingRespPacket.cs" />
<Compile Include="Packets\MqttPubAckPacket.cs" />
<Compile Include="Packets\MqttPublishPacket.cs" />
<Compile Include="Packets\MqttPubRecPacket.cs" />
<Compile Include="Packets\MqttUnsubscribe.cs" />
<Compile Include="Packets\MqttSubscribePacket.cs" />
<Compile Include="Packets\TopicFilter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Protocol\MqttConnectReturnCode.cs" />
<Compile Include="Protocol\MqttControlPacketType.cs" />
<Compile Include="Protocol\MqttQualityOfServiceLevel.cs" />
<Compile Include="Protocol\MqttSubscribeReturnCode.cs" />
<Compile Include="Serializer\ByteReader.cs" />
<Compile Include="Serializer\ByteWriter.cs" />
<Compile Include="Serializer\DefaultMqttV311PacketSerializer.cs" />
<Compile Include="Serializer\IMqttPacketSerializer.cs" />
<Compile Include="Serializer\MqttPacketReader.cs" />
<Compile Include="Serializer\MqttPacketWriter.cs" />
<Compile Include="Server\MqttClientSession.cs" />
<Compile Include="Server\MqttClientSessionManager.cs" />
<Compile Include="Server\MqttOutgoingPublicationsManager.cs" />
<Compile Include="Server\MqttServer.cs" />
<Compile Include="Server\MqttServerOptions.cs" />
<Compile Include="Server\MqttClientPublishPacketContext.cs" />
<Compile Include="Server\MqttTopicFilterComparer.cs" />
<Compile Include="Server\MqttClientSubscriptionsManager.cs" />
<Compile Include="Internal\TaskExtensions.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x64'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x86'" />
</Project>
-15
View File
@@ -1,15 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("MQTTnet")]
[assembly: AssemblyDescription("The core library of MQTTnet")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Christian Kratky")]
[assembly: AssemblyProduct("MQTTnet")]
[assembly: AssemblyCopyright("Copyright © Christian Kratky 2016-2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("0e10d0ea-8e4b-4903-ab9e-93a187d07922")]
[assembly: AssemblyVersion("2.1.0.4")]
[assembly: AssemblyFileVersion("2.1.0.4")]
+13 -7
View File
@@ -4,36 +4,42 @@ namespace MQTTnet.Core.Serializer
{
public class ByteReader
{
private readonly int _source;
private int _index;
private readonly int _byte;
public ByteReader(byte @byte)
public ByteReader(int source)
{
_byte = @byte;
_source = source;
}
public bool Read()
{
if (_index >= 8)
{
throw new InvalidOperationException("End of the byte reached.");
throw new InvalidOperationException("End of byte reached.");
}
var result = ((1 << _index) & _byte) > 0;
var result = ((1 << _index) & _source) > 0;
_index++;
return result;
}
public byte Read(int count)
{
if (_index + count > 8)
{
throw new InvalidOperationException("End of byte will be reached.");
}
var result = 0;
for (var i = 0; i < count; i++)
{
if (Read())
if (((1 << _index) & _source) > 0)
{
result |= 1 << i;
}
_index++;
}
return (byte)result;
+1 -1
View File
@@ -9,7 +9,7 @@ namespace MQTTnet.Core.Serializer
public byte Value => (byte)_byte;
public void Write(byte @byte, int count)
public void Write(int @byte, int count)
{
for (var i = 0; i < count; i++)
{
@@ -1,6 +1,5 @@
using System;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -13,7 +12,7 @@ namespace MQTTnet.Core.Serializer
{
public class DefaultMqttV311PacketSerializer : IMqttPacketSerializer
{
public async Task SerializeAsync(MqttBasePacket packet, IMqttCommunicationChannel destination)
public Task SerializeAsync(MqttBasePacket packet, IMqttCommunicationChannel destination)
{
if (packet == null) throw new ArgumentNullException(nameof(packet));
if (destination == null) throw new ArgumentNullException(nameof(destination));
@@ -21,99 +20,85 @@ namespace MQTTnet.Core.Serializer
var connectPacket = packet as MqttConnectPacket;
if (connectPacket != null)
{
await SerializeAsync(connectPacket, destination);
return;
return SerializeAsync(connectPacket, destination);
}
var connAckPacket = packet as MqttConnAckPacket;
if (connAckPacket != null)
{
await SerializeAsync(connAckPacket, destination);
return;
return SerializeAsync(connAckPacket, destination);
}
var disconnectPacket = packet as MqttDisconnectPacket;
if (disconnectPacket != null)
{
await SerializeAsync(disconnectPacket, destination);
return;
return SerializeAsync(disconnectPacket, destination);
}
var pingReqPacket = packet as MqttPingReqPacket;
if (pingReqPacket != null)
{
await SerializeAsync(pingReqPacket, destination);
return;
return SerializeAsync(pingReqPacket, destination);
}
var pingRespPacket = packet as MqttPingRespPacket;
if (pingRespPacket != null)
{
await SerializeAsync(pingRespPacket, destination);
return;
return SerializeAsync(pingRespPacket, destination);
}
var publishPacket = packet as MqttPublishPacket;
if (publishPacket != null)
{
await SerializeAsync(publishPacket, destination);
return;
return SerializeAsync(publishPacket, destination);
}
var pubAckPacket = packet as MqttPubAckPacket;
if (pubAckPacket != null)
{
await SerializeAsync(pubAckPacket, destination);
return;
return SerializeAsync(pubAckPacket, destination);
}
var pubRecPacket = packet as MqttPubRecPacket;
if (pubRecPacket != null)
{
await SerializeAsync(pubRecPacket, destination);
return;
return SerializeAsync(pubRecPacket, destination);
}
var pubRelPacket = packet as MqttPubRelPacket;
if (pubRelPacket != null)
{
await SerializeAsync(pubRelPacket, destination);
return;
return SerializeAsync(pubRelPacket, destination);
}
var pubCompPacket = packet as MqttPubCompPacket;
if (pubCompPacket != null)
{
await SerializeAsync(pubCompPacket, destination);
return;
return SerializeAsync(pubCompPacket, destination);
}
var subscribePacket = packet as MqttSubscribePacket;
if (subscribePacket != null)
{
await SerializeAsync(subscribePacket, destination);
return;
return SerializeAsync(subscribePacket, destination);
}
var subAckPacket = packet as MqttSubAckPacket;
if (subAckPacket != null)
{
await SerializeAsync(subAckPacket, destination);
return;
return SerializeAsync(subAckPacket, destination);
}
var unsubscribePacket = packet as MqttUnsubscribePacket;
if (unsubscribePacket != null)
{
await SerializeAsync(unsubscribePacket, destination);
return;
return SerializeAsync(unsubscribePacket, destination);
}
var unsubAckPacket = packet as MqttUnsubAckPacket;
if (unsubAckPacket != null)
{
await SerializeAsync(unsubAckPacket, destination);
return;
return SerializeAsync(unsubAckPacket, destination);
}
throw new MqttProtocolViolationException("Packet type invalid.");
@@ -216,7 +201,7 @@ namespace MQTTnet.Core.Serializer
default:
{
throw new ProtocolViolationException();
throw new MqttProtocolViolationException("Packet type not supported.");
}
}
}
@@ -288,11 +273,12 @@ namespace MQTTnet.Core.Serializer
await reader.ReadRemainingDataByteAsync();
await reader.ReadRemainingDataByteAsync();
var protocolName = await reader.ReadRemainingDataAsync(4);
if (Encoding.UTF8.GetString(protocolName, 0, protocolName.Length) != "MQTT")
{
throw new ProtocolViolationException("Protocol name is not 'MQTT'.");
throw new MqttProtocolViolationException("Protocol name is not 'MQTT'.");
}
var protocolLevel = await reader.ReadRemainingDataByteAsync();
@@ -366,12 +352,7 @@ namespace MQTTnet.Core.Serializer
{
if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession)
{
throw new ProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7].");
}
if (!string.IsNullOrEmpty(packet.ClientId) && !Regex.IsMatch(packet.ClientId, "^[a-zA-Z0-9]*$"))
{
throw new ProtocolViolationException("ClientId contains invalid characters [MQTT-3.1.3-5].");
throw new MqttProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7].");
}
}
@@ -379,23 +360,21 @@ namespace MQTTnet.Core.Serializer
{
if (packet.QualityOfServiceLevel == 0 && packet.Dup)
{
throw new ProtocolViolationException("Dup flag must be false for QoS 0 packets [MQTT-3.3.1-2].");
throw new MqttProtocolViolationException("Dup flag must be false for QoS 0 packets [MQTT-3.3.1-2].");
}
}
private async Task SerializeAsync(MqttConnectPacket packet, IMqttCommunicationChannel destination)
private static readonly byte[] MqttPrefix = Encoding.UTF8.GetBytes("MQTT");
private Task SerializeAsync(MqttConnectPacket packet, IMqttCommunicationChannel destination)
{
ValidateConnectPacket(packet);
using (var output = new MqttPacketWriter())
{
// Write variable header
output.Write(0x00); // 3.1.2.1 Protocol Name
output.Write(0x04); // ""
output.Write('M');
output.Write('Q');
output.Write('T');
output.Write('T');
output.Write(0x00, 0x04); // 3.1.2.1 Protocol Name
output.Write(MqttPrefix);
output.Write(0x04); // 3.1.2.2 Protocol Level
var connectFlags = new ByteWriter(); // 3.1.2.3 Connect Flags
@@ -405,7 +384,7 @@ namespace MQTTnet.Core.Serializer
if (packet.WillMessage != null)
{
connectFlags.Write((byte)packet.WillMessage.QualityOfServiceLevel, 2);
connectFlags.Write((int)packet.WillMessage.QualityOfServiceLevel, 2);
connectFlags.Write(packet.WillMessage.Retain);
}
else
@@ -413,7 +392,7 @@ namespace MQTTnet.Core.Serializer
connectFlags.Write(0, 2);
connectFlags.Write(false);
}
connectFlags.Write(packet.Password != null);
connectFlags.Write(packet.Username != null);
@@ -438,11 +417,11 @@ namespace MQTTnet.Core.Serializer
}
output.InjectFixedHeader(MqttControlPacketType.Connect);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
private async Task SerializeAsync(MqttConnAckPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttConnAckPacket packet, IMqttCommunicationChannel destination)
{
using (var output = new MqttPacketWriter())
{
@@ -453,26 +432,26 @@ namespace MQTTnet.Core.Serializer
output.Write((byte)packet.ConnectReturnCode);
output.InjectFixedHeader(MqttControlPacketType.ConnAck);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
private async Task SerializeAsync(MqttDisconnectPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttDisconnectPacket packet, IMqttCommunicationChannel destination)
{
await SerializeEmptyPacketAsync(MqttControlPacketType.Disconnect, destination);
return SerializeEmptyPacketAsync(MqttControlPacketType.Disconnect, destination);
}
private async Task SerializeAsync(MqttPingReqPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttPingReqPacket packet, IMqttCommunicationChannel destination)
{
await SerializeEmptyPacketAsync(MqttControlPacketType.PingReq, destination);
return SerializeEmptyPacketAsync(MqttControlPacketType.PingReq, destination);
}
private async Task SerializeAsync(MqttPingRespPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttPingRespPacket packet, IMqttCommunicationChannel destination)
{
await SerializeEmptyPacketAsync(MqttControlPacketType.PingResp, destination);
return SerializeEmptyPacketAsync(MqttControlPacketType.PingResp, destination);
}
private async Task SerializeAsync(MqttPublishPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttPublishPacket packet, IMqttCommunicationChannel destination)
{
ValidatePublishPacket(packet);
@@ -503,29 +482,29 @@ namespace MQTTnet.Core.Serializer
fixedHeader.Write(packet.Dup);
output.InjectFixedHeader(MqttControlPacketType.Publish, fixedHeader.Value);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
private async Task SerializeAsync(MqttPubAckPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttPubAckPacket packet, IMqttCommunicationChannel destination)
{
using (var output = new MqttPacketWriter())
{
output.Write(packet.PacketIdentifier);
output.InjectFixedHeader(MqttControlPacketType.PubAck);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
private async Task SerializeAsync(MqttPubRecPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttPubRecPacket packet, IMqttCommunicationChannel destination)
{
using (var output = new MqttPacketWriter())
{
output.Write(packet.PacketIdentifier);
output.InjectFixedHeader(MqttControlPacketType.PubRec);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
@@ -540,24 +519,24 @@ namespace MQTTnet.Core.Serializer
}
}
private async Task SerializeAsync(MqttPubCompPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttPubCompPacket packet, IMqttCommunicationChannel destination)
{
using (var output = new MqttPacketWriter())
{
output.Write(packet.PacketIdentifier);
output.InjectFixedHeader(MqttControlPacketType.PubComp);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
private async Task SerializeAsync(MqttSubscribePacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttSubscribePacket packet, IMqttCommunicationChannel destination)
{
using (var output = new MqttPacketWriter())
{
output.Write(packet.PacketIdentifier);
if (packet.TopicFilters?.Any() == true)
if (packet.TopicFilters?.Count > 0)
{
foreach (var topicFilter in packet.TopicFilters)
{
@@ -567,11 +546,11 @@ namespace MQTTnet.Core.Serializer
}
output.InjectFixedHeader(MqttControlPacketType.Subscribe, 0x02);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
private async Task SerializeAsync(MqttSubAckPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttSubAckPacket packet, IMqttCommunicationChannel destination)
{
using (var output = new MqttPacketWriter())
{
@@ -586,11 +565,11 @@ namespace MQTTnet.Core.Serializer
}
output.InjectFixedHeader(MqttControlPacketType.SubAck);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
private async Task SerializeAsync(MqttUnsubscribePacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttUnsubscribePacket packet, IMqttCommunicationChannel destination)
{
using (var output = new MqttPacketWriter())
{
@@ -605,27 +584,27 @@ namespace MQTTnet.Core.Serializer
}
output.InjectFixedHeader(MqttControlPacketType.Unsubscibe, 0x02);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
private async Task SerializeAsync(MqttUnsubAckPacket packet, IMqttCommunicationChannel destination)
private Task SerializeAsync(MqttUnsubAckPacket packet, IMqttCommunicationChannel destination)
{
using (var output = new MqttPacketWriter())
{
output.Write(packet.PacketIdentifier);
output.InjectFixedHeader(MqttControlPacketType.UnsubAck);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
private async Task SerializeEmptyPacketAsync(MqttControlPacketType type, IMqttCommunicationChannel destination)
private Task SerializeEmptyPacketAsync(MqttControlPacketType type, IMqttCommunicationChannel destination)
{
using (var output = new MqttPacketWriter())
{
output.InjectFixedHeader(type);
await output.WriteToAsync(destination);
return output.WriteToAsync(destination);
}
}
}
+3 -2
View File
@@ -107,15 +107,16 @@ namespace MQTTnet.Core.Serializer
return await ReadRemainingDataAsync(length);
}
public async Task<byte[]> ReadRemainingDataAsync()
public Task<byte[]> ReadRemainingDataAsync()
{
return await ReadRemainingDataAsync(RemainingLength - (int)_remainingData.Position);
return ReadRemainingDataAsync(RemainingLength - (int)_remainingData.Position);
}
public async Task<byte[]> ReadRemainingDataAsync(int length)
{
var buffer = new byte[length];
await _remainingData.ReadAsync(buffer, 0, buffer.Length);
return buffer;
}
+30 -32
View File
@@ -9,7 +9,7 @@ namespace MQTTnet.Core.Serializer
{
public sealed class MqttPacketWriter : IDisposable
{
private readonly MemoryStream _buffer = new MemoryStream();
private readonly MemoryStream _buffer = new MemoryStream(512);
public void InjectFixedHeader(byte fixedHeader)
{
@@ -20,31 +20,28 @@ namespace MQTTnet.Core.Serializer
return;
}
var backupBuffer = _buffer.ToArray();
var remainingLength = (int)_buffer.Length;
using (var buffer = new MemoryStream())
_buffer.SetLength(0);
_buffer.WriteByte(fixedHeader);
// Alorithm taken from http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html.
var x = remainingLength;
do
{
_buffer.WriteTo(buffer);
_buffer.SetLength(0);
_buffer.WriteByte(fixedHeader);
// Alorithm taken from http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html.
var x = remainingLength;
do
var encodedByte = x % 128;
x = x / 128;
if (x > 0)
{
var encodedByte = (byte)(x % 128);
x = x / 128;
if (x > 0)
{
encodedByte = (byte)(encodedByte | 128);
}
encodedByte = encodedByte | 128;
}
_buffer.WriteByte(encodedByte);
} while (x > 0);
_buffer.WriteByte((byte)encodedByte);
} while (x > 0);
buffer.Position = 0;
buffer.WriteTo(_buffer);
}
_buffer.Write(backupBuffer, 0, backupBuffer.Length);
}
public void InjectFixedHeader(MqttControlPacketType packetType, byte flags = 0)
@@ -59,11 +56,6 @@ namespace MQTTnet.Core.Serializer
_buffer.WriteByte(value);
}
public void Write(char value)
{
_buffer.WriteByte((byte)value);
}
public void Write(ushort value)
{
var buffer = BitConverter.GetBytes(value);
@@ -73,11 +65,15 @@ namespace MQTTnet.Core.Serializer
public void Write(ByteWriter value)
{
if (value == null) throw new ArgumentNullException(nameof(value));
_buffer.WriteByte(value.Value);
}
public void Write(byte[] value)
public void Write(params byte[] value)
{
if (value == null) throw new ArgumentNullException(nameof(value));
_buffer.Write(value, 0, value.Length);
}
@@ -94,14 +90,16 @@ namespace MQTTnet.Core.Serializer
Write(value);
}
public Task WriteToAsync(IMqttCommunicationChannel destination)
{
if (destination == null) throw new ArgumentNullException(nameof(destination));
return destination.WriteAsync(_buffer.ToArray());
}
public void Dispose()
{
_buffer?.Dispose();
}
public async Task WriteToAsync(IMqttCommunicationChannel destination)
{
await destination.WriteAsync(_buffer.ToArray());
}
}
}
@@ -0,0 +1,9 @@
namespace MQTTnet.Core.Server
{
public class GetOrCreateClientSessionResult
{
public bool IsExistingSession { get; set; }
public MqttClientSession Session { get; set; }
}
}
@@ -11,16 +11,16 @@ using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Server
{
public class MqttOutgoingPublicationsManager
public class MqttClientMessageQueue
{
private readonly AutoResetEvent _resetEvent = new AutoResetEvent(false);
private readonly List<MqttClientPublishPacketContext> _pendingPublishPackets = new List<MqttClientPublishPacketContext>();
private readonly AsyncGate _gate = new AsyncGate();
private readonly MqttServerOptions _options;
private CancellationTokenSource _cancellationTokenSource;
private IMqttCommunicationAdapter _adapter;
public MqttOutgoingPublicationsManager(MqttServerOptions options)
public MqttClientMessageQueue(MqttServerOptions options)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
}
@@ -29,17 +29,18 @@ namespace MQTTnet.Core.Server
{
if (_cancellationTokenSource != null)
{
throw new InvalidOperationException($"{nameof(MqttOutgoingPublicationsManager)} already started.");
throw new InvalidOperationException($"{nameof(MqttClientMessageQueue)} already started.");
}
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
_cancellationTokenSource = new CancellationTokenSource();
Task.Run(async () => await SendPendingPublishPacketsAsync(_cancellationTokenSource.Token)).Forget();
Task.Run(() => SendPendingPublishPacketsAsync(_cancellationTokenSource.Token));
}
public void Stop()
{
_adapter = null;
_cancellationTokenSource?.Cancel();
_cancellationTokenSource = null;
}
@@ -52,7 +53,7 @@ namespace MQTTnet.Core.Server
lock (_pendingPublishPackets)
{
_pendingPublishPackets.Add(new MqttClientPublishPacketContext(senderClientSession, publishPacket));
_resetEvent.Set();
_gate.Set();
}
}
@@ -62,12 +63,17 @@ namespace MQTTnet.Core.Server
{
try
{
_resetEvent.WaitOne();
await _gate.WaitOneAsync();
if (cancellationToken.IsCancellationRequested)
{
return;
}
if (_adapter == null)
{
continue;
}
List<MqttClientPublishPacketContext> pendingPublishPackets;
lock (_pendingPublishPackets)
{
@@ -81,7 +87,7 @@ namespace MQTTnet.Core.Server
}
catch (Exception e)
{
MqttTrace.Error(nameof(MqttOutgoingPublicationsManager), e, "Error while sending pending publish packets.");
MqttTrace.Error(nameof(MqttClientMessageQueue), e, "Error while sending pending publish packets.");
}
finally
{
@@ -106,11 +112,11 @@ namespace MQTTnet.Core.Server
}
catch (MqttCommunicationException exception)
{
MqttTrace.Warning(nameof(MqttOutgoingPublicationsManager), exception, "Sending publish packet failed.");
MqttTrace.Warning(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed.");
}
catch (Exception exception)
{
MqttTrace.Error(nameof(MqttOutgoingPublicationsManager), exception, "Sending publish packet failed.");
MqttTrace.Error(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed.");
}
finally
{
+29 -25
View File
@@ -11,12 +11,12 @@ using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Server
{
public class MqttClientSession
public sealed class MqttClientSession : IDisposable
{
private readonly ConcurrentDictionary<ushort, MqttPublishPacket> _pendingIncomingPublications = new ConcurrentDictionary<ushort, MqttPublishPacket>();
private readonly MqttClientSubscriptionsManager _subscriptionsManager = new MqttClientSubscriptionsManager();
private readonly MqttOutgoingPublicationsManager _outgoingPublicationsManager;
private readonly MqttClientMessageQueue _messageQueue;
private readonly Action<MqttClientSession, MqttPublishPacket> _publishPacketReceivedCallback;
private readonly MqttServerOptions _options;
@@ -24,15 +24,17 @@ namespace MQTTnet.Core.Server
private IMqttCommunicationAdapter _adapter;
private string _identifier;
private MqttApplicationMessage _willApplicationMessage;
public MqttClientSession(MqttServerOptions options, Action<MqttClientSession, MqttPublishPacket> publishPacketReceivedCallback)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_publishPacketReceivedCallback = publishPacketReceivedCallback ?? throw new ArgumentNullException(nameof(publishPacketReceivedCallback));
_outgoingPublicationsManager = new MqttOutgoingPublicationsManager(options);
_messageQueue = new MqttClientMessageQueue(options);
}
public bool IsConnected => _adapter != null;
public async Task RunAsync(string identifier, MqttApplicationMessage willApplicationMessage, IMqttCommunicationAdapter adapter)
{
if (adapter == null) throw new ArgumentNullException(nameof(adapter));
@@ -45,7 +47,7 @@ namespace MQTTnet.Core.Server
_adapter = adapter;
_cancellationTokenSource = new CancellationTokenSource();
_outgoingPublicationsManager.Start(adapter);
_messageQueue.Start(adapter);
while (!_cancellationTokenSource.IsCancellationRequested)
{
var packet = await adapter.ReceivePacketAsync(TimeSpan.Zero);
@@ -65,8 +67,8 @@ namespace MQTTnet.Core.Server
{
_publishPacketReceivedCallback(this, _willApplicationMessage.ToPublishPacket());
}
_outgoingPublicationsManager.Stop();
_messageQueue.Stop();
_cancellationTokenSource.Cancel();
_adapter = null;
@@ -74,7 +76,7 @@ namespace MQTTnet.Core.Server
}
}
public void DispatchPublishPacket(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
public void EnqueuePublishPacket(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
{
if (senderClientSession == null) throw new ArgumentNullException(nameof(senderClientSession));
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
@@ -84,66 +86,68 @@ namespace MQTTnet.Core.Server
return;
}
_outgoingPublicationsManager.Enqueue(senderClientSession, publishPacket);
_messageQueue.Enqueue(senderClientSession, publishPacket);
MqttTrace.Verbose(nameof(MqttClientSession), $"Client '{_identifier}: Enqueued pending publish packet.");
}
private async Task HandleIncomingPacketAsync(MqttBasePacket packet)
public void Dispose()
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
}
private Task HandleIncomingPacketAsync(MqttBasePacket packet)
{
var subscribePacket = packet as MqttSubscribePacket;
if (subscribePacket != null)
{
await _adapter.SendPacketAsync(_subscriptionsManager.Subscribe(subscribePacket), _options.DefaultCommunicationTimeout);
return;
return _adapter.SendPacketAsync(_subscriptionsManager.Subscribe(subscribePacket), _options.DefaultCommunicationTimeout);
}
var unsubscribePacket = packet as MqttUnsubscribePacket;
if (unsubscribePacket != null)
{
await _adapter.SendPacketAsync(_subscriptionsManager.Unsubscribe(unsubscribePacket), _options.DefaultCommunicationTimeout);
return;
return _adapter.SendPacketAsync(_subscriptionsManager.Unsubscribe(unsubscribePacket), _options.DefaultCommunicationTimeout);
}
var publishPacket = packet as MqttPublishPacket;
if (publishPacket != null)
{
await HandleIncomingPublishPacketAsync(publishPacket);
return;
return HandleIncomingPublishPacketAsync(publishPacket);
}
var pubRelPacket = packet as MqttPubRelPacket;
if (pubRelPacket != null)
{
await HandleIncomingPubRelPacketAsync(pubRelPacket);
return;
return HandleIncomingPubRelPacketAsync(pubRelPacket);
}
var pubAckPacket = packet as MqttPubAckPacket;
if (pubAckPacket != null)
{
await HandleIncomingPubAckPacketAsync(pubAckPacket);
return;
return HandleIncomingPubAckPacketAsync(pubAckPacket);
}
if (packet is MqttPingReqPacket)
{
await _adapter.SendPacketAsync(new MqttPingRespPacket(), _options.DefaultCommunicationTimeout);
return;
return _adapter.SendPacketAsync(new MqttPingRespPacket(), _options.DefaultCommunicationTimeout);
}
if (packet is MqttDisconnectPacket || packet is MqttConnectPacket)
{
_cancellationTokenSource.Cancel();
return;
return Task.FromResult((object)null);
}
MqttTrace.Warning(nameof(MqttClientSession), $"Client '{_identifier}': Received not supported packet ({packet}). Closing connection.");
_cancellationTokenSource.Cancel();
return Task.FromResult((object)null);
}
private async Task HandleIncomingPubAckPacketAsync(MqttPubAckPacket pubAckPacket)
{
await Task.FromResult(0);
await Task.FromResult((object)null);
}
private async Task HandleIncomingPublishPacketAsync(MqttPublishPacket publishPacket)
@@ -1,93 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Server
{
public class MqttClientSessionManager
{
private readonly ConcurrentDictionary<string, MqttClientSession> _clientSessions = new ConcurrentDictionary<string, MqttClientSession>();
private readonly MqttServerOptions _options;
public MqttClientSessionManager(MqttServerOptions options)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
}
public async Task RunClientSessionAsync(MqttClientConnectedEventArgs eventArgs)
{
try
{
var connectPacket = await eventArgs.ClientAdapter.ReceivePacketAsync(_options.DefaultCommunicationTimeout) as MqttConnectPacket;
if (connectPacket == null)
{
throw new MqttProtocolViolationException("The first packet from a client must be a 'Connect' packet [MQTT-3.1.0-1].");
}
var connectReturnCode = MqttConnectReturnCode.ConnectionAccepted;
if (_options.ConnectionValidator != null)
{
connectReturnCode = _options.ConnectionValidator(connectPacket);
}
MqttClientSession clientSession = null;
var isSessionPresent = _clientSessions.ContainsKey(connectPacket.ClientId);
if (isSessionPresent && connectPacket.CleanSession)
{
MqttClientSession _;
_clientSessions.TryRemove(connectPacket.ClientId, out _);
}
else if (!connectPacket.CleanSession)
{
_clientSessions.TryGetValue(connectPacket.ClientId, out clientSession);
}
await eventArgs.ClientAdapter.SendPacketAsync(new MqttConnAckPacket
{
ConnectReturnCode = connectReturnCode,
IsSessionPresent = clientSession != null
}, _options.DefaultCommunicationTimeout);
if (connectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
{
return;
}
if (clientSession == null)
{
clientSession = new MqttClientSession(_options, DispatchPublishPacket);
_clientSessions.TryAdd(connectPacket.ClientId, clientSession);
}
await clientSession.RunAsync(eventArgs.Identifier, connectPacket.WillMessage, eventArgs.ClientAdapter);
}
catch (Exception exception)
{
MqttTrace.Error(nameof(MqttServer), exception, exception.Message);
}
finally
{
await eventArgs.ClientAdapter.DisconnectAsync();
}
}
public void Clear()
{
_clientSessions.Clear();
}
private void DispatchPublishPacket(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
{
foreach (var clientSession in _clientSessions.Values.ToList())
{
clientSession.DispatchPublishPacket(senderClientSession, publishPacket);
}
}
}
}
@@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Server
{
public class MqttClientSessionsManager
{
private readonly object _syncRoot = new object();
private readonly Dictionary<string, MqttClientSession> _clientSessions = new Dictionary<string, MqttClientSession>();
private readonly MqttServerOptions _options;
public MqttClientSessionsManager(MqttServerOptions options)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
}
public async Task RunClientSessionAsync(MqttClientConnectedEventArgs eventArgs)
{
try
{
var connectPacket = await eventArgs.ClientAdapter.ReceivePacketAsync(_options.DefaultCommunicationTimeout) as MqttConnectPacket;
if (connectPacket == null)
{
throw new MqttProtocolViolationException("The first packet from a client must be a 'CONNECT' packet [MQTT-3.1.0-1].");
}
var connectReturnCode = ValidateConnection(connectPacket);
if (connectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
{
await eventArgs.ClientAdapter.SendPacketAsync(new MqttConnAckPacket
{
ConnectReturnCode = connectReturnCode
}, _options.DefaultCommunicationTimeout);
return;
}
var clientSession = GetOrCreateClientSession(connectPacket);
await eventArgs.ClientAdapter.SendPacketAsync(new MqttConnAckPacket
{
ConnectReturnCode = connectReturnCode,
IsSessionPresent = clientSession.IsExistingSession
}, _options.DefaultCommunicationTimeout);
await clientSession.Session.RunAsync(eventArgs.Identifier, connectPacket.WillMessage, eventArgs.ClientAdapter);
}
catch (Exception exception)
{
MqttTrace.Error(nameof(MqttServer), exception, exception.Message);
}
finally
{
await eventArgs.ClientAdapter.DisconnectAsync();
}
}
public void Clear()
{
lock (_syncRoot)
{
_clientSessions.Clear();
}
}
public IList<string> GetConnectedClients()
{
lock (_syncRoot)
{
return _clientSessions.Where(s => s.Value.IsConnected).Select(s => s.Key).ToList();
}
}
private MqttConnectReturnCode ValidateConnection(MqttConnectPacket connectPacket)
{
if (_options.ConnectionValidator != null)
{
return _options.ConnectionValidator(connectPacket);
}
return MqttConnectReturnCode.ConnectionAccepted;
}
private GetOrCreateClientSessionResult GetOrCreateClientSession(MqttConnectPacket connectPacket)
{
lock (_syncRoot)
{
MqttClientSession clientSession;
var isSessionPresent = _clientSessions.TryGetValue(connectPacket.ClientId, out clientSession);
if (isSessionPresent)
{
if (connectPacket.CleanSession)
{
_clientSessions.Remove(connectPacket.ClientId);
clientSession.Dispose();
clientSession = null;
MqttTrace.Verbose(nameof(MqttClientSessionsManager), $"Disposed existing session of client '{connectPacket.ClientId}'.");
}
else
{
MqttTrace.Verbose(nameof(MqttClientSessionsManager), $"Reusing existing session of client '{connectPacket.ClientId}'.");
}
}
var isExistingSession = true;
if (clientSession == null)
{
isExistingSession = false;
clientSession = new MqttClientSession(_options, DispatchPublishPacket);
_clientSessions[connectPacket.ClientId] = clientSession;
MqttTrace.Verbose(nameof(MqttClientSessionsManager), $"Created a new session for client '{connectPacket.ClientId}'.");
}
return new GetOrCreateClientSessionResult { IsExistingSession = isExistingSession, Session = clientSession };
}
}
private void DispatchPublishPacket(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
{
foreach (var clientSession in _clientSessions.Values.ToList())
{
clientSession.EnqueuePublishPacket(senderClientSession, publishPacket);
}
}
}
}
+17 -9
View File
@@ -1,15 +1,15 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Internal;
namespace MQTTnet.Core.Server
{
public class MqttServer
{
private readonly MqttClientSessionManager _clientSessionManager;
private readonly MqttClientSessionsManager _clientSessionsManager;
private readonly IMqttServerAdapter _adapter;
private readonly MqttServerOptions _options;
@@ -20,22 +20,28 @@ namespace MQTTnet.Core.Server
_options = options ?? throw new ArgumentNullException(nameof(options));
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
_clientSessionManager = new MqttClientSessionManager(options);
_clientSessionsManager = new MqttClientSessionsManager(options);
}
public IList<string> GetConnectedClients()
{
return _clientSessionsManager.GetConnectedClients();
}
public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
public void InjectClient(string identifier, IMqttCommunicationAdapter adapter)
{
if (adapter == null) throw new ArgumentNullException(nameof(adapter));
if (_cancellationTokenSource == null) throw new InvalidOperationException("The MQTT server is not started.");
OnClientConnected(this, new MqttClientConnectedEventArgs(identifier, adapter));
}
public void Start()
{
if (_cancellationTokenSource != null)
{
throw new InvalidOperationException("The server is already started.");
}
if (_cancellationTokenSource != null) throw new InvalidOperationException("The MQTT server is already started.");
_cancellationTokenSource = new CancellationTokenSource();
@@ -53,7 +59,7 @@ namespace MQTTnet.Core.Server
_adapter.ClientConnected -= OnClientConnected;
_adapter.Stop();
_clientSessionManager.Clear();
_clientSessionsManager.Clear();
MqttTrace.Information(nameof(MqttServer), "Stopped.");
}
@@ -61,7 +67,9 @@ namespace MQTTnet.Core.Server
private void OnClientConnected(object sender, MqttClientConnectedEventArgs eventArgs)
{
MqttTrace.Information(nameof(MqttServer), $"Client '{eventArgs.Identifier}': Connected.");
Task.Run(async () => await _clientSessionManager.RunClientSessionAsync(eventArgs), _cancellationTokenSource.Token).Forget();
ClientConnected?.Invoke(this, eventArgs);
Task.Run(() => _clientSessionsManager.RunClientSessionAsync(eventArgs), _cancellationTokenSource.Token);
}
}
}
+55
View File
@@ -0,0 +1,55 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>MQTTnet</id>
<version>2.1.2.0</version>
<authors>Christian Kratky</authors>
<owners>Christian Kratky</owners>
<licenseUrl>https://github.com/chkr1011/MQTTnet/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl>
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description>
<releaseNotes>* [Server] Added support for complex client IDs.
* [Server] Fixed an issue with not correctly removed old client sessions.
* [Server] Several minor performance improvements.
* [Server] An existing client session is no longer closed if a new client connection is invalid.
* [Client] Added support for sending "CleanSession" flag.</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2017</copyright>
<tags>MQTT MQTTClient MQTTServer MQTTBroker Broker</tags>
</metadata>
<files>
<!-- Universal Windows -->
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\Release\MQTTnet.Core.dll" target="lib\uap10.0"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\Release\MQTTnet.dll" target="lib\uap10.0"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\Release\MQTTnet.pri" target="lib\uap10.0"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\ARM\Release\MQTTnet.Core.dll" target="lib\uap10.0-arm"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\ARM\Release\MQTTnet.dll" target="lib\uap10.0-arm"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\ARM\Release\MQTTnet.pri" target="lib\uap10.0-arm"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x64\Release\MQTTnet.Core.dll" target="lib\uap10.0-x64"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x64\Release\MQTTnet.dll" target="lib\uap10.0-x64"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x64\Release\MQTTnet.pri" target="lib\uap10.0-x64"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x86\Release\MQTTnet.Core.dll" target="lib\uap10.0-x86"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x86\Release\MQTTnet.dll" target="lib\uap10.0-x86"/>
<file src=".\Frameworks\MQTTnet.UniversalWindows\bin\x86\Release\MQTTnet.pri" target="lib\uap10.0-x86"/>
<!-- .NET Framework -->
<file src=".\Frameworks\MQTTnet.NetFramework\bin\Release\MQTTnet.Core.dll" target="lib\net45"/>
<file src=".\Frameworks\MQTTnet.NetFramework\bin\Release\MQTTnet.dll" target="lib\net45"/>
<file src=".\Frameworks\MQTTnet.NetFramework\bin\x86\Release\MQTTnet.Core.dll" target="lib\net45-x86"/>
<file src=".\Frameworks\MQTTnet.NetFramework\bin\x86\Release\MQTTnet.dll" target="lib\net45-x86"/>
<file src=".\Frameworks\MQTTnet.NetFramework\bin\x86\Release\MQTTnet.Core.dll" target="lib\net45-x64"/>
<file src=".\Frameworks\MQTTnet.NetFramework\bin\x86\Release\MQTTnet.dll" target="lib\net45-x64"/>
<!-- .NET Core App -->
<file src=".\Frameworks\MQTTnet.NetCoreApp\bin\Release\netcoreapp1.1\MQTTnet.Core.dll" target="lib\netcoreapp1.1"/>
<file src=".\Frameworks\MQTTnet.NetCoreApp\bin\Release\netcoreapp1.1\MQTTnet.dll" target="lib\netcoreapp1.1"/>
</files>
</package>
+135 -70
View File
@@ -1,10 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
VisualStudioVersion = 15.0.26228.9
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core", "MQTTnet.Core\MQTTnet.Core.csproj", "{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestMqttClient", "Tests\MQTTnet.TestMqttClient\MQTTnet.TestMqttClient.csproj", "{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Core.Tests.csproj", "{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}"
@@ -15,14 +13,25 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.UniversalWindows",
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9248C2E1-B9D6-40BF-81EC-86004D7765B4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.NetCore", "Frameworks\MQTTnet.NetCore\MQTTnet.NetCore.csproj", "{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frameworks", "Frameworks", "{32A630A7-2598-41D7-B625-204CD906F5FB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestMqttServer", "Tests\MQTTnet.TestMqttServer\MQTTnet.TestMqttServer.csproj", "{6F8C0C0C-59EC-4921-9267-370AE113C34F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core", "MQTTnet.Core\MQTTnet.Core.csproj", "{2ECB99E4-72D0-4C23-99BA-93D511D3967D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{002203AF-2565-4C0D-95ED-027FDEFE0C35}"
ProjectSection(SolutionItems) = preProject
MQTTnet.nuspec = MQTTnet.nuspec
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.NetCoreApp", "Frameworks\MQTTnet.NetCoreApp\MQTTnet.NetCoreApp.csproj", "{1A1B7F51-5328-4395-9D9C-07D70965825E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Any CPU|Any CPU = Any CPU|Any CPU
Any CPU|ARM = Any CPU|ARM
Any CPU|x64 = Any CPU|x64
Any CPU|x86 = Any CPU|x86
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
@@ -33,70 +42,86 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Debug|ARM.ActiveCfg = Debug|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Debug|ARM.Build.0 = Debug|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Debug|x64.ActiveCfg = Debug|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Debug|x64.Build.0 = Debug|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Debug|x86.ActiveCfg = Debug|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Debug|x86.Build.0 = Debug|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Release|Any CPU.Build.0 = Release|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Release|ARM.ActiveCfg = Release|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Release|ARM.Build.0 = Release|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Release|x64.ActiveCfg = Release|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Release|x64.Build.0 = Release|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Release|x86.ActiveCfg = Release|Any CPU
{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}.Release|x86.Build.0 = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x64.ActiveCfg = Any CPU|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x64.Build.0 = Any CPU|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x86.ActiveCfg = Any CPU|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x86.Build.0 = Any CPU|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|ARM.Build.0 = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x64.ActiveCfg = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x64.Build.0 = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x86.ActiveCfg = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x86.Build.0 = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x64.ActiveCfg = Debug|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x64.Build.0 = Debug|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x86.ActiveCfg = Debug|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x86.Build.0 = Debug|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|Any CPU.Build.0 = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|ARM.ActiveCfg = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|ARM.Build.0 = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x64.ActiveCfg = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x64.Build.0 = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x86.ActiveCfg = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x86.Build.0 = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x64.ActiveCfg = Release|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x64.Build.0 = Release|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x86.ActiveCfg = Release|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x86.Build.0 = Release|x86
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|x64.ActiveCfg = Any CPU|x64
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|x64.Build.0 = Any CPU|x64
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|x86.ActiveCfg = Any CPU|x86
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|x86.Build.0 = Any CPU|x86
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|ARM.ActiveCfg = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|ARM.Build.0 = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.ActiveCfg = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.Build.0 = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.ActiveCfg = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.Build.0 = Debug|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.ActiveCfg = Debug|x64
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x64.Build.0 = Debug|x64
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.ActiveCfg = Debug|x86
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Debug|x86.Build.0 = Debug|x86
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|Any CPU.Build.0 = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|ARM.ActiveCfg = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|ARM.Build.0 = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.ActiveCfg = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.Build.0 = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.ActiveCfg = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.Build.0 = Release|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.ActiveCfg = Release|x64
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x64.Build.0 = Release|x64
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.ActiveCfg = Release|x86
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Release|x86.Build.0 = Release|x86
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|x64.ActiveCfg = Any CPU|x64
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|x64.Build.0 = Any CPU|x64
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|x86.ActiveCfg = Any CPU|x86
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Any CPU|x86.Build.0 = Any CPU|x86
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|ARM.ActiveCfg = Debug|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|ARM.Build.0 = Debug|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x64.ActiveCfg = Debug|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x64.Build.0 = Debug|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x86.ActiveCfg = Debug|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x86.Build.0 = Debug|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x64.ActiveCfg = Debug|x64
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x64.Build.0 = Debug|x64
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x86.ActiveCfg = Debug|x86
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Debug|x86.Build.0 = Debug|x86
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|Any CPU.Build.0 = Release|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|ARM.ActiveCfg = Release|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|ARM.Build.0 = Release|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x64.ActiveCfg = Release|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x64.Build.0 = Release|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x86.ActiveCfg = Release|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x86.Build.0 = Release|Any CPU
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x64.ActiveCfg = Release|x64
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x64.Build.0 = Release|x64
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x86.ActiveCfg = Release|x86
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}.Release|x86.Build.0 = Release|x86
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|ARM.ActiveCfg = Any CPU|ARM
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|ARM.Build.0 = Any CPU|ARM
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|x64.ActiveCfg = Any CPU|x64
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|x64.Build.0 = Any CPU|x64
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|x86.ActiveCfg = Any CPU|x86
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Any CPU|x86.Build.0 = Any CPU|x86
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Debug|ARM.ActiveCfg = Debug|ARM
@@ -113,38 +138,78 @@ Global
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x64.Build.0 = Release|x64
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x86.ActiveCfg = Release|x86
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x86.Build.0 = Release|x86
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Debug|ARM.ActiveCfg = Debug|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Debug|ARM.Build.0 = Debug|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Debug|x64.ActiveCfg = Debug|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Debug|x64.Build.0 = Debug|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Debug|x86.ActiveCfg = Debug|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Debug|x86.Build.0 = Debug|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Release|Any CPU.Build.0 = Release|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Release|ARM.ActiveCfg = Release|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Release|ARM.Build.0 = Release|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Release|x64.ActiveCfg = Release|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Release|x64.Build.0 = Release|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Release|x86.ActiveCfg = Release|Any CPU
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C}.Release|x86.Build.0 = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x64.ActiveCfg = Any CPU|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x64.Build.0 = Any CPU|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x86.ActiveCfg = Any CPU|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x86.Build.0 = Any CPU|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|ARM.ActiveCfg = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|ARM.Build.0 = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x64.ActiveCfg = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x64.Build.0 = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x86.ActiveCfg = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x86.Build.0 = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x64.ActiveCfg = Debug|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x64.Build.0 = Debug|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x86.ActiveCfg = Debug|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x86.Build.0 = Debug|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|Any CPU.Build.0 = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|ARM.ActiveCfg = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|ARM.Build.0 = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x64.ActiveCfg = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x64.Build.0 = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x86.ActiveCfg = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x86.Build.0 = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x64.ActiveCfg = Release|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x64.Build.0 = Release|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x86.ActiveCfg = Release|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x86.Build.0 = Release|x86
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|x64.ActiveCfg = Any CPU|x64
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|x64.Build.0 = Any CPU|x64
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|x86.ActiveCfg = Any CPU|x86
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|x86.Build.0 = Any CPU|x86
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|ARM.ActiveCfg = Debug|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|ARM.Build.0 = Debug|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|x64.ActiveCfg = Debug|x64
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|x64.Build.0 = Debug|x64
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|x86.ActiveCfg = Debug|x86
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Debug|x86.Build.0 = Debug|x86
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|Any CPU.Build.0 = Release|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|ARM.ActiveCfg = Release|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|ARM.Build.0 = Release|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|x64.ActiveCfg = Release|x64
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|x64.Build.0 = Release|x64
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|x86.ActiveCfg = Release|x86
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Release|x86.Build.0 = Release|x86
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|x64.ActiveCfg = Any CPU|x64
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|x64.Build.0 = Any CPU|x64
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|x86.ActiveCfg = Any CPU|x86
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Any CPU|x86.Build.0 = Any CPU|x86
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|ARM.Build.0 = Debug|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|x64.ActiveCfg = Debug|x64
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|x64.Build.0 = Debug|x64
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|x86.ActiveCfg = Debug|x86
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Debug|x86.Build.0 = Debug|x86
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|Any CPU.Build.0 = Release|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|ARM.ActiveCfg = Release|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|ARM.Build.0 = Release|Any CPU
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x64.ActiveCfg = Release|x64
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x64.Build.0 = Release|x64
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x86.ActiveCfg = Release|x86
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -154,7 +219,7 @@ Global
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{BD60C727-D8E8-40C3-B8E3-C95A864AE611} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{88BE3FC9-79DC-4440-AC6B-C21BD97C6A3C} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{6F8C0C0C-59EC-4921-9267-370AE113C34F} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{1A1B7F51-5328-4395-9D9C-07D70965825E} = {32A630A7-2598-41D7-B625-204CD906F5FB}
EndGlobalSection
EndGlobal
+16 -4
View File
@@ -3,13 +3,25 @@
</p>
# MQTTnet
MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server.
MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server. The implementation is based on the documentation from http://mqtt.org/.
## Supported frameworks
* .NET Framework 4.5.2+
* .NET Core 1.0+
* Universal Windows (UWP) 10.0.10240+
* .NET Standard 1.1+
* .NET Core 1.1+
* .NET Core App 1.1+
* .NET Framework 4.5.2+ (x86, x64, AnyCPU)
* Universal Windows (UWP) 10.0.10240+ (x86, x64, ARM, AnyCPU)
## Supported MQTT versions
* 3.1.1
## Nuget
This library is available as a nuget package: https://www.nuget.org/packages/MQTTnet/
## Contributions
If you want to contribute to this project just create a pull request.
# MqttClient
## Example
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MQTTnet.Core.Tests</RootNamespace>
<AssemblyName>MQTTnet.Core.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -30,6 +30,54 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|AnyCPU'">
<OutputPath>bin\Any CPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x64'">
<OutputPath>bin\x64\Any CPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Any CPU\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="System" />
@@ -42,6 +90,7 @@
<Compile Include="MqttServerTests.cs" />
<Compile Include="MqttSubscriptionsManagerTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestMqttCommunicationAdapter.cs" />
<Compile Include="TestMqttServerAdapter.cs" />
<Compile Include="TopicFilterComparerTests.cs" />
</ItemGroup>
@@ -50,7 +99,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
<Project>{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}</Project>
<Project>{2ecb99e4-72d0-4c23-99ba-93d511d3967d}</Project>
<Name>MQTTnet.Core</Name>
</ProjectReference>
</ItemGroup>
+3 -53
View File
@@ -1,8 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Client;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
@@ -71,8 +68,8 @@ namespace MQTTnet.Core.Tests
private MqttClient ConnectTestClient(string clientId, MqttApplicationMessage willMessage, MqttServer server)
{
var adapterA = new TestMqttClientAdapter();
var adapterB = new TestMqttClientAdapter();
var adapterA = new TestMqttCommunicationAdapter();
var adapterB = new TestMqttCommunicationAdapter();
adapterA.Partner = adapterB;
adapterB.Partner = adapterA;
@@ -111,51 +108,4 @@ namespace MQTTnet.Core.Tests
Assert.AreEqual(expectedReceivedMessagesCount, receivedMessagesCount);
}
}
public class TestMqttClientAdapter : IMqttCommunicationAdapter
{
private readonly BlockingCollection<MqttBasePacket> _incomingPackets = new BlockingCollection<MqttBasePacket>();
public TestMqttClientAdapter Partner { get; set; }
public async Task ConnectAsync(MqttClientOptions options, TimeSpan timeout)
{
await Task.FromResult(0);
}
public async Task DisconnectAsync()
{
await Task.FromResult(0);
}
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout)
{
ThrowIfPartnerIsNull();
Partner.SendPacketInternal(packet);
await Task.FromResult(0);
}
public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout)
{
ThrowIfPartnerIsNull();
return await Task.Run(() => _incomingPackets.Take());
}
private void SendPacketInternal(MqttBasePacket packet)
{
if (packet == null) throw new ArgumentNullException(nameof(packet));
_incomingPackets.Add(packet);
}
private void ThrowIfPartnerIsNull()
{
if (Partner == null)
{
throw new InvalidOperationException("Partner is not set.");
}
}
}
}
@@ -11,5 +11,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("a7ff0c91-25de-4ba6-b39e-f54e8dadf1cc")]
[assembly: AssemblyVersion("2.1.0.4")]
[assembly: AssemblyFileVersion("2.1.0.4")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,56 @@
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Client;
using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Tests
{
public class TestMqttCommunicationAdapter : IMqttCommunicationAdapter
{
private readonly BlockingCollection<MqttBasePacket> _incomingPackets = new BlockingCollection<MqttBasePacket>();
public TestMqttCommunicationAdapter Partner { get; set; }
public async Task ConnectAsync(MqttClientOptions options, TimeSpan timeout)
{
await Task.FromResult(0);
}
public async Task DisconnectAsync()
{
await Task.FromResult(0);
}
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout)
{
ThrowIfPartnerIsNull();
Partner.SendPacketInternal(packet);
await Task.FromResult(0);
}
public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout)
{
ThrowIfPartnerIsNull();
return await Task.Run(() => _incomingPackets.Take());
}
private void SendPacketInternal(MqttBasePacket packet)
{
if (packet == null) throw new ArgumentNullException(nameof(packet));
_incomingPackets.Add(packet);
}
private void ThrowIfPartnerIsNull()
{
if (Partner == null)
{
throw new InvalidOperationException("Partner is not set.");
}
}
}
}
@@ -35,6 +35,39 @@
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|AnyCPU'">
<OutputPath>bin\Any CPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Any CPU\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Any CPU\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -47,14 +80,14 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
<Project>{99c884f3-b4b9-417d-aa92-dc7dd1c4cfee}</Project>
<Name>MQTTnet.Core</Name>
</ProjectReference>
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetFramework\MQTTnet.NetFramework.csproj">
<Project>{a480ef90-0eaa-4d9a-b271-47a9c47f6f7d}</Project>
<Name>MQTTnet.NetFramework</Name>
</ProjectReference>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
<Project>{2ecb99e4-72d0-4c23-99ba-93d511d3967d}</Project>
<Name>MQTTnet.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+3 -1
View File
@@ -33,7 +33,9 @@ namespace MQTTnet.TestMqttClient
{
var options = new MqttClientOptions
{
Server = "localhost"
Server = "localhost",
ClientId = "XYZ",
CleanSession = true
};
var client = new MqttClientFactory().CreateMqttClient(options);
@@ -31,6 +31,40 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|AnyCPU'">
<OutputPath>bin\Any CPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Any CPU\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Any CPU\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -43,14 +77,14 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
<Project>{99C884F3-B4B9-417D-AA92-DC7DD1C4CFEE}</Project>
<Name>MQTTnet.Core</Name>
</ProjectReference>
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetFramework\MQTTnet.NetFramework.csproj">
<Project>{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}</Project>
<Name>MQTTnet.NetFramework</Name>
</ProjectReference>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
<Project>{2ecb99e4-72d0-4c23-99ba-93d511d3967d}</Project>
<Name>MQTTnet.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>