This commit is contained in:
josesimoes 2022-03-14 16:24:03 +00:00
Родитель 1e04b0f6b6 67ebe259b9
Коммит 3cf6a8dffe
51 изменённых файлов: 2628 добавлений и 866 удалений

Просмотреть файл

@ -29,18 +29,27 @@
<Reference Include="mscorlib, Version=1.10.5.4, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.CoreLibrary.1.10.5\lib\mscorlib.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.Runtime.Events, Version=1.9.1.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.Runtime.Events.1.9.1\lib\nanoFramework.Runtime.Events.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.System.Collections, Version=1.2.0.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Collections.1.2.0\lib\nanoFramework.System.Collections.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.System.Text, Version=1.1.1.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Text.1.1.1\lib\nanoFramework.System.Text.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Math, Version=1.4.1.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Math.1.4.1-preview.5\lib\System.Math.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Math, Version=1.4.1.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Math.1.4.1\lib\System.Math.dll</HintPath>
@ -49,6 +58,7 @@
<Reference Include="System.Net, Version=1.7.0.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Net.1.7.0\lib\System.Net.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -6,4 +6,4 @@
<package id="nanoFramework.System.Math" version="1.4.1" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Net" version="1.7.0" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Text" version="1.1.1" targetFramework="netnanoframework10" />
</packages>
</packages>

Просмотреть файл

@ -29,22 +29,32 @@
<Reference Include="mscorlib, Version=1.10.5.4, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.CoreLibrary.1.10.5\lib\mscorlib.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.Runtime.Events, Version=1.9.1.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.Runtime.Events.1.9.1\lib\nanoFramework.Runtime.Events.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.System.Collections, Version=1.2.0.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Collections.1.2.0\lib\nanoFramework.System.Collections.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.System.Text, Version=1.1.1.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Text.1.1.1\lib\nanoFramework.System.Text.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Device.Gpio, Version=1.0.1.2, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Device.Gpio.1.0.1\lib\System.Device.Gpio.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Math, Version=1.4.1.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Math.1.4.1-preview.5\lib\System.Math.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Math, Version=1.4.1.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Math.1.4.1\lib\System.Math.dll</HintPath>
@ -53,6 +63,7 @@
<Reference Include="System.Net, Version=1.7.0.3, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\..\..\packages\nanoFramework.System.Net.1.7.0\lib\System.Net.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
</ItemGroup>
<ItemGroup>

740
amqp-vs2015.sln Normal file
Просмотреть файл

@ -0,0 +1,740 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.Net", "test\Test.Amqp.Net\Test.Amqp.Net.csproj", "{06CAA70A-20A7-4334-AF03-D6228039C178}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{679989B2-8717-4ECC-9CAD-B104CFA91C38}"
ProjectSection(SolutionItems) = preProject
src\amqp.snk = src\amqp.snk
nuspec\AMQPNetLite.Core.nuspec = nuspec\AMQPNetLite.Core.nuspec
nuspec\AMQPNetLite.NetMF.nuspec = nuspec\AMQPNetLite.NetMF.nuspec
nuspec\AMQPNetLite.nuspec = nuspec\AMQPNetLite.nuspec
nuspec\AMQPNetLite.Serialization.nuspec = nuspec\AMQPNetLite.Serialization.nuspec
nuspec\AMQPNetLite.WebSockets.nuspec = nuspec\AMQPNetLite.WebSockets.nuspec
nuspec\AMQPNetMicro.nuspec = nuspec\AMQPNetMicro.nuspec
appveyor.yml = appveyor.yml
build.cmd = build.cmd
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{8F701234-EC60-485C-BCDB-8EE233246832}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Drain", "Examples\Interop\Interop.Drain\Interop.Drain.csproj", "{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Spout", "Examples\Interop\Interop.Spout\Interop.Spout.csproj", "{68470436-2F0D-4A76-B1E6-9C8517844C3E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Server", "Examples\Interop\Interop.Server\Interop.Server.csproj", "{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Client", "Examples\Interop\Interop.Client\Interop.Client.csproj", "{C272B10E-36BE-4F36-A128-331F715514E6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServiceBus", "ServiceBus", "{4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceBus.Cbs", "Examples\ServiceBus\ServiceBus.Cbs\ServiceBus.Cbs.csproj", "{4681C268-36DB-4838-BD21-9EC9A8363269}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PeerToPeer", "PeerToPeer", "{7FF80B2D-4158-41D3-BC87-60C018028F53}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.Server", "Examples\PeerToPeer\PeerToPeer.Server\PeerToPeer.Server.csproj", "{24C152B0-3813-43C6-82DD-8BB601642F6C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.Client", "Examples\PeerToPeer\PeerToPeer.Client\PeerToPeer.Client.csproj", "{8FC90E46-024B-4089-9590-A7E8C2B092BE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Device", "Device", "{BF554E12-7096-465F-B1D0-9ACFF00877F2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device.Thermometer", "Examples\Device\Device.Thermometer\Device.Thermometer.csproj", "{43570F0D-DE6C-423E-A275-AC619A813B79}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceBus.EventHub", "Examples\ServiceBus\ServiceBus.EventHub\ServiceBus.EventHub.csproj", "{36F33391-4918-4C6D-9CAE-1ECD32262257}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerfTest", "test\PerfTest\PerfTest.csproj", "{B23AC1B1-1551-41F3-8763-E68A53B172BB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device.Controller2", "Examples\Device\Device.Controller2\Device.Controller2.csproj", "{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.Certificate", "Examples\PeerToPeer\PeerToPeer.Certificate\PeerToPeer.Certificate.csproj", "{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceBus.MessageSession", "Examples\ServiceBus\ServiceBus.MessageSession\ServiceBus.MessageSession.csproj", "{D1E69C74-4A33-4079-9665-8818A8479FFB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Listener", "Listener", "{89F13102-4826-4406-844B-7B21C47885E7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Listener.ContainerHost", "Examples\Listener\Listener.ContainerHost\Listener.ContainerHost.csproj", "{E8D670D3-B1B4-45CA-9440-9630529599B2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Listener.IContainer", "Examples\Listener\Listener.IContainer\Listener.IContainer.csproj", "{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestAmqpBroker", "test\TestAmqpBroker\TestAmqpBroker.csproj", "{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.CustomType", "Examples\PeerToPeer\PeerToPeer.CustomType\PeerToPeer.CustomType.csproj", "{30536F8F-E4DA-46B3-B0D0-082632AD74B4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceBus.EventHub.NetMF", "Examples\ServiceBus\ServiceBus.EventHub.NetMF\ServiceBus.EventHub.NetMF.csproj", "{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.Receiver", "Examples\PeerToPeer\PeerToPeer.Receiver\PeerToPeer.Receiver.csproj", "{E5D42E35-B5C4-426D-B568-96926EBA588E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.NetCore", "test\Test.Amqp.NetCore\Test.Amqp.NetCore.csproj", "{6BCA313F-794F-4C54-9F96-C500290E147C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Device.SmallMemory", "Examples\Device\Device.SmallMemory\Device.SmallMemory.csproj", "{69E4A20C-EF50-49C6-8DAC-F76B9D565767}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docfx", "docfx", "{EB7EBF85-48AB-4EA0-9F00-825364BFA6FD}"
ProjectSection(SolutionItems) = preProject
docs\docfx.json = docs\docfx.json
docs\index.md = docs\index.md
docs\toc.yml = docs\toc.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "articles", "articles", "{5637969B-A822-425A-A831-F70AA2275777}"
ProjectSection(SolutionItems) = preProject
docs\articles\azure_eventhubs.md = docs\articles\azure_eventhubs.md
docs\articles\buffer_management.md = docs\articles\buffer_management.md
docs\articles\building_application.md = docs\articles\building_application.md
docs\articles\contributing.md = docs\articles\contributing.md
docs\articles\device_to_iothub.md = docs\articles\device_to_iothub.md
docs\articles\fault_tolerance.md = docs\articles\fault_tolerance.md
docs\articles\hello_amqp.md = docs\articles\hello_amqp.md
docs\articles\installation.md = docs\articles\installation.md
docs\articles\listener.md = docs\articles\listener.md
docs\articles\serialization.md = docs\articles\serialization.md
docs\articles\service_to_iothub.md = docs\articles\service_to_iothub.md
docs\articles\test_amqp_broker.md = docs\articles\test_amqp_broker.md
docs\articles\toc.yml = docs\articles\toc.yml
docs\articles\tracing.md = docs\articles\tracing.md
docs\articles\versioning.md = docs\articles\versioning.md
docs\articles\working_with_code.md = docs\articles\working_with_code.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceBus.Topic", "Examples\ServiceBus\ServiceBus.Topic\ServiceBus.Topic.csproj", "{D454DB5E-820F-4A92-B31E-A41A9D20B086}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.Net35", "test\Test.Amqp.Net35\Test.Amqp.Net35.csproj", "{7852029D-235C-40B7-8957-8E78414C3F97}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeerToPeer.CustomTransport", "Examples\PeerToPeer\PeerToPeer.CustomTransport\PeerToPeer.CustomTransport.csproj", "{4573C570-520F-4F49-90B4-03D4532C2BA2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{3A334EFA-47FA-4CE2-9306-FDFF7CF47157}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LongHaulTest", "test\LongHaulTest\LongHaulTest.csproj", "{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.Net40", "test\Test.Amqp.Net40\Test.Amqp.Net40.csproj", "{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceBus.WebSockets", "Examples\ServiceBus\ServiceBus.WebSockets\ServiceBus.WebSockets.csproj", "{F0A0D04C-6665-43C2-A3A3-870248A331B9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Reconnect", "Reconnect", "{B61E3B51-78CB-4047-8078-0B987E5E9742}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReconnectSender", "Examples\Reconnect\ReconnectSender\ReconnectSender.csproj", "{EDD03052-3A73-4D9E-9B94-6844134BABFB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Serialization", "Serialization", "{3C94DB48-3DDB-429C-8033-87F560607AA6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization.Poco", "Examples\Serialization\Serialization.Poco\Serialization.Poco.csproj", "{629621F7-4D91-4F49-B373-FDFE6BB573D4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "netmf", "netmf", "{E0C378B0-4AF7-4C1F-A068-81A23FF8894E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Micro.NetMF", "netmf\Amqp.Micro.NetMF.csproj", "{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetMF42", "netmf\Amqp.NetMF42.csproj", "{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetMF43", "netmf\Amqp.NetMF43.csproj", "{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetMF44", "netmf\Amqp.NetMF44.csproj", "{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Amqp.NetMF", "netmf\Test.Amqp.NetMF.csproj", "{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Net", "csproj\Amqp.Net.csproj", "{92153715-1D99-43B1-B291-470CF91A156D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Net35", "csproj\Amqp.Net35.csproj", "{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Net40", "csproj\Amqp.Net40.csproj", "{4A250B81-35E9-4D2F-8030-62909F6C8C63}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.NetCore", "csproj\Amqp.NetCore.csproj", "{35F64888-3446-444D-8E44-128378434AB3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Uwp", "csproj\Amqp.Uwp.csproj", "{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|ARM.ActiveCfg = Debug|Any CPU
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|x64.ActiveCfg = Debug|Any CPU
{06CAA70A-20A7-4334-AF03-D6228039C178}.Debug|x86.ActiveCfg = Debug|Any CPU
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|Any CPU.Build.0 = Release|Any CPU
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|ARM.ActiveCfg = Release|Any CPU
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|x64.ActiveCfg = Release|Any CPU
{06CAA70A-20A7-4334-AF03-D6228039C178}.Release|x86.ActiveCfg = Release|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|ARM.ActiveCfg = Debug|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|x64.ActiveCfg = Debug|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Debug|x86.ActiveCfg = Debug|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|Any CPU.Build.0 = Release|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|ARM.ActiveCfg = Release|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|x64.ActiveCfg = Release|Any CPU
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7}.Release|x86.ActiveCfg = Release|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|x64.ActiveCfg = Debug|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Debug|x86.ActiveCfg = Debug|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|Any CPU.Build.0 = Release|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|ARM.ActiveCfg = Release|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|x64.ActiveCfg = Release|Any CPU
{68470436-2F0D-4A76-B1E6-9C8517844C3E}.Release|x86.ActiveCfg = Release|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|x64.ActiveCfg = Debug|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Debug|x86.ActiveCfg = Debug|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|Any CPU.Build.0 = Release|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|ARM.ActiveCfg = Release|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|x64.ActiveCfg = Release|Any CPU
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2}.Release|x86.ActiveCfg = Release|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|x64.ActiveCfg = Debug|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Debug|x86.ActiveCfg = Debug|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|Any CPU.Build.0 = Release|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|ARM.ActiveCfg = Release|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|x64.ActiveCfg = Release|Any CPU
{C272B10E-36BE-4F36-A128-331F715514E6}.Release|x86.ActiveCfg = Release|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|ARM.ActiveCfg = Debug|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|x64.ActiveCfg = Debug|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Debug|x86.ActiveCfg = Debug|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|Any CPU.Build.0 = Release|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|ARM.ActiveCfg = Release|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|x64.ActiveCfg = Release|Any CPU
{4681C268-36DB-4838-BD21-9EC9A8363269}.Release|x86.ActiveCfg = Release|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|ARM.ActiveCfg = Debug|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|x64.ActiveCfg = Debug|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Debug|x86.ActiveCfg = Debug|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|Any CPU.Build.0 = Release|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|ARM.ActiveCfg = Release|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|x64.ActiveCfg = Release|Any CPU
{24C152B0-3813-43C6-82DD-8BB601642F6C}.Release|x86.ActiveCfg = Release|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|ARM.ActiveCfg = Debug|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|x64.ActiveCfg = Debug|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Debug|x86.ActiveCfg = Debug|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|Any CPU.Build.0 = Release|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|ARM.ActiveCfg = Release|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|x64.ActiveCfg = Release|Any CPU
{8FC90E46-024B-4089-9590-A7E8C2B092BE}.Release|x86.ActiveCfg = Release|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|Any CPU.Build.0 = Debug|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|ARM.ActiveCfg = Debug|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|x64.ActiveCfg = Debug|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Debug|x86.ActiveCfg = Debug|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|Any CPU.ActiveCfg = Release|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|Any CPU.Build.0 = Release|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|Any CPU.Deploy.0 = Release|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|ARM.ActiveCfg = Release|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|x64.ActiveCfg = Release|Any CPU
{43570F0D-DE6C-423E-A275-AC619A813B79}.Release|x86.ActiveCfg = Release|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Debug|Any CPU.Build.0 = Debug|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Debug|ARM.ActiveCfg = Debug|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Debug|x64.ActiveCfg = Debug|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Debug|x86.ActiveCfg = Debug|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Release|Any CPU.ActiveCfg = Release|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Release|Any CPU.Build.0 = Release|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Release|ARM.ActiveCfg = Release|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Release|x64.ActiveCfg = Release|Any CPU
{36F33391-4918-4C6D-9CAE-1ECD32262257}.Release|x86.ActiveCfg = Release|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Debug|ARM.ActiveCfg = Debug|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Debug|x64.ActiveCfg = Debug|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Debug|x86.ActiveCfg = Debug|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Release|Any CPU.Build.0 = Release|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Release|ARM.ActiveCfg = Release|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Release|x64.ActiveCfg = Release|Any CPU
{B23AC1B1-1551-41F3-8763-E68A53B172BB}.Release|x86.ActiveCfg = Release|Any CPU
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|ARM.ActiveCfg = Debug|ARM
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|ARM.Build.0 = Debug|ARM
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|ARM.Deploy.0 = Debug|ARM
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|x64.ActiveCfg = Debug|Any CPU
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|x86.ActiveCfg = Debug|x86
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|x86.Build.0 = Debug|x86
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Debug|x86.Deploy.0 = Debug|x86
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|Any CPU.Build.0 = Release|Any CPU
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|Any CPU.Deploy.0 = Release|Any CPU
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|ARM.ActiveCfg = Release|ARM
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|ARM.Build.0 = Release|ARM
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|ARM.Deploy.0 = Release|ARM
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|x64.ActiveCfg = Release|Any CPU
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|x86.ActiveCfg = Release|x86
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|x86.Build.0 = Release|x86
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C}.Release|x86.Deploy.0 = Release|x86
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Debug|ARM.ActiveCfg = Debug|Any CPU
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Debug|x64.ActiveCfg = Debug|Any CPU
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Debug|x86.ActiveCfg = Debug|Any CPU
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Release|Any CPU.Build.0 = Release|Any CPU
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Release|ARM.ActiveCfg = Release|Any CPU
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Release|x64.ActiveCfg = Release|Any CPU
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE}.Release|x86.ActiveCfg = Release|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Debug|ARM.ActiveCfg = Debug|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Debug|x64.ActiveCfg = Debug|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Debug|x86.ActiveCfg = Debug|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Release|Any CPU.Build.0 = Release|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Release|ARM.ActiveCfg = Release|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Release|x64.ActiveCfg = Release|Any CPU
{D1E69C74-4A33-4079-9665-8818A8479FFB}.Release|x86.ActiveCfg = Release|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Debug|ARM.ActiveCfg = Debug|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Debug|x64.ActiveCfg = Debug|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Debug|x86.ActiveCfg = Debug|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Release|Any CPU.Build.0 = Release|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Release|ARM.ActiveCfg = Release|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Release|x64.ActiveCfg = Release|Any CPU
{E8D670D3-B1B4-45CA-9440-9630529599B2}.Release|x86.ActiveCfg = Release|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Debug|ARM.ActiveCfg = Debug|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Debug|x64.ActiveCfg = Debug|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Debug|x86.ActiveCfg = Debug|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Release|Any CPU.Build.0 = Release|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Release|ARM.ActiveCfg = Release|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Release|x64.ActiveCfg = Release|Any CPU
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4}.Release|x86.ActiveCfg = Release|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|ARM.ActiveCfg = Debug|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|x64.ActiveCfg = Debug|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Debug|x86.ActiveCfg = Debug|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|Any CPU.Build.0 = Release|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|ARM.ActiveCfg = Release|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|x64.ActiveCfg = Release|Any CPU
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B}.Release|x86.ActiveCfg = Release|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Debug|ARM.ActiveCfg = Debug|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Debug|x64.ActiveCfg = Debug|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Debug|x86.ActiveCfg = Debug|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Release|Any CPU.Build.0 = Release|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Release|ARM.ActiveCfg = Release|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Release|x64.ActiveCfg = Release|Any CPU
{30536F8F-E4DA-46B3-B0D0-082632AD74B4}.Release|x86.ActiveCfg = Release|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Debug|ARM.ActiveCfg = Debug|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Debug|x64.ActiveCfg = Debug|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Debug|x86.ActiveCfg = Debug|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Release|Any CPU.Build.0 = Release|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Release|Any CPU.Deploy.0 = Release|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Release|ARM.ActiveCfg = Release|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Release|x64.ActiveCfg = Release|Any CPU
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF}.Release|x86.ActiveCfg = Release|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Debug|x64.ActiveCfg = Debug|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Debug|x86.ActiveCfg = Debug|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Release|Any CPU.Build.0 = Release|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Release|ARM.ActiveCfg = Release|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Release|x64.ActiveCfg = Release|Any CPU
{E5D42E35-B5C4-426D-B568-96926EBA588E}.Release|x86.ActiveCfg = Release|Any CPU
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|ARM.ActiveCfg = Debug|ARM
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|ARM.Build.0 = Debug|ARM
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|ARM.Deploy.0 = Debug|ARM
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|x64.ActiveCfg = Debug|x64
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|x64.Build.0 = Debug|x64
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|x64.Deploy.0 = Debug|x64
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|x86.ActiveCfg = Debug|x86
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|x86.Build.0 = Debug|x86
{6BCA313F-794F-4C54-9F96-C500290E147C}.Debug|x86.Deploy.0 = Debug|x86
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|Any CPU.Build.0 = Release|Any CPU
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|Any CPU.Deploy.0 = Release|Any CPU
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|ARM.ActiveCfg = Release|ARM
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|ARM.Build.0 = Release|ARM
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|ARM.Deploy.0 = Release|ARM
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|x64.ActiveCfg = Release|x64
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|x64.Build.0 = Release|x64
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|x64.Deploy.0 = Release|x64
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|x86.ActiveCfg = Release|x86
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|x86.Build.0 = Release|x86
{6BCA313F-794F-4C54-9F96-C500290E147C}.Release|x86.Deploy.0 = Release|x86
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Debug|ARM.ActiveCfg = Debug|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Debug|x64.ActiveCfg = Debug|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Debug|x86.ActiveCfg = Debug|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Release|Any CPU.Build.0 = Release|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Release|Any CPU.Deploy.0 = Release|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Release|ARM.ActiveCfg = Release|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Release|x64.ActiveCfg = Release|Any CPU
{69E4A20C-EF50-49C6-8DAC-F76B9D565767}.Release|x86.ActiveCfg = Release|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Debug|ARM.ActiveCfg = Debug|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Debug|x64.ActiveCfg = Debug|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Debug|x86.ActiveCfg = Debug|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Release|Any CPU.Build.0 = Release|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Release|ARM.ActiveCfg = Release|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Release|x64.ActiveCfg = Release|Any CPU
{D454DB5E-820F-4A92-B31E-A41A9D20B086}.Release|x86.ActiveCfg = Release|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Debug|x64.ActiveCfg = Debug|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Debug|x86.ActiveCfg = Debug|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Release|Any CPU.Build.0 = Release|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Release|ARM.ActiveCfg = Release|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Release|x64.ActiveCfg = Release|Any CPU
{7852029D-235C-40B7-8957-8E78414C3F97}.Release|x86.ActiveCfg = Release|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Debug|ARM.ActiveCfg = Debug|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Debug|ARM.Build.0 = Debug|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Debug|x64.ActiveCfg = Debug|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Debug|x64.Build.0 = Debug|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Debug|x86.ActiveCfg = Debug|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Debug|x86.Build.0 = Debug|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Release|Any CPU.Build.0 = Release|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Release|ARM.ActiveCfg = Release|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Release|ARM.Build.0 = Release|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Release|x64.ActiveCfg = Release|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Release|x64.Build.0 = Release|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Release|x86.ActiveCfg = Release|Any CPU
{4573C570-520F-4F49-90B4-03D4532C2BA2}.Release|x86.Build.0 = Release|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Debug|ARM.ActiveCfg = Debug|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Debug|ARM.Build.0 = Debug|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Debug|x64.ActiveCfg = Debug|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Debug|x64.Build.0 = Debug|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Debug|x86.ActiveCfg = Debug|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Debug|x86.Build.0 = Debug|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Release|Any CPU.Build.0 = Release|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Release|ARM.ActiveCfg = Release|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Release|ARM.Build.0 = Release|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Release|x64.ActiveCfg = Release|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Release|x64.Build.0 = Release|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Release|x86.ActiveCfg = Release|Any CPU
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0}.Release|x86.Build.0 = Release|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Debug|ARM.ActiveCfg = Debug|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Debug|ARM.Build.0 = Debug|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Debug|x64.ActiveCfg = Debug|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Debug|x64.Build.0 = Debug|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Debug|x86.ActiveCfg = Debug|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Debug|x86.Build.0 = Debug|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Release|Any CPU.Build.0 = Release|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Release|ARM.ActiveCfg = Release|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Release|ARM.Build.0 = Release|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Release|x64.ActiveCfg = Release|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Release|x64.Build.0 = Release|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Release|x86.ActiveCfg = Release|Any CPU
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C}.Release|x86.Build.0 = Release|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Debug|ARM.ActiveCfg = Debug|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Debug|ARM.Build.0 = Debug|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Debug|x64.ActiveCfg = Debug|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Debug|x64.Build.0 = Debug|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Debug|x86.ActiveCfg = Debug|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Debug|x86.Build.0 = Debug|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Release|Any CPU.Build.0 = Release|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Release|ARM.ActiveCfg = Release|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Release|ARM.Build.0 = Release|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Release|x64.ActiveCfg = Release|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Release|x64.Build.0 = Release|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Release|x86.ActiveCfg = Release|Any CPU
{F0A0D04C-6665-43C2-A3A3-870248A331B9}.Release|x86.Build.0 = Release|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Debug|ARM.ActiveCfg = Debug|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Debug|ARM.Build.0 = Debug|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Debug|x64.ActiveCfg = Debug|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Debug|x64.Build.0 = Debug|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Debug|x86.ActiveCfg = Debug|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Debug|x86.Build.0 = Debug|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Release|Any CPU.Build.0 = Release|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Release|ARM.ActiveCfg = Release|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Release|ARM.Build.0 = Release|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Release|x64.ActiveCfg = Release|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Release|x64.Build.0 = Release|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Release|x86.ActiveCfg = Release|Any CPU
{EDD03052-3A73-4D9E-9B94-6844134BABFB}.Release|x86.Build.0 = Release|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Debug|ARM.ActiveCfg = Debug|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Debug|ARM.Build.0 = Debug|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Debug|x64.ActiveCfg = Debug|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Debug|x64.Build.0 = Debug|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Debug|x86.ActiveCfg = Debug|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Debug|x86.Build.0 = Debug|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Release|Any CPU.Build.0 = Release|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Release|ARM.ActiveCfg = Release|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Release|ARM.Build.0 = Release|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Release|x64.ActiveCfg = Release|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Release|x64.Build.0 = Release|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Release|x86.ActiveCfg = Release|Any CPU
{629621F7-4D91-4F49-B373-FDFE6BB573D4}.Release|x86.Build.0 = Release|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Debug|ARM.Build.0 = Debug|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Debug|x64.ActiveCfg = Debug|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Debug|x64.Build.0 = Debug|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Debug|x86.ActiveCfg = Debug|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Debug|x86.Build.0 = Debug|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Release|Any CPU.Build.0 = Release|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Release|ARM.ActiveCfg = Release|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Release|ARM.Build.0 = Release|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Release|x64.ActiveCfg = Release|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Release|x64.Build.0 = Release|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Release|x86.ActiveCfg = Release|Any CPU
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98}.Release|x86.Build.0 = Release|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|ARM.Build.0 = Debug|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|x64.ActiveCfg = Debug|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|x64.Build.0 = Debug|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|x86.ActiveCfg = Debug|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Debug|x86.Build.0 = Debug|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|Any CPU.Build.0 = Release|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|ARM.ActiveCfg = Release|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|ARM.Build.0 = Release|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|x64.ActiveCfg = Release|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|x64.Build.0 = Release|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|x86.ActiveCfg = Release|Any CPU
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8}.Release|x86.Build.0 = Release|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|ARM.ActiveCfg = Debug|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|ARM.Build.0 = Debug|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|x64.ActiveCfg = Debug|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|x64.Build.0 = Debug|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|x86.ActiveCfg = Debug|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Debug|x86.Build.0 = Debug|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|Any CPU.Build.0 = Release|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|ARM.ActiveCfg = Release|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|ARM.Build.0 = Release|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|x64.ActiveCfg = Release|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|x64.Build.0 = Release|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|x86.ActiveCfg = Release|Any CPU
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19}.Release|x86.Build.0 = Release|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Debug|ARM.ActiveCfg = Debug|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Debug|ARM.Build.0 = Debug|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Debug|x64.ActiveCfg = Debug|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Debug|x64.Build.0 = Debug|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Debug|x86.ActiveCfg = Debug|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Debug|x86.Build.0 = Debug|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Release|Any CPU.Build.0 = Release|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Release|ARM.ActiveCfg = Release|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Release|ARM.Build.0 = Release|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Release|x64.ActiveCfg = Release|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Release|x64.Build.0 = Release|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Release|x86.ActiveCfg = Release|Any CPU
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC}.Release|x86.Build.0 = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|ARM.ActiveCfg = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|ARM.Build.0 = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|ARM.Deploy.0 = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x64.ActiveCfg = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x64.Build.0 = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x64.Deploy.0 = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x86.ActiveCfg = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x86.Build.0 = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Debug|x86.Deploy.0 = Debug|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|Any CPU.Build.0 = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|Any CPU.Deploy.0 = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|ARM.ActiveCfg = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|ARM.Build.0 = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|ARM.Deploy.0 = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x64.ActiveCfg = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x64.Build.0 = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x64.Deploy.0 = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x86.ActiveCfg = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x86.Build.0 = Release|Any CPU
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426}.Release|x86.Deploy.0 = Release|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|ARM.ActiveCfg = Debug|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|ARM.Build.0 = Debug|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|x64.ActiveCfg = Debug|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|x64.Build.0 = Debug|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|x86.ActiveCfg = Debug|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Debug|x86.Build.0 = Debug|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Release|Any CPU.Build.0 = Release|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Release|ARM.ActiveCfg = Release|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Release|ARM.Build.0 = Release|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Release|x64.ActiveCfg = Release|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Release|x64.Build.0 = Release|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Release|x86.ActiveCfg = Release|Any CPU
{92153715-1D99-43B1-B291-470CF91A156D}.Release|x86.Build.0 = Release|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|ARM.ActiveCfg = Debug|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|ARM.Build.0 = Debug|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|x64.ActiveCfg = Debug|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|x64.Build.0 = Debug|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|x86.ActiveCfg = Debug|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Debug|x86.Build.0 = Debug|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|Any CPU.Build.0 = Release|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|ARM.ActiveCfg = Release|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|ARM.Build.0 = Release|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|x64.ActiveCfg = Release|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|x64.Build.0 = Release|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|x86.ActiveCfg = Release|Any CPU
{4FB9C0D9-C3A8-4FB5-86CD-927E5EBC6885}.Release|x86.Build.0 = Release|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Debug|ARM.ActiveCfg = Debug|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Debug|ARM.Build.0 = Debug|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Debug|x64.ActiveCfg = Debug|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Debug|x64.Build.0 = Debug|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Debug|x86.ActiveCfg = Debug|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Debug|x86.Build.0 = Debug|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Release|Any CPU.Build.0 = Release|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Release|ARM.ActiveCfg = Release|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Release|ARM.Build.0 = Release|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Release|x64.ActiveCfg = Release|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Release|x64.Build.0 = Release|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Release|x86.ActiveCfg = Release|Any CPU
{4A250B81-35E9-4D2F-8030-62909F6C8C63}.Release|x86.Build.0 = Release|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Debug|ARM.ActiveCfg = Debug|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Debug|ARM.Build.0 = Debug|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Debug|x64.ActiveCfg = Debug|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Debug|x64.Build.0 = Debug|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Debug|x86.ActiveCfg = Debug|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Debug|x86.Build.0 = Debug|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Release|Any CPU.Build.0 = Release|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Release|ARM.ActiveCfg = Release|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Release|ARM.Build.0 = Release|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Release|x64.ActiveCfg = Release|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Release|x64.Build.0 = Release|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Release|x86.ActiveCfg = Release|Any CPU
{35F64888-3446-444D-8E44-128378434AB3}.Release|x86.Build.0 = Release|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Debug|ARM.ActiveCfg = Debug|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Debug|ARM.Build.0 = Debug|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Debug|x64.ActiveCfg = Debug|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Debug|x64.Build.0 = Debug|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Debug|x86.ActiveCfg = Debug|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Debug|x86.Build.0 = Debug|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Release|Any CPU.Build.0 = Release|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Release|ARM.ActiveCfg = Release|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Release|ARM.Build.0 = Release|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Release|x64.ActiveCfg = Release|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Release|x64.Build.0 = Release|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Release|x86.ActiveCfg = Release|Any CPU
{75DC3484-F6C8-4373-A8C4-9D1A8C9FC3B0}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{06CAA70A-20A7-4334-AF03-D6228039C178} = {3A334EFA-47FA-4CE2-9306-FDFF7CF47157}
{612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05} = {8F701234-EC60-485C-BCDB-8EE233246832}
{D6201667-DFEC-4BEF-8F4F-BE5EE5F07FE7} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
{68470436-2F0D-4A76-B1E6-9C8517844C3E} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
{09975981-F2D3-43AE-B70D-F4DEE7B0B0D2} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
{C272B10E-36BE-4F36-A128-331F715514E6} = {612E8E0A-6CB6-45C9-9A05-CFC7F26A5C05}
{4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56} = {8F701234-EC60-485C-BCDB-8EE233246832}
{4681C268-36DB-4838-BD21-9EC9A8363269} = {4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}
{7FF80B2D-4158-41D3-BC87-60C018028F53} = {8F701234-EC60-485C-BCDB-8EE233246832}
{24C152B0-3813-43C6-82DD-8BB601642F6C} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
{8FC90E46-024B-4089-9590-A7E8C2B092BE} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
{BF554E12-7096-465F-B1D0-9ACFF00877F2} = {8F701234-EC60-485C-BCDB-8EE233246832}
{43570F0D-DE6C-423E-A275-AC619A813B79} = {BF554E12-7096-465F-B1D0-9ACFF00877F2}
{36F33391-4918-4C6D-9CAE-1ECD32262257} = {4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}
{B23AC1B1-1551-41F3-8763-E68A53B172BB} = {3A334EFA-47FA-4CE2-9306-FDFF7CF47157}
{D6E83FC7-0D39-48AB-8DFA-FE89011CDD3C} = {BF554E12-7096-465F-B1D0-9ACFF00877F2}
{E55CB1DD-2F8E-4052-A119-6F3FD9ED10BE} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
{D1E69C74-4A33-4079-9665-8818A8479FFB} = {4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}
{89F13102-4826-4406-844B-7B21C47885E7} = {8F701234-EC60-485C-BCDB-8EE233246832}
{E8D670D3-B1B4-45CA-9440-9630529599B2} = {89F13102-4826-4406-844B-7B21C47885E7}
{4B7BFDB9-406A-4EBE-93C3-5D40D6A986F4} = {89F13102-4826-4406-844B-7B21C47885E7}
{78A9C0DF-1999-4D97-AE22-50ADC44F9A7B} = {3A334EFA-47FA-4CE2-9306-FDFF7CF47157}
{30536F8F-E4DA-46B3-B0D0-082632AD74B4} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
{F37DE470-865E-4F80-BC9C-FAC7BC11D3CF} = {4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}
{E5D42E35-B5C4-426D-B568-96926EBA588E} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
{6BCA313F-794F-4C54-9F96-C500290E147C} = {3A334EFA-47FA-4CE2-9306-FDFF7CF47157}
{69E4A20C-EF50-49C6-8DAC-F76B9D565767} = {BF554E12-7096-465F-B1D0-9ACFF00877F2}
{5637969B-A822-425A-A831-F70AA2275777} = {EB7EBF85-48AB-4EA0-9F00-825364BFA6FD}
{D454DB5E-820F-4A92-B31E-A41A9D20B086} = {4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}
{7852029D-235C-40B7-8957-8E78414C3F97} = {3A334EFA-47FA-4CE2-9306-FDFF7CF47157}
{4573C570-520F-4F49-90B4-03D4532C2BA2} = {7FF80B2D-4158-41D3-BC87-60C018028F53}
{F052E9A9-15BD-4DB4-8539-8961B7BA7DC0} = {3A334EFA-47FA-4CE2-9306-FDFF7CF47157}
{CD62609E-EA4E-48F4-B1FB-DF9BB98A132C} = {3A334EFA-47FA-4CE2-9306-FDFF7CF47157}
{F0A0D04C-6665-43C2-A3A3-870248A331B9} = {4A93A5B6-B935-4F86-B3DE-95B0F6EBEA56}
{B61E3B51-78CB-4047-8078-0B987E5E9742} = {8F701234-EC60-485C-BCDB-8EE233246832}
{EDD03052-3A73-4D9E-9B94-6844134BABFB} = {B61E3B51-78CB-4047-8078-0B987E5E9742}
{3C94DB48-3DDB-429C-8033-87F560607AA6} = {8F701234-EC60-485C-BCDB-8EE233246832}
{629621F7-4D91-4F49-B373-FDFE6BB573D4} = {3C94DB48-3DDB-429C-8033-87F560607AA6}
{C9111380-CFA2-4A3E-B0DF-87A1C1888F98} = {E0C378B0-4AF7-4C1F-A068-81A23FF8894E}
{C80D0C64-C34A-4DF4-9E26-E1D2F4FFEFC8} = {E0C378B0-4AF7-4C1F-A068-81A23FF8894E}
{5D8F78FC-0719-495F-9AD0-1EDD7EC9AA19} = {E0C378B0-4AF7-4C1F-A068-81A23FF8894E}
{97A6D8B7-2F39-45AC-91D7-A59FABF38CEC} = {E0C378B0-4AF7-4C1F-A068-81A23FF8894E}
{2C4CBC7A-16BD-4F27-86BA-3CF38BE0F426} = {3A334EFA-47FA-4CE2-9306-FDFF7CF47157}
EndGlobalSection
EndGlobal

1192
amqp.sln

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -4,11 +4,14 @@ branches:
- master
skip_tags: true
init:
- git config --global core.autocrlf true
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
FRAMEWORKS_TO_BUILD: REST_OF_FRAMEWORKS
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
FRAMEWORKS_TO_BUILD: NANOFRAMEWORK
before_build:
@ -73,9 +76,9 @@ before_build:
$webClient.DownloadFile("http://vsixgallery.com/feed/author/nanoframework", $vsixFeedXml)
[xml]$feedDetails = Get-Content $vsixFeedXml
# assuming this is building on VS2017 only
$extensionUrl = $feedDetails.feed.entry[0].content.src
$vsixPath = Join-Path $($env:USERPROFILE) "nanoFramework.Tools.VS2017.Extension.zip"
# assuming this is building on VS2019 only
$extensionUrl = $feedDetails.feed.entry[1].content.src
$vsixPath = Join-Path $($env:USERPROFILE) "nanoFramework.Tools.VS2019.Extension.zip"
# download VS extension
Write-Debug "Download VSIX file from $extensionUrl to $vsixPath"
@ -89,7 +92,7 @@ before_build:
# copy build files to msbuild location
Write-Debug "Copy build files to msbuild location"
$msbuildPath = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild"
$msbuildPath = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild"
Copy-Item -Path "$($env:USERPROFILE)\nf-extension\`$MSBuild\nanoFramework" -Destination $msbuildPath -Recurse
'OK' | Write-Host -ForegroundColor Green
@ -115,9 +118,9 @@ build_script:
{
Write-Output "Invoking build.cmd script ..."
& c:\projects\amqpnetlite\build.cmd | Write-Output
& c:\projects\amqpnetlite\build.cmd --solution "amqp-vs2015.sln amqp-dotnet.sln amqp-netmf.sln" | Write-Output
& c:\projects\amqpnetlite\build.cmd release | Write-Output
& c:\projects\amqpnetlite\build.cmd release --solution "amqp-vs2015.sln amqp-dotnet.sln amqp-netmf.sln" | Write-Output
}
Else

Просмотреть файл

@ -6,7 +6,7 @@ ECHO.
SET return-code=0
SET build-sln=amqp.sln amqp-dotnet.sln amqp-netmf.sln
SET build-sln=amqp.sln
SET build-target=build
SET build-config=Debug
SET build-platform=Any CPU
@ -54,7 +54,7 @@ GOTO :args-error
:args-solution
SHIFT
SET build-sln=%1
SET build-sln=%~1
GOTO args-loop
:args-config
SHIFT
@ -166,7 +166,7 @@ IF "%MSTestPath%" == "" (
ECHO.
ECHO Running NET tests...
"%MSTestPath%" /testcontainer:.\bin\%build-config%\Test.Amqp.Net\Test.Amqp.Net.dll
"%MSTestPath%" /testcontainer:.\bin\%build-config%\Test.Amqp.Net\Test.Amqp.Net.dll /nologo
IF ERRORLEVEL 1 (
SET return-code=1
ECHO Test failed!
@ -177,7 +177,7 @@ IF ERRORLEVEL 1 (
ECHO.
ECHO Running NET40 tests...
"%MSTestPath%" /testcontainer:.\bin\%build-config%\Test.Amqp.Net40\Test.Amqp.Net40.dll
"%MSTestPath%" /testcontainer:.\bin\%build-config%\Test.Amqp.Net40\Test.Amqp.Net40.dll /nologo
IF ERRORLEVEL 1 (
SET return-code=1
ECHO Test failed!
@ -187,7 +187,7 @@ IF ERRORLEVEL 1 (
ECHO.
ECHO Running NET35 tests...
"%MSTestPath%" /testcontainer:.\bin\%build-config%\Test.Amqp.Net35\Test.Amqp.Net35.dll
"%MSTestPath%" /testcontainer:.\bin\%build-config%\Test.Amqp.Net35\Test.Amqp.Net35.dll /nologo
IF ERRORLEVEL 1 (
SET return-code=1
ECHO Test failed!
@ -195,14 +195,16 @@ IF ERRORLEVEL 1 (
GOTO :exit
)
IF "%build-sln:amqp-dotnet.sln=%" == "%build-sln%" GOTO :done-test
IF NOT "%build-sln:amqp.sln=%" == "%build-sln%" GOTO :run-dotnet-test
IF NOT "%build-sln:amqp-dotnet.sln=%" == "%build-sln%" GOTO :run-dotnet-test
GOTO :done-test
:run-dotnet-test
ECHO Running DOTNET (.Net Core 2.0) tests...
ECHO Running DOTNET (netcoreapp 2.1) tests...
"%dotnetPath%" test -c %build-config% --no-build test\Test.Amqp\Test.Amqp.csproj -- no-broker
IF ERRORLEVEL 1 (
SET return-code=1
ECHO .Net Core 2. 0 Test failed!
ECHO dotnet Test failed!
GOTO :exit
)
@ -225,13 +227,25 @@ IF /I "%build-config%" NEQ "Release" (
IF NOT EXIST ".\Build\Packages" MKDIR ".\Build\Packages"
ECHO Building NuGet package with version %build-version%
IF NOT "%build-sln:amqp.sln=%" == "%build-sln%" (
"%NuGetPath%" pack .\nuspec\AMQPNetLite.nuspec -Version %build-version% -BasePath .\ -OutputDirectory ".\Build\Packages"
IF NOT "%build-sln:amqp.sln=%" == "%build-sln%" GOTO :package-main
IF NOT "%build-sln:amqp-vs2015.sln=%" == "%build-sln%" GOTO :package-main
IF NOT "%build-sln:amqp-dotnet.sln=%" == "%build-sln%" GOTO :package-dotnet
GOTO :package-netmf
:package-main
"%NuGetPath%" pack .\nuspec\AMQPNetLite.nuspec -Version %build-version% -BasePath .\ -OutputDirectory ".\Build\Packages"
IF ERRORLEVEL 1 (
SET return-code=1
GOTO :exit
)
:package-dotnet
FOR %%G IN (AMQPNetLite.Core AMQPNetLite.Serialization AMQPNetLite.WebSockets) DO (
"%NuGetPath%" pack .\nuspec\%%G.nuspec -Version %build-version% -BasePath .\ -OutputDirectory ".\Build\Packages" -Symbols -SymbolPackageFormat snupkg
IF ERRORLEVEL 1 (
SET return-code=1
GOTO :exit
)
)
:package-netmf
IF NOT "%build-sln:amqp-netmf.sln=%" == "%build-sln%" (
FOR %%G IN (AMQPNetLite.NetMF AMQPNetMicro) DO (
"%NuGetPath%" pack .\nuspec\%%G.nuspec -Version %build-version% -BasePath .\ -OutputDirectory ".\Build\Packages"
@ -241,15 +255,6 @@ IF NOT "%build-sln:amqp-netmf.sln=%" == "%build-sln%" (
)
)
)
IF NOT "%build-sln:amqp-dotnet.sln=%" == "%build-sln%" (
FOR %%G IN (AMQPNetLite.Core AMQPNetLite.Serialization AMQPNetLite.WebSockets) DO (
"%NuGetPath%" pack .\nuspec\%%G.nuspec -Version %build-version% -BasePath .\ -OutputDirectory ".\Build\Packages" -Symbols -SymbolPackageFormat snupkg
IF ERRORLEVEL 1 (
SET return-code=1
GOTO :exit
)
)
)
IF NOT "%build-sln:amqp-nanoFramework.sln=%" == "%build-sln%" (
FOR %%G IN (AMQPNetLite.nanoFramework AMQPNetMicro.nanoFramework) DO (
"%NuGetPath%" pack .\nuspec\%%G.nuspec -Version %build-version% -BasePath .\ -OutputDirectory ".\Build\Packages"

Просмотреть файл

@ -125,6 +125,9 @@
<Compile Include="..\src\Listener\ListenerLink.cs">
<Link>Listener\ListenerLink.cs</Link>
</Compile>
<Compile Include="..\src\MessageDelivery.cs">
<Link>MessageDelivery.cs</Link>
</Compile>
<Compile Include="..\src\Net\IConnectionFactory.cs" />
<Compile Include="..\src\Net\TcpKeepAliveSettings.cs" />
<Compile Include="..\src\Net\TransportProvider.cs" />

Просмотреть файл

@ -63,6 +63,9 @@
<Link>Handler\IDelivery.cs</Link>
</Compile>
<Compile Include="..\src\IAmqpObject.cs" />
<Compile Include="..\src\MessageDelivery.cs">
<Link>MessageDelivery.cs</Link>
</Compile>
<Compile Include="..\src\Net35\TcpTransport.cs">
<Link>Internal\TcpTransport.cs</Link>
</Compile>

Просмотреть файл

@ -133,6 +133,9 @@
<Compile Include="..\src\Listener\X509Identity.cs">
<Link>Listener\X509Identity.cs</Link>
</Compile>
<Compile Include="..\src\MessageDelivery.cs">
<Link>MessageDelivery.cs</Link>
</Compile>
<Compile Include="..\src\Net\IConnectionFactory.cs" />
<Compile Include="..\src\Net\Map.Net.cs">
<Link>Types\Map.Net.cs</Link>

Просмотреть файл

@ -186,6 +186,9 @@
<Link>Internal\LinkedList.cs</Link>
</Compile>
<Compile Include="..\src\Message.cs" />
<Compile Include="..\src\MessageDelivery.cs">
<Link>MessageDelivery.cs</Link>
</Compile>
<Compile Include="..\src\Net\AmqpSettings.cs" />
<Compile Include="..\src\Net\AsyncPump.cs">
<Link>Internal\AsyncPump.cs</Link>

Просмотреть файл

@ -185,6 +185,9 @@
<Link>Internal\LinkedList.cs</Link>
</Compile>
<Compile Include="..\src\Message.cs" />
<Compile Include="..\src\MessageDelivery.cs">
<Link>MessageDelivery.cs</Link>
</Compile>
<Compile Include="..\src\Net\AmqpSettings.cs" />
<Compile Include="..\src\Net\AsyncPump.cs">
<Link>Internal\AsyncPump.cs</Link>

Просмотреть файл

@ -74,6 +74,10 @@ undesired behavior, e.g. UI freeze if it is called from a UI thread. In these ca
should use the `ConnectionFactory` class to perform asynchronous non-blocking creation of
a connection.
On platforms where `ConnectionFactory` is supported, the default factory (`Connection.Factory`) is
used for all connections created by the constructors. Therefore, any change made to the settings of
the default factory is applied to connections created afterwards.
### ConnectionFactory
`ConnectionFactory` provides asynchronous connection creation, and it also gives more control
@ -224,21 +228,12 @@ recovery by recreating the object, and sometimes maybe its container object.
## Threading
Send and receive methods on links are thread safe.
Usually the library completes an async operation or invokes a callback when a network event
occurs. These events are generated when a network package is received. So the execution happens
on the I/O thread where the connection pump is running. Blocking the thread means no more incoming
frames can be processed and it is very likely to cause deadlock, application hang or timeout errors.
To avoid such issues, application should not mix sync and async APIs. DO not perform blocking calls
from the async callback.
Below are examples for potential issues.
```
SenderLink sender = new SenderLink(session, "sender", "q1");
await sender.SendAsync(new Message("m1"));
sender.Send(new Message("m2"));
```
The Send call will timeout because the returned acknowledgement cannot be processed when the I/O
thread is blocked.
Send and receive methods on links are thread safe.
The library does not create any threads for sending or receiving messages. Instead the async API relies on an asynchronous connection "pump",
meaning a continous loop that asynchronously processes I/O. It is critical for proper operation that the application does not block this pump.
There are two ways in which an application can accidentally block the pump. The first is by performing a blocking operation in a callback:
```
SenderLink sender = new SenderLink(session, "sender", "q1");
@ -247,8 +242,37 @@ sender.Send(
(m, o, s) => Thread.Sleep(120000),
sender);
```
Thread.Sleep is a hypothetical example of having blocking calls in the MessageCallback.
The second occurs when an async operation is completed and its continuation runs *synchronously*:
```
SenderLink sender = new SenderLink(session, "sender", "q1");
await sender.SendAsync( new Message("test"));
Thead.Sleep(120000);
```
The above code will block the pump if the continuation of SendAsync happens to be run synchronously (which it frequently will be).
The problem is the same as with the first example, the async pump does not get a chance to release the currently executing thread back to the
thread pool and therefore has no chance to await further I/O. This means that no messages can be processed and will typically cause deadlock,
application hang or timeout errors.
Specifically it is important to understand that blocking operations to be avoided include the sync API of this library:
```
SenderLink sender = new SenderLink(session, "sender", "q1");
await sender.SendAsync(new Message("m1"));
sender.Send(new Message("m2"));
```
Here, the Send call will timeout because the returned acknowledgement cannot be processed when the I/O
processing is blocked.
The solution for callbacks is naturally to schedule blocking work asynchronously instead of blocking the calling thread. The solution for continuations
depends on the application, which must either ensure that continuations of async operations never occur on threads that do blocking work, or the async operations can be wrapped by the application using a `TaskCompletionSource` with `TaskCreationOptions.RunContinuationsAsynchronously` specified.
For more details see the following issues:
https://github.com/Azure/amqpnetlite/issues/237
https://github.com/Azure/amqpnetlite/issues/490
## Advanced topics
* [Listener](listener.md)
* [Serialization](serialization.md)

Просмотреть файл

@ -5,10 +5,14 @@ ContainerHost is the easiest way to start an AMQP listener. Multiple endpoints c
The application is required to register at least one of the following processors to process AMQP events. Multiple message/request processors can be registered as long as their addresses are different. At most one link processor can be registered.
When the container host receives an attach performative from the remote peer,
(1) if a message/request processor is found at the registered address, the host creates a link endpoint for that address and all received messages are routed to that processor.
(2) otherwise, if a link processor is registered, the attach request is routed to the processor.
(3) otherwise, the attach is rejected with "amqp:not-found" error.
When the container host receives an attach performative from the remote peer,
(1) if an address resolver is set, the host first calls the resolver to translate the address from the incoming attach request.
The resolver allows the application to implement various logic for mapping a peer specified address to a listener address, which
is used to register a processor. Common scenarios are message processor to route messages to different destinations and message
source to serve messages from multiple nodes.
(2) if a message/request processor is found at the registered address, the host creates a link endpoint for that address and all received messages are routed to that processor.
(3) otherwise, if a link processor is registered, the attach request is routed to the processor.
(4) otherwise, the attach is rejected with "amqp:not-found" error.
Protocol behavior can be configured through the Listeners properties of the container host.

Просмотреть файл

@ -15,7 +15,9 @@ At least one Uri should be specified. Multiple are allowed (typically one for "a
If "amqps" Uri is present, the "cert" option must exist to specify a server certificate for the Tls listener.
If "queues" option is present, the broker is preconfigured with a list of queues. If it does not exist, the broker implicitly creates a queue upon an attach request and deletes it when the associated connection is closed. This allows running the tests easily without creating or draining the queue. Note that this is different from AMQP dynamic nodes. You can still create dynamic nodes through the protocol.
If "queues" option is present, the broker is preconfigured with a list of queues. If it does not exist, the broker implicitly creates a queue upon the first attach request
and deletes it when the last connection is closed. This allows running the tests easily without creating or draining the queue. Note that this is different from AMQP dynamic nodes.
You can still create dynamic nodes through the protocol.
When "trace" option is specified, the traces will be printed to the console window.

Просмотреть файл

@ -69,6 +69,9 @@
<Compile Include="..\src\Framing\Data.cs">
<Link>Framing\Data.cs</Link>
</Compile>
<Compile Include="..\src\MessageDelivery.cs">
<Link>MessageDelivery.cs</Link>
</Compile>
<Compile Include="NETMF\TimeoutException.cs" />
<Compile Include="NETMF\List.cs" />
<Compile Include="NETMF\Map.cs" />

Просмотреть файл

@ -162,6 +162,9 @@
<Compile Include="..\src\Link.cs" />
<Compile Include="..\src\LinkedList.cs" />
<Compile Include="..\src\Message.cs" />
<Compile Include="..\src\MessageDelivery.cs">
<Link>MessageDelivery.cs</Link>
</Compile>
<Compile Include="NetMF\Fx.cs" />
<Compile Include="NetMF\List.cs" />
<Compile Include="NetMF\Map.cs" />

Просмотреть файл

@ -162,6 +162,9 @@
<Compile Include="..\src\Link.cs" />
<Compile Include="..\src\LinkedList.cs" />
<Compile Include="..\src\Message.cs" />
<Compile Include="..\src\MessageDelivery.cs">
<Link>MessageDelivery.cs</Link>
</Compile>
<Compile Include="..\src\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
</Compile>

Просмотреть файл

@ -44,7 +44,8 @@ namespace Amqp
/// <summary>
/// Initializes a new instance of the Address class from a string.
/// </summary>
/// <param name="address">The string representation of the address.</param>
/// <param name="address">The string representation of the address. User and password in
/// the string, if any, MUST be URL encoded.</param>
public Address(string address)
{
this.Port = -1;
@ -57,8 +58,8 @@ namespace Amqp
/// </summary>
/// <param name="host">The domain of the address.</param>
/// <param name="port">The port number of the address.</param>
/// <param name="user">User name for SASL PLAIN profile.</param>
/// <param name="password">Password for SASL PLAIN profile.</param>
/// <param name="user">User name for SASL PLAIN profile without URL encoding.</param>
/// <param name="password">Password for SASL PLAIN profile without URL encoding.</param>
/// <param name="path">The path of the address.</param>
/// <param name="scheme">Protocol scheme, which can be either "amqp" or "amqps".</param>
public Address(string host, int port, string user = null, string password = null, string path = "/", string scheme = Amqps)

Просмотреть файл

@ -107,11 +107,11 @@ namespace Amqp
internal const uint DefaultMaxFrameSize = 256 * 1024;
internal const ushort DefaultMaxSessions = 256;
internal const int DefaultMaxLinksPerSession = 64;
internal const int DefaultMaxLinksPerSession = 1024;
internal static int HeartBeatCloseTimeout = 20 * 1000;
const uint MaxIdleTimeout = 30 * 60 * 1000;
readonly Address address;
readonly OnOpened onOpened;
readonly object lockObject;
IHandler handler;
Session[] localSessions;
Session[] remoteSessions;
@ -120,9 +120,7 @@ namespace Amqp
uint maxFrameSize;
uint remoteMaxFrameSize;
ITransport writer;
Pump reader;
HeartBeat heartBeat;
private readonly object lockObject = new object();
Connection(Address address, ushort channelMax, uint maxFrameSize)
{
@ -132,6 +130,7 @@ namespace Amqp
this.remoteMaxFrameSize = uint.MaxValue;
this.localSessions = new Session[1];
this.remoteSessions = new Session[1];
this.lockObject = new object();
}
/// <summary>
@ -142,7 +141,7 @@ namespace Amqp
/// The connection initialization includes establishing the underlying transport,
/// which typically has blocking network I/O. Depending on the current synchronization
/// context, it may cause deadlock or UI freeze. Please use the ConnectionFactory.CreateAsync
/// method instead.
/// method instead if it is available for the platform.
/// </remarks>
public Connection(Address address)
: this(address, null)
@ -154,6 +153,12 @@ namespace Amqp
/// </summary>
/// <param name="address">The address.</param>
/// <param name="handler">The protocol handler.</param>
/// <remarks>
/// The connection initialization includes establishing the underlying transport,
/// which typically has blocking network I/O. Depending on the current synchronization
/// context, it may cause deadlock or UI freeze. Please use the ConnectionFactory.CreateAsync
/// method instead if it is available for the platform.
/// </remarks>
public Connection(Address address, IHandler handler)
: this(address, DefaultMaxSessions, DefaultMaxFrameSize)
{
@ -174,7 +179,7 @@ namespace Amqp
/// The connection initialization includes establishing the underlying transport,
/// which typically has blocking network I/O. Depending on the current synchronization
/// context, it may cause deadlock or UI freeze. Please use the ConnectionFactory.CreateAsync
/// method instead.
/// method instead if it is available for the platform.
/// </remarks>
public Connection(Address address, SaslProfile saslProfile, Open open, OnOpened onOpened)
: this(address, DefaultMaxSessions, DefaultMaxFrameSize)
@ -197,16 +202,33 @@ namespace Amqp
}
#if NETFX || NETFX40 || DOTNET || NETFX_CORE || WINDOWS_STORE || WINDOWS_PHONE
static ushort GetChannelMax(AmqpSettings amqpSettings, Open open)
{
return open != null ? open.ChannelMax : (ushort)(amqpSettings.MaxSessionsPerConnection - 1);
}
static uint GetMaxFrameSize(AmqpSettings amqpSettings, Open open)
{
return open != null ? open.MaxFrameSize : (uint)amqpSettings.MaxFrameSize;
}
internal Connection(IBufferManager bufferManager, AmqpSettings amqpSettings, Address address,
IAsyncTransport transport, Open open, OnOpened onOpened, IHandler handler)
: this(address, (ushort)(amqpSettings.MaxSessionsPerConnection - 1), (uint)amqpSettings.MaxFrameSize)
: this(address, DefaultMaxSessions, DefaultMaxFrameSize)
{
this.onOpened = onOpened;
this.handler = handler;
this.Init(bufferManager, amqpSettings, transport, open);
}
internal void Init(IBufferManager bufferManager, AmqpSettings amqpSettings, IAsyncTransport transport, Open open)
{
transport.SetConnection(this);
this.handler = handler;
this.BufferManager = bufferManager;
this.channelMax = GetChannelMax(amqpSettings, open);
this.maxFrameSize = GetMaxFrameSize(amqpSettings, open);
this.MaxLinksPerSession = amqpSettings.MaxLinksPerSession;
this.onOpened = onOpened;
this.writer = new TransportWriter(transport, this.OnIoException);
// after getting the transport, move state to open pipe before starting the pump
@ -218,13 +240,13 @@ namespace Amqp
HostName = amqpSettings.HostName ?? this.address.Host,
ChannelMax = this.channelMax,
MaxFrameSize = this.maxFrameSize,
IdleTimeOut = (uint)amqpSettings.IdleTimeout
IdleTimeOut = (uint)amqpSettings.IdleTimeout / 2
};
}
if (open.IdleTimeOut > 0)
{
this.heartBeat = new HeartBeat(this, open.IdleTimeOut);
this.heartBeat = new HeartBeat(this, open.IdleTimeOut * 2);
}
this.SendHeader();
@ -232,12 +254,19 @@ namespace Amqp
this.state = ConnectionState.OpenPipe;
}
static ConnectionFactory connectionFactory;
/// <summary>
/// Gets a factory with default settings.
/// Gets a factory with default settings. Any changes to the settings are
/// applied to the connections created from this factory instance.
/// </summary>
/// <remarks>
/// On platforms where <seealso cref="ConnectionFactory"/> is supported, this
/// is also used for connections initialized by the constructors.
/// </remarks>
public static ConnectionFactory Factory
{
get { return new ConnectionFactory(); }
get { return connectionFactory ?? (connectionFactory = new ConnectionFactory()); }
}
/// <summary>
@ -270,8 +299,14 @@ namespace Amqp
{
return new WrappedByteBuffer(buffer, offset, length);
}
void Connect(SaslProfile saslProfile, Open open)
{
Factory.ConnectAsync(this.address, saslProfile, open, this).ConfigureAwait(false).GetAwaiter().GetResult();
}
#else
internal int MaxLinksPerSession = DefaultMaxLinksPerSession;
Pump reader;
ByteBuffer AllocateBuffer(int size)
{
@ -282,8 +317,71 @@ namespace Amqp
{
return new ByteBuffer(buffer.Buffer, offset, length, length);
}
void Connect(SaslProfile saslProfile, Open open)
{
if (open != null)
{
this.maxFrameSize = open.MaxFrameSize;
this.channelMax = open.ChannelMax;
}
else
{
open = new Open()
{
ContainerId = MakeAmqpContainerId(),
HostName = this.address.Host,
MaxFrameSize = this.maxFrameSize,
ChannelMax = this.channelMax
};
}
if (open.IdleTimeOut > 0)
{
this.heartBeat = new HeartBeat(this, open.IdleTimeOut * 2);
}
ITransport transport;
{
TcpTransport tcpTransport = new TcpTransport();
tcpTransport.Connect(this, this.address, DisableServerCertValidation);
transport = tcpTransport;
}
try
{
if (saslProfile != null)
{
transport = saslProfile.Open(this.address.Host, transport);
}
else if (this.address.User != null)
{
transport = new SaslPlainProfile(this.address.User, this.address.Password).Open(this.address.Host, transport);
}
}
catch
{
transport.Close();
throw;
}
this.writer = new Writer(transport);
// after getting the transport, move state to open pipe before starting the pump
this.SendHeader();
this.SendOpen(open);
this.state = ConnectionState.OpenPipe;
this.reader = new Pump(this, transport);
this.reader.Start();
}
#endif
internal static string MakeAmqpContainerId()
{
return "AMQPNetLite-" + Guid.NewGuid().ToString().Substring(0, 8);
}
internal ushort AddSession(Session session)
{
this.ThrowIfClosed("AddSession");
@ -413,73 +511,6 @@ namespace Amqp
}
}
void Connect(SaslProfile saslProfile, Open open)
{
if (open != null)
{
this.maxFrameSize = open.MaxFrameSize;
this.channelMax = open.ChannelMax;
}
else
{
open = new Open()
{
ContainerId = Guid.NewGuid().ToString(),
HostName = this.address.Host,
MaxFrameSize = this.maxFrameSize,
ChannelMax = this.channelMax
};
}
if (open.IdleTimeOut > 0)
{
this.heartBeat = new HeartBeat(this, open.IdleTimeOut);
}
ITransport transport;
#if NETFX
if (WebSocketTransport.MatchScheme(address.Scheme))
{
WebSocketTransport wsTransport = new WebSocketTransport();
wsTransport.ConnectAsync(address, null).ConfigureAwait(false).GetAwaiter().GetResult();
transport = wsTransport;
}
else
#endif
{
TcpTransport tcpTransport = new TcpTransport();
tcpTransport.Connect(this, this.address, DisableServerCertValidation);
transport = tcpTransport;
}
try
{
if (saslProfile != null)
{
transport = saslProfile.Open(this.address.Host, transport);
}
else if (this.address.User != null)
{
transport = new SaslPlainProfile(this.address.User, this.address.Password).Open(this.address.Host, transport);
}
}
catch
{
transport.Close();
throw;
}
this.writer = new Writer(transport);
// after getting the transport, move state to open pipe before starting the pump
this.SendHeader();
this.SendOpen(open);
this.state = ConnectionState.OpenPipe;
this.reader = new Pump(this, transport);
this.reader.Start();
}
void ThrowIfClosed(string operation)
{
if (this.state >= ConnectionState.CloseSent)
@ -768,7 +799,7 @@ namespace Amqp
return shouldContinue;
}
void OnException(Exception exception)
internal void OnException(Exception exception)
{
Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", exception.ToString());
AmqpException amqpException = exception as AmqpException;
@ -848,7 +879,7 @@ namespace Amqp
public void Start(uint remote)
{
this.remote = remote / 2;
this.remote = remote;
this.lastSend = DateTime.UtcNow;
this.lastReceive = DateTime.UtcNow;
this.SetTimer();
@ -1032,6 +1063,11 @@ namespace Amqp
ProtocolHeader header = Reader.ReadHeader(this.transport);
this.connection.OnHeader(header);
}
catch (AmqpException amqpException)
{
this.connection.OnException(amqpException);
return;
}
catch (Exception exception)
{
this.connection.OnIoException(exception);
@ -1046,6 +1082,10 @@ namespace Amqp
ByteBuffer buffer = Reader.ReadFrameBuffer(this.transport, sizeBuffer, this.connection.maxFrameSize);
this.connection.OnFrame(buffer);
}
catch (AmqpException amqpException)
{
this.connection.OnException(amqpException);
}
catch (Exception exception)
{
this.connection.OnIoException(exception);

Просмотреть файл

@ -21,7 +21,7 @@ namespace Amqp
using Amqp.Types;
using Amqp.Handler;
class Delivery : IDelivery, INode
sealed class Delivery : IDelivery, INode
{
Message message;
@ -56,7 +56,16 @@ namespace Amqp
public Message Message
{
get { return this.message; }
set { this.message = value; value.Delivery = this; }
set
{
if (value.Delivery != null)
{
value.Delivery.message = null;
}
this.message = value;
this.message.Delivery = this;
}
}
public static void ReleaseAll(Delivery delivery, Error error)
@ -95,5 +104,11 @@ namespace Amqp
this.State = state;
this.Link.OnDeliveryStateChanged(this);
}
public void Dispose()
{
this.Buffer.ReleaseReference();
this.message = null;
}
}
}

Просмотреть файл

@ -45,7 +45,7 @@ namespace Amqp.Framing
}
/// <summary>
/// Indicates if handle field was defined (index=0).
/// Indicates if handle field was defined.
/// </summary>
public bool HasHandle
{
@ -53,7 +53,7 @@ namespace Amqp.Framing
}
/// <summary>
/// Gets or sets the next-incoming-id field (index=1).
/// Gets or sets the next-incoming-id field (index=0).
/// </summary>
public uint NextIncomingId
{

Просмотреть файл

@ -82,6 +82,7 @@ namespace Amqp.Framing
/// <summary>
/// Gets or sets the idle-time-out field (index=4).
/// </summary>
/// <remarks>To avoid spurious timeouts, the value SHOULD be half the actual timeout threshold.</remarks>
public uint IdleTimeOut
{
get { return this.GetField(4, this.idleTimeOut, 0u); }

Просмотреть файл

@ -89,6 +89,28 @@ namespace Amqp.Handler
/// Handler MUST call System.Net.Security.SslStream.AuthenticateAsClient(string) or one of its overloads.
/// </summary>
SslAuthenticate,
#if NETFX || NETFX40 || DOTNET
/// <summary>
/// A System.Net.Sockets.Socket (<see cref="Event.Context"/>) is accepted.
/// </summary>
SocketAccept,
/// <summary>
/// A System.Net.Security.SslStream (<see cref="Event.Context"/>) is accepted.
/// </summary>
SslStreamAccept,
/// <summary>
/// A System.Net.HttpListenerContext (<see cref="Event.Context"/>) is accepted in the WebSockets listener.
/// </summary>
HttpAccept,
/// <summary>
/// A System.Net.WebSockets.WebSocketContext (<see cref="Event.Context"/>) is accepted.
/// </summary>
WebSocketAccept,
/// <summary>
/// A <see cref="Amqp.Listener.ListenerConnection"/> is accepted.
/// </summary>
ConnectionAccept,
#endif
}
/// <summary>

Просмотреть файл

@ -133,6 +133,8 @@ namespace Amqp.Listener
/// <summary>
/// Gets or sets a factory that creates a <see cref="IHandler"/> for an accepted connection.
/// </summary>
/// <remarks>The delegate is called once for each accepted transport. It allows for creating
/// a handler per connection if needed (<see cref="Amqp.Connection.Handler"/>).</remarks>
public Func<ConnectionListener, IHandler> HandlerFactory
{
get;
@ -237,17 +239,16 @@ namespace Amqp.Listener
throw new ArgumentNullException("certificate");
}
async Task HandleTransportAsync(IAsyncTransport transport)
async Task HandleTransportAsync(IAsyncTransport transport, IHandler handler, object context)
{
IPrincipal principal = null;
if (this.saslSettings != null)
{
ListenerSaslProfile profile = new ListenerSaslProfile(this);
transport = await profile.NegotiateAsync(transport);
transport = await profile.NegotiateAsync(transport).ConfigureAwait(false);
principal = profile.GetPrincipal();
}
IHandler handler = this.HandlerFactory?.Invoke(this);
var connection = new ListenerConnection(this, this.address, handler, transport);
if (principal == null)
{
@ -277,10 +278,15 @@ namespace Amqp.Listener
if (shouldClose)
{
await connection.CloseAsync();
await connection.CloseAsync().ConfigureAwait(false);
}
else
{
if (handler != null && handler.CanHandle(EventId.ConnectionAccept))
{
handler.Handle(Event.Create(EventId.ConnectionAccept, connection, context: context));
}
AsyncPump pump = new AsyncPump(this.BufferManager, transport);
pump.Start(connection);
}
@ -494,6 +500,11 @@ namespace Amqp.Listener
protected override ITransport UpgradeTransport(ITransport transport)
{
if (this.innerProfile != null)
{
return this.innerProfile.UpgradeTransportInternal(transport);
}
return transport;
}
@ -545,7 +556,7 @@ namespace Amqp.Listener
class TcpTransportListener : TransportListener
{
Socket[] listenSockets;
readonly Socket[] listenSockets;
public TcpTransportListener(ConnectionListener listener, string host, int port)
{
@ -618,9 +629,15 @@ namespace Amqp.Listener
this.Listener.tcpSettings.Configure(socket);
}
IAsyncTransport transport = await this.CreateTransportAsync(socket);
IHandler handler = this.Listener.HandlerFactory?.Invoke(this.Listener);
if (handler != null && handler.CanHandle(EventId.SocketAccept))
{
handler.Handle(Event.Create(EventId.SocketAccept, null, context: socket));
}
await this.Listener.HandleTransportAsync(transport);
IAsyncTransport transport = await this.CreateTransportAsync(socket, handler).ConfigureAwait(false);
await this.Listener.HandleTransportAsync(transport, handler, socket).ConfigureAwait(false);
}
catch (Exception exception)
{
@ -629,7 +646,7 @@ namespace Amqp.Listener
}
}
protected virtual Task<IAsyncTransport> CreateTransportAsync(Socket socket)
protected virtual Task<IAsyncTransport> CreateTransportAsync(Socket socket, IHandler handler)
{
var tcs = new TaskCompletionSource<IAsyncTransport>();
tcs.SetResult(new ListenerTcpTransport(socket, this.Listener.BufferManager));
@ -646,7 +663,7 @@ namespace Amqp.Listener
try
{
args.AcceptSocket = null;
Socket acceptSocket = await socket.AcceptAsync(args, SocketFlags.None);
Socket acceptSocket = await socket.AcceptAsync(args, SocketFlags.None).ConfigureAwait(false);
if (acceptSocket != null)
{
var task = this.HandleSocketAsync(acceptSocket);
@ -677,13 +694,13 @@ namespace Amqp.Listener
this.certificate = certificate;
}
protected override async Task<IAsyncTransport> CreateTransportAsync(Socket socket)
protected override async Task<IAsyncTransport> CreateTransportAsync(Socket socket, IHandler handler)
{
SslStream sslStream;
if (this.Listener.sslSettings == null)
{
sslStream = new SslStream(new NetworkStream(socket));
await sslStream.AuthenticateAsServerAsync(this.certificate);
await sslStream.AuthenticateAsServerAsync(this.certificate).ConfigureAwait(false);
}
else
{
@ -691,7 +708,12 @@ namespace Amqp.Listener
this.Listener.sslSettings.RemoteCertificateValidationCallback);
await sslStream.AuthenticateAsServerAsync(this.certificate, this.Listener.sslSettings.ClientCertificateRequired,
this.Listener.sslSettings.Protocols, this.Listener.sslSettings.CheckCertificateRevocation);
this.Listener.sslSettings.Protocols, this.Listener.sslSettings.CheckCertificateRevocation).ConfigureAwait(false);
}
if (handler != null && handler.CanHandle(EventId.SslStreamAccept))
{
handler.Handle(Event.Create(EventId.SslStreamAccept, null, context: sslStream));
}
return new ListenerTcpTransport(sslStream, this.Listener.BufferManager);
@ -725,7 +747,8 @@ namespace Amqp.Listener
try
{
var transport = await this.provider.CreateAsync(this.Listener.address);
await this.Listener.HandleTransportAsync(transport);
IHandler handler = this.Listener.HandlerFactory?.Invoke(this.Listener);
await this.Listener.HandleTransportAsync(transport, handler, null).ConfigureAwait(false);
}
catch (ObjectDisposedException)
{
@ -769,12 +792,11 @@ namespace Amqp.Listener
#if NETFX
class WebSocketTransportListener : TransportListener
{
readonly ConnectionListener listener;
HttpListener httpListener;
public WebSocketTransportListener(ConnectionListener listener, string scheme, string host, int port, string path)
{
this.listener = listener;
this.Listener = listener;
// if certificate is set, it must be bound to host:port by netsh http command
string address = string.Format("{0}://{1}:{2}{3}", scheme, host, port, path);
@ -795,11 +817,11 @@ namespace Amqp.Listener
this.httpListener.Close();
}
async Task HandleListenerContextAsync(HttpListenerContext context)
async Task HandleListenerContextAsync(HttpListenerContext context, IHandler handler)
{
try
{
int status = await this.CreateTransportAsync(context);
int status = await this.CreateTransportAsync(context, handler).ConfigureAwait(false);
if (status != 0)
{
Trace.WriteLine(TraceLevel.Error, "Failed to create ws transport ", status);
@ -816,23 +838,23 @@ namespace Amqp.Listener
}
}
async Task<int> CreateTransportAsync(HttpListenerContext context)
async Task<int> CreateTransportAsync(HttpListenerContext context, IHandler handler)
{
X509Certificate2 clientCertificate = null;
if (this.listener.sslSettings != null && this.listener.sslSettings.ClientCertificateRequired)
if (this.Listener.sslSettings != null && this.Listener.sslSettings.ClientCertificateRequired)
{
clientCertificate = await context.Request.GetClientCertificateAsync(); ;
clientCertificate = await context.Request.GetClientCertificateAsync().ConfigureAwait(false);
if (clientCertificate == null)
{
return 40300;
}
if (this.listener.sslSettings.RemoteCertificateValidationCallback != null)
if (this.Listener.sslSettings.RemoteCertificateValidationCallback != null)
{
SslPolicyErrors sslError = SslPolicyErrors.None;
X509Chain chain = new X509Chain();
chain.ChainPolicy.RevocationMode = this.listener.sslSettings.CheckCertificateRevocation ?
chain.ChainPolicy.RevocationMode = this.Listener.sslSettings.CheckCertificateRevocation ?
X509RevocationMode.Online : X509RevocationMode.NoCheck;
chain.Build(clientCertificate);
if (chain.ChainStatus.Length > 0)
@ -840,7 +862,7 @@ namespace Amqp.Listener
sslError = SslPolicyErrors.RemoteCertificateChainErrors;
}
bool success = this.listener.sslSettings.RemoteCertificateValidationCallback(
bool success = this.Listener.sslSettings.RemoteCertificateValidationCallback(
this, clientCertificate, chain, sslError);
if (!success)
{
@ -877,9 +899,14 @@ namespace Amqp.Listener
return 40003;
}
var wsContext = await context.AcceptWebSocketAsync(subProtocol);
var wsContext = await context.AcceptWebSocketAsync(subProtocol).ConfigureAwait(false);
if (handler != null && handler.CanHandle(EventId.WebSocketAccept))
{
handler.Handle(Event.Create(EventId.WebSocketAccept, null, context: wsContext));
}
var wsTransport = new ListenerWebSocketTransport(wsContext.WebSocket, principal);
await this.listener.HandleTransportAsync(wsTransport);
await this.Listener.HandleTransportAsync(wsTransport, handler, wsContext.WebSocket).ConfigureAwait(false);
return 0;
}
@ -890,9 +917,15 @@ namespace Amqp.Listener
{
try
{
HttpListenerContext context = await this.httpListener.GetContextAsync();
HttpListenerContext context = await this.httpListener.GetContextAsync().ConfigureAwait(false);
var task = this.HandleListenerContextAsync(context);
IHandler handler = this.Listener.HandlerFactory?.Invoke(this.Listener);
if (handler != null && handler.CanHandle(EventId.HttpAccept))
{
handler.Handle(Event.Create(EventId.HttpAccept, null, context: context));
}
var task = this.HandleListenerContextAsync(context, handler);
}
catch (Exception exception)
{

Просмотреть файл

@ -62,7 +62,9 @@ namespace Amqp.Listener
/// * After the link attach is handled, wrap it in a Target/SourceLinkEndpoint
/// that works with the previously implemented message processor or source.
///
/// Upon receiving an attach performative, the registered message level
/// Upon receiving an attach performative, the host uses the address to look up
/// the registered processors. If an address resolver is set, it is called first
/// and the result overwrites the address in attach. The registered message level
/// processors (IMessageProcessor, IMessageSource, IRequestProcessor) are
/// checked first. If a processor matches the address on the received attach
/// performative, a link is automatically created and the send/receive requests
@ -139,7 +141,7 @@ namespace Amqp.Listener
/// </summary>
public ContainerHost(IList<Address> addressList)
{
this.containerId = string.Join("-", this.GetType().Name, Guid.NewGuid().ToString("N"));
this.containerId = Connection.MakeAmqpContainerId();
this.customTransports = new Dictionary<string, TransportProvider>(StringComparer.OrdinalIgnoreCase);
this.linkCollection = new LinkCollection(this.containerId);
this.onLinkClosed = this.OnLinkClosed;
@ -183,6 +185,21 @@ namespace Amqp.Listener
get { return this.listeners; }
}
/// <summary>
/// Gets or sets an address resolver for all processors.
/// </summary>
/// <remarks>
/// The resolver returns a non-null string which was registered earlier for a
/// processor that can handle the incoming attach request. If a null string is
/// returned, the host continues to search for registered processors that matches
/// the address exactly in the attach.
/// </remarks>
public Func<ContainerHost, Attach, string> AddressResolver
{
get;
set;
}
/// <summary>
/// Opens the container host object.
/// </summary>
@ -323,9 +340,12 @@ namespace Amqp.Listener
static void ThrowIfExists<T>(string address, Dictionary<string, T> processors)
{
if (processors.ContainsKey(address))
lock (processors)
{
throw new AmqpException(ErrorCode.NotAllowed, typeof(T).Name + " processor has been registered at address " + address);
if (processors.ContainsKey(address))
{
throw new AmqpException(ErrorCode.NotAllowed, typeof(T).Name + " processor has been registered at address " + address);
}
}
}
@ -392,36 +412,44 @@ namespace Amqp.Listener
throw new AmqpException(ErrorCode.Stolen, string.Format("Link '{0}' has been attached already.", attach.LinkName));
}
string address = attach.Role ? ((Source)attach.Source).Address : ((Target)attach.Target).Address;
if (string.IsNullOrWhiteSpace(address))
string address = null;
if (this.AddressResolver != null)
{
throw new AmqpException(ErrorCode.InvalidField, "The address field cannot be empty");
address = this.AddressResolver(this, attach);
}
if (listenerLink.Role)
if (address == null)
{
MessageProcessor messageProcessor;
if (TryGetProcessor(this.messageProcessors, address, out messageProcessor))
{
messageProcessor.AddLink(listenerLink, address);
return true;
}
}
else
{
MessageSource messageSource;
if (TryGetProcessor(this.messageSources, address, out messageSource))
{
messageSource.AddLink(listenerLink, address);
return true;
}
address = attach.Role ? ((Source)attach.Source).Address : ((Target)attach.Target).Address;
}
RequestProcessor requestProcessor;
if (TryGetProcessor(this.requestProcessors, address, out requestProcessor))
if (address != null)
{
requestProcessor.AddLink(listenerLink, address, attach);
return true;
if (listenerLink.Role)
{
MessageProcessor messageProcessor;
if (TryGetProcessor(this.messageProcessors, address, out messageProcessor))
{
messageProcessor.AddLink(listenerLink, address);
return true;
}
}
else
{
MessageSource messageSource;
if (TryGetProcessor(this.messageSources, address, out messageSource))
{
messageSource.AddLink(listenerLink, address);
return true;
}
}
RequestProcessor requestProcessor;
if (TryGetProcessor(this.requestProcessors, address, out requestProcessor))
{
requestProcessor.AddLink(listenerLink, address, attach);
return true;
}
}
if (this.linkProcessor != null)
@ -430,6 +458,11 @@ namespace Amqp.Listener
return false;
}
if (string.IsNullOrWhiteSpace(address))
{
throw new AmqpException(ErrorCode.InvalidField, "The address field cannot be empty.");
}
throw new AmqpException(ErrorCode.NotFound, "No processor was found at " + address);
}

Просмотреть файл

@ -53,7 +53,9 @@ namespace Amqp.Listener
/// </summary>
/// <param name="flowContext">Context of the received flow performative.</param>
/// <remarks>
/// A sending endpoint should send messages per the requested message count.
/// A sending endpoint should send messages per the requested message count. If not enough
/// messages are available, it should also check <see cref="ListenerLink.IsDraining"/> and
/// call <see cref="ListenerLink.CompleteDrain"/>.
/// A receiving endpoint may receive a flow if the sender wants to exchange flow
/// state or send custom properties.
/// </remarks>

Просмотреть файл

@ -17,11 +17,10 @@
namespace Amqp.Listener
{
using System;
using System.Security.Principal;
using System.Threading;
using Amqp.Framing;
using Amqp.Handler;
using System.Collections.Generic;
using System.Security.Principal;
/// <summary>
/// An AMQP connection used by the listener.
@ -30,6 +29,7 @@ namespace Amqp.Listener
{
readonly static OnOpened onOpened = OnOpen;
readonly ConnectionListener listener;
Dictionary<string, object> properties;
internal ListenerConnection(ConnectionListener listener, Address address, IHandler handler, IAsyncTransport transport)
: base(listener.BufferManager, listener.AMQP, address, transport, null, onOpened, handler)
@ -47,6 +47,14 @@ namespace Amqp.Listener
internal set;
}
/// <summary>
/// Custom properties attached to the connection. This is not thread safe.
/// </summary>
public IDictionary<string, object> Properties
{
get { return this.properties ?? (this.properties = new Dictionary<string, object>()); }
}
internal ConnectionListener Listener
{
get { return this.listener; }

Просмотреть файл

@ -32,6 +32,7 @@ namespace Amqp.Listener
object state;
SequenceNumber deliveryCount;
uint credit;
bool drain;
// caller can initialize the link for an endpoint, a sender or a receiver
// based on its needs.
@ -85,6 +86,14 @@ namespace Amqp.Listener
get { return this.state; }
}
/// <summary>
/// Gets a value that indicates whether the link is in drain mode (applicable when the link is in sender role).
/// </summary>
public bool IsDraining
{
get { return this.drain; }
}
internal uint Credit
{
get { return this.credit; }
@ -112,6 +121,10 @@ namespace Amqp.Listener
/// <param name="onCredit">The callback to be invoked when delivery limit changes (by received flow performatives).</param>
/// <param name="onDispose">The callback to be invoked when disposition is received.</param>
/// <param name="state">The user state attached to the link.</param>
/// <remarks>
/// In the <see cref="onCredit"/> callback, if the application does not have enough messages to satisfy the credits, it should check the
/// <see cref="IsDraining"/> property. If the value is true, it should discard remaining credits and call <see cref="CompleteDrain"/>.
/// </remarks>
public void InitializeSender(Action<int, Fields, object> onCredit, Action<Message, DeliveryState, bool, object> onDispose, object state)
{
ThrowIfNotNull(this.linkEndpoint, "endpoint");
@ -241,6 +254,27 @@ namespace Amqp.Listener
}
}
/// <summary>
/// Completes the drain mode. The library will comsume all availble link credits and send a flow to the remote peer.
/// </summary>
/// <remarks>
/// The application should reset any credits that it may keep before calling this function. After this, the application
/// should not send any messages, when they are available, until it receives another onCredit callback with credits.
/// </remarks>
public void CompleteDrain()
{
lock (this.ThisLock)
{
if (this.drain)
{
this.deliveryCount += (int)this.credit;
this.credit = 0;
this.drain = false;
this.SendFlow(this.deliveryCount, this.credit, this.drain);
}
}
}
internal void SafeAddClosed(ClosedCallback callback)
{
this.Closed += callback;
@ -359,6 +393,7 @@ namespace Amqp.Listener
{
if (!this.role)
{
this.drain = flow.Drain;
var theirLimit = (SequenceNumber)(flow.DeliveryCount + flow.LinkCredit);
var myLimit = this.deliveryCount + (SequenceNumber)this.credit;
delta = theirLimit - myLimit;

Просмотреть файл

@ -78,7 +78,7 @@ namespace Amqp.Listener
{
while (!this.link.IsDetaching)
{
ReceiveContext receiveContext = await this.messageSource.GetMessageAsync(this.link);
ReceiveContext receiveContext = await this.messageSource.GetMessageAsync(this.link).ConfigureAwait(false);
if (receiveContext != null)
{
try
@ -104,6 +104,16 @@ namespace Amqp.Listener
break;
}
}
else if (this.link.IsDraining)
{
lock (this.syncRoot)
{
this.receiving = false;
}
this.link.CompleteDrain();
break;
}
}
}
}

Просмотреть файл

@ -193,18 +193,26 @@ namespace Amqp
return message;
}
/// <summary>
/// Gets the information of the message delivery. It can be used to acknowledge the message
/// later even if the message has been disposed or discarded.
/// </summary>
/// <returns>A <see cref="MessageDelivery"/> object, or null if delivery has not happened yet.</returns>
public MessageDelivery GetDelivery()
{
return this.Delivery == null ? MessageDelivery.None : new MessageDelivery(this.Delivery);
}
/// <summary>
/// Disposes the current message to release resources.
/// </summary>
public void Dispose()
{
#if NETFX || NETFX40 || DOTNET
if (this.Delivery != null &&
this.Delivery.Buffer != null)
if (this.Delivery != null)
{
this.Delivery.Buffer.ReleaseReference();
this.Delivery.Dispose();
this.Delivery = null;
}
#endif
}
internal ByteBuffer Encode(int reservedBytes)
@ -280,7 +288,10 @@ namespace Amqp
return 64;
}
int GetEstimatedMessageSize()
/// <summary>
/// Gets estimated message size in bytes.
/// </summary>
public int GetEstimatedMessageSize()
{
int size = 0;
if (this.Header != null) size += 64;

71
src/MessageDelivery.cs Normal file
Просмотреть файл

@ -0,0 +1,71 @@
// ------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the ""License""); you may not use this
// file except in compliance with the License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------
namespace Amqp
{
using Amqp.Framing;
/// <summary>
/// Contains the state associated with a message delivery.
/// </summary>
public struct MessageDelivery
{
readonly Delivery delivery;
internal MessageDelivery(Delivery delivery)
{
this.delivery = delivery;
}
/// <summary>
/// Returs an empty value for a message that is not delivered yet.
/// </summary>
public static MessageDelivery None
{
get { return default(MessageDelivery); }
}
/// <summary>
/// Gets the delivery tag.
/// </summary>
public byte[] Tag
{
get { return this.delivery.Tag; }
}
/// <summary>
/// Gets the delivery state.
/// </summary>
public DeliveryState State
{
get { return this.delivery.State; }
}
/// <summary>
/// Gets the Link over which the message was transferred, or null if the message is not transferred yet.
/// </summary>
public Link Link
{
get { return this.delivery.Link; }
}
internal Delivery Delivery
{
get { return this.delivery; }
}
};
}

Просмотреть файл

@ -68,7 +68,8 @@ namespace Amqp
}
/// <summary>
/// Gets or sets the open.idle-time-out field.
/// Gets or sets the connection idle timeout. Half the value is set
/// as the value of open.idle-time-out field.
/// </summary>
public int IdleTimeout
{

Просмотреть файл

@ -91,6 +91,10 @@ namespace Amqp
{
await this.PumpAsync(connection.MaxFrameSize, connection.OnHeader, connection.OnFrame).ConfigureAwait(false);
}
catch (AmqpException amqpException)
{
connection.OnException(amqpException);
}
catch (Exception exception)
{
connection.OnIoException(exception);

Просмотреть файл

@ -110,15 +110,37 @@ namespace Amqp
/// Creates a new connection with a custom open frame and a callback to handle remote open frame.
/// </summary>
/// <param name="address">The address of remote endpoint to connect to.</param>
/// <param name="open">If specified, it is sent to open the connection, otherwise an open frame created from the AMQP settings property is sent.</param>
/// <param name="open">If specified, it is sent to open the connection, otherwise an open frame created from the AMQP settings is sent.</param>
/// <param name="onOpened">If specified, it is invoked when an open frame is received from the remote peer.</param>
/// <returns>A task for the connection creation operation. On success, the result is an AMQP <see cref="Connection"/></returns>
/// <remarks>The Open object, when provided, is used as is, and not augmented by the AMQP settings.</remarks>
public Task<Connection> CreateAsync(Address address, Open open = null, OnOpened onOpened = null)
{
return this.CreateAsync(address, open, onOpened, null);
}
async Task<Connection> CreateAsync(Address address, Open open, OnOpened onOpened, IHandler handler)
internal async Task ConnectAsync(Address address, SaslProfile saslProfile, Open open, Connection connection)
{
if (saslProfile == null)
{
if (address.User != null)
{
saslProfile = new SaslPlainProfile(address.User, address.Password);
}
else if (this.saslSettings != null && this.saslSettings.Profile != null)
{
saslProfile = this.saslSettings.Profile;
}
}
IAsyncTransport transport = await this.CreateTransportAsync(address, saslProfile, connection.Handler).ConfigureAwait(false);
connection.Init(this.BufferManager, this.AMQP, transport, open);
AsyncPump pump = new AsyncPump(this.BufferManager, transport);
pump.Start(connection);
}
async Task<IAsyncTransport> CreateTransportAsync(Address address, SaslProfile saslProfile, IHandler handler)
{
IAsyncTransport transport;
TransportProvider provider;
@ -145,27 +167,38 @@ namespace Amqp
throw new NotSupportedException(address.Scheme);
}
try
if (saslProfile != null)
{
try
{
transport = await saslProfile.OpenAsync(address.Host, this.BufferManager, transport, null).ConfigureAwait(false);
}
catch
{
transport.Close();
throw;
}
}
return transport;
}
async Task<Connection> CreateAsync(Address address, Open open, OnOpened onOpened, IHandler handler)
{
SaslProfile saslProfile = null;
if (address.User != null)
{
if (address.User != null)
{
SaslPlainProfile profile = new SaslPlainProfile(address.User, address.Password);
transport = await profile.OpenAsync(address.Host, this.BufferManager, transport, null).ConfigureAwait(false);
}
else if (this.saslSettings != null && this.saslSettings.Profile != null)
{
transport = await this.saslSettings.Profile.OpenAsync(address.Host, this.BufferManager, transport, null).ConfigureAwait(false);
}
saslProfile = new SaslPlainProfile(address.User, address.Password);
}
catch
else if (this.saslSettings != null && this.saslSettings.Profile != null)
{
transport.Close();
throw;
saslProfile = this.saslSettings.Profile;
}
IAsyncTransport transport = await this.CreateTransportAsync(address, saslProfile, handler).ConfigureAwait(false);
Connection connection = new Connection(this.BufferManager, this.AMQP, address, transport, open, onOpened, handler);
AsyncPump pump = new AsyncPump(this.BufferManager, transport);
Connection connection = new Connection(this.BufferManager, this.AMQP, address, transport, open, onOpened, handler);
pump.Start(connection);
return connection;

Просмотреть файл

@ -41,7 +41,7 @@ namespace Amqp
this.amqpSettings = new AmqpSettings()
{
MaxFrameSize = (int)Connection.DefaultMaxFrameSize,
ContainerId = "AMQPNetLite-" + Guid.NewGuid().ToString("N").Substring(0, 8),
ContainerId = Connection.MakeAmqpContainerId(),
IdleTimeout = int.MaxValue,
MaxSessionsPerConnection = Connection.DefaultMaxSessions,
MaxLinksPerSession = Connection.DefaultMaxLinksPerSession

Просмотреть файл

@ -36,7 +36,7 @@ namespace Amqp
{
async Task<IConnection> IConnectionFactory.CreateAsync(Address address)
{
return await this.CreateAsync(address, null, null);
return await this.CreateAsync(address, null, null).ConfigureAwait(false);
}
}
}

Просмотреть файл

@ -34,8 +34,10 @@ namespace Amqp
// but it seems that the value is passed to the PAL implementation
// so it should work if the runtime supports it.
// 3 = TcpKeepAliveTime, 17 = TcpKeepAliveInterval
socket.SetSocketOption(SocketOptionLevel.Tcp, (SocketOptionName)3, (int)settings.KeepAliveTime);
socket.SetSocketOption(SocketOptionLevel.Tcp, (SocketOptionName)17, (int)settings.KeepAliveInterval);
int timeInSeconds = (int)Math.Ceiling(settings.KeepAliveTime / 1000.0);
int intervalInSeconds = (int)Math.Ceiling(settings.KeepAliveInterval / 1000.0);
socket.SetSocketOption(SocketOptionLevel.Tcp, (SocketOptionName)3, timeInSeconds);
socket.SetSocketOption(SocketOptionLevel.Tcp, (SocketOptionName)17, intervalInSeconds);
#else
// This is only supported on Windows

Просмотреть файл

@ -152,14 +152,14 @@ namespace Amqp
}
#if !NETFX40
Task task = await Task.WhenAny(tcs.Task, Task.Delay(timeout));
Task task = await Task.WhenAny(tcs.Task, Task.Delay(timeout)).ConfigureAwait(false);
if (task != tcs.Task)
{
tcs.TrySetException(new TimeoutException(Fx.Format(SRAmqp.AmqpTimeout,
"close", timeout, this.GetType().Name)));
}
#endif
await tcs.Task;
await tcs.Task.ConfigureAwait(false);
}
}

Просмотреть файл

@ -6,7 +6,7 @@
public class TcpKeepAliveSettings
{
/// <summary>
/// How often a keep-alive transmission is sent to an idle connection.
/// Gets or sets a value in milliseconds that defines how often a keep-alive transmission is sent to an idle connection.
/// </summary>
public uint KeepAliveTime
{
@ -15,7 +15,8 @@
}
/// <summary>
/// How often a keep-alive transmission is sent when no response is received from previous keep-alive transmissions.
/// Gets or sets a value in milliseconds that defines how often a keep-alive transmission
/// is sent when no response is received from previous keep-alive transmissions.
/// </summary>
public uint KeepAliveInterval
{

Просмотреть файл

@ -119,7 +119,7 @@ namespace Amqp
IAsyncTransport transport;
if (address.UseSsl)
{
RemoteCertificateValidationCallback remoteCertificateValidationCallback = null;
RemoteCertificateValidationCallback remoteCertificateValidationCallback = Connection.DisableServerCertValidation ? noneCertValidator : null;
LocalCertificateSelectionCallback localCertificateSelectionCallback = null;
var ssl = factory.SslInternal;
if (ssl != null)

Просмотреть файл

@ -25,5 +25,5 @@ using System.Reflection;
// Revision
//
[assembly: AssemblyVersion("2.1.0")]
[assembly: AssemblyFileVersion("2.4.3")]
[assembly: AssemblyInformationalVersion("2.4.3")]
[assembly: AssemblyFileVersion("2.4.4")]
[assembly: AssemblyInformationalVersion("2.4.4")]

Просмотреть файл

@ -240,9 +240,18 @@ namespace Amqp
/// </summary>
/// <param name="message">The message to accept.</param>
public void Accept(Message message)
{
this.Accept(message.GetDelivery());
}
/// <summary>
/// Accepts a message. It sends an accepted outcome to the peer.
/// </summary>
/// <param name="messageDelivery">Delivery information of a message to accept.</param>
public void Accept(MessageDelivery messageDelivery)
{
this.ThrowIfDetaching("Accept");
this.DisposeMessage(message, new Accepted(), null);
this.UpdateDelivery(messageDelivery, new Accepted(), null);
}
/// <summary>
@ -251,8 +260,17 @@ namespace Amqp
/// <param name="message">The message to release.</param>
public void Release(Message message)
{
this.ThrowIfDetaching("Release");
this.DisposeMessage(message, new Released(), null);
this.Release(message.GetDelivery());
}
/// <summary>
/// Releases a message. It sends a released outcome to the peer.
/// </summary>
/// <param name="messageDelivery">Delivery information of a message to release.</param>
public void Release(MessageDelivery messageDelivery)
{
this.ThrowIfDetaching("Accept");
this.UpdateDelivery(messageDelivery, new Released(), null);
}
/// <summary>
@ -261,9 +279,19 @@ namespace Amqp
/// <param name="message">The message to reject.</param>
/// <param name="error">The error, if any, for the rejection.</param>
public void Reject(Message message, Error error = null)
{
this.Reject(message.GetDelivery(), error);
}
/// <summary>
/// Rejects a message. It sends a rejected outcome to the peer.
/// </summary>
/// <param name="messageDelivery">Delivery information of a message to reject.</param>
/// <param name="error">The error, if any, for the rejection.</param>
public void Reject(MessageDelivery messageDelivery, Error error = null)
{
this.ThrowIfDetaching("Reject");
this.DisposeMessage(message, new Rejected() { Error = error }, null);
this.UpdateDelivery(messageDelivery, new Rejected() { Error = error }, null);
}
/// <summary>
@ -274,15 +302,27 @@ namespace Amqp
/// <param name="undeliverableHere">Indicates if the message should not be redelivered to this endpoint.</param>
/// <param name="messageAnnotations">Annotations to be combined with the current message annotations.</param>
public void Modify(Message message, bool deliveryFailed, bool undeliverableHere = false, Fields messageAnnotations = null)
{
this.Modify(message.GetDelivery(), deliveryFailed, undeliverableHere, messageAnnotations);
}
/// <summary>
/// Modifies a message. It sends a modified outcome to the peer.
/// </summary>
/// <param name="messageDelivery">Delivery information of a message to reject.</param>
/// <param name="deliveryFailed">If set, the message's delivery-count is incremented.</param>
/// <param name="undeliverableHere">Indicates if the message should not be redelivered to this endpoint.</param>
/// <param name="messageAnnotations">Annotations to be combined with the current message annotations.</param>
public void Modify(MessageDelivery messageDelivery, bool deliveryFailed, bool undeliverableHere = false, Fields messageAnnotations = null)
{
this.ThrowIfDetaching("Modify");
this.DisposeMessage(message, new Modified()
{
DeliveryFailed = deliveryFailed,
UndeliverableHere = undeliverableHere,
MessageAnnotations = messageAnnotations
},
null);
this.UpdateDelivery(messageDelivery, new Modified()
{
DeliveryFailed = deliveryFailed,
UndeliverableHere = undeliverableHere,
MessageAnnotations = messageAnnotations
},
null);
}
/// <summary>
@ -297,7 +337,22 @@ namespace Amqp
/// <paramref name="deliveryState"/>.</remarks>
public void Complete(Message message, DeliveryState deliveryState)
{
this.DisposeMessage(message, null, deliveryState);
this.Complete(message.GetDelivery(), deliveryState);
}
/// <summary>
/// Completes a received message. It settles the delivery and sends
/// a disposition with the delivery state to the remote peer.
/// </summary>
/// <param name="messageDelivery">Delivery information of a message to reject.</param>
/// <param name="deliveryState">An <see cref="Outcome"/> or a TransactionalState.</param>
/// <remarks>This method is not transaction aware. It should be used to bypass
/// transaction context look up when transactions are not used at all, or
/// to manage AMQP transactions directly by providing a TransactionalState to
/// <paramref name="deliveryState"/>.</remarks>
public void Complete(MessageDelivery messageDelivery, DeliveryState deliveryState)
{
this.UpdateDelivery(messageDelivery, null, deliveryState);
}
internal override void OnFlow(Flow flow)
@ -476,9 +531,14 @@ namespace Amqp
}
// deliveryState overwrites outcome
void DisposeMessage(Message message, Outcome outcome, DeliveryState deliveryState)
void UpdateDelivery(MessageDelivery messageDelivery, Outcome outcome, DeliveryState deliveryState)
{
Delivery delivery = message.Delivery;
Delivery delivery = messageDelivery.Delivery;
if (delivery == null)
{
throw new InvalidOperationException("Message was not delivered yet.");
}
if (delivery == null || delivery.Link != this)
{
throw new InvalidOperationException("Message was not received by this link.");

Просмотреть файл

@ -93,15 +93,37 @@ namespace Amqp
/// Creates a new connection with a custom open frame and a callback to handle remote open frame.
/// </summary>
/// <param name="address">The address of remote endpoint to connect to.</param>
/// <param name="open">If specified, it is sent to open the connection, otherwise an open frame created from the AMQP settings property is sent.</param>
/// <param name="open">If specified, it is sent to open the connection, otherwise an open frame created from the AMQP settings is sent.</param>
/// <param name="onOpened">If specified, it is invoked when an open frame is received from the remote peer.</param>
/// <returns>A task for the connection creation operation. On success, the result is an AMQP <see cref="Connection"/></returns>
/// <remarks>The Open object, when provided, is used as is, and not augmented by the AMQP settings.</remarks>
public Task<Connection> CreateAsync(Address address, Open open, OnOpened onOpened)
{
return this.CreateAsync(address, open, onOpened, null);
}
async Task<Connection> CreateAsync(Address address, Open open, OnOpened onOpened, IHandler handler)
internal async Task ConnectAsync(Address address, SaslProfile saslProfile, Open open, Connection connection)
{
if (saslProfile == null)
{
if (address.User != null)
{
saslProfile = new SaslPlainProfile(address.User, address.Password);
}
else if (this.saslSettings != null && this.saslSettings.Profile != null)
{
saslProfile = this.saslSettings.Profile;
}
}
IAsyncTransport transport = await this.CreateTransportAsync(address, saslProfile, connection.Handler).ConfigureAwait(false);
connection.Init(null, this.AMQP, transport, open);
AsyncPump pump = new AsyncPump(null, transport);
pump.Start(connection);
}
async Task<IAsyncTransport> CreateTransportAsync(Address address, SaslProfile saslProfile, IHandler handler)
{
IAsyncTransport transport;
#if !WINDOWS_PHONE
@ -125,18 +147,38 @@ namespace Amqp
throw new NotSupportedException(address.Scheme);
}
if (saslProfile != null)
{
try
{
transport = await saslProfile.OpenAsync(address.Host, null, transport, null).ConfigureAwait(false);
}
catch
{
transport.Close();
throw;
}
}
return transport;
}
async Task<Connection> CreateAsync(Address address, Open open, OnOpened onOpened, IHandler handler)
{
SaslProfile saslProfile = null;
if (address.User != null)
{
SaslPlainProfile profile = new SaslPlainProfile(address.User, address.Password);
transport = await profile.OpenAsync(address.Host, null, transport, null).ConfigureAwait(false);
saslProfile = new SaslPlainProfile(address.User, address.Password);
}
else if (this.saslSettings != null && this.saslSettings.Profile != null)
{
transport = await this.saslSettings.Profile.OpenAsync(address.Host, null, transport, null).ConfigureAwait(false);
saslProfile = this.saslSettings.Profile;
}
AsyncPump pump = new AsyncPump(null, transport);
IAsyncTransport transport = await this.CreateTransportAsync(address, saslProfile, handler).ConfigureAwait(false);
Connection connection = new Connection(null, this.AMQP, address, transport, open, onOpened, handler);
AsyncPump pump = new AsyncPump(null, transport);
pump.Start(connection);
return connection;

Просмотреть файл

@ -73,6 +73,7 @@ namespace Test.Amqp
public void TestCleanup()
{
this.host.AddressResolver = null;
if (this.linkProcessor != null)
{
this.host.UnregisterLinkProcessor(this.linkProcessor);
@ -93,6 +94,66 @@ namespace Test.Amqp
this.ClassCleanup();
}
[TestMethod]
public void ContainerHostAddressResolverTest()
{
string name = "router";
var processor = new TestMessageProcessor();
this.host.AddressResolver = (h, a) => name;
this.host.RegisterMessageProcessor(name, processor);
int count = 10;
var connection = new Connection(Address);
var session = new Session(connection);
for (int i = 0; i < count; i++)
{
var sender = new SenderLink(session, "send-link", "node" + i);
var message = new Message("msg" + i);
message.Properties = new Properties() { To = "node" + i };
sender.Send(message, null, null);
sender.Close();
}
session.Close();
connection.Close();
Assert.AreEqual(count, processor.Messages.Count);
for (int i = 0; i < count; i++)
{
var message = processor.Messages[i];
Assert.AreEqual("node" + (i % 10), message.Properties.To);
}
}
[TestMethod]
public void ContainerHostDynamicProcessorTest()
{
string name = "ContainerHostDynamicProcessorTest";
var processor = new TestMessageProcessor();
this.host.AddressResolver = (h, a) =>
{
h.RegisterMessageProcessor(name, processor);
return name;
};
int count = 10;
var connection = new Connection(Address);
var session = new Session(connection);
var sender = new SenderLink(session, "send-link", name);
for (int i = 0; i < count; i++)
{
var message = new Message("msg" + i);
message.Properties = new Properties() { GroupId = name };
sender.Send(message, Timeout);
}
sender.Close();
session.Close();
connection.Close();
}
[TestMethod]
public void ContainerHostMessageProcessorTest()
{
@ -177,6 +238,70 @@ namespace Test.Amqp
Assert.AreEqual(rejected, source.DeadLetterCount, string.Join(",", source.DeadletterMessage.Select(m => m.Properties.MessageId)));
}
[TestMethod]
public void ContainerHostMessageSourceDrainTest()
{
string name = "ContainerHostMessageSourceDrainTest";
int count = 10;
Queue<Message> messages = new Queue<Message>();
for (int i = 0; i < count; i++)
{
messages.Enqueue(new Message("test") { Properties = new Properties() { MessageId = name + i } });
}
var source = new TestMessageSource(messages);
this.host.RegisterMessageSource(name, source);
var connection = new Connection(Address);
var session = new Session(connection);
var receiver = new ReceiverLink(session, "receiver0", name);
receiver.SetCredit(count + 4, CreditMode.Drain);
for (int i = 1; i <= count; i++)
{
var message = receiver.Receive();
Assert.IsTrue(message != null);
receiver.Accept(message);
}
{
messages.Enqueue(new Message("test") { Properties = new Properties() { MessageId = name + count } });
var message = receiver.Receive(TimeSpan.FromMilliseconds(500));
Assert.IsTrue(message == null);
}
receiver.Close();
session.Close();
connection.Close();
}
[TestMethod]
public void ContainerHostAnyMessageSourceTest()
{
string name = "*";
int count = 10;
Queue<Message> messages = new Queue<Message>();
for (int i = 0; i < count; i++)
{
messages.Enqueue(new Message("test") { Properties = new Properties() { MessageId = name + i } });
}
this.host.AddressResolver = (h, a) => name;
var source = new TestMessageSource(messages);
this.host.RegisterMessageSource(name, source);
var connection = new Connection(Address);
var session = new Session(connection);
var receiver = new ReceiverLink(session, "receiver0", null);
for (int i = 1; i <= count; i++)
{
Message message = receiver.Receive();
receiver.Accept(message);
}
receiver.Close();
session.Close();
connection.Close();
}
[TestMethod]
public void ContainerHostRequestProcessorTest()
{
@ -887,6 +1012,25 @@ namespace Test.Amqp
connection.Close();
}
[TestMethod]
public void ContainerHostListenerCustomSaslMechanismTest()
{
string name = "ContainerHostListenerCustomSaslMechanismTest";
var serverSaslProfile = new CustomSaslProfile(name);
this.host.Listeners[0].SASL.EnableMechanism(name, serverSaslProfile);
this.host.RegisterMessageProcessor(name, new TestMessageProcessor());
var factory = new ConnectionFactory();
factory.SASL.Profile = new CustomSaslProfile(name);
var connection = factory.CreateAsync(new Address(Address.Host, Address.Port, null, null, "/", Address.Scheme)).Result;
var session = new Session(connection);
var sender = new SenderLink(session, name, name);
sender.Send(new Message("msg1"), Timeout);
connection.Close();
Assert.IsTrue(serverSaslProfile.Transport != null);
}
[TestMethod]
public void ContainerHostSaslPlainNegativeTest()
{
@ -1395,9 +1539,11 @@ namespace Test.Amqp
{
}
public ITransport Transport { get; private set;}
protected override ITransport UpgradeTransport(ITransport transport)
{
return transport;
return this.Transport = transport;
}
protected override DescribedList GetStartCommand(string hostname)
@ -1411,6 +1557,11 @@ namespace Test.Amqp
protected override DescribedList OnCommand(DescribedList command)
{
if (command.Descriptor.Code == 0x0000000000000041 /* SaslInit.Code */)
{
return new SaslOutcome() { Code = SaslCode.Ok };
}
return null;
}
}

Просмотреть файл

@ -149,6 +149,110 @@ namespace Test.Amqp
connection.Close();
}
#if NETFX || NETFX35 || NETFX_CORE || DOTNET
[TestMethod]
#endif
public void TestMethod_MessageDeliveryAccept()
{
string testName = "MessageDeliveryAccept";
Connection connection = new Connection(testTarget.Address);
Session session = new Session(connection);
SenderLink sender = new SenderLink(session, "sender-" + testName, testTarget.Path);
Message message = new Message("msg accept");
sender.Send(message, null, null);
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path);
message = receiver.Receive();
MessageDelivery messageDelivery = message.GetDelivery();
message.Dispose();
receiver.Accept(messageDelivery);
connection.Close();
}
#if NETFX || NETFX35 || NETFX_CORE || DOTNET
[TestMethod]
#endif
public void TestMethod_MessageDeliveryRelease()
{
string testName = "MessageDeliveryRelease";
Connection connection = new Connection(testTarget.Address);
Session session = new Session(connection);
SenderLink sender = new SenderLink(session, "sender-" + testName, testTarget.Path);
Message message = new Message("msg release");
sender.Send(message, null, null);
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path);
message = receiver.Receive();
MessageDelivery messageDelivery = message.GetDelivery();
message.Dispose();
receiver.Release(messageDelivery);
connection.Close();
}
#if NETFX || NETFX35 || NETFX_CORE || DOTNET
[TestMethod]
#endif
public void TestMethod_MessageDeliveryReject()
{
string testName = "MessageDeliveryReject";
Connection connection = new Connection(testTarget.Address);
Session session = new Session(connection);
SenderLink sender = new SenderLink(session, "sender-" + testName, testTarget.Path);
Message message = new Message("msg reject");
sender.Send(message, null, null);
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path);
message = receiver.Receive();
MessageDelivery messageDelivery = message.GetDelivery();
message.Dispose();
receiver.Reject(messageDelivery);
connection.Close();
}
#if NETFX || NETFX35 || NETFX_CORE || DOTNET
[TestMethod]
#endif
public void TestMethod_MessageDeliveryModify()
{
string testName = "MessageDeliveryModify";
Connection connection = new Connection(testTarget.Address);
Session session = new Session(connection);
SenderLink sender = new SenderLink(session, "sender-" + testName, testTarget.Path);
Message message = new Message("msg modify");
sender.Send(message, null, null);
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path);
message = receiver.Receive();
MessageDelivery messageDelivery = message.GetDelivery();
message.Dispose();
receiver.Modify(messageDelivery, true);
connection.Close();
}
#if NETFX || NETFX35 || NETFX_CORE || DOTNET
[TestMethod]
#endif
public void TestMethod_MessageDeliveryResend()
{
string testName = "MessageDeliveryResend";
Connection connection = new Connection(testTarget.Address);
Session session = new Session(connection);
SenderLink sender = new SenderLink(session, "sender-" + testName, testTarget.Path);
Message message = new Message("msg resend");
sender.Send(message, null, null);
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path);
message = receiver.Receive();
MessageDelivery messageDelivery = message.GetDelivery();
message.Properties = new Properties() { GroupId = "abcdefg" };
sender.Send(message, null, null);
message.Dispose();
receiver.Accept(messageDelivery);
connection.Close();
}
#if NETFX || NETFX35 || NETFX_CORE || DOTNET
[TestMethod]
#endif
@ -623,6 +727,68 @@ namespace Test.Amqp
connection.Close();
}
#if NETFX || NETFX35 || NETFX_CORE || DOTNET
[TestMethod]
#endif
public void TestMethod_ReceiveDrain()
{
string testName = "ReceiveDrain";
Connection connection = new Connection(testTarget.Address);
Session session = new Session(connection);
SenderLink sender = new SenderLink(session, "sender-" + testName, testTarget.Path);
Message msg = new Message() { Properties = new Properties() { MessageId = "12345" } };
sender.Send(msg);
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path);
receiver.SetCredit(2, CreditMode.Drain);
msg = receiver.Receive();
Assert.IsTrue(msg != null);
msg = new Message() { Properties = new Properties() { MessageId = "67890" } };
sender.Send(msg);
msg = receiver.Receive(TimeSpan.FromTicks(600 * TimeSpan.TicksPerMillisecond));
Assert.IsTrue(msg == null);
connection.Close();
}
#if NETFX || NETFX35 || NETFX_CORE || DOTNET
[TestMethod]
#endif
public void TestMethod_ReceiveReceiveSend()
{
string testName = "ReceiveReceiveSend";
Connection connection = new Connection(testTarget.Address);
Session session = new Session(connection);
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path);
Message msg = receiver.Receive(TimeSpan.FromTicks(500 * TimeSpan.TicksPerMillisecond));
Assert.IsTrue(msg == null);
receiver.Close();
session.Close();
session = new Session(connection);
receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path);
msg = receiver.Receive(TimeSpan.FromTicks(500 * TimeSpan.TicksPerMillisecond));
Assert.IsTrue(msg == null);
Connection connection2 = new Connection(testTarget.Address);
Session session2 = new Session(connection2);
SenderLink sender = new SenderLink(session2, "sender-" + testName, testTarget.Path);
msg = new Message() { Properties = new Properties() { MessageId = "12345" } };
sender.Send(msg);
msg = receiver.Receive(TimeSpan.FromTicks(6000 * TimeSpan.TicksPerMillisecond));
Assert.IsTrue(msg != null);
receiver.Accept(msg);
connection2.Close();
connection.Close();
}
#if NETFX || NETFX35 || NETFX_CORE || DOTNET
[TestMethod]
#endif
@ -915,6 +1081,7 @@ namespace Test.Amqp
}
});
Connection.DisableServerCertValidation = true;
Address sslAddress = new Address("amqps://guest:guest@localhost:5671");
Connection connection = new Connection(sslAddress, handler);
Session session = new Session(connection);

Просмотреть файл

@ -100,6 +100,101 @@ namespace Test.Amqp
}).Unwrap().GetAwaiter().GetResult();
}
[TestMethod]
public void ConnectionMaxFrameSizeNegativeTest()
{
Stream networkStream = null;
this.testListener.RegisterTarget(TestPoint.Flow, (stream, channel, fields) =>
{
networkStream = stream;
TestListener.FRM(stream, 0x13UL, 0, channel, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, false, false,
new Fields() { { new Symbol("big-string"), new string('a', 1024) } }); // flow
return TestOutcome.Stop;
});
string testName = "ConnectionMaxFrameSizeNegativeTest";
Trace.WriteLine(TraceLevel.Information, "sync test");
{
Open open = new Open() { ContainerId = testName, HostName = "localhost", MaxFrameSize = 512 };
Connection connection = new Connection(this.address, null, open, null);
Session session = new Session(connection);
ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "any");
try
{
receiver.Receive();
}
catch (AmqpException) { }
Assert.IsTrue(connection.Error != null);
Assert.AreEqual((Symbol)ErrorCode.InvalidField, connection.Error.Condition);
Assert.AreEqual(ConnectionState.End, connection.ConnectionState);
try
{
Thread.Sleep(300);
networkStream.WriteByte(0);
Assert.IsTrue(false, "transport connection not closed");
}
catch (IOException) { }
catch (ObjectDisposedException) { }
}
Trace.WriteLine(TraceLevel.Information, "async test");
networkStream = null;
Task.Factory.StartNew(async () =>
{
ConnectionFactory factory = new ConnectionFactory();
factory.AMQP.MaxFrameSize = 512;
IConnection connection = await factory.CreateAsync(this.address);
ISession session = connection.CreateSession();
IReceiverLink receiver = session.CreateReceiver("receiver-" + testName, "any");
try
{
await receiver.ReceiveAsync();
}
catch (AmqpException) { }
Assert.IsTrue(connection.Error != null);
Assert.AreEqual((Symbol)ErrorCode.InvalidField, connection.Error.Condition);
try
{
networkStream.WriteByte(0);
Assert.IsTrue(false, "transport connection not closed");
}
catch (IOException) { }
catch (ObjectDisposedException) { }
await connection.CloseAsync();
}).Unwrap().GetAwaiter().GetResult();
}
[TestMethod]
public void ConnectionWithUserOpenTest()
{
string testName = "ConnectionWithUserOpenTest";
List receivedOpen = null;
this.testListener.RegisterTarget(TestPoint.Open, (stream, channel, fields) =>
{
receivedOpen = fields;
return TestOutcome.Continue;
});
Task.Factory.StartNew(async () =>
{
ConnectionFactory factory = new ConnectionFactory();
factory.AMQP.MaxFrameSize = 2048;
factory.AMQP.MaxSessionsPerConnection = 10;
Open open = new Open() { ContainerId = testName, HostName = "localhost", MaxFrameSize = 4096, ChannelMax = 128 };
Connection connection = await factory.CreateAsync(this.address, open, null);
Session session = new Session(connection);
SenderLink sender = new SenderLink(session, "sender-" + testName, "any");
await sender.SendAsync(new Message("test") { Properties = new Properties() { MessageId = testName } });
await connection.CloseAsync();
Assert.IsTrue(receivedOpen != null);
Assert.AreEqual(open.MaxFrameSize, receivedOpen[2]);
Assert.AreEqual(open.ChannelMax, receivedOpen[3]);
}).Unwrap().GetAwaiter().GetResult();
}
[TestMethod]
public void RemoteSessionChannelTest()
{
@ -209,14 +304,16 @@ namespace Test.Amqp
Trace.WriteLine(TraceLevel.Information, "sync test");
{
Open open = new Open() { ContainerId = testName, HostName = "localhost", IdleTimeOut = 1000 };
Open open = new Open() { ContainerId = testName, HostName = "localhost", IdleTimeOut = 500 };
Connection connection = new Connection(this.address, null, open, null);
Session session = new Session(connection);
SenderLink sender = new SenderLink(session, "sender-" + testName, "any");
sender.Send(new Message("test") { Properties = new Properties() { MessageId = testName } });
Thread.Sleep(1200);
var h = connection.GetType().GetField("heartBeat", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.IsTrue(h != null, "heart beat is not initialized");
Thread.Sleep(600);
Assert.IsTrue(!connection.IsClosed, "connection should not be closed");
Thread.Sleep(600);
Assert.IsTrue(connection.IsClosed, "connection not closed");
}

Просмотреть файл

@ -46,7 +46,7 @@ namespace Listener.IContainer
{
foreach (string q in queues)
{
this.queues.Add(q, new TestQueue(this));
this.queues.Add(q, new TestQueue(this, q));
}
}
else
@ -111,7 +111,7 @@ namespace Listener.IContainer
{
lock (this.queues)
{
this.queues.Add(queue, new TestQueue(this));
this.queues.Add(queue, new TestQueue(this, queue));
}
}
@ -220,9 +220,8 @@ namespace Listener.IContainer
{
if (dynamic || (this.implicitQueue && !link.Name.StartsWith("$explicit:")))
{
queue = new TestQueue(this);
queue = new TestQueue(this, address, !dynamic);
this.queues.Add(address, queue);
connection.Closed += (o, e) => this.RemoveQueue(address);
}
else
{
@ -361,6 +360,9 @@ namespace Listener.IContainer
sealed class TestQueue
{
readonly TestAmqpBroker broker;
readonly string address;
readonly bool isImplicit;
readonly HashSet<Connection> connections;
readonly LinkedList<BrokerMessage> messages;
readonly LinkedList<Consumer> waiters;
readonly Dictionary<int, Publisher> publishers;
@ -368,23 +370,27 @@ namespace Listener.IContainer
readonly object syncRoot;
int currentId;
public TestQueue(TestAmqpBroker broker)
public TestQueue(TestAmqpBroker broker, string address, bool isImplicit = false)
{
this.broker = broker;
this.address = address;
this.isImplicit = isImplicit;
this.connections = isImplicit ? new HashSet<Connection>() : null;
this.messages = new LinkedList<BrokerMessage>();
this.waiters = new LinkedList<Consumer>();
this.publishers = new Dictionary<int, Publisher>();
this.consumers = new Dictionary<int, Consumer>();
this.syncRoot = this.waiters;
this.syncRoot = new object();
}
public void CreatePublisher(ListenerLink link)
{
int id = Interlocked.Increment(ref this.currentId);
Publisher publisher = new Publisher(this, link, id);
lock (this.publishers)
lock (this.syncRoot)
{
this.publishers.Add(id, publisher);
this.OnClientConnected(link);
}
}
@ -392,9 +398,34 @@ namespace Listener.IContainer
{
int id = Interlocked.Increment(ref this.currentId);
Consumer consumer = new Consumer(this, link, id);
lock (this.consumers)
lock (this.syncRoot)
{
this.consumers.Add(id, consumer);
this.OnClientConnected(link);
}
}
void OnClientConnected(Link link)
{
if (this.isImplicit && !this.connections.Contains(link.Session.Connection))
{
this.connections.Add(link.Session.Connection);
link.Session.Connection.Closed += OnConnectionClosed;
}
}
void OnConnectionClosed(IAmqpObject sender, Error error)
{
if (this.isImplicit)
{
lock (this.syncRoot)
{
this.connections.Remove((Connection)sender);
if (this.connections.Count == 0)
{
this.broker.RemoveQueue(this.address);
}
}
}
}
@ -455,7 +486,7 @@ namespace Listener.IContainer
}
}
void Dequeue(Consumer consumer, int credit)
void Dequeue(Consumer consumer, int credit, bool drain)
{
List<BrokerMessage> messageList = new List<BrokerMessage>();
lock (this.syncRoot)
@ -492,7 +523,11 @@ namespace Listener.IContainer
}
}
if (consumer.Credit > 0)
if (drain)
{
consumer.Credit = 0;
}
else if (consumer.Credit > 0)
{
this.waiters.AddLast(consumer);
}
@ -538,11 +573,20 @@ namespace Listener.IContainer
}
}
void OnPublisherClosed(int id, Publisher publisher)
{
lock (this.syncRoot)
{
this.publishers.Remove(id);
}
}
void OnConsumerClosed(int id, Consumer consumer)
{
lock (this.syncRoot)
{
this.consumers.Remove(id);
this.waiters.Remove(consumer);
var node = this.messages.First;
while (node != null)
{
@ -576,10 +620,7 @@ namespace Listener.IContainer
void OnLinkClosed(IAmqpObject sender, Error error)
{
lock (this.queue.publishers)
{
this.queue.publishers.Remove(this.id);
}
this.queue.OnPublisherClosed(this.id, this);
}
static void OnMessage(ListenerLink link, Message message, DeliveryState deliveryState, object state)
@ -631,7 +672,6 @@ namespace Listener.IContainer
readonly TestQueue queue;
readonly ListenerLink link;
readonly int id;
int tag;
public Consumer(TestQueue queue, ListenerLink link, int id)
{
@ -652,11 +692,6 @@ namespace Listener.IContainer
this.link.SendMessage(message, message.Buffer);
}
ArraySegment<byte> GetNextTag()
{
return new ArraySegment<byte>(BitConverter.GetBytes(Interlocked.Increment(ref this.tag)));
}
void OnLinkClosed(IAmqpObject sender, Error error)
{
this.Credit = 0;
@ -666,7 +701,12 @@ namespace Listener.IContainer
static void OnCredit(int credit, Fields properties, object state)
{
var thisPtr = (Consumer)state;
thisPtr.queue.Dequeue(thisPtr, credit);
thisPtr.queue.Dequeue(thisPtr, credit, thisPtr.link.IsDraining);
if (thisPtr.link.IsDraining)
{
thisPtr.Credit = 0;
thisPtr.link.CompleteDrain();
}
}
static void OnDispose(Message message, DeliveryState deliveryState, bool settled, object state)

Просмотреть файл

@ -150,6 +150,54 @@ namespace Test.Amqp
await connection.CloseAsync();
}
[TestMethod]
public async Task ReceiverSenderAsync()
{
string testName = "ReceiverSenderAsync";
ConnectionFactory connectionFactory = new ConnectionFactory();
// Creating first ReceiverLink
Connection firstReceiverConnection = await connectionFactory.CreateAsync(this.testTarget.Address);
Session firstReceiverSession = new Session(firstReceiverConnection);
ReceiverLink firstReceiverLink = new ReceiverLink(firstReceiverSession, "receiver-link", testName);
// Does not work when creating SenderLink after first ReceiverLink
var senderConnection = await connectionFactory.CreateAsync(this.testTarget.Address);
var senderSession = new Session(senderConnection);
var senderLink = new SenderLink(senderSession, "sender-link", testName);
// Send and receive message
await senderLink.SendAsync(new Message(testName));
Message firstMessageReceived = await firstReceiverLink.ReceiveAsync(TimeSpan.FromMilliseconds(1000));
// Close first reveiver link
await firstReceiverLink.CloseAsync();
await firstReceiverSession.CloseAsync();
await firstReceiverConnection.CloseAsync();
// Creating second ReceiverLink
Connection secondReceiverConnection = await connectionFactory.CreateAsync(this.testTarget.Address);
Session secondReceiverSession = new Session(secondReceiverConnection);
ReceiverLink secondReceiverLink = new ReceiverLink(secondReceiverSession, "receiver-link", testName);
// Send and receive message
await senderLink.SendAsync(new Message(testName));
Message message = await secondReceiverLink.ReceiveAsync(TimeSpan.FromMilliseconds(1000));
Assert.IsTrue(message != null, "No message received");
secondReceiverLink.Accept(message);
// Close second reveiver link
await secondReceiverLink.CloseAsync();
await secondReceiverSession.CloseAsync();
await secondReceiverConnection.CloseAsync();
// Close sender link
await senderLink.CloseAsync();
await senderSession.CloseAsync();
await senderConnection.CloseAsync();
}
#endif
#if NETFX40

Просмотреть файл

@ -20,6 +20,7 @@
<AppxBundle>Never</AppxBundle>
<AllowCrossPlatformRetargeting>False</AllowCrossPlatformRetargeting>
<IntermediateOutputPath>..\..\obj\$(Configuration)\$(MSBuildProjectName)\</IntermediateOutputPath>
<PackageCertificateThumbprint>04523CFB02DAE8D40D906A2B7AB4D171D46EB550</PackageCertificateThumbprint>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

Двоичный файл не отображается.